Open yankj12 opened 6 years ago
分析日志后发现,使用异步httpclient,虽然每天是发送了很多请求,但是因为服务端并发限制,这些请求只有很少部分成功。此时瓶颈在于服务端并发数。
和服务端进行沟通,修改接口,将多个请求合并为一个请求,这样可以大大减少请求次数(将500个请求合并为一个)。
测试之后发现disruptor每天生产的数据很多,但是消费的很少,最开始怀疑是disruptor漏数据了。但是打印日志(一个比较长的分析过程)后发现,并不是disruptor漏数据,而是disruptor的消费者消费的比较慢(开始速度还可以,但是慢慢的就慢了)。分析应用的流程及其他日志,发现disruptor消费变慢的时间点前后,经常伴随着连接超时的异常,异常信息中连接超时时间为60s,结合正常的请求日志,正常的请求基本在1s内相应,所以修改了连接超时时间(connectTimeout、socketTimeout)为20s。
修改之后观察日志发现满足每天请求一百万以上的要求(基本两个小时可以消费25万数据)。
最后移除了连接池、异步httpclient相关的技术。增加了很多日志细节输入并调整日志级别,避免生产日志过多。
开发设计阶段,对并发没有很好的进行评估,要达到每天消费100万数据的要求,服务端每秒钟并发多少,请求端每秒最大连接数多少,每次请求大概耗时多少,可能的瓶颈在什么环节。这些都没有进行了解
流程中哪些可以异步,哪些可以合并,这些没有仔细分析 比如:调用服务端接口,可以将多个请求合并这点,就要比一次次请求要好很多
双方系统交互,代码的含义此次设计既有浪费又有不够用的地方。需要结合双方处理流程设计 比如说:0待处理;1处理中;2成功;3失败。这样的代码看似是没问题的,但是双方流程中如果服务端每天定时将未成功的状态码重刷,并且不关心状态,只关心是否处理完,那么3就是没有用的。
好的开发设计优于技术框架的选型,接口及流程设计的不好,技术选型很慢弥补。
提出假设-->验证假设-->做出调整
每天消费掉100W消息
目前使用框架及中间件
disruptor
httpclient
HttpAsyncClients 异步请求HttpAsyncClients-官网资料 异步http请求 HttpAsyncClients
日志输出logback
java框架SpringBoot
定时任务框架
SpringBoot @Scheduled
遇到的问题
每天消费数据量只有20W,达不到100W的级别(2018/8/29)
有时候logback日志输出
感觉有时候程序执行了,但是有些日志没有输出
disruptor
定时任务的问题
不能保证每隔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自带的线程池
优化后处理效率满足要求