本文是毛仁的“ API工程共享”的研究注释
GRPC使用协议缓冲区的接口定义语言(IDL)。,这些.proto文件可用于生成针对客户和服务器的语言或平台的根源,允许多个不同的平台进行通信。通过共享.proto文件,团队可以生成代码来使用彼此的服务而无需使用代码依赖关系。
炸鱼的文章:它确实令人头疼。原始代码放在哪里?
在关于存储方法以及原始带来的优势和缺点的讨论之后,有几种解决方案:
镜子仓库
在我自己的微服务仓库中,有一个原始目录,它是要放置自己的原始目录,然后当我将微服务提交到后备箱或分支上时,它可能会触发称为自动同步的镜像来镜像镜像。,它将帮助您复制它,这相当于说我不需要向您打开我的源代码原型,它将自动复制一个集中的仓库
炸鱼文章中的集中仓库仍分为仓库。电台B是一个统一的仓库。为什么?因为Google Cloud的整个API的示例将在仓库中,否则您如何让用户找到哪个GitHub?我如何找到这么多项目?找不到它?根本应该建造一个统一的仓库,并应该完成一个项目。
我们推导的最早想法是因为我不小心看到了Google Apis.okura的仓库可以解决许多问题,包括高码共享。实际上,API文件也是如此。它集中在存储库中。检索,检查甚至读取文档很方便。
我们不喜欢其他公司喜欢获得UI背景。我们喜欢git。它很方便扩展,包括CICD流程,包括编码样式检查,包括兼容性检测,包括代码审查等。Expansion,Gitlab扩展,GitHub的某些动作,做很多工作
过去,为了统一搜索和标准化的API,我们在内部建立了一个统一的Bapis仓库,以整合所有内部和外部API。这只是一个陈述。
集中仓库的最大风险是什么?每个人都可以改变
Okura的核心是放弃阅读权限的管理。对于编写操作,有微型管理,也就是说,您可以看到我的API语句,但实际上不能称呼它,但是对于登记入住的登机手续迁移,主干,您可以将所有者文件添加到不同级别,这将描述谁可以合并代码或负责审查的谁两个字符,然后您可以轻松地使用gitlab的挂钩函数,然后使用所有者文件来执行一些良好的许可管理,以定位右键的权限。目录级别的固定管理
最后,您的同事们不能随便移动,即作者的写作许可,合并许可已关闭,只允许通过合并请求的评论区域回复某些说明。例如,您可以回复批准,表明可以成功签入此代码,以便进行一些良好的权限测试
如何搬进来?我们的想法是在微服务的原始目录中管理您的原始文件,然后自动同步,它等同于编写插件-in,可以自动复制到API Warehouse.laware.las.clip.in。调用代码并将其推入源仓库
移动终端采用自定义工具方法来自动更新同步代码阶段中的最新原始仓库,然后依靠Bazel构建整个仓库
源代码依赖性将引入许多问题
依赖性信息在您的项目中丢失以依靠其他服务,并且依赖性信息已成为源代码依赖性。您不知道您依赖哪种服务。这是Protobuf的依赖性。现在,它已成为源代码依赖性,服务依赖性丢失了。将来,我必须在整个级别上执行一些总体代码。例如,我想依靠该服务依赖谁。您无法弄清楚,因为它已成为源代码依赖性
原始尚未更新。如果我的原始文件已更新,您如何保证此人已经生成.h/.a文件,因为此相关信息丢失了,为什么您每次都必须执行此操作?它不会生成.h/.A文件
当钻石取决于我的A服务的A服务时,它取决于源代码,但我的A服务也取决于C服务。C服务取决于集中式仓库Bapis。同时,B和C之间存在另一个因子关系,然后目前可以为C代码注册两次。Protobuf有一个限制,即不允许重复声誉文件和软件包名称。
然后,它的版本可能是无能的,也就是说,存在风险。这就是为什么Google Basic构造工具管理原始工具的原因。
经过多次讨论,有几个核心认知:
原始的一个真理来源,只有在一个仓库中,如果只有一个副本,那么此副本是唯一的真理和高度信任的,那么,如果您复制此proto文件,它最终将成为sourceupdate,该副本的副本无法保证可以更新
镜像方法同步了局部微服务目录中的原始福夫的定义。镜同步与集中仓库同步。实际上,有两份副本。
使用git subsodules以仓库中的目录形式携带git subsodules介绍
子模块允许您将GIT存储库保留为另一个Git存储库的子目录。这使您可以将另一个存储的Gourdon分开并保持提交分离。
该图中的该目录的形式是本地目录的形式,但由git subsodules方法列入
如果公司的代码在一起并且API的定义在一起,那么Okura绝对是最佳解决方案,其次是GIT子模型,这也是Google的建议
我们倾向于最终专注于仓库,只有一个副本,这些副本不会进行任何副本。它通过子模型引入其自身的微服务,这意味着您的微服务将通过子模型通过子模块集中API,将其复制到本地项目中,但是它是由子模型携带的,然后您可以使您的整个编译过程更加轻松地通过一系列外壳工具,使您的整个汇编过程更容易
在统一的仓库中管理原型,以仓库命名
根目录:
目录结构和包装对齐。让我们看一下如何管理Googleapis的大量API?
第一个是Googleapis项目的Github。它的第一个级别目录称为Google,这是公司名称。第二个目录是其业务领域。
目录结构的包装名称和Protobuf完全对齐,这很方便检索
复杂业务的功能目录分为公共,枚举,错误,资源,服务等。
公共业务功能:API,RPC,在Googleapis的根目录中输入,还有公共业务功能,例如API,RPC,类型
使用简单的协议,它与错误模型无关,这使我们能够在不同的API,API协议(例如GRPC或HTTP)和错误上下文(例如,异步,批处理或工作流错误)中获得一致的体验。
使用大量资源服务器的一组标准错误并不能定义不同类型的“无法查找”错误,而是使用标准的Google.rpc.code.code.not_found错误代码,并告诉客户端查找任何特定资源.smaller状态空间降低了文档的复杂性,在客户端库中提供了更好的常规映射,并降低了客户端的逻辑复杂性。同时,它不限制它是否包含可操作信息。
我们过去定义了数十万个错误代码,约404,大约404,而错误代码找不到。为什么在设计HTTP Restful或GRPC接口时不使用标准状态代码?人们具有标准404或未找到的状态代码,使用状态代码映射通用错误信息是不好的?您无法调用接口并返回数十个特定的错误代码。对于呼叫者而言,您根本无法使用。当我的接口返回3个自定义错误代码时,您将面临错误编程。您根据错误代码继续进行不同的处理,这非常困难,每个接口必须定义
这里的核心想法是使用标准的HTTP状态代码。例如,500是内部错误,503是网关错误,504是超时,404,401是参数错误。代码或称为错误代码,首先使用它们,因为并非所有错误都要求我们调用业务提示,这意味着我调整您的服务并报告错误。无法纠正服务器生成的错误,除非有一些业务逻辑要求我进行一些跳跃或一些特殊的逻辑,否则这应该不是特别多。我认为两个或三个已经非常了。
因此,当您发现大多数其他人的界面时,您只需要使用一般标准状态代码进行映射,它将大大降低客户端的逻辑复杂性,同时,它不限于包括一些可操作的可操作暗示信息的暗示,即,您可以包括您要下一步要做的一些信息,也就是说,这并不相互矛盾
如果您的API服务取决于其他服务,则不应盲目地将这些服务的错误传播给客户。
例如,您必须说我现在有一个移动终端的接口,那么哪些错误将返回此接口?您总是不清楚,为什么不这样说?因为我们整个微服务的呼叫链是a音调b,b调整c,c调整d和d将逐层传输,然后a的错误代码可能是一个ABCD错误代码的收集。您认为您可以描述它返回的错误代码吗?根本无法描述它
因此,服务之间的依赖性不应盲目地传输到下游服务生成的这些错误代码到客户,并且一次与许多海外公司(如Uber,Twitter,Netflix和许多中国朋友)一样,他们都有许多人互相通信,他们确实确实如此不建议您使用此全局错误代码。例如,部门A从01开始,B部的B从02开始。类似于这种签订SO的绅士合同的方式,或者是宽松的,不受欢迎的脆弱和脆弱的。
当翻译错误错误时,我们建议以下操作:
例如,您返回的错误代码为4,并且已删除了代表性产品。我对此错误非常感兴趣,但是错误代码4已在我的项目中使用,因此我将其翻译成我尚未使用的错误代码。6,因此每次翻译时,您都可以向上一个说明呼叫者的层,您可以解释您将返回错误代码,因为您是由您定义的,并且将其翻译。您对翻译感兴趣。
在GRPC传输过程中,它将要求您实现GRPC状态接口的方法,因此在KRAOT V2项目中,我们首先使用由上一个定义中的消息错误定义的错误模型。转换为error_details中的errorInfo。当服务将其退还给客户
换句话说,这两个服务可以使用框架对齐,因为您基于错误模型,例如消息错误。这样,当您穿越语言时,通过errorInfo.model一致性使用相同的模型
errors.proto定义业务域错误原型。它使用最基本的Protobuf枚举将生成的源代码放在Biz大目录中,例如BIZ/错误
在某个微服务项目中,errors.proto文件实际上放置在API目录定义中。前面提到的API目录定义实际上是您服务中的API目录。我只是谈论了一个子模型。现在,您可以将其理解为Athis API目录是另一个仓库的子模型。最后,您将此信息提交给子模型,然后通过参考获得最新版本。
此errors.proto文件实际上列出了各种错误代码,或称为错误字符串。实际上,我们建议您使用字符串更加灵活,因为您不知道它在数字没有编写文档之前在做什么。如果我使用字符串,我可以告诉you_not_found告诉您用户找不到它,但是我告诉你是3548。你不知道这意味着什么。如果我不写文档,我不会写文档。
因此,我们建议使用Protobuf Enum来定义错误的内容信息,该信息是在此处定义的,但是生成的代码基于DDD的战术设计,该设计属于域名,因为业务设计是现场的事物。例外是其在域中的最终源代码是其最终源代码的最终源代码吗?它在BIZ的错误目录中
有了这种认知,我们将做三件事
首先,您的BIZ目录保留在字段逻辑中。您的现场逻辑可以直接依靠Biz..errs的目录,因为您会丢下一些业务错误
其次,我们的数据有点类似于DDD的基础架构,即DDD的基础架构。它取决于并意识到BIZ的存储库和ACL。存储库是我们所谓的仓库。ACL是抗腐蚀层。
因为我们之前已经谈论过它的整个反转游戏,所以让我们的数据取决于BIZ,并最终让我们的BIZ依赖性。它不依赖任何人或基础架构。
也就是说,最后我也可以依靠Biz的错误。我也许可以检查MySQL。结果,我没有找到这个东西。我会返回一个sql no排,但我肯定不会返回此错误。此错误编号,例如user_not_found,我是出于错误,因此它可以依靠Biz的错误
目前,Kratos不支持根本原因保存。根保存是什么?我只是说您可能已经报告了内部错误。此内部错误。实际上,您具有上层传输框架,即在HTTP和GRPC的中间件中。然后根本原因是告诉您底层是错误的
不支持解开,它不支持递归根本原因。如果根本原因支持原因,则可以允许kratos错误通过根本原因,以便我们可以获取我们的go wrap wrap errrs,但也支持我们的状态codewith原因,大型类别错误和小型类别错误,大类别错误是状态代码,小型错误是我刚刚说过的特定信息。对于特定的错误代码,您可以返回500并带来理由,这可能是一种方法
从客户端消费者端,您只能看到api.proto和error.proto文件。相应的代码是调用测量的API和错误枚举定义
获取这两个文件后,您可以生成相应的代码,然后调用API
例如,图中的代码是一种调用服务端GRPC的方法,然后我可能会返回错误。我们可以使用Kratos提供的短车,即快速方法,然后传递错误。实际上,他将其称为错误。作为标准库,迫使其将其转换为Kratos的错误类型,然后获取其原因字段,然后使用此枚举值确定它,以便您可以确定是否是Prementa Business错误
第二种写作方式您可以获得原始Kratos的错误模型,这是以下模型
新出来后,请使用标准库的错误进行转换。转换转换后,使用开关以获取其原因字段,然后您可以编写一些业务逻辑
这样,您的客户端代码是交叉语言,交叉传输,交叉 - 协议,无论是grpc,http,它也以相同的方式解决
基于OpenAPI插件-in + IDL ProtoBuf注释(IDL为定义,IDL为代码,IDL是文档),最终您可以在makefile中使用make api来在makefile中生成openapi.yaml。您可以直接在GitLab/vscode插头-in直接查看。
因为我们可以在IDL文件上写大量评论,那么当您谈论这个地方时,您会了解IDL的好处?
IDL文件是定义的,并同时代码,这意味着您已经发表了声明,然后您可以使用ProtoC生成代码,并且是交叉语言代码。同时,真理是唯一的事实标准
最后,您可以在makefile中定义API指令,然后生成openapi.yaml。这是大肆的JSON。
生成YAML文件后,GitLab现在直接支持OpenAPI.YAML文件,因此您可以直接打开GitLab以单击它,并且您可以看到如此酷的UI。
还有一个非常关键的观点。我们当前的IDL既定义,代码和文档。实际上,IDL也具有核心作用。该定义表明它是一种元信息,一个元数据,最后可以将此API Metata元数据用于大量的微服务治理
因为当您要控制时,您会说每个服务的接口是路由和融合的限制。这些元信息在哪里?我们知道先前的Dubbo 2.x和3.x在3.x之前注册到注册中心,这导致了整个数据中心的存储爆炸。那么元信息在哪里?
我们考虑为什么Protobuf定义文件,然后在序列化后它比JSON小?因为它本身没有描述,其定义和序列化是分开的,也就是说,原始有效负载没有任何定义信息,因此可以高度压缩,可以压缩或更紧凑以更紧凑
因此,同样的原因是,IDL的定义与其元信息分开,生成代码分开,这意味着您只需要拥有一个真实源的唯一PB文件即可。基于此PB文件,您有一种方法来实现它。要成为元数据服务,您可以将其用于微服务的治理
您可以选择一个服务,然后查看其具有什么界面,然后可以使用控制表面来制作熔化,流量限制和其他功能,然后您也可以根据此元信息进行调试。您可以制作一个凉爽的UI,使其成为一些参数,甚至可以编写一些扩展名。例如,此字段称为等,建议它的本字段,然后您可以在呈现UI时填写默认值,然后您可以进行一些调试,甚至可以进行一些调试。包括测试,您可以生成一个大型基于此API的测试案例数
API工程共享https://www.bilibili.com/video/bv17m4y1f7qc/
接口定义语言https://docs.microsoft.com/zh-cn/dotnet/architecture/grpc-wcf-developers/internition-langue
什么头痛,原始代码在哪里?
git子模型https://git-scm.com/book/en/v2/git-submodules
kratos https://github.com/go-kratos/kratos
error_details.proto https://github.com/googleapis/googleapis/blob/master/google/rpc/error_details.proto#l1112
PKG/错误https://github.com/pkg/error
随着时间的推移修改GRPC服务
原始:https://juejin.cn/post/7097866377460973599