Go-Kit概况
截止到本文发布时,Go-Kit
在github上的star数为22.2k,超过了我们已经一起看过的Go-Micro
与Kratos
。
Go-Kit
不同于前两者,它更像是一种Go语言的工具集,而不是一种统一化的框架。
今天,我们一起来看CNCF的 Remote Procedure Call - RPC 模块中最具代表性的项目 - gRPC。
gRPC官网的定义很简洁,重点强调了其高性能的特点:
A high performance, open source universal RPC framework.
我们再看一段官方更详细的描述:
gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.
除了高性能,这里还提到了两个重要特性:
第一点体现出了gRPC的高度可扩展性。这里的插件化不仅体现在上面列举的这些具体功能,甚至像序列化的方案、底层通信的协议,都可以做到快速替换与迭代。
第二点在实际生产上应用的case并不多,仍需要大量的实践与经验沉淀后,才建议大家尝试。目前,绝大多数的gRPC通信都是发生在后端服务之间。
接下来,我们来谈谈官网列举的四个特性:
gRPC采用Protocol Buffers
进行定义,从整体来说阅读体验确实是比较简洁的,但在实际工程中仍存在两个问题:
Protocol Buffers
的朋友都有了解,主流IDE对pb
文件的错误提示和文件格式化都有缺失,很多问题都无法在coding的过程中实时提示,而是需要运行二进制命令protoc
后才能了解。快速启动 - 强调的是通过Protocol Buffers
生成的代码,可以在各语言内用简洁的代码就可运行(这部分与各语言强相关)
快速扩容 - 这个特性需要与Kubernetes
的能力结合。
跨语言与平台的特性,非常依赖背后的生态 - 需要大量的工作去兼容多语言,也要兼顾性能、稳定性等问题。
所以,这不仅仅是技术上的问题,更需要社区、资金等复杂因素的支持。
作为云原生Service Mesh代表性的产品之一,Envoy占据了大壁江山。
Envoy is an L7 proxy and communication bus designed for large modern service oriented architectures.
核心理念:
The network should be transparent to applications. When network and application problems do occur it should be easy to determine the source of the problem.
网络应对应用程序透明。当网络和应用程序出现问题时,应该很容易地确定问题根源。
文档资料:
我们依旧挑选三个核心特性展开:
进程外架构,其实就是一种微服务理念的体现,它的利与弊也是和微服务强相关的。
优点很直观 - Envoy可以支持多语言,也可以独立于业务快速迭代与发展。
而弊端在官网上没有体现,最关键的一点是:性能损耗。作为一种side-car模式,Envoy是在本机内、进程间进行通信,远远地比进程内调用的压栈、出栈更花时间。
很多运维同学都会拿Envoy去对比Nginx,确实在很多特性上,两者有很大的相似之处。但在这个特性上,Envoy有得天独厚的优势。
以一个常见的动态负载均衡为例,nginx需要结合consul template来实现,还需要对应用程序做一定的侵入。而Envoy可以与Kubernetes完美契合,大幅度减少维护成本。
Envoy 的最主要目标是使网络透明,而最佳的可观测性往往会从OpenTelemetry推荐的三点入手:Metrics、Logging、Tracing。
Envoy提供了大量的插件,一方面保证了Envoy内部的问题清晰明了,同时也能快速地协助定位到应用侧的问题。
作为CNCF中的控制平面的主打产品,Contour的知名度远不如Google的Istio。但由于种种原因,Istio并没有被捐献给云原生基金会,于是CNCF就孵化了Contour。
定义
Contour is an open source Kubernetes ingress controller providing the control plane for the Envoy edge and service proxy. Contour supports dynamic configuration updates and multi-team ingress delegation out of the box while maintaining a lightweight profile.
三大特性
- Envoy Inside
- Flexible Architecture
- TLS Certificate Delegation
从定义与三个特性的描述里,我们很难真实地感受到Contour的特点。
今天我将换一个角度:从控制平面与数据平面进行分析。如果我们能清楚地认识到这两者的定义与边界,那么会对云原生的Service Mesh理念,以及Envoy、Contour、Istio等产品有更深的理解。
这篇博客的定义很具有参考意义:
控制平面的关键功能就是控制与管理,重点对象是配置信息。
我们可以将数据平面看作为基础的Nginx服务,它是和底层的应用强相关的,解析相关的数据包并实现路由、负载均衡等功能。但Nginx自身也需要有一定的配置信息,比如说:
在我看来,控制平面更像是数据平面的配置中心,解决的是高频变化或应用间差异性很大的配置信息,让数据平面更稳定地运行。
从架构层面来说,如果一层解决不了问题,那就再抽象一层。
从具体的工程实践来说,数据平面主要负责的是底层实现,在保证稳定性的情况下更要兼具性能,所以不宜有太多丰富的功能。这时,引入了控制平面,我们可以将很多的配置信息通过界面UI方式进行管理,下发到各个控制平面,然后控制平面再针对性地进行转发到数据平面,就能大幅度地提高整个Service Mesh方案的可维护性。
Emissary-Ingress是CNCF中又一个与网络相关的项目。这款软件的前身叫作Ambassador。但Ambassador是一款商业软件,为了避免相关的问题,更名为Emissary-Ingress后被捐献给了CNCF。因为网上资料更多的都是Ambassador,下面统一用Ambassador对这款软件进行描述。
CNCF上的定义为:
open source Kubernetes-native API gateway for microservices built on the Envoy Proxy
我们很容易将这个产品与Istio、Envoy混淆起来,那它们之间的区别是什么呢?这里有篇文章,介绍了具体的实践,但我们直接可以从标题中得到关键信息:
而Envoy+Contour对标的是Istio,所以不难看出,云原生推荐将Ambassador作为一种边缘网关,更多地是作为整体流量的出入口。如果说service mesh是一种对网络的精细化管理,那么边缘网关更多地是对整体流量的管理。
但在实际使用中,两者有大量的重叠功能,如路由、认证、限速等,而我也没有在网上找到相关的Best Practice,这部分就很需要大家的经验与摸索了。从我的角度来看,更倾向于大家多使用Envoy的特性,毕竟它的生态最成熟。即便后续有了替代品,对方也往往会提供对应的兼容方案。
这里,我引用了一个链接,讲述了微服务网关(Emissary-Ingress定位)与传统企业级网关的差异。
微服务网关相对而言会更轻量级,而且对外以服务的维度呈现。
微服务网关更倡导自运维的方式。
传统企业级网关 - L7 error-handling (e.g. custom error page or payload). Run gateway/API with additional logging. Troubleshoot issue in staging environment
微服务网关 - Configure more detailed monitoring. Enable traffic shadowing and / or canarying
微服务网关更强调的是网络侧的更细致化的管理,突出了灵活性。
这两天,有个读者跟我讨论了一个关于链路追踪的问题 - 他发现通过context传递的trace-id丢失了。从根本上来说,这涉及到了Context在Go程序外的传递的理解,细想的话很有意思,所以我今天专门拿出来讲讲。
如果你对Go语言有一定的基础,会很习惯地使用Context作为上下文信息的传递:无论是内部函数的调用,还是RPC的调用,这就会产生一种错觉:context的传递是水到渠成的。
这位同学的调用链路是 Go程序 - MQ - Go程序,发现context中的trace-id丢失了。
trace-id用于分布式的链路追踪
分析这个问题不难,有很多种思路,但我比较建议大家从底层实现去理解:
Go语言的Client将context封装到Header里,Server将context从Header中解析出来。
默认的官方库是不会写直接写的,需要做一层浅封装:
发送前,从ctx中将对应的k-v填入到header;
收到后,从header中提取k-v,写入到context。
要验证一下上面的猜想很简单,我强烈大家用最底层的方式:Wireshark抓包。事实也如我们的预期,Go语言的ctx传递正是用这种方式实现的。而MQ这种第三方组件,往往不会去解析这种特定的Header,所以会发生丢失。
这时,我们有什么样的解决方案呢?
Github: https://github.com/Junedayday/code_reading
Blog: http://junes.tech/
Bilibili: https://space.bilibili.com/293775192
公众号: golangcoding
Unix设计哲学在程序员的圈子里经久不衰,备受追捧。而Go
语言背后有很多Unix
与C语言
的影子,三位创始人Rob Pike(罗伯. 派克),Ken Thompson(肯. 汤普森)和Robert Griesemer(罗伯特. 格利茨默)都是这两块领域的泰山北斗。了解Unix的设计哲学,对写出优秀的代码很有帮助。
Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.
做一件事,做好它。让程序能够互相协同工作。应该让程序处理文本数据流,因为这是一个通用的接口。
作为管道机制的发明者,Doug McIlroy对这块的解释重点很具有管道特色。这里,我们聚焦于一个点:做好一件事。
将其拆分一下,主要分为两块:
做好
这个标准,尽可能地按照自己的认知上限去做,才可能有成长)。case by case
去看。
- 你永远不会知道你的程序会在什么地方耗费时间。程序的瓶颈常常出现在意想不到的地方,因此在你确信找到瓶颈后再动手优化代码吧。
- 测试代码。只有在你详细测试了代码,并且发现一部分代码耗费了绝大部分的运行时间时再对程序作速度优化。
- 功能全面的算法(fancy algorithm)在处理小规模问题时效率很低,这是因为算法时间效率中的常量很大,而问题往往规模很小。除非你知道你遇到的常常是复杂的情况,否则就让代码丑陋但是简单而高效吧。(即使问题规模确实很大,也首先尝试第二条规则。)
- 功能全面的算法比简单的算法更容易产生bug,更难实现。尽量使用简单的算法和数据结构。
- 数据决定一切。如果选择的数据结构能很好的管理数据,算法部分往往不言自明。记住,数据结构,而非算法,才是编程的关键。
- 没有第六条规则。
按照wiki上的说法,1、2可以归纳为 过早的优化是一切罪恶的根源,3、4可以理解为 疑惑不定之时最适合穷举。
而第五条就非常有意思,也就是 数据结构比算法更重要。
这点,和我们在刷算法题时认知相反 - 在做算法题目时,我们往往已经得到了一个具体的数据结构,要做的更多是根据这个数据结构选择合适的算法。当数据结构确定时,可选择的算法就很有限了,这也大大缩小了题解的范围。
在复杂的场景中,我们首先得确定数据结构,这一步尤为复杂:
关于Unix的设计哲学还有很多优秀的见解,但综合起来,可以归纳为KISS
原则,也就是简单性。希望大家能在工程实践中,多多思考怎么保证简单性,对做出优秀的设计会很有启发。
今天我们一起来看CNCF中的第二个项目 - CrossPlane
。它位于CNCF全景图中Kubernetes
旁,受众比较小。
先看一段来自官网 https://crossplane.io/ 的信息:
Crossplane is an open source Kubernetes add-on that enables platform teams to assemble infrastructure from multiple vendors, and expose higher level self-service APIs for application teams to consume, without having to write any code.
我们依旧抽取其中关键的词进行解析:
Kubernetes add-on
CrossPlane的定位是Kubernetes
的插件,并非一个独立的平台assemble infrastructure from multiple vendors
统一封装多个依赖方的基础设施expose higher level self-service APIs
暴露高层接口然后,官方描述了五个关键性的特征:
概括起来,可以定义为:使用 kubectl 封装了各类云的API,来统一管理基础设施、服务和应用。
我们从具体的实践角度来看,统一封装接口往往只是加分项,而核心在于 支持的云基础设施与服务的范围。
从 官方文档 可以看到,CrossPlane
主要支持了亚马逊云、谷歌云、微软云等厂商。可以看到,这款产品主要面向的是国外的公有云厂商。这其实也决定了CrossPlane
更多面向的是国外开发者。
学习CrossPlane
的更多细节,对我们来说暂时没有更大的意义。我们可以尝试着从其理念中得到以下启发:
CNCF
统一了大致上的理念,但细节上的实现各有不同;尤其是结合了账号、权限、资源分配等各类特性后,对接起来的复杂度很高。Kubernetes
这个核心项目带来大量侵入性极强的代码。这时,引入另一个项目作为防腐层,很具有扩展意义。今天的话题将围绕着一篇谈论微服务架构的文章展开。下面给出原文链接,以及一个翻译的版本:
文中给出了以下九个微服务特征:
这些点,每个抛出来都可以写一篇长文。建议有兴趣的各位可以阅读原文,结合自己的实践多多思考。
这里,我选择三个最近感触比较深的点,自己也曾经陷入过的认知误区,在这里和大家聊聊:
业务能力的概念很抽象,虽然我们会经常提及,但在实践过程中又往往容易忽略。
从系统的角度来看,业务能力往往就是对外呈现的功能,对应到内部的技术模块,往往已经决定了七七八八。如何将这些技术模块做合理的拆分与合并,就是微服务架构需要考量的点。这里我谈谈最近比较有心得的三个考量点:
当然,还有更多的内容,需要大家在实践中摸索。
这一点在云原生的服务中体现得淋漓尽致:以RPC、Service Mesh、服务发现等技术为代表。
终端体现在Pod
这一层,也就是对一个具体运行的App来说,通过Istio、CoreDNS等技术将分布式的服务做到和单体应用一致,然后通过轻量级的通讯方案,如HTTP进行交互。这种方式的优点很明显:
目前云原生的Service Mesh技术还未完全形成行业标准,相信很快随着它的落地,将迎来微服务的又一波热潮。
容错性设计,也就是为错误而设计,这一点很反直觉。
作为一名开发者,我们实现功能的思路往往是按照顺序的逻辑步骤;一个一个步骤的串联,才能保证最后的功能实现。但这个时候,如果要我们去关注各类错误的发生,小到网络波动、程序崩溃,大到机房断电,很容易无所适从。
这里,我谈谈自己的理解:主要从发生的概率与影响的严重程度来思考,不要过度追求细节。这里有一个很重要的权衡点 - **健壮性 **与 简单性 :一般来说,要保证程序足够健壮,会引入各种异常的容错性设计,增加系统的复杂度,但这一点并不是绝对的。
从系统整体功能的维度,虽然看起来增加了复杂度,但通过分层、模块化、服务拆分等方式,分而治之 - 一些简单的模块用简单的规则组合成一个大模块,可维护性远远高于一个复杂的模块。
CoreDNS
是CNCF全景图中 协调与服务发现 模块的核心项目,在Kubernetes
1.12版本之后成为了默认的DNS服务。熟悉CoreDNS
是掌握Kubernetes
必不可少的技能。
照例,我们先一起看下其核心定义,非常简洁明了:
官网 - CoreDNS: DNS and Service Discovery
CNCF - CoreDNS is a DNS server that chains plugins
今天,我们将围绕一个关键词chains plugins
- 链式插件 展开,这也是CoreDNS
实现的核心特性。
官方对这个特性的定义如下,
CoreDNS chains plugins. Each plugin performs a DNS function, such as Kubernetes service discovery, prometheus metrics, rewriting queries, or just serving from zone files. And many more.
从中不难看出,CoreDNS
将各种DNS
的功能抽象成一个插件,进行链式调用。
我们用 官方github上的Corefile 来了解这个特性:
1 | example.org:1053 { |
example.org:1053
时,依次触发 file、transfer、errors、log四个插件上面的语法与nginx
非常类似,而作者实际上是参考Caddy
软件进行设计的,有兴趣的可以查阅相关资料,例如这个 博客。
链式调用是一种表述形式非常强的语法:它以一个大众容易接受的顺序逻辑,讲述了一个完整的调用过程,将各个细节也描述地很清晰。
既然链式调用的描述方式那么棒,为什么目前没有大规模地推广到各类工具上呢?这里,我谈谈个人的三个理解:
CoreDNS
在设计之初就强制采用这种规范,没有历史包袱;同样的,Corefile这种声明方式,也或多或少带来了一些问题,例如:
5
是数字还是字符串;CoreDNS
的成功,链式调用插件 这个特性只体现了简单性的理念,并不是关键性的原因,而更多地是依赖大量开箱即用的插件。
看起来,这功能描述与CICD
流程差不多,但使用体验差距很大。在传统的模式下,我们执行的是一个具体的动作,比如扩1个应用、升级2个程序等;而在k8s里,使用者只要声明最终的预期状态,比如5个应用运行v1.0版本的程序,那么整个系统该扩容还是缩容、该升级还是回滚,都由k8s自行根据当前状态进行判断。
ab4ea1c14f669e0e42040689da7aa074c4e479f3
云原生有五大代表性的技术 - 容器、服务网格、微服务、不可变基础设施和声明式 API。相对于其余四种概念,不可变基础设施 - Immutable Infrastructure
更难理解,今天我们来一起看看。
入门可以参考这篇文章 - https://zhuanlan.zhihu.com/p/382203966
网上可搜索到的不可变基础设施定义有很多,这里我选择一个比较有代表性的:
Immutable infrastructure refers to servers (or VMs) that are never modified after deployment.
从开发者的角度来看,不可变基础设施是一个很棒的概念。如果用一个词总结它的优点,那就是 时间与空间上的一致性。
如果有一个传统应用希望改造成适配 不可变基础设施 的场景,那么会有哪些常见的改造点呢?
第二点有些抽象,这里我举三个具体的例子:
但在实际的工程中,追求 不可变基础设施 很难完全落地,我们可以适当地做一些权衡:
不难看出,只要我们保证应用在基础设施上产生的数据 可在任意时间丢失,就能实现了一定程度上 应用无状态化,也能保证了不可变基础设施的落地。
不可变基础设施是一种理念,具体落地的技术非常依赖容器或虚拟机,以及分布式存储等配套设施。我们没有必要把它作为一种技术标准去强制执行,而应该结合现状,选择性地朝着这个方向不断优化。
Github: https://github.com/Junedayday/code_reading
Blog: http://junes.tech/
Bilibili: https://space.bilibili.com/293775192
公众号: golangcoding
在2021年年底,Go
推出了1.18Beta
版本。由于正式版本没有完全敲定,普通开发人员没有必要研究到底层实现,但如果能先形成一个全局上的认知,能帮助我们领先一步。
关于1.18的核心改动,是 对泛型(Generics)的支持。Go语言的泛型语法比较简单,如下:
1 | type numeric interface { |
如果要在实际工程上落地,还有很多考量点,我这边重点提三点:
除了泛型,另外一个比较大的特性就是Fuzzy Testing
。
这个特性是为单元测试提供更全面的数据输入,这样就能覆盖更多的case,提前发现问题。关键词Fuzzy
支持的主要特性是将一个输入参数,从具体的值变成范围,如原先输入a=1
,现在支持a
输入范围为[-10,10]
。在跑单元测试时,大量的Fuzzy
肯定会带来一定的性能压力,这时可以引入一定的并发特性。
总体来说,Go1.18
对工程侧的影响更多地是提高代码的 简洁性。新特性的学习成本很低,我们不用过于急着引入,可以多花时间学习底层原理。
Go Blog - https://go.dev/blog/go1.18beta1
Medium - https://betterprogramming.pub/golang-1-18-what-you-need-to-know-a5701f7e14ab
CNCF作为云原生的代表性组织,提供了大量开源的软件,以及配套的、开箱即用的解决方案。有很多朋友对CNCF和云原生的认识可能仍停留在新闻报道里。今天,我先带大家在整体上入个门,后续选择具有代表性的软件进行分析。
由于篇幅所限,我的分享只会提重点知识,帮大家建立这部分的知识框架,更详细的内容需要大家自行学习。
CNCF的概览可以参考这个全景图 - https://landscape.cncf.io/,更新迭代非常频繁。其中,最核心的为下面五块:
其余还包括Kubernetes的平台提供商、Serverless、成员、认证的服务提供商等周边内容,并不在我们讨论的范围之内。但从基金会来看,它提供了一整套生态,非常有助于落地。
那么,如何认识这五块呢?其实Landscape提供了很好的图形效果,我们只要记住两点:
相信到这里,你对CNCF已经有了初步认识。
今天,给大家推荐一篇来自左耳朵耗子-陈皓的文章。
以上11点,理解会因人而异,我重点挑三个争议性比较大的聊聊,其余的内容建议大家阅读原文。
借用书中的一句话:使用最科学严谨的技术模型为主,并以不严谨的模型作为补充,也就是先紧后松。
有不少开发者在实际工程中的实践往往相反:为了追求快速落地,会希望毕其功于一役,引入所谓的“一站式解决方案”(如例子中NoSQL),但实践下来引入大量的问题,让后人叫苦不迭。
关于这个问题,我个人有三个思考:
为了缩小讨论范围,我对这里 技术债务 做一个收口:不仅仅是指有弊端的技术问题,更是需要投入时间精力等成本去维护。有技术债务,不代表就一定要去还,而需要一个契机 - 维护的成本 > 修复的收益。
举个例子,某个程序写得很烂,性能很差:
还技术债,技术能力只是一个基本,以下两点更为重要:
这个观点是很aggressive的,遇到这样的观念冲突时,决策者找不到客观标准去评估,就很难有二义性的定义:要么激进,要么保守;要么创新,要么实用。这种情况下,我遇到过的比较好的解法有两种:
第一种情况在实际工作场景中并不多见,尤其当团队规模很大时,就像CTO往往不是公司技术最强的那位。所以,我更倾向于大家多尝试第二种途径。
当然,我也遇到过很多效果不好的解法,比如说:决策者既然不清楚怎么做才好,那就找2个执行者进行battle,一个代表创新方,另一个代表保守方。也许在少数情况下,最后能帮助决策者找到正确的方向;但更多的实际场景中,会产生如下问题:
在我看来,这类决策者往往是偏管理,技术上的掌控力不足,导致在决策时没有足够的倾向性;同时,与执行者之间的信任也不足,就希望把决策这件事下移、尝试着走平衡之道。
我个人的想法是:先选择一个能力相对优秀的执行者,认真评估其方案,然后交由对方执行;最后哪怕失败了,也可以通过复盘改进,想想下次如何更好地决策,更好地把控方案;当然,如果你认为纯粹是执行者的问题,那就换个可信赖的人。
今天,我们一起来看看CNCF中的最核心项目 - Kubernetes
。Kubernetes
相关内容非常庞大,我们依旧关注聚焦于核心能力。
Kubernetes
位于CNCF核心的 调度与编排 模块,也就是整个解决方案的基石。在CNCF上的介绍为:
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.
对这个定义,我们关注两个点:
automating deployment, scaling, and management
自动化的部署、扩缩容和管理,这是k8s核心能力;containerized applications
容器化应用,这是k8s操作的基本对象;为了更好地介绍Kubernetes,我对官方首页描述中的关键特性再做一些更详细地说明:
自动化扩缩容和升级回滚。这个特性是k8s最核心的,也是大规模推广的根本原因。
看起来,这功能描述与CICD
流程差不多,但使用体验差距很大。在传统的模式下,我们执行的是一个具体的动作,比如扩1个机器、升级2个程序等;而在k8s里,使用者只要声明最终的预期状态,比如5台机器运行v1.0版本的程序,那么整个系统该扩容还是缩容、该升级还是回滚,都由k8s自行根据当前状态进行判断。
这个,就是云原生的一大特性:声明式API ,而不是传统上的命令式API。
声明式API不一定比命令式API好。在应用程序开发时,命令式API更容易理解。
服务发现与负载均衡。这个功能很大程度上减少了分布式软件运行模式的复杂性。
服务发现,以前非常依赖zookeeper
/etcd
等这类注册中心,往往需要侵入到业务代码;而负载均衡,则很依赖nginx
这类软件,并在上面做复杂配置。
当然,k8s给出的只是通用解法,对一些具备很强业务属性的服务发现与负载均衡,仍需要程序自行实现。
存储编排。存储的编排是k8s重点演进的功能。
k8s抽象了存储概念,从传统的本地存储扩展为分布式云存储,对上层应用屏蔽了存储这块的复杂度。
为扩展性而设计。
扩展性是k8s非常重视的点,无论是开放出容器、网络、存储等接口规范,还是像自定义资源(CRD)等插件的开放,都体现出了一种开放的精神,也是k8s如今能作为云原生标志性的软件的立足之本。
有一个点希望大家认识到:k8s的成功不是简单地因为开放性,更重要的是,它定义的这些开放性的规范与接口,都是Google
经过实践总结出来的经验,符合主流厂商的趋势与开发者的需求。
Github: https://github.com/Junedayday/code_reading
Blog: http://junes.tech/
Bilibili: https://space.bilibili.com/293775192
公众号: golangcoding
在讲解Kratos的过程中,我们引入了google推出的wire这个工具。我们先阅读一下官方的定义:
Wire is a code generation tool that automates connecting components using dependency injection.
从关键词入手:
我们从具体的case着手,学习wire这个工具。
作为云原生程序监控的标准组件,Prometheus支持了各类Paas、Saas平台,并提供了一整套采集+存储+展示的解决方案。
今天我们专注于自定义服务中的Prometheus的监控,在框架中引入Prometheus相关的组件。关于更细致的使用方式,我会给出相关的链接,有兴趣进一步学习Prometheus的同学可以边参考资料边实践。