如何通过三行配置解决在Kubernetes中的gRPC扩展问题

一切都始于我向我们的高级软件工程师提出的一个问题:
“忘掉通信速度。你真的觉得在gRPC中开发通信比REST更好吗?”
我不想听到的答案立刻就来了:“绝对是的。”

在我提出这个问题之前,我一直在监控我们的服务在滚动更新和扩展Pod时出现的奇怪行为。我们的大多数微服务以往都通过REST调用进行通信,没有任何问题。我们已经将一些这些集成迁移到了gRPC,主要是因为我们想摆脱REST的开销。最近,我们观察到了一些问题,都指向了同一个方向——我们的gRPC通信。当然,我们遵循了在Kubernetes中运行gRPC而不使用服务网格的建议实践,我们在服务器上使用了一个无头服务对象,并在gRPC中使用了客户端的“轮询”负载平衡与DNS发现等。

扩展Pod数量

Kubernetes内部负载均衡器不是用于负载均衡RPC,而是用于负载均衡TCP连接。
第四层负载均衡器由于其简单性而很常见,因为它们与协议无关。但是,gRPC破坏了Kubernetes提供的连接级负载均衡。这是因为gRPC是基于HTTP/2构建的,而HTTP/2被设计为维护一个长期存在的TCP连接,该连接中的所有请求都可以在任何时间点同时处于活动状态。这减少了连接管理的开销。然而,在这种情况下,连接级别的负载平衡并不是非常有用,因为一旦建立了连接,就不再需要进行负载平衡。所有的请求都会固定到原始目标Pod,直到发生新的DNS发现(使用无头服务)。这不会发生,直到至少有一个现有连接断开

问题示例:

  1. 2个客户端(A)调用2个服务器(B)。
  2. 自动缩放器介入并扩展了客户端。
  3. 服务器Pod负载过重,因此自动缩放器介入并增加了服务器Pod的数量,但没有进行负载平衡。甚至可以看到新Pod上没有传入的流量。
  4. 客户端被缩减。
  5. 客户端再次扩展,但负载仍然不平衡。
  6. 一个服务器Pod因过载而崩溃,发生了重新发现。
  7. 在图片中没有显示,但是当Pod恢复时,情况看起来与图3类似,即新Pod不会接收流量。

img

gRPC负载均衡的示例

2行配置解决了这个问题。 技术上说是一行

正如我之前提到的,我们使用“客户端负载均衡”,并使用无头服务对象进行DNS发现。其他选项可能包括使用代理负载均衡或实现另一种发现方法,该方法将询问Kubernetes API而不是DNS。

除此之外,gRPC文档提供了服务器端连接管理提案,我们也尝试过它。

