天天看点

近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

最近,业务增长的很迅猛,对于我们后台这块也是一个不小的挑战,这次遇到的核心业务接口的性能瓶颈,并不是单独的一个问题导致的,而是几个问题揉在一起:我们解决一个之后,发上线,之后发现还有另一个的性能瓶颈问题。这也是我经验不足,导致没能一下子定位解决;而我又对我们后台整个团队有着固执的自尊,不想通过大量水平扩容这种方式挺过压力高峰,导致线上连续几晚都出现了不同程度的问题,肯定对于我们的业务增长是有影响的。这也是我不成熟和要反思的地方。这系列文章主要记录下我们针对这次业务增长,对于我们后台微服务系统做的通用技术优化,针对业务流程和缓存的优化由于只适用于我们的业务,这里就不再赘述了。本系列会分为如下几篇:

改进客户端负载均衡算法

开发日志输出异常堆栈的过滤插件

针对 x86 云环境改进异步日志等待策略

增加对于同步微服务的 http 请求等待队列的监控以及云上部署,需要小心达到实例网络流量上限导致的请求响应缓慢

针对系统关键业务增加必要的侵入式监控

相对于基于 spring-webflux 的异步微服务,基于 spring-webmvc 的同步微服务没有很好的处理客户端有请求超时配置的情况。当客户端请求超时时,客户端会直接返回超时异常,但是调用的服务端任务,在基于 spring-webmvc 的同步微服务并没有被取消,基于 spring-webflux 的异步微服务是会被取消的。目前,还没有很好的办法在同步环境中可以取消这些已经超时的任务。

我们的基于 spring-webmvc 的同步微服务,http 容器使用的是 undertow。在 spring-boot 环境下,我们可以配置处理 http 请求的线程池大小:

其背后的线程池,是 jboss 的线程池:<code>org.jboss.threads.enhancedqueueexecutor</code>,spring-boot 目前不能通过配置修改这个线程池的队列大小,默认队列大小是 integer.max

我们需要监控这个线程池的队列大小,并针对这个指标做一些操作:

当这个任务持续增多的时候,就代表这时候请求处理跟不上请求到来的速率了,需要报警。

当累积到一定数量时,需要将这个实例暂时从注册中心取下,并扩容。

待这个队列消费完之后,重新上线。

当超过一定时间还是没有消费完的话,将这个实例重启。

幸运的是,<code>org.jboss.threads.enhancedqueueexecutor</code> 本身通过 jmx 暴露了 http servlet 请求的线程池的各项指标:

近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

我们的项目中,使用两种监控:

prometheus + grafana 微服务指标监控,这个主要用于报警以及快速定位问题根源

jfr 监控,这个主要用于详细定位单实例问题

对于 http 请求等待队列监控,我们应该通过 prometheus 接口向 grafana 暴露,采集指标并完善响应操作。

暴露 prometheus 接口指标的代码是:

之后,调用 <code>/actuator/prometheus</code> 我们就能看到对应的指标:

当发生队列堆积时,我们能快速的报警,并且直观地从 grafana 监控上发现:

近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

现在的公有云,都会针对物理机资源进行虚拟化,对于网络网卡资源,也是会虚拟化的。以 aws 为例,其网络资源的虚拟化实现即 ena(elastic network adapter)。它会对以下几个指标进行监控并限制:

带宽:每个虚拟机实例(aws 中为每个 ec2 实例),都具有流量出的最大带宽以及流量入的最大带宽。这个统计使用一种网络 i/o 积分机制,根据平均带宽使用率分配网络带宽,最后的效果是允许短时间内超过额定带宽,但是不能持续超过。

每秒数据包 (pps,packet per second) 个数:每个虚拟机实例(aws 中为每个 ec2 实例)都限制 pps 大小

连接数:建立连接的个数是有限的

链接本地服务访问流量:一般在公有云,每个虚拟机实例 (aws 中为每个 ec2 实例)访问 dns,元数据服务器等,都会限制流量

同时,成熟的公有云,这些指标一般都会对用户提供展示分析界面,例如 aws 的 cloudwatch 中,就提供了以下几个指标的监控:

近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

在业务流量突增时,我们通过 jfr 发现访问 redis 有性能瓶颈,但是 redis 本身的监控显示他并没有遇到性能瓶颈。这时候就需要查看是否因为网络流量限制导致其除了问题,在我们出问题的时间段,我们发现 networkbandwidthoutallowanceexceeded 事件显著提高了很多:

近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

对于这种问题,就得需要考虑垂直扩容(提升实例配置)与水平扩容(多实例负载均衡)了,或者减少网络流量(增加压缩等)

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:
近期业务大量突增微服务性能优化总结-4.增加对于同步微服务的 HTTP 请求等待队列的监控增加对于同步微服务的 HTTP 请求等待队列的监控对于公有云部署,关注网络限制的监控

继续阅读