Service Mesh(服务网格)现在几乎是微服务架构的标配了。用Istio或者Linkerd,能轻松实现服务发现、负载均衡、熔断、限流、链路追踪等功能,不用在业务代码里写一堆中间件。
但Service Mesh也有代价。Sidecar代理会带来额外的网络延迟和资源开销。如果配置不当,性能问题会很严重。
我最近对线上的Istio集群做了一次性能调优,把P99响应时间从800ms降到了150ms,降了80%。今天分享整个调优过程,包括问题定位、瓶颈分析、具体优化手段,以及踩过的坑。
一、问题背景
我们的微服务架构用的是Istio 1.10,大概有50多个服务,跑在Kubernetes集群上。每个服务都注入了Envoy Sidecar。
最近用户反馈,系统响应变慢了,尤其是高峰期,经常超时。我们查了监控,发现P99响应时间确实很高,高峰期能到800ms以上,而业务逻辑本身只需要几十毫秒。
一开始我们以为是业务代码的问题,查了半天,发现业务服务的处理时间都正常。问题出在Sidecar上——请求经过Sidecar转发,延迟增加了很多。
于是我们开始了Service Mesh的性能调优。
二、问题定位
调优的第一步,是定位问题到底出在哪里。
1. 监控数据
我们先看了Istio的监控数据(Prometheus + Grafana),发现:
- Envoy的CPU使用率很高,高峰期能到80%
- Envoy的内存占用也不低
- Sidecar到业务容器的本地调用延迟不高
- 但Sidecar之间的网络延迟很高
这说明问题不在业务容器,而在Sidecar之间的通信。
2. 链路追踪
我们用Jaeger看了链路追踪,发现一个请求经过多个服务时,每个服务的处理时间都很短,但服务之间的网络延迟很高。
比如一个请求经过A→B→C三个服务:
- A处理:20ms
- A到B的网络:150ms
- B处理:30ms
- B到C的网络:200ms
- C处理:40ms
- 总耗时:440ms
网络延迟占了总耗时的80%。这说明Sidecar之间的通信有问题。
3. 日志分析
我们查了Envoy的日志,发现有大量的连接超时和重试。尤其是在高峰期,连接池经常打满,导致请求排队。
这说明连接池配置有问题。
三、瓶颈分析
定位到问题后,我们分析了具体的瓶颈。
瓶颈一:连接池配置不合理
Istio默认的连接池配置比较保守:
- 每台主机的最大连接数:1024
- 连接超时:10秒
- 最大请求数:1024
- 最大并发请求数:1024
对于我们的流量来说,这个配置太小了。高峰期连接池打满,请求排队,导致延迟增加。
瓶颈二:TLS握手开销大
Istio默认开启了mTLS(双向TLS),服务之间的通信都要加密。TLS握手需要多次往返,开销很大。
而且默认配置下,连接复用率不高,每次请求都要重新握手,延迟更高。
瓶颈三:Sidecar资源不足
我们给Sidecar配的资源是:CPU 100m,内存128Mi。对于高流量服务来说,这个配置太低了。
Envoy处理请求需要CPU,资源不足时,处理变慢,延迟增加。
瓶颈四:服务发现延迟
Istio用EDS(端点发现服务)来做服务发现。默认配置下,端点更新是批量的,有延迟。当服务扩缩容时,新的端点不能及时被发现,导致请求发到已经不存在的实例上,重试增加延迟。
瓶颈五:可观测性开销
我们开启了很多可观测性功能:链路追踪、访问日志、Metrics采集。这些功能本身也有开销,尤其是访问日志,每条请求都要写日志,IO开销不小。
四、优化手段
针对这些瓶颈,我们做了以下优化。
优化一:调整连接池配置
这是效果最明显的优化。我们根据服务的流量特点,调整了DestinationRule的连接池配置。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: my-service
spec:
host: my-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 4096
connectTimeout: 5s
http:
http2MaxRequests: 4096
maxRequestsPerConnection: 100
maxRetries: 3关键调整:
- maxConnections从1024提到4096
- 增加maxRequestsPerConnection,提高连接复用率
- connectTimeout从10秒降到5秒,快速失败
调整后,连接池不再打满,请求排队现象消失,延迟降了不少。
优化二:优化TLS配置
mTLS的开销主要在握手阶段。我们做了两个优化:
- 提高连接复用率:通过调整连接池,让连接保持更久,复用率更高,减少握手次数。
- 使用TLS 1.3:Istio 1.10支持TLS 1.3,握手更快,开销更小。我们在PeerAuthentication里配置了TLS 1.3。
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: STRICT
tls:
minProtocolVersion: TLSV1_3TLS 1.3的握手只需要1次往返,比TLS 1.2的2次往返快很多。
优化三:增加Sidecar资源
我们给高流量服务的Sidecar增加了资源:
- CPU从100m提到500m
- 内存从128Mi提到256Mi
对于低流量服务,保持原配置。这样既保证了性能,又不会浪费太多资源。
调整后,Envoy的CPU使用率降到了30%左右,处理速度明显提升。
优化四:优化服务发现
我们调整了Istio的配置,加快端点更新:
- 减小EDS推送间隔:默认是15秒,我们改成了5秒。
- 开启增量EDS:只推送变化的端点,减少推送量。
- 调整健康检查配置:让不健康的端点更快被移除。
调整后,服务扩缩容时,新端点能更快被发现,减少了请求失败和重试。
优化五:精简可观测性
我们精简了可观测性功能,减少开销:
- 关闭访问日志:默认的访问日志每条都写,开销大。我们改成了采样日志,只记录10%的请求。
- 调整链路追踪采样率:从100%采样改成10%采样,足够排查问题,开销小很多。
- 精简Metrics:只保留必要的Metrics,去掉不需要的。
调整后,Sidecar的CPU和IO开销降了不少。
优化六:使用HTTP/2
我们把服务之间的通信从HTTP/1.1改成了HTTP/2。HTTP/2支持多路复用,一个连接可以同时处理多个请求,减少了连接数和握手开销。
在DestinationRule里配置:
trafficPolicy:
connectionPool:
http:
h2UpgradePolicy: UPGRADEHTTP/2的多路复用,显著提高了连接利用率,降低了延迟。
五、优化效果
做完这些优化后,效果很明显:
- P99响应时间:从800ms降到150ms,降了80%
- P95响应时间:从400ms降到80ms
- 平均响应时间:从150ms降到40ms
- 错误率:从2%降到0.1%
- Sidecar CPU使用率:从80%降到30%
- 连接超时:基本消失
用户反馈系统快了很多,高峰期也不卡了。
六、踩过的坑
调优过程中踩了不少坑,分享一下。
坑一:连接池调太大
刚开始我们把连接池调得很大(maxConnections=8192),结果下游服务被打挂了。因为连接太多,下游服务处理不过来,反而更慢。
后来我们根据下游服务的处理能力,合理设置连接池大小,不是越大越好。
坑二:关闭mTLS
有人建议直接关闭mTLS,说这样性能最好。但我们评估后,觉得安全性更重要,没有关闭。而是通过优化TLS配置来降低开销。
如果你的服务在可信网络里,对安全要求不高,可以考虑关闭mTLS。但大部分场景下,还是建议开启。
坑三:Sidecar资源给太多
我们给所有服务的Sidecar都加了资源,结果集群资源不够用了,调度不了Pod。
后来我们只给高流量服务加资源,低流量服务保持原配置。这样既保证了性能,又不会浪费资源。
坑四:采样率太低
我们把链路追踪采样率降到了1%,结果出问题的时候,找不到追踪数据,没法排查。
后来改成了10%,既能减少开销,又能保证有足够的数据排查问题。
坑五:HTTP/2兼容性问题
改成HTTP/2后,有几个老服务不兼容,请求失败。因为这些老服务用的是HTTP/1.1,不支持HTTP/2。
后来我们给这些老服务单独配置了HTTP/1.1,其他服务用HTTP/2。升级的时候要注意兼容性。
七、调优建议
总结一下Service Mesh性能调优的建议。
1. 先监控,再调优
不要盲目调优。先建立完善的监控,看清楚瓶颈在哪里,再有针对性地优化。
2. 连接池是关键
连接池配置对性能影响最大。根据服务的流量特点,合理设置连接池大小和超时时间。
3. 资源要够
Sidecar的资源要给够,尤其是高流量服务。资源不足,什么优化都白搭。
4. 精简功能
不要什么功能都开。根据实际需要,精简可观测性和安全功能,减少开销。
5. 逐步优化
不要一次改太多。一项一项优化,每改一项都看效果,确认没问题再改下一项。
6. 压测验证
每次优化后,都要做压测验证,确认性能确实提升了,而且没有引入新问题。
八、写在最后
Service Mesh是个好东西,能大大简化微服务的治理。但它也不是银弹,用不好会带来性能问题。
这次调优让我深刻体会到,任何技术都有代价。引入Service Mesh的时候,就要考虑到它的性能开销,做好调优准备。
性能调优是一个持续的过程。不是调一次就完事了,随着业务增长和流量变化,需要不断调整。
希望这篇文章能帮到正在用Service Mesh的同学。如果你也遇到了性能问题,不妨按照上面的思路排查一下。
2022年了,云原生越来越普及,Service Mesh也会越来越成熟。但不管技术怎么变,性能调优的思路是相通的:定位瓶颈、分析原因、针对性优化、验证效果。
最后,用一句话总结:"性能不是调出来的,是设计出来的。但好的设计,也需要持续的调优。"
祝大家的系统都能又快又稳。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录