从 HTTP 到 gRPC:APISIX 中 etcd 操作的迁移之路
罗泽轩,API7.ai 技术专家/技术工程师,Apache APISIX PMC 成员。
原文链接
Apache APISIX 现有基于 HTTP 的 etcd 操作的局限性
etcd 在 2.x 版本的时候,对外暴露的是 HTTP 1 (以下简称 HTTP)的接口。etcd 升级到 3.x 版本后,其对外 API 的协议从普通的 HTTP 切换到了 gRPC。为了兼顾那些不能使用 gRPC 的特殊群体,etcd 通过 gRPC-gateway 的方式代理 HTTP 请求,以 gRPC 形式去访问新的 gRPC API。
APISIX 开始用 etcd 的时候,用的是 etcd v2 的 API。从 2020 年的 APISIX 2.0 版本起,我们把要求的 etcd 版本升级到 3.x。etcd 对 HTTP 的兼容帮了我们很大的忙,这样就不用花很大心思去重新实现操作 etcd 的方式了,只需调整下新的一组 API 的调用方式和响应处理。然而在实践过程中,我们也发现了跟 etcd 的 HTTP API 相关的一些问题。事实上,拥有 gRPC-gateway 并不意味着能够完美支持 HTTP 访问,这里还是有些细微的差别。
我把过去几年来在 etcd 上遇到的相关问题列了一下:
- 在某些情况下,etcd 默认没有启用 gRPC-gateway。由于维护者的疏忽,在某些平台上,etcd 在配置时没有默认启用 gRPC-gateway,所以我们不得不在文档中添加一个注释,以检查 etcd 当前是否启用了 gRPC-gateway。具体可参考 https://github.com/apache/apisix/pull/2940。
- gRPC 默认将响应限制在 4MB 以内。etcd 在其提供的 sdk 中解除了这一限制,但忘记了在 gRPC-gateway 中解除。因此,官方的 etcdctl(使用了 sdk)工作正常,但 APISIX 却无法正常访问。具体可参考 https://github.com/etcd-io/etcd/issues/12576。
- 同样的问题 —— 这次是发生在同一连接的最大请求数上。Go 的 HTTP2 实现有一个 MaxConcurrentStreams的配置,控制单个客户端能同时发送的请求数,默认是 250。正常情况下,哪个客户端会同时发送超过 250 个请求呢?所以 etcd 一直沿用这一配置。然而 gRPC-gateway 这个代理所有 HTTP 请求到本机的 gRPC 接口的“客户端”,却有可能超出这一限制。具体可参考 https://github.com/etcd-io/etcd/issues/14185。
- etcd 在开启 mTLS 后,会用同一个证书来作为 gRPC-gateway 的服务端证书,兼 gRPC-gateway 访问 gRPC 接口时的客户端证书。如果该证书上启用了 server auth 的拓展,但是没有启用 client auth 的拓展,那么会导致证书检验出错。直接用 etcdctl 访问不会有这个问题,因为该证书在这种情况下不会作为客户端证书使用。具体可参考 https://github.com/etcd-io/etcd/issues/9785。
- etcd 在开启 mTLS 后,允许针对证书里面的用户信息配置安全策略。如上所述,gRPC-gateway 在访问 gRPC 接口时用的是固定的一个客户端证书,而非一开始访问 HTTP 接口所用的证书信息。这个功能自然就没办法正确工作了。具体可参考 https://github.com/apache/apisix/issues/5608。
造成上述问题的原因可以归纳为两点:
- gRPC-gateway(或许还有其他将 HTTP 转换为 gRPC 的尝试)并不是万能的。
- etcd 的开发者没有对 HTTP 到 gRPC 的路径给予足够的重视。毕竟他们最大的用户,Kubernetes,并不会使用它。
要想从本源上解决这一问题,我们需要直接通过 gRPC 来操作 etcd,这样就不用走为了兼容而保留的 HTTP 路径。
克服各种挑战,迁移到 gRPC
跳过 lua-protobuf 的 bug
在迁移过程中,我们遇到的第一个问题,是一个预想不到的第三方库的 bug。像绝大多数 OpenResty 应用一样,我们采用 lua-protobuf 来完成 protobuf 的 decode/encode。在引入 etcd 的 proto 文件之后,我们发现 Lua 代码中会出现偶发的奔溃,报错说遇到了 "table overflow"。由于这个崩溃不能稳定复现,我的第一反应是寻找最小可复现的例子。但是有趣的是,如果单独使用 etcd 的 proto 文件,那么无论如何都无法复现该问题。这个崩溃似乎只能出现在 APISIX 运行的时候,真是神奇。通过一些调试,我把问题锁定到了 lua-protobuf 在解析 proto 文件的 oneof 字段时的逻辑。lua-protobuf 在解析时会尝试预分配 table 大小,而分配的大小是按照某个值计算过来的。有一定几率,这个值会是个负数,然后 LuaJIT 在分配时把这个数转成很大的正数,结果导致了 "table overflow" 错误。我向作者报告了该问题,并在我们内部维护了一个带 workaround 的 fork。lua-protobuf 作者反应很迅速,次日就提供了一个修复,并在几天后发布了新的版本。原来 lua-protobuf 在清理不再使用的 proto 文件时,曾经漏了减少某些字段,导致在后续处理 oneof 时会得到一个不合理的负数。之所以是偶现的问题,之所以无法在单独使用 etcd 的 proto 文件时复现,都是因为少了“清理”这一关键的前置操作。
向 HTTP 的行为对齐
世间鲜有东西是从头开始的,往往不得不从当前继承一些负担。在迁移过程中,我发现一个问题,就是现有的 API 返回的并不是一个简单的请求执行结果,而是个包含 status 和 body 的 HTTP response,然后由调用方去处理这个 HTTP response。这么一来,gRPC 的响应结果就需要套上一个 HTTP response 的壳。不然调用方就需要改动很多处地方来适配新的响应格式。尤其考虑到旧的基于 HTTP 的 etcd 操作也需要同时支持,虽然兼容 HTTP response 的套壳行为并非我所欲,但是还是得向现实低头妥协。除了要加壳之外,我们还需要对 gRPC 响应做一些裁剪。比如在没有对应数据时,HTTP 不会返回任何数据,而 gRPC 会返回一个空 table。裁剪结果嘛,自然都是向 HTTP 的行为靠齐。
从短连接到长连接
在基于 HTTP 的 etcd 操作中,APISIX 都是采用短连接,所以不需要考虑诸如连接管理的问题。反正用的时候发起新连接,用完 close 即可。但 gRPC 就不能这么操作了。迁移到 gRPC 的一大目的就是为了达到多路复用,如果每次操作都创建新的 gRPC 连接,那么就无从实现这一目的。这里需要感谢 gRPC 功能的内核 gRPC-go 自带了连接管理的能力,面对连接中断可以自动重连。这样判断是否需要复用连接,在 APISIX 这一层就只需考虑业务需求。APISIX 的 etcd 操作可以分为两类,一类是去对 etcd 的数据做增删改查;另一类是从控制面同步配置。虽然理论上这两种 etcd 操作可以共享同一个 gRPC 连接,但是出于权责划分的考虑,我们决定把它们分成两个连接。对于增删改查的连接,由于 APISIX 启动时和启动后的连接需要分开对待,所以在获取新的连接时加了个判断,如果当前连接是启动时创建且目前需要的是启动后的连接,那么会关闭当前连接并创建新的连接。对于配置同步,我开发了新的同步方式,让每一种资源都采用当前连接下面的一个 stream 来 watch etcd。
迁移到 gRPC 后,我们得到了什么样的好处
迁移到 gRPC 后,一个显而易见的好处是操作 etcd 所需的连接大大减少。原来通过 HTTP 操作 etcd 时,APISIX 都是采用短连接。而且在同步配置时,每种资源都会有一个单独的连接。在切换到 gRPC 之后,我们可以用上 gRPC 的多路复用功能,每个资源都只使用单个 stream,而不是完整的连接。这样一来,连接数就不再随着资源数的增加而增加。考虑到 APISIX 的后续开发将会引入更多的资源类型,比如当前最新的 3.1 版就新增了 secrets,采用 gRPC 带来的连接数的减少将会越来越明显。
使用 gRPC 同步时,每个进程只有一条用于配置同步的连接(如果开启了 stream 子系统,那么是两条)。在下图中我们能看到两个进程共有四个连接,其中两个是配置同步,还有一个连接由 Admin API 使用,剩下一个连接是特权 agent 上报 server info。
作为对比,下图是保持其他配置不变,使用原有的配置同步方式所需的连接数。具体有多少我就不数了。另外这些连接还是短连接。
这两个配置的区别,仅在于是否启用了 gRPC 来做 etcd 操作:
etcd:use_grpc: truehost:- "http://127.0.0.1:2379"prefix: "/apisix"...
除了连接数的减少外,使用 gRPC 来直接访问 etcd 而非绕道 gRPC-gateway,能够解决文中一开始提到的关于 mTLS 鉴权等一系列受限于架构的问题。此外,我们也相信使用 gRPC 后遇到更少的问题,因为 Kubernetes 就是通过 gRPC 来操作 etcd 的,如果有问题,在 Kubernetes 社区应该会更早地发现。
当然,作为一个新生事物,APISIX 通过 gRPC 操作 etcd 时不免会有一些新的问题。毕竟我们之所以发现了许多 HTTP 路径下的问题,是因为我们对 HTTP 用得比较多。所以目前我们还是默认采用原有的基于 HTTP 的方式来操作 etcd。不过用户可以自行在 config.yaml
中配置 etcd 下的 use_grpc
为 true,尝试一下新的方式是否更优。我们也会听取各路反馈意见,继续完善基于 gRPC 的 etcd 操作,并持续积累更多的经验。在后续的某个时候,当我们判断新方式足够成熟时,就会把它确定为默认的途径。
关于 API7.ai 与 APISIX
API7.ai 是一家提供 API 处理和分析的开源基础软件公司,于 2019 年开源了新一代云原生 API 网关 -- APISIX 并捐赠给 Apache 软件基金会。此后,API7.ai 一直积极投入支持 Apache APISIX 的开发、维护和社区运营。与千万贡献者、使用者、支持者一起做出世界级的开源项目,是 API7.ai 努力的目标。
相关文章:
从 HTTP 到 gRPC:APISIX 中 etcd 操作的迁移之路
罗泽轩,API7.ai 技术专家/技术工程师,Apache APISIX PMC 成员。 原文链接 Apache APISIX 现有基于 HTTP 的 etcd 操作的局限性 etcd 在 2.x 版本的时候,对外暴露的是 HTTP 1 (以下简称 HTTP)的接口。etcd 升级到 3.x…...
【C语言每日一题】——倒置字符串
【C语言每日一题】——倒置字符串😎前言🙌倒置字符串🙌总结撒花💞😎博客昵称:博客小梦 😊最喜欢的座右铭:全神贯注的上吧!!! 😊作者简…...
Native扩展开发的一般流程(类似开发一个插件)
文章目录大致开发流程1、编写对应的java类服务2、将jar包放到对应位置3、配置文件中进行服务配置4、在代码中调用5、如何查看服务调用成功大致开发流程 1、编写服务,打包为jar包2、将jar包放到指定的位置3、在配置文件中进行配置,调用对应的服务 1、编…...
【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供
华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 任务调度 题目 现有一个 CPU 和一些任务需要处理,已提前获知每个任务的任务 ID、优先级、所需执行时间和到达时间。 CPU 同时只能运行一个任务,请编写一个任务调度程序,采用“可抢占优先权调度”调度…...
Spring3定时任务
简介 Spring 内部有一个 task 是 Spring 自带的一个设定时间自动任务调度,提供了两种方式进行配置,一种是注解的方式,而另外一种就是 XML 配置方式了;注解方式比较简洁,XML 配置方式相对而言有些繁琐,但是应用场景的不…...
数据库版本管理工具Flyway应用研究
目录1 为什么使用数据库版本控制2 数据库版本管理工具选型:Flyway、Liquibase、Bytebase、阿里 DMSFlywayLiquibaseBytebase阿里 DMS3 Flyway数据库版本管理研究3.1 参考资料3.2 Flyway概述3.3 Flyway原理3.4 Flyway版本和功能3.5 Flyway概念3.5.1 版本迁移…...
更换 Ubuntu 系统 apt 命令安装软件源
更换 Ubuntu 系统 apt 命令安装软件源清华大学开源软件镜像站 https://mirrors.tuna.tsinghua.edu.cn/ 1. Ubuntu 的软件源配置文件 /etc/apt/sources.list MIRRORS -> 使用帮助 -> ubuntu https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/ Ubuntu 系统 apt 命令安…...
2023年可见光通信(LiFi)研究新进展
可见光无线通信Light Fidelity(LiFi)又称“光保真技术”,是一种利用可见光进行数据传输的全新无线传输技术。LiFi是一种以半导体光源作为信号发射源,利用无需授权的自由光谱实现无线连接的新型无线通信技术,支持高密度…...
Greenplum的两阶段提交
注:本文章引自终于把分布式事务讲明白了! 在前面的文章中,我们了解了单机库中的事务一致性实现以及分布式事务中的两阶段提交协议。大多数分布式系统都是采用了两阶段提交塄来保证事务的原子性,Greenplum也是采用了两阶段提交&am…...
多元回归分析 | CNN-BiLSTM卷积双向长短期记忆神经网络多输入单输出预测(Matlab完整程序)
多元回归分析 | CNN-BiLSTM卷积双向长短期记忆神经网络多输入单输出预测(Matlab完整程序) 目录 多元回归分析 | CNN-BiLSTM卷积双向长短期记忆神经网络多输入单输出预测(Matlab完整程序)预测结果评价指标基本介绍程序设计参考资料预测结果 评价指标 训练结束: 已完成最大轮…...
git命令行推送本地分支到远程仓库
之前说过Git与IDEA强强联合(HTTPS协议连接)那么如何使用命令行来推送代码呢? 如下图所示为一个基于layui的前端代码: 目录工作区文件: 本地内容就是将这些内容推送到远程仓库 首先使用git命令初始化git本地仓库&…...
在vscode中使用Typescript并运行
首先呢,我们在学习ts之前,需要先安装ts 1、安装 typescript npm install -g typescript //检查是否安装tsc -v 2、生成配置文件,cd进入该文件夹,在控制台输 tsc --init 此时我们就可以看到在ts文件夹下面出现了 一个tsco…...
【C++提高编程】C++全栈体系(十九)
C提高编程 第三章 STL - 常用容器 一、string容器 1. string基本概念 本质: string是C风格的字符串,而string本质上是一个类 string和char * 区别: char * 是一个指针string是一个类,类内部封装了char*,管理这个…...
Java版电能表协议解析源码(DL/T645-2007)、Modbus串口虚拟工具、网络串口调试工具分享
什么是Modbus通信协议Modbus串口调试工具Java版协议解析源码 网络与串口二合一调试助手TCPCOM: https://download.csdn.net/download/liuyuan_java/87454762 Modbus调试工具,模拟串口调试工具 https://download.csdn.net/download/liuyuan_java/874274…...
2023美赛选题建议 美国大学生数学建模竞赛ABCDEF题
选题建议和粗略思路已更新完毕 对于没有基础的同学来说CD两题上手难度较高,大家可以根据自己的实际情况选择最适合自己的题目,团队将持续更新各题后续内容,Q群322297051 A题主要难度就是建立第一问的模型,综合来看难度不大&…...
2023,想跳槽的可以再等等
今天讲讲跳槽。 金三银四即将开启,一些不满现状,被外界的“高薪”“好福利”吸引的人,一般就在这时候毅然决然地跳槽了。 跳槽是为了寻求更好的发展,但在跳槽前我们也不能确定下家就是更好的归宿,这就更加需要我们审…...
Java之滑动窗口详解
目录 一.滑动窗口 1.什么滑动窗口 2.滑动窗口的三要素 二.找到字符串中所有字母异位词 1.题目描述 2.问题分析 3.代码实现 三.字符串的排列 1.题目描述 2.问题分析 3.代码实现 四.考试的最大困扰度 1.题目描述 2.问题分析 3.代码实现 五.替换后的最长重复字符 …...
Webpack(应用一:基本使用,只需六步骤)
前言 上一篇文章已经说明了webpack的定义以及需求 本偏文章主要讲解webpack的基本使用 tips:现在以vscode编辑器来展示,只需要几个步骤就可以实现webpack的基本使用。 一、首先要安装node.js 1、不会安装node.js的,可以在网上自己找教程来…...
【Python小游戏】智商爆棚,推荐一款益智类亲子娱乐首选—某程序员老爸:成语编成填空“游戏”,贪玩女儿1天牢记500词(厉害了我的Python)
前言 成语填空想必大家都是十分熟悉的了,特别是有在上小学的家长肯定都有十分深刻的印象。 在我们的认知里看图猜成语不就是一些小儿科的东西吗? 当然了你也别小看了成语调控小游戏,有的时候知识储备不够,你还真的不一定猜得出…...
使用web3连接Georli测试网络
文章目录1.使用geth方式在终端2.写成脚本2.1 通过metamask (现成的太复杂,搞不太来)2.2 通过自己的接口3.通过truffle方式连接 (不成功)目前的工作情况是,已在remix写好执行合约并部署在Georli测试网络中&a…...
Python uWSGI 的安装配置
以 Ubuntu/Debian 为例,先安装依赖包: apt-get install build-essential python-dev Python 安装 uWSGI 1、通过 pip 命令: pip install uwsgi 2、下载安装脚本: curl http://uwsgi.it/install | bash -s default /tmp/uwsgi 将…...
033.Solidity入门——20函数的可视范围
修饰符可见性描述public在合约内和合约外都可以被访问,即合约内外部都可以调用该函数。这种类型的函数可以被合约内和合约外的任何地址调用。private只有在当前合约内可以被访问,即只有合约内可以调用该函数。这种类型的函数只能在合约内部被调用。exter…...
智能家居项目(三)之框架设计及框架代码文件工程建立
目录 一、智能家居项目框架设计草图 二、框架代码文件工程建立 三、添加声音识别模块的串口读取功能 一、智能家居项目框架设计草图 代码思路讲解: 1、一个指令工厂,一个控制工厂,实际上就是通过链表链起来的数据。具体怎么链接起来&…...
全网最全的Ansible中常用模块讲解
目录 前言 一、ansible实现管理的方式 二、Ad-Hoc执行方式中如何获得帮助 三、ansible命令运行方式及常用参数 四、ansible的基本颜色代表信 五、ansible中的常用模块 1、command 2、shell 3、script 4、copy 5、fetch 6、file 7、 unarchive 8、archive 9、h…...
linux程序分析工具
嵌入式调试工具1. nm2. addr2line3. readelf3.1 ELF 文件分类3.2 ELF文件组成3.3使用1. nm nm源于name,是linux下一个文本分析工具,可以罗列指定文件中的符号(函数名、变量,以及符号类型)。 nm命令参数如下: 用法:nm …...
Python3,2分钟掌握Doscoart库,你也能成为艺术家。
2行代码绘制水彩画1、引言2、 代码实战2.1 模块介绍2.2 模块安装2.3 代码示例2.3.1 创建默认图片2.3.2 设置参数创建图片2.3.3 查看设置参数2.3.4 查看配置2.3.5 保存配置2.3.6 加载配置2.3.7 导出配置文件2.3.7 生成Python代码2.3.8 调用文档3、总结1、引言 小屌丝࿱…...
1225057-68-0,Alkyne PEG4 TAMRA-5,四甲基罗丹明-四聚乙二醇-炔基TAMRA红色荧光染料连接剂
中英文别名:CAS号:1225057-68-0 | 英文名:5-TAMRA-PEG4-Alkyne |中文名:5-四甲基罗丹明-四聚乙二醇-炔基物理参数:CASNumber:1225057-68-0Molecular formula:C36H41N3O8Molecular weight&#x…...
Ae:解释素材
所谓解释素材 Interpret Footage,就是通过修改素材的某些属性(像素长宽比、帧速率、颜色配置文件及 Alpha 通道类型等),让它能更好地参与到合成中去。Ae菜单:文件/解释素材快捷键:Ctrl Alt G在项目面板里…...
无文件攻击
无文件攻击是一种高级持续性威胁(APT)的攻击方式,它不会在目标系统的磁盘上留下可执行文件,而是利用系统内置的工具或脚本执行恶意代码,从而绕过传统的安全防护措施。无文件攻击的最大特点就是恶意代码直接在内存中运行…...
JS高级——数据类型
数据类型 基本类型 String: 任意字符串Number: 任意的数字boolean: true/falseundefined: undefinednull: null 对象类型 Object: 任意对象Function 一种特别的对象(可以执行)Array: 一种特别的对象 判断 typeof //不能区分数组与对象、null与obje…...
杭州做网站设计公司/优化器
语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的口语输出的技术。 刚开始项目需求订单实时播报,最初采用的H5的语音合成Speech Synthesis APIÿ…...
网站编程工具/百度 营销推广怎么收费
前言 在去年十月的时候参加了一个小比赛,做了一个人脸识别程序并很意外地获得省里面的一等奖,视频演示链接在这里,有同学想要做这方面的毕业设计or课程设计,发一篇博客来分享一下当时的开发过程。 视频演示链接 Github链接 项目简…...
网页制作师培训机构/安徽网站seo公司
今天在做即时通讯群聊时,调用MultiUserChat.getHostedRooms(conn, SmackTools.getInstance().conn.getServiceName());方法获取服务列表时总是出现空指针的情况。 当时出现这个错误的时候感觉是非怪的,因为参数:conn和服务名都不为空。而Mult…...
嘉兴品牌网站建设/直接打开百度
最近做了一个小工具,里面涉及到一些取SQL Server 服务器信息的一些东西,找了好久,找到一个不错的,贴出来分享。 系统函数 SERVERPROPERTY ( propertyname ) 包含要返回的服务器属性信息的表达式。propertyname 可以是下列值之一&a…...
网站中文域名好不好/seo石家庄
1. 需求 目前我们开发的TCP服务端程序只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢? 完成多任务,可以使用线程,比进程更加节省内存资源。 2. 具体实现步骤 编写一个TCP服务端程序,循环等…...
网站制作模板代码/爱站工具包怎么使用
仿网易彩票,最终要做成的效果如下: 一、分层搭建 1.新建一个项目,Lottery.只支持7.1以上坚屏。 2.将素材全部图片全部拉到相应的文件夹里。 3.选中Lottery--右键Show in Finder ,在Lottery文件夹下新建一个Classes,并分别分层成MVC文件夹。 4…...