yankj12 / blog

技术研究、管理实践、其他的一些文章
MIT License
1 stars 2 forks source link

每天消费掉100W消息 #42

Open yankj12 opened 6 years ago

yankj12 commented 6 years ago

每天消费掉100W消息

目前使用框架及中间件

遇到的问题

每天消费数据量只有20W,达不到100W的级别(2018/8/29)

有时候logback日志输出

感觉有时候程序执行了,但是有些日志没有输出

disruptor

定时任务的问题

不能保证每隔5分钟执行一次

@Scheduled(fixedRateString 设置的每隔5分钟执行一次,但是实际上每次需要等执行的任务执行结束下一次定时任务才能开始

怀疑跟jvm gc有关,可能是gc的时候程序不会运行,但是gc也不会持续很长时间啊(存疑)

在linux上查找下jstat命令所在的位置 find / -iname jstat

查看gc信息 Linux使用jstat命令查看jvm的GC情况 jstat -gc 进程号 毫秒数 也可以输出到文件 jstat -gc 进程号 毫秒数 > 日志名.log 但看了下gc信息,gc导致问题的可能性很小

logback打印disruptor的日志

优化的思路

梳理流程,将同步的地方调整为异步

http请求使用异步httpclient

将阻塞io调整为非阻塞io,包括读取文件和http请求

Netty构建NIO的httpClient 传统的BIO里面socket.read(),如果TCP RecvBuffer里没有数据,函数会一直阻塞,直到收到数据,返回读到的数据。 对于NIO,如果TCP RecvBuffer有数据,就把数据从网卡读到内存,并且返回给用户;反之则直接返回0,永远不会阻塞。 最新的AIO(Async I/O)里面会更进一步:不但等待就绪是非阻塞的,就连数据从网卡到内存的过程也是异步的。

使用池技术,如线程池、资源池等

httpclient线程池使用httpclient自带的线程池

httpclient连接池相关类
org.apache.http.client.config.RequestConfig
org.apache.http.impl.nio.reactor.IOReactorConfig
org.apache.http.nio.reactor.ConnectingIOReactor
org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager
org.apache.http.impl.nio.client.CloseableHttpAsyncClient

优化后处理效率满足要求

yankj12 commented 5 years ago

调整的经过

服务端并发限制

分析日志后发现,使用异步httpclient,虽然每天是发送了很多请求,但是因为服务端并发限制,这些请求只有很少部分成功。此时瓶颈在于服务端并发数。

合并请求

和服务端进行沟通,修改接口,将多个请求合并为一个请求,这样可以大大减少请求次数(将500个请求合并为一个)。

结合日志分析瓶颈

提出假设、验证假设再提出新的假设

测试之后发现disruptor每天生产的数据很多,但是消费的很少,最开始怀疑是disruptor漏数据了。但是打印日志(一个比较长的分析过程)后发现,并不是disruptor漏数据,而是disruptor的消费者消费的比较慢(开始速度还可以,但是慢慢的就慢了)。分析应用的流程及其他日志,发现disruptor消费变慢的时间点前后,经常伴随着连接超时的异常,异常信息中连接超时时间为60s,结合正常的请求日志,正常的请求基本在1s内相应,所以修改了连接超时时间(connectTimeout、socketTimeout)为20s。

观察日志验证

修改之后观察日志发现满足每天请求一百万以上的要求(基本两个小时可以消费25万数据)。

细节调整

最后移除了连接池、异步httpclient相关的技术。增加了很多日志细节输入并调整日志级别,避免生产日志过多。

总结

不足

设计阶段评估不足

开发设计阶段,对并发没有很好的进行评估,要达到每天消费100万数据的要求,服务端每秒钟并发多少,请求端每秒最大连接数多少,每次请求大概耗时多少,可能的瓶颈在什么环节。这些都没有进行了解

流程设计

一些经验