如何优化部署在k8s的应用响应。
经过两个礼拜一番折腾之后,本博客已经整体迁移到了k8s集群上。
但网站访问速度和之前Docker Swarm单体服务器部署的方式相比慢的离谱。
SSR渲染时间已经要6秒+, 达到了无法忍受的地步,于是开始排查服务端请求为何如此慢的原因。
问题排查
分析
代码并没有任何变动,还是 consul + gRPC 的组合,那就只可能是运行环境导致了问题被暴露出来。
之前的部署方式是单体的,所有服务跑在一台机器,不存在太大的网络开销。
部署在异地三节点的k8s集群上之后,服务间的网络调用开销过大导致响应不及时。
A、B、C节点部署了账户服务,gateway调用服务时采用的是轮询算法,随机调用一个节点的账户服务来获得结果。即使A节点在完整的gateway服务和账户服务,gateway也可能调用B节点的账户服务。一旦gateway需要调用多次账户服务情况下,调用节点会打散到各个节点,网络开销巨大。
解决方案
从优化k8s部署配置和应用代码来减少网络开销。
优化k8s部署
k8s高级调度策略存在两个策略。
-
亲和性: 当两个服务的 Pod 强相关,尽量把两个服务 Pod 放在同一个 Node 以减少开销。
-
反亲和性:为了服务的高可用性,尽量的打散 Pod 。
事实上,我的博客服务每个Node基本上都部署了一个 Pod,不存在单节点Pod的情况,那么问题原因就出我的 gateway 服务调用问题。我需要让gateway 服务尽量的调用当前节点存在的服务Pod。
通过查阅k8s文档,终于发现了蛛丝马迹。Service Topology 就是我最终采用的方案。加上 topologyKeys 配置之后,可以让服务优先调用其他服务在本机已有的pod。具体的参数请阅读文档。
减少服务调用次数
由于网站是采用的微服务架构,所以很多数据无法一次性获取,都需要从别的服务获取再组装。
文章列表的接口需要调用账户服务来获取用户信息。优化之前,一个文章列表10个文章,会调用10次账户服务,优化后,我新开发了一个使用多个用户ID 获取过个用户信息的方法,10次网络开销变成了一次。
参考文档
特别鸣谢
感谢以下用户对本文的支持与鼓励