当前位置: 首页 > news >正文

在Kubernetes中实现gRPC流量负载均衡

在尝试将gRPC服务部署到Kubernetes集群中时,一些用户(包括我)面临的挑战之一是实现适当的负载均衡。在深入了解如何平衡gRPC的方式之前,我们首先需要回答一个问题,即为什么需要平衡流量,如果Kubernetes已经完成了这项工作。

本文关注于Kubernetes和Golang。

为什么在Kubernetes中无法适当地平衡gRPC流量?

之所以难以平衡gRPC流量的主要原因是人们将gRPC视为HTTP,这就是问题的根源。设计上它们是不同的,虽然HTTP为每个请求创建和关闭连接,但gRPC使用HTTP2协议,在长时间的TCP连接上运行,使得平衡更加困难,因为多个请求通过同一个连接进行多路复用。然而,这并不是配置gRPC服务在Kubernetes中出现平衡问题的唯一原因,以下是一些常见的错误配置:

  • 错误的gRPC客户端配置
  • 错误的Kubernetes服务配置

错误的gRPC客户端配置

设置gRPC客户端时常见的情况是选择默认配置,这对于1-1连接类型完全有效,但对于生产环境来说并不如我们所希望的有效。这背后的原因是因为默认的gRPC客户端提供了使用简单的IP/DNS记录连接的可能性,这只会创建一个与目标服务的连接。

因此,需要为与多个服务器建立连接进行不同的设置,将连接类型从1-1转换为1-N。

默认设置

func main(){conn, err := grpc.Dial("my-domain:50051", grpc.WithInsecure())if err != nil {log.Fatalf("error connecting with gRPC server: %v", err)}defer conn.Close()cli := test.NewTestServiceClient(conn)rs, err := cli.DoSomething(context.Background(), ...)...
}

新的设置

func main() {address := fmt.Sprintf("%s:///%s", "dns", "my-domain:50051")conn, err := grpc.Dial(address,grpc.WithInsecure(),grpc.WithBalancerName(roundrobin.Name))if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()...
}

这里有两个重要的更改需要注意:

  • 地址: 最终解析的地址将类似于 dns:///my-domain:50051,之所以使用这种格式是因为Dial函数允许我们使用由Scheme://Authority/Endpoint组成的目标,而在我们的情况下,我跳过了Authority。因此,首先我添加了dns作为方案,因为我希望解析一个域并持续观察其更改,解析器选项有透传(默认)、dns和手动,更多详情请参阅这里。
  • 负载均衡器选项: 如果我们的客户端现在连接到多个服务器,那么我们的gRPC客户端可以根据所选择的负载均衡算法平衡请求。

总结一下,我们的gRPC客户端现在能够创建不同的连接,前提是域名解析为多个A或AAAA记录,而且不仅如此,现在还能够将请求均匀地分配到不同的服务器。

现在让我们看看如何让它与Kubernetes一起工作的缺失部分。

错误的Kubernetes服务配置

在Kubernetes中创建服务非常简单,我们只需要定义服务名称、端口和选择器,以便服务可以动态地将Pod分组并自动平衡请求,如下所示:

apiVersion: v1
kind: Service
metadata:name: my-service
spec:selector:app: my-appports:- name: grpcprotocol: TCPport: 50051targetPort: 50051

那么,对于先前的设置,问题在于默认的Kubernetes服务只创建了一个DNS记录,链接到单个IP。因此,当您执行类似 nslookup my-service.{namespace}.svc.cluster.local 的操作时,返回的是一个单个IP,这使得在常见的gRPC实现中连接图看起来像这样:

img

例如,使用默认的Kubernetes服务的连接图:

绿线表示与客户端的活动连接,黄色表示未活动的Pod。客户端与Kubernetes服务创建了持久连接,同时服务也与其中一个Pod创建了连接,但这并不意味着服务与其余的Pod没有连接。

让我们使用一个无头服务来解决这个问题:

apiVersion: v1
kind: Service
metadata:name: my-service
spec:clusterIP: None **this is the key***selector:app: my-appports:- name: grpcprotocol: TCPport: 50051targetPort: 50051

创建了无头服务后,nslookup看起来有些不同,现在它返回与之关联的记录(将Pod的IP分组到服务中),从而使gRPC客户端更好地了解需要连接的服务器数量。

现在您已经看到了gRPC客户端的配置,您必须知道为什么Kubernetes服务返回与一组Pod关联的IP非常重要。原因是客户端可以看到所有需要建立连接的服务器。在这一点上,您可能已经意识到了一个注意事项,即平衡的责任现在在客户端部分,而不在Kubernetes的一侧。我们现在需要从Kubernetes那里得到的主要任务是保持与服务关联的Pod列表的最新状态。