以下是我为设置以下服务器参数提供的建议,以及gRPC初始化的Go代码片段示例:

  • MAX_CONNECTION_AGE设置为30秒。这个时间段足够长,可以在没有昂贵且频繁的连接建立过程的情况下进行低延迟通信。此外,它允许服务相对快速地响应新Pod的存在,因此流量分布将保持平衡。
  • MAX_CONNECTION_AGE_GRACE设置为10秒。定义了连接保持活动状态以完成未完成的RPC的最大时间。
  grpc.KeepaliveParams(keepalive.ServerParameters{MaxConnectionAge:      time.Second * 30,  // THIS one does the trickMaxConnectionAgeGrace: time.Second * 10,})

在现实世界中的行为:

img

gRPC配置更改应用前后的Pod数量

img

在gRPC配置更改后观察到的新Pod中的网络I/O活动

接下来是第三行

扩展问题已经解决,但另一个问题变得更加明显。焦点转向了客户端在滚动更新期间出现的gRPC code=UNAVAILABLE 错误。奇怪的是,这只在滚动更新期间观察到,而在单个Pod扩展事件中却没有观察到。

img

滚动更新期间的gRPC错误数量

部署滚动的过程很简单:创建一个新的副本集,创建一个新的Pod,当Pod准备就绪时,旧的Pod将从旧的副本集中终止,以此类推。每个Pod之间的启动时间间隔为15秒。关于gRPC DNS重新发现,我们知道它仅在旧连接中断或以GOAWAY信号结束时才会启动。因此,客户端每15秒开始一次新的重新发现,但获取到了过时的DNS记录。然后,它们不断进行重新发现,直到成功为止。

除非不是DNS问题…

几乎每个地方都有DNS TTL缓存。基础设施DNS具有其自己的缓存。Java客户端遭受了它们默认的30秒TTL缓存,而Go客户端通常没有实现DNS缓存。与此相反,Java客户端报告了数百或数千次此问题的发生。当然,我们可以缩短TTL缓存的时间,但为什么要在滚动更新期间只影响gRPC呢?

幸运的是,有一个易于实现的解决方法。或者更好地说,解决方案:让新Pod启动时设置30秒的延迟

.spec.minReadySeconds = 30

Kubernetes部署规范允许我们设置新Pod必须处于就绪状态的最短时间,然后才会开始终止旧Pod。在此时间之后,连接被终止,gRPC客户端收到GOAWAY信号并开始重新发现。TTL已经过期,因此客户端获取到了新的、最新的记录。

结论

从配置的角度来看,gRPC就像一把瑞士军刀,可能不会默认适合您的基础架构或应用程序。查看文档,进行调整,进行实验,并充分利用您已经拥有的资源。我相信可靠和弹性的通信应该是您的最终目标。

我还建议查看以下内容:

  • Keepalives。对于短暂的内部集群连接来说可能没有意义,但在某些其他情况下可能会有用。
  • 重试。有时,值得首先进行一些退避重试,而不是通过尝试创建新连接来过载基础设施。
  • 代码映射。将您的gRPC响应代码映射到众所周知的HTTP代码,以更好地了解发生了什么情况。
  • 负载均衡。平衡是关键。不要忘记设置回退并进行彻底的测试。
  • 服务器访问日志(gRPC code=OK)可能会因默认设置为信息级别而太冗长。考虑将它们降低到调试级别并进行筛选。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/153397.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lua学习笔记

单行注释: 多行注释: 命名: Lua不支持下划线大写字母,比如:_ABC 但支持:_abc 关键字: 全局变量: 直接变量名 内容就是全局 局部变量: 加上local即可 nil&#xff1…

服务器上部署python脚本

1.查看服务器上的python是否自带,一般都自带 2.将本地脚本上传到服务器 3.直接运行一下脚本看报什么错误 代码错误, 将f删除后报别的错误 上面是未安装依赖的错误。我们安装一下依赖 下面是编码的解决 #!/usr/bin/python # -*- coding: utf-8 -*- 先把…

查找算法——二分查找法

一、介绍 首先需要将查找的数据排好序,再进行二分查找法来进行查找,二分查找是将数据范围不断分割为两份,不断比较中间值与待查找值的大小来确定其在哪个区间范围的一种方法。例如:在一组数据(1,4&#xff…

只会 Windows 也能轻松搭建远程桌面 RustDesk 自用服务器

网管小贾 / sysadm.cc “哥,你啥时候回来啊?XX业务系统又出问题了!” “情况紧急,老大说让你远程处理,总之尽快解决!” 虽说我常年出差在外总能收到这样的消息,似乎早已习惯,但是公…

分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测

分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测 目录 分类预测 | MATLAB实现KOA-CNN-LSTM开普勒算法优化卷积长短期记忆神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现KOA-CNN-LSTM开普勒算法优化…

精品Python语言django基于爬虫的新闻资讯分析系统的设计与实现

《[含文档PPT源码等]精品Python项目django基于爬虫的新闻资讯分析系统的设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等! 软件开发环境及开发工具: 开发语言:python 使用框架:Django 前…

代码理解技术应用实践介绍

作者 | CQT&星云团队 一、前言 代码理解作为软件知识图谱重要的技术之一,可以为构建、测试、定位、代码解释等提供基础的技术和数据保障,也是持续集成的起点,只有理解了代码才能有目的性的进行有效构建。代码理解对于软件开发的成功和维…

Linux 部署 MinIO 分布式对象存储 配置为 typora 图床

前言 MinIO 是一款高性能的对象存储系统,它可以用于大规模的 AI/ML、数据湖和数据库工作负载。它的 API 与Amazon S3 云存储服务完全兼容,可以在任何云或本地基础设施上运行。MinIO 是开源软件,也提供商业许可和支持 MinIO 的特点有&#x…

WPS/word 表格跨行如何续表、和表的名称

1:具体操作: 将光标定位在跨页部分的第一行任意位置,按下快捷键ctrlshiftenter,就可以在跨页的表格上方插入空行(在空行可以写,表1-3 xxxx(续)) 在空行中输入…

vue cli和vite区别

1.Vue CLI脚手架 什么是Vue脚手架? 在真实开发中我们不可能每一个项目从头来完成所有的webpack配置,这样显示开发的效率会大大的降低;所以在真实开发中,我们通常会使用脚手架来创建一个项目,Vue的项目我们使用的就是…

苍穹外卖项目

1. 苍穹外卖项目介绍 1.1 项目介绍 定位:专门为餐饮企业(餐厅、饭店)定制的一款软件产品 项目架构:体现项目中的业务功能模块 1.2 产品原型 产品原型:用于展示项目的业务功能,一般由产品经理进行设计 …

安全与隐私:直播购物App开发中的重要考虑因素

随着直播购物App的崭露头角,开发者需要特别关注安全性和隐私问题。本文将介绍在直播购物App开发中的一些重要安全和隐私考虑因素,并提供相关的代码示例。 1. 数据加密 在直播购物App中,用户的个人信息和支付信息是极为敏感的数据。为了保护…

忘记压缩包密码?解决方法一键找回,省时又便捷!

使用在线rar/zip解密工具,找回rar/zip密码并解密压缩包的方法非常简单。具体步骤如下:首先,在百度上搜索“密码帝官网”,这是一个专业的解密服务网站。然后,点击搜索结果中的链接,进入官网首页。在页面上方…

Netty(四)NIO-优化与源码

Netty优化与源码 1. 优化 1.1 扩展序列化算法 序列化,反序列化主要用于消息正文的转换。 序列化:将java对象转为要传输对象(byte[]或json,最终都是byte[]) 反序列化:将正文还原成java对象。 //java自带的序列化 // 反序列化 b…

【Java】微服务——Feign远程调用

目录 1.Feign替代RestTemplate1)引入依赖2)添加注解3)编写Feign的客户端4)测试5)总结 2.自定义配置2.1.配置文件方式2.2.Java代码方式 3.Feign使用优化4.最佳实践4.1.继承方式4.2.抽取方式4.3.实现基于抽取的最佳实践1…

麻省理工学院与Meta AI共同开发StreamingLLM框架,实现语言模型无限处理长度

🦉 AI新闻 🚀 麻省理工学院与Meta AI共同开发StreamingLLM框架,实现语言模型无限处理长度 摘要:麻省理工学院与Meta AI的研究人员联合研发了一款名为StreamingLLM的框架,解决了大语言模型在RAM与泛化问题上的挑战&am…

微信小程序 获取当前屏幕的可见高宽度

很多时候我们做一下逻辑 需要用整个窗口的高度或宽度参与计算 而且很多时候我们js中拿到的单位都是px像素点 没办法和rpx同流合污 官方提供了wx.getSystemInfoSync() 可以获取到部分窗口信息 其中就包括了整个窗口的宽度和高度 wx.getSystemInfoSync().windowHeight 返回值为像…

微店商品链接获取微店商品详情数据(用 Python实现微店商品信息抓取)

在网页抓取方面,可以使用 Python、Java 等编程语言编写程序,通过模拟 HTTP 请求,获取微店网站上的商品页面。在数据提取方面,可以使用正则表达式、XPath 等方式从 HTML 代码中提取出有用的信息。值得注意的是,微店网站…

[stm32]外中断控制灯光

在STM32CubeMX中配置外部中断功能和参数 1、将上拉输入的引脚设置为:GPIO_EXTI功能 2、GPIO模式设为下降沿触发外部中断,使能上拉电阻,用户标签 3、要将NVIC的相关中断勾选 只有将中断源进行勾选,相关的中断请求才能得到内核的…

xshell安装完成在windows不能打开

文章目录 问题描述问题排查解决第一步第二步 问题描述 安装打开xshell的时候总是点击没有任何的反应,重启电脑后再次点击xshell也没有任何的响应。只有在重装软件后才能正常打开。 问题排查 点击打开xshell7的时候总是报如下错 在这里能看到具体的描述&#xff…