前言
早期,在我们的部门中后端的技术栈语言主要有三种语言,分别是php/python/erlang
,其中用于做服务的是 php/erlang
。
在我们的体系中,日志采集服务体系目前都是用erlang写的,而php写的服务多是基于swoole写的一些基础服务。
在tga服务中,我们需要从kafka
-> 服务
-> 本地文件
的模式。
业务据流图如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| +---------------------------------------------------------------+ | | | | | +---------------------------------------------+ | | | | | | | | | | | kafka服务 | | | | | | | | | | | | | | | +----------------------+----------------------+ | | | | | | | | +----------------------v-----------------------+ | +----------------------------+ | | | | | | | | | | | | | | | | | | | | mthinkingdata服务 | <---------------------+ logbus服务 | | | | | | | | | | | | | | | | | | | | +----------------------+-----------------------+ | +----------------------------+ | | | | | | | +----------------------v------------------------+ | | | | | | | | | | | | | | | 本地文件 +-------+ | | | | | | | | | | | | | +-----------------------------------------------+ | | | +---------------------------------------------------------------+
|
于是我们试探性的自研基于swoole的kafka客户端,我们自己实现根据kafka协议的封包,解包,流程处理。(swoole-kafka
)
mthinkingdata服务
就是我们基于kafka-swoole
研发的业务服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| +------------+ | | | message1 +------------+ | | | +------------+ | | +------------+ +------+--------+ | | | | | message2 +-----+ snappy压缩 | | | | | +------------+ +------+--------+ | +---------------+ | | | | | message[3..n] +----------+ | | +---------------+
|
在这个过程中,我们发现php对于cpu密集型的处理存在瓶颈,因为我们在生产者一方如果发送多条协议的情况下,会经过 snappy
算法的压缩再推送以便减少network-io(增加cpu-io)。
消费者在接受消息的时候也是被压缩过的数据,所以我们需要解压,在这个解压的过程中,是个十分消费cpu的过程,即使我们当时是基于swoole4.3的协程版本来处理,
不行的是的抢占式协程当时并没有很好的完成,我们没办法达到快速的接受多个数据包的行为。消费速度也并不是特别理想。
在这个大环境下,我们还需要借助redis来作为中间的存储。而redis是单线程的,我们在这个过程中,试过使用pipeline
等手段减少tcp中的响应包的带来的性能损耗。但是由于redis只能利用单核的缘故,批量处理一批指令后,最高的cpu利用率接近100%下无法再增长。
也因此,我们的服务注定无法达到很好的性能测试。
我们得出结论,当时服务的瓶颈在于:
- php语言本身的性能
- swoole协程不支持抢占式调度
- 未实现动态伸缩扩展worker数量(感兴趣可以去看看kafka-swoole的架构分享)
- redis未能利用多核,cpu利用率达到峰值