img

例如,在具有无头Kubernetes服务的连接图中,可以看到连接发生了一些变化,现在我们不通过Kubernetes服务来访问Pod,而是使用Kubernetes服务来检索与域名关联的Pod列表,然后直接与Pod建立连接。但是不要因为直接连接到Pod而感到惊慌,因为我们在客户端中设置了DNS解析器类型,该解析器将持续监视与无头服务的更改,并将与可用的Pod保持最新的连接。

为什么不使用服务网格?

如果可以的话,请使用服务网格,因为在服务网格中,所有这些设置都是透明的,而且最重要的是它是与编程语言无关的。关键区别在于服务网格利用了Sidecar模式和控制平面来编排入站和出站流量,还可以看到所有网络和流量类型(HTTP、TCP等),从而能够正确平衡请求。简而言之,如果您不使用服务网格,那么您需要直接从每个客户端连接到多个服务器,或者连接到一个L7代理来帮助平衡请求。

附加信息

尽管先前的设置可以工作,但我在尝试在alpine Linux映像中进行Pod轮换或扩展时重新平衡连接时遇到了问题。经过一些研究,我意识到我并不是唯一遇到这种问题的人,可以查看这里和这里的一些相关的GitHub问题。这就是为什么我决定创建自己的解析器的原因,您可以在这里查看我创建的自定义解析器,我创建的自定义解析器非常基础,但现在可以正常工作,gRPC客户端现在可以再次监听域名的更改,我还为该库添加了一个可配置的监听器,它每隔一段时间查找域名并更新提供给gRPC连接管理器的IP集合,如果您想贡献,欢迎加入。

另一方面,因为我想深入了解,所以我决定创建自己的gRPC代理(我也学到了很多东西),利用了gRPC的http2基础,我可以创建一个代理,而无需更改proto负载消息或甚至不知道proto文件的定义(还使用了前面提到的自定义解析器)。

最后,我想说的是,如果您的gRPC客户端需要与许多服务器连接,我强烈建议使用代理作为平衡的机制,因为将这个机制放在主应用程序中将增加复杂性和资源消耗,尝试保持许多打开的连接并重新平衡它们,想象一下,如果最终的平衡在应用程序中,您将有一个与N个服务器连接的实例(1-N),但是使用代理,您将有一个与M个代理连接到N个服务器的实例(1-M-N),其中M<N,因为每个代理实例可以处理与不同服务器的许多连接。

相关文章:

在Kubernetes中实现gRPC流量负载均衡

在尝试将gRPC服务部署到Kubernetes集群中时&#xff0c;一些用户&#xff08;包括我&#xff09;面临的挑战之一是实现适当的负载均衡。在深入了解如何平衡gRPC的方式之前&#xff0c;我们首先需要回答一个问题&#xff0c;即为什么需要平衡流量&#xff0c;如果Kubernetes已经…...

Floorplanning with Graph Attention

Floorplanning with Graph Attention DAC ’22 目录 Floorplanning with Graph Attention摘要1.简介2.相关工作3.问题公式化4. FLORA的方法4.1 解决方案概述4.2 C-谱聚类算法 4.3 基于GAT的模型4.4 合成训练数据集生成 摘要 布图规划一直是一个关键的物理设计任务&#xff0…...

centos7 配置coreboot编译环境 以及编译问题解决

需要的配置 (有的资源在国外可能需要翻墙) 操作系统: centos7.9 参考文章 coreboot源码分析之编译和运行coreboot - 知乎 //coreboot编译总说明 https://www.coreboot.org/Build_HOWTO#Requirements https://poe.com/ChatGPT 注意: 因为github不稳定 所以gitee为主 1. 下载…...

大型语言模型:RoBERTa — 一种鲁棒优化的 BERT 方法

一、介绍 BERT模型的出现导致了NLP的重大进展。BERT的架构源自Transformer&#xff0c;在各种下游任务上实现了最先进的结果&#xff1a;语言建模&#xff0c;下一句预测&#xff0c;问答&#xff0c;NER标记等。 大型语言模型&#xff1a;BERT — 来自变压器的双向编码器表示 …...

解析navicate数据库密码

在线运行地址:代码在线运行 - 在线工具 <?php class NavicatPassword {protected $version 0;protected $aesKey libcckeylibcckey;protected $aesIv libcciv libcciv ;protected $blowString 3DC5CA39;protected $blowKey null;protected $blowIv null;public func…...

mysql字段类型与oracle字段类型对应关系

MySQL与Oracle两种数据库在工作中&#xff0c;都是用的比较多的数据库&#xff0c;由于MySQL与Oracle在数据类型上有部分差异&#xff0c;在我们迁移数据库时&#xff0c;会遇上一定的麻烦&#xff0c;下面介绍MySQL与Oracle数据库数据类型的对应关系。 一、常见数据类型在MyS…...

linux 中 tar \ zip 解压错误后撤回

#zip zipinfo -1 path/xx.zip | xargs rm -rf#tar tar -tf xx.tar | xargs rm -rf...

对象图 UML从入门到放弃之四

1.劝退说明 对象图提供了系统在某个特定时刻的状态快照。这是一种有用的描述系统的方法&#xff0c;当系统的结构是动态构建起来而不是由其静态的类结构决定时&#xff0c;更是如此。不过&#xff0c;应该对画太多的对象图保持警惕。在大部分情况下&#xff0c;它们都可以从相应…...

FPGA实现HDMI输入转SDI视频输出,提供4套工程源码和技术支持

目录 1、前言免责声明 2、我目前已有的SDI编解码方案3、设计思路框架核模块解析设计框图IT6802解码芯片配置及采集ADV7611解码芯片配置及采集silicon9011解码芯片配置及采集纯verilog的HDMI 解码模块RGB888转YUV422SPMTE编码SDI模式图像缓存SPMTE SDIGTXGV8500 4、vivado工程1-…...

针对FTP的SSRF攻击

前言 ssrf中常用的协议有http&#xff0c;gopher等。但http协议在ssrf中的用处也仅限于访问内网页面&#xff0c;在可以crlf的情况下才有可能扩大攻击范围。gopher协议比较特殊&#xff0c;在部分环境下支持此协议&#xff0c;如&#xff1a;curl。但还有一些环境就不支持了&a…...

线性代数中涉及到的matlab命令-第一章:行列式

目录 1&#xff0c;逆序数 2&#xff0c;行列式定义和性质 2.1&#xff0c;常用特性及命令 2.2&#xff0c;求行列式 2.3&#xff0c;行列式的性质 2&#xff0c;行列式按行&#xff08;列&#xff09;展开 3&#xff0c;范德蒙德行列式 在学习线性代数过程中&#…...

QT编程,QT内存管理、信号与槽、

目录 一、QT工具 二、QT内存管理 三、信号与槽 1、信号与槽特点 2、信号 3、槽函数 4、连接 5、发送信号 6、取消连接 一、QT工具 1、Qt Designer&#xff1a;界面设计编辑工具 2、Qt Assistant: Qt技术文档浏览器 3、Qt Linguist: 国际化语言翻译工具 4、…...

springcloud之项目实战环境准备

写在前面 为了更好的学习springcloud&#xff0c;我们来一起开发一个实战项目&#xff0c;加深理解。 1&#xff1a;项目介绍 在开始项目实战之前先来做一个整体的项目介绍&#xff0c;从而能够让对项目的整体架构和模板有一个比较清晰的认知。 大家都知道双11&#xff0c;…...

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

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

JVM Optimization Learning(四)

目录 一、调优 1、基础概念 2、什么是调优&#xff1f; 3、调优&#xff0c;从规划开始 4、调优案例 一、调优 1、基础概念 吞吐量&#xff1a;用户代码执行时间 /&#xff08;用户代码执行时间 垃圾回收时间&#xff09; 响应时间&#xff1a;STW越短&#xff0c;响应…...

新华三辅导笔记 2023/10/9-2023/10/13

新华三辅导笔记 一、需要用到的软件二、计算机网络概述1、计算机网络的定义和基本功能&#xff08;1&#xff09;什么是计算机网络&#xff08;2&#xff09;计算机网络的基本功能 2、&#xff08;1&#xff09;局域网、城域网和广域网&#xff08;范围划分&#xff09;&#x…...

边坡安全监测系统的功能优势

随着科技的进步&#xff0c;边坡安全监测系统在各种工程项目中发挥着越来越重要的作用。这款系统通过实时监测垂直、水平位移数据&#xff0c;以折线图的方式显示在监控平台中&#xff0c;为工程人员提供了直观、便捷的监控工具&#xff0c;从而能够及时掌握边坡稳定状况&#…...

【架构】研发高可用架构和系统设计经验

研发高可用架构和系统设计经验 从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面去剖析一个高可用的系统需要有哪些关键的设计和考虑。 一、高可用架构和系统设计思想 1.可用性和高可用概念 可用性是一个可以量化的指标,计算的公…...

Linux线程安全

线程安全 Linux线程互斥进程线程间的互斥相关背景概念互斥量mutex互斥量的接口互斥量实现原理探究 可重入VS线程安全概念常见的线程不安全的情况常见的线程安全的情况常见的不可重入的情况常见的可重入的情况可重入与线程安全联系可重入与线程安全区别 常见锁概念死锁死锁的四个…...

Windows安装Node.js

1、Node.js介绍 ①、Node.js简介 Node.js是一个开源的、跨平台的JavaScript运行环境&#xff0c;它允许开发者使用JavaScript语言来构建高性能的网络应用程序和服务器端应用。Node.js的核心特点包括&#xff1a; 1. 事件驱动: Node.js采用了事件驱动的编程模型&#xff0c;通…...

想要开发一款游戏, 需要注意什么?

开发一款游戏是一个复杂而令人兴奋的过程。游戏开发是指创建、设计、制作和发布电子游戏的过程。它涵盖了从最初的概念和创意阶段到最终的游戏发布和维护阶段的各个方面。 以下是一些需要注意的关键事项&#xff1a; 游戏概念和目标&#xff1a; 确定游戏开发的核心概念和目标…...

横向AlGaN/GaN基SBD结构及物理模型数据库的开发

GaN基功率器件凭借其临界电场高、电子饱和漂移速度大、热导率高等优良性能在大功率快充、充电桩、新能源汽车等领域具备广泛应用空间。为进一步助推半导体高频、高功率微电子器件的发展进程&#xff0c;天津赛米卡尔科技有限公司技术团队依托先进的半导体TCAD仿真平台成功开发出…...

使用安卓Termux+Hexo,手机也能轻松搭建个人博客网站

文章目录 前言1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址5.结语 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并…...

Spring在业务中常见的使用方式

目录 通过IOC实现策略模式 通过AOP实现拦截 通过Event异步解耦 通过Spring管理事务 通过IOC实现策略模式 很多时候&#xff0c;我们需要对不同的场景进行不同的业务逻辑处理举个例子&#xff0c;譬如不同的场景需要不同支付方式&#xff0c;普通的逻辑是使用if-else&#x…...

PyTorch 深度学习实战

文章目录 前言1. 环境安装1.Anaconda2.pytorch cuda 环境3.测试 前言 1. 环境安装 1.Anaconda 可以参考这里&#xff1a;Anaconda学习 2.pytorch cuda 环境 我是按照下面的博客一步步完成&#xff0c;亲测有效 Pytorch安装教程&#xff08;最全最详细版&#xff09; 我的…...

学生用RockyLinux9.2模板虚拟机说明

“RockyLinux9.2”模板虚拟机下载地址 链接&#xff1a;https://pan.baidu.com/s/1xcakszIQ7Kp9Nw_NA9Znlg?pwdqzmm 提取码&#xff1a;qzmm 1.模板机是基于“Rocky-9.2-x86_64-minimal.iso”安装 2.模板机是2023.10.10执行dnf update && dnf upgrade更新和升级软件…...

BUUCTF reverse3 1

先运行下 看来是输入正确的flag 使用DIE查看文件 看起来没有壳&#xff0c;直接IDA打开 shift F12查找字符串 一路跟踪 到汇编窗口后F5 这里对Destination和Str2进行比较&#xff0c;Str2有值那么Str2就是经过上面一系列处理之后得到的内容了 继续分析上面的代码 根据…...

关于webWorker未解问题

今天尝试学习webworker,尝试在vue3项目里面使用 使用的就是常规方法,使用worker-loader,加上在vue.config.js内部添加配置 使用完发现问题 如图所见,该worker仅仅配置点击后传输字符串"1",并在worker内部打印,发现打印不出来 但是仅仅只是将引入的文件换个名字 …...

自然语言处理(NLP)的开发框架

自然语言处理&#xff08;NLP&#xff09;领域有许多开源的框架和库&#xff0c;用于处理文本数据和构建NLP应用程序。以下是一些常见的NLP开源框架及其特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合…...

Spring Boot与Kubernetes结合:构建高可靠、高性能的微服务架构

Spring Boot和Kubernetes&#xff08;K8s&#xff09;是当今非常热门的技术&#xff0c;它们的结合可以帮助开发者更高效地构建、部署和管理应用程序。本文将详细介绍Spring Boot和Kubernetes的主要特点&#xff0c;以及它们结合使用的优势。 一、Spring Boot的特点 Spring B…...