AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

Golang在BFE的应用 by 陶春华@百度

发布者 golang
发布于 1457485666177  浏览 8562 关键词 Go, DevOps 
分享到

第1页

Golang在BFE的应用

百度运维部 陶春华 taochunhua@baidu.com

2016年1月



第2页

个人简介

• 陶春华,运维部,Baidu Front End团队

– 2010年,天津大学,计算机专业博士

• 2013年7月,加入百度

– 使用GO开发的项目

• 7层流量代理GO-BFE • 应用层防火墙WAF

• 百度GOLANG委员会成员



第3页

BFE(Baidu Front End)

• 百度统一前端

– 七层流量接入平台



BFE New.baidu.com Music.baidu.com



News



Music



第4页

BFE(Baidu Front End)



• 主要服务



• 接入转发 接入与转发

• 防攻击、流量调度、数据分析



流量调度



• 业务现状



BFE



• 覆盖大部分重要产品



防攻击



数据分析



• 日请求量 > 1000亿



第5页

为什么重写BFE

• 现存问题

– 修改成本高

• 事件驱动的编程模型:编码和调试难度大

• C语言本身的难度和开发效率 – 配置管理方式落后

• 为单产品线设计,无法支持平台化要求 • 配置变更(修改、重载、验证)能力差

– 变更和稳定性的矛盾 • 程序出core



第6页

技术选型:Go vs Nginx

• 学习成本 • 开发成本

–并发编程模型:同步(Go) vs 异步(Nginx)

– 内存管理 – 语言描述能力

• 性能

– 在BFE的场景下,性能在可接受范围内 – 通过算法设计和架构设计来弥补



第7页

几个问题

• GC优化 • http协议栈 • 分布式架构 • 好用的工具链



第8页

GC带来的问题

– GC是个好东西,但也有问题 – 难以避免的延迟(几十到几百ms)

• 经验公式:10万对象1ms 扫描时间

–1个tcp连接,约10个对象=> 1万连接,1ms gc延迟

• GO-BFE的实时需求

– 请求的处理延迟 平均1ms以内,最大10ms

• 实测

– 100万连接,400ms gc延迟



第9页

GC优化思路

• Go的gc算法

– Mark and Sweep:大量时间时间用于扫描对象

• 常规手段的核心:减少对象数

– 小对象合并成大对象

• 利用Array来合并一组对象(内部对象计数为1)

– 把数据放到C代码里面,通过cgo做接口使用

– 对象复用 (对象池) – 深度优化系统结构和算法



第10页

通过Array减少引用计数



OBJ1 OBJ2 OBJ3



OBJ1 OBJ2 OBJ3



第11页

困境

• 减小对象数的困境

– 常态下需要保持几十万的连接 => 几十个ms – 修改golang网络库,重写基本数据结构

• 不使用让go管理内存

– 通过Cgo手工维护,很危险 (go中调用c代码) – 不能解决问题:大量go对象难以避免



第12页

车轮大战!



Parent Listen



Time1



Child Serv



Child Wait



Child Wait



Parent Listen



Time2



Child Wait



Child Serv



Child Wait



第13页

轮转GC方案



• 基本思路

– 关闭GC – 多进程轮流工作

• 单进程状态

– 服务态 – 等待态 – 垃圾回收状态



开始



一个进程的状态转移



超时

服务



超时



超时

垃圾收集



等待

超时



第14页

GC优化 – 多进程配合



Ts Tw Tg P1 S W G S W G

To P2 S W G S W G

To P3 S W G S W ...



. . .



S: Serve W: Wait G: GC



Ts: time for Serve Tw: time for Wait Tg: time for GC To: time for overlap



Ts Tw Tg To

P0 S W G S

To P1 S To P2 S To P3 To S To P4 S P5 S



进程数的计算:N = 1 +



𝑇𝑤 + 𝑇𝑔 + 𝑇𝑜 𝑇𝑠 − 𝑇𝑜



第15页

技术细节

• 本质上:多个进程监听同一个端口

– 高版本linux直接支持 – 低版本linux方案

• 父进程Listen • 子进程Accept



第16页

技术细节

• 服务态

– 调用Accept,获取新的请求

• 等待态

– 不调用Accept,已经连接的client,可以继续收发 – 等待这些已有的连接关闭

• 垃圾收集态

– 主动调用GC



第17页

GC优化 – 补充分析

• HTTP场景

– 短连接 – 长连接

• 平均连接上的请求是3个 • 90%(20s以内)、98%(50s之内)

– 大文件请求

• 对gc造成的延迟(几十ms)不敏感



第18页

多说一句Go 1.5:没有银弹

• Stop-The-World(STW)缩短了,决定因素也变了 –Time spent looping over goroutines –Time spent looping over malloc spans

• 实际运行,还是有几十个ms的STW时间 – GO-BFE的场景和服务模式,大量的goroutine必然 存在

• 需要根据线上运行实际情况来做选型



第19页

协议一致性问题

• GO-BFE 参考了Go的http库 • 基于Go的http实现是否完善,符合rfc标准

– 没有大规模的应用的例子

• 需要一些方法来验证

– 网络协议一致性测试是难点



第20页

协议一致性



• Macaroon框架

Mock client GO-BFE



• Tcpcopy线上引流对比

Tcpcopy online query

BFE GO-BFE



Mock server



RealServer



第21页

一个例子

• url encode case

1. http://xxx.baidu.com/item/JELIM+PLASTIC+SURGERY+%26+AESTHET IC

2. http://xxx.baidu.com/item/JELIM+PLASTIC+SURGERY+&+AESTHETIC



第22页

分布式架构

• BFE程序结构:core+众多功能模块

– 分流 – Cache – Dict

• 问题:

– 变更频率 – 启停速度 – 功能单一,各自扩展

• 同步/异步,开发效率4:1



BGW BFE RS



cache dict



第23页

Go工具链的一些经验

• 测试 • 程序性能调优 • 服务内部状态暴露



第24页

• Go自带test框架

• Quick/slow • Ut/benchmark

• Race detection

• Html coverage



测试



第25页

调优(pprof)

– 易用

• 一行代码: import “net/http/pprof” • 不需要编译不同版本

– 全面

• Cpu/Memory, Blocking, Goroutine, Gc

– 可读

• Call graph • 定位到代码行



第26页

调优(pprof)



第27页

程序内部状态暴露

–内置http server –多种格式输出:Json、noah –指标

• 数量多:2000+项 • 类型丰富:

–计数器、分布漏桶、累计量、切片量、文本

• feature核心指标 • 用户特征类指标



第28页

总结

• Go可以用于高并发、低延迟的程序开发 • Go极大的提升了开发效率



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。