前言
早期,在我们的部门中后端的技术栈语言主要有三种语言,分别是php/python/erlang,其中用于做服务的是 php/erlang。
在我们的体系中,日志采集服务体系目前都是用erlang写的,而php写的服务多是基于swoole写的一些基础服务。
在tga服务中,我们需要从kafka -> 服务 -> 本地文件的模式。
业务据流图如下:
| 12
 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研发的业务服务。
| 12
 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利用率达到峰值