Golang在接入层长连接服务中的实践-黄欣
Golang 在接入层长连接服务中的实践 黄欣 基础平台-架构部 目录 • 背景 • 架构 • 心得 目录 • 架构 • 心得 背景—why 长连接? • 业务场景 – 大量实时计算 • 司机乘客撮合 • 实时计价 – 高频度的数据交互 • 坐标数据 • 计价数据 – App和服务端双向可达 • 上行(抢单) • 下行(派单) 背景—why golang? • 开发效率 rsp || nil So easy, So efficient 心得—coding—实现 • what’s diff? – conn svr • 常驻内存,内存中有个大连接对象map(资源问题) • 请求都是基于连接的(如果模块间存在资源的互相引用,当资源变更的情况 下,容易发生panic)(竟态问题) • 对象编程 – 封装:conn资源(包括goruntine)作为结构体封装起来,保证所有资源 statusLoop() 心得—profiling • Timer优化 • Channel使用优化 心得—timer优化 • 为什么需要优化? – 万级别的连接 – 每个连接上大量的定时任务(心跳检测,注册检测,认证检测) 实际情况:当10w左右连接,什么数据不收发,只有定时器检测心跳超时,cpu 能耗掉一个core • 怎么优化? – 特点: • 秒级别定时任务 • 范围最多60s – 方案:0 码力 | 31 页 | 1.67 MB | 1 年前3Go Web编程
s 转换为 []byte 类型 c[0] = 'c' s2 := string(c) // 再转换回 string 类型 fmt.Printf("%s\n", s2) Go中可以使用+操作符来连接两个字符串: s := "hello," m := " world" a := s + m fmt.Printf("%s\n", a) 修改字符串也可写为: s := "hello" s 后通过IP地址找到IP对应的服务器后,要求建立TCP连接,等浏览 器发送完HTTP Request(请求)包后,服务器接收到请求包之后才开始处理请求包,服务器调用自身服务,返回HTTP Response(响应)包;客户端收到来自服务器的响应后开始渲染这个Response包里的主体(body),等收到全部的内 容随后断开与该服务器之间的TCP连接。 图3.1 用户访问一个Web站点的过程 TTP协议与客户端通信。这个客户端通常指的是Web浏览器(其实手机端 客户端内部也是浏览器实现的)。 Web服务器的工作原理可以简单地归纳为: 客户机通过TCP/IP协议建立到服务器的TCP连接 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言 的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端0 码力 | 295 页 | 5.91 MB | 1 年前32.2.6 字节跳动在 Go 网络库上的实践
1. Conn 难以探活, 维护连接池成本高 Go net 在 RPC 场景下的问题 2. BIO 式编程, 连接量大时, 调度开销大 1. Conn 难以探活, 维护连接池成本高 Go net 在 RPC 场景下的问题 2. BIO 式编程, 连接量大时, 调度开销大 1. Conn 难以探活, 维护连接池成本高 Go net 在 RPC 场景下的问题 场景下的问题 2. BIO 式编程, 连接量大时, 调度开销大 1. Conn 难以探活, 维护连接池成本高 业界调研 netpoll gnet easygo (sofa-mosn) evio go net Epoll(ET/LT) LT LT ET/LT LT ET NIO ZeroCopy Buffer Multisyscall 搭建 Multisyscall 2. TCP ZeroCopy 4. io_uring 1. 单连接多路复用(ZeroCopy) 单连接多路复用 – 组包/拆包 Msg Msg Msg Msg Msg Msg Msg Msg Conn write read Buffer Buffer 单连接多路复用 – ZeroCopy LinkBuffer Conn writev readv LinkBuffer0 码力 | 42 页 | 3.19 MB | 1 年前32-6-Golang 在 Baidu-FrontEnd 的应用-陶春华
–GC是个好东西,但也有问题 –难以避免的延迟(几十到几百ms) • 经验公式:10万对象1ms 扫描时间 –1个tcp连接,约10个对象=> 1万连接,1ms gc延迟 • GO-BFE的实时需求 –请求的处理延迟 平均1ms以内,最大10ms • 实测 –100万连接,400ms gc延迟 GC优化思路 • Go的gc算法(go1.3) –Mark and Sweep:大量时间时间用于扫描对象 (对象池) –深度优化系统结构和算法 通过Array减少引用计数 OBJ1 OBJ2 OBJ3 OBJ1 OBJ2 OBJ3 困境 • 减小对象数的困境 –常态下需要保持几十万的连接 => 几十个ms –修改golang网络库,重写基本数据结构 • 不使用让go管理内存 –通过Cgo手工维护,很危险 (go中调用c代码) –不能解决问题:大量go对象难以避免 车轮大战! 子进程Accept 技术细节 • 服务态 –调用Accept,获取新的请求 • 等待态 –不调用Accept,已经连接的client,可以继续收发 –等待这些已有的连接关闭 • 垃圾收集态 –主动调用GC GC优化 – 补充分析 • HTTP场景 –短连接 –长连接 • 平均连接上的请求是3个 • 90%(20s以内)、98%(50s之内) –大文件请求 • 对gc造成的延迟(几十ms)不敏感0 码力 | 35 页 | 730.17 KB | 1 年前3Go性能优化概览-曹春晖
系统设计,本机上会有 udp 通信 阻塞导致⾼延迟 锁瓶颈的⼀般优化⼿段: • 缩⼩临界区:只锁必须锁的对象,临界区内尽量不放慢操作,如 syscall • 降低锁粒度:全局锁 -> 对象锁,全局锁 -> 连接锁,连接锁 -> 请求锁,⽂ 件锁 -> 多个⽂件各种锁 • 同步改异步:如同步⽇志 -> 异步⽇志,若队列满则丢弃,不阻塞业务逻辑 CPU 使⽤太⾼了-编解码使⽤ CPU 过⾼ 通过更换 json 这些内存的构成部分: 1. Goroutine 栈占⽤的内存(难优化,⼀条 tcp 连接⾄少对应⼀个 goroutine) 2. Tcp read buffer 占⽤的内存(难优化,因为⼤部分连接阻塞在 read 上, read buffer 基本没有可以释放的时机) 3. Tcp write buffer 占⽤的内存(易优化,因为活跃连接不多) 原因: ⻅下⻚ 内存占⽤过⾼-goroutine 数量太多导致内存占⽤⾼ slice,查找时间复杂度增加,但内存使⽤ 降低 • offheap • 邪道:动态调整 GOGC • Goroutine 栈占⽤过多内存 • 减少 goroutine 数量 • 如每个连接⼀读⼀写 -> 合并为⼀个连接⼀个 goroutine • Goroutine pool 限制最⼤ goroutine 数量 • 使⽤裸 epoll 库(evio,gev 等)修改⽹络编程⽅式(只适⽤于对延迟不敏感的业务)0 码力 | 40 页 | 8.69 MB | 1 年前31.5 Go 语言构建高并发分布式系统实践
中, Go语⾔言优势体现在:开发体验好 、⼀一定量级下服务稳定 、性能满⾜足 需要 ⼀一定量级下服务稳定: 50+内部产品,万款开发平台app 实时⻓长连接数亿量级,⽇日独数⼗十亿量级 1分钟内亿量级⼲⼴广播,⽇日下发峰值百亿量级 400台物理机,9个独⽴立集群,国内外近10个IDC 运维管理的go语⾔言编写的常驻service服务实例接近3000个。 上⾏行通道,回调⽀支持 对智能硬件产品,提供定制化消息推送与转发服务 性能满⾜足需要: 线上单机最⾼高160w⻓长连接 (24核 E5-2630 @ 2.30GHz 64G内存 ) qps在2~5w(取决于协议版本,业务逻辑,接⼊入端⺴⽹网络状况) 测试环境,可以通过300w⻓长连接压测(⺴⽹网络,连接稳定,⽆无带宽限制,实际可以更⾼高 ,决定于⼲⼴广播时候业务内存开销的cpu消耗带来的⼼心跳或者业务延时能否接受) Android IOS Linux Web Windows Flash Iframe for ever 写 ������/ � �� �������� ������� 长连接客户端 认证或注册的io调 用 加载离线消息 ����� 客户端关注的 阻塞io逻辑,放 心阻塞执行不 用担心阻塞线 程,调度器会 帮忙调度其他 可执行协程 ������� ��� 读0 码力 | 39 页 | 5.23 MB | 1 年前3Go 入门指南(The way to Go)
分钟以内,如果你在 B 型树莓派上编译,一般需要 1 个小时),你会在终 端看到如下信息被打印: 图 2.3 完成编译后在终端打印的信息 注意事项 在测试 net/http 包时有一个测试会尝试连接 google.com ,你可能会看到如下所示的一个无厘头 的错误报告: Go入门指南 - 16 - 本文档使用 看云 构建 ‘make[2]: Leaving directory `/lo Billion = 1e9 // float constant const hardEight = (1 << 100) >> 97 根据上面的例子我们可以看到,反斜杠 \ 可以在常量表达式中作为多行的连接符使用。 与各种类型的数字型变量相比,你无需担心常量之间的类型转换问题,因为它们都是非常理想的数字。 不过需要注意的是,当常量赋值给一个精度过小的数字型变量时,可能会因为无法正确表达常量所代表的 3/4 节、第 8.1.1 节和第 14.2.1 节)new() 是一个函数,不要忘记它 的括号 Go入门指南 - 118 - 本文档使用 看云 构建 copy、 append 用于复制和连接切片 panic、 recover 两者均用于错误处理机制 print、 println 底层打印函数(详见第 4.2 节),在部署环境中建议使用 fmt 包 complex、 real0 码力 | 380 页 | 2.97 MB | 1 年前3Go 入门指南(The way to Go)
分钟以内,如果你在 B 型树莓派上编译,一般需要 1 个小时),你会在终端看 到如下信息被打印: 图 2.3 完成编译后在终端打印的信息 注意事项 在测试 net/http 包时有一个测试会尝试连接 google.com ,你可能会看到如下所示的一个无厘头的错误报 告: 1. ‘make[2]: Leaving directory `/localusr/go/src/pkg/net’ 1e9 // float constant 5. const hardEight = (1 << 100) >> 97 根据上面的例子我们可以看到,反斜杠 \ 可以在常量表达式中作为多行的连接符使用。 与各种类型的数字型变量相比,你无需担心常量之间的类型转换问题,因为它们都是非常理想的数字。 不过需要注意的是,当常量赋值给一个精度过小的数字型变量时,可能会因为无法正确表达常量所代表的数值而导致 的初始化之后的值,因此它比 new 进行更多的工作(详见第 7.2.3/4 节、第 8.1.1 节和 第 14.2.1 节)new() 是一个函数,不要忘记它的括号 copy、 append 用于复制和连接切片 panic、 recover 两者均用于错误处理机制 print、 println 底层打印函数(详见第 4.2 节),在部署环境中建议使用 fmt 包 complex、 real imag0 码力 | 466 页 | 4.44 MB | 1 年前32.2 龚浩华(月牙寂)p2p缓存系统 基于Golang的Aop设计模式
功能监听识别连接 2、任务管理模块 常驻 管理任务、分流client P2P缓存框架 3、任务模块 文件缓存度:是否需要下载 文件热点程度:是否热点 文件下载状态:sleep、down、限速 client数量、存活 自身存在的必要检查:如超时无client连接 P2P缓存框架 4、文件模块 具体文件的存储,另外再加上内存缓存系统 5、client 对应于与客户端的一个连接,通过协议进行 通信。通过任务模块再来进行文件模块的读 写,将数据发送给客户端 6、下载模块 如何识别热点?群体智能 群体智能 1、每个任务定时尝试下载(是否有下载空缺) 2、当某个任务有新的连接数连接的时候尝试下 载(是否有下载空缺) 3、当任务正在下载的时候,如果下载速度慢, 或无下载速度的时候,sleep,让出下载 群体热点算法 热点任务优先下载 限制下载任务数量 1、全局收集任务,根据任务连接数排名,在 前n的任务给分发下载时间片。 2、任务定时更新自己的时间片0 码力 | 29 页 | 338.20 KB | 1 年前3使用Go与redis构建有趣的应用
“msg::10086” “request::256” “user::peter” … 获取客户端 获取客户端 go get github.com/mediocregopher/radix.v2 连接客户端 package main import ( "fmt" "github.com/mediocregopher/radix.v2/redis" ) func main() repl := client.Cmd("PING") content, _ := repl.Str() fmt.Println(content) // "PONG" } 连接客户端 package main import ( "fmt" "github.com/mediocregopher/radix.v2/redis" ) func main() repl := client.Cmd("PING") content, _ := repl.Str() fmt.Println(content) // "PONG" } 连接服务器器 连接客户端 package main import ( "fmt" "github.com/mediocregopher/radix.v2/redis" ) func main()0 码力 | 176 页 | 2.34 MB | 1 年前3
共 34 条
- 1
- 2
- 3
- 4