在搭建环境的时候其实我就有很多疑问了,怎么有这么多概念?
微服务、RPC, gRPC, protoc等等,它们都是啥?本篇文章来进行比较详细的解释。
本文围绕 2020 年的 Go Micro v2 整理概念。下面的接口和默认组件属于当时的记录,不同版本可能变化;使用时请以项目固定版本的 v2 API 文档 为准。
微服务
使用一套小服务来开发单个应用的方式,每个服务运行在独立的进程里,一般采用轻量级的通讯机制互联,并且它们可以通过自动化的方式部署。
RPC
- 远程过程调用(Remote Procedure Call,RPC)是一个计算机通信协议
- 该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程
- 如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用
gRPC
- gRPC由google开发,是一款语言中立、平台中立、开源的远程过程调用系统
- gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用
protobuff
- gRPC可以实现微服务,将大的项目拆分为多个小且独立的业务模块,也就是服务,各服务间使用高效的protobuf协议进行RPC调用,gRPC默认使用protocol buffer,这是google开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如JSON)
- 可以用proto files创建gRPC服务,用message类型来定义方法参数和返回类型
个人理解
结合这里和我们上一篇的文章,我们可以得到以下结论
- 我们是使用了proto file(user.proto)来定义对应的方法和返回类型,其中message结构来定义接收参数和返回参数的名称以及类型。 service结构来定义对应的远程调用的方法和接受的对应的参数。
1 | syntax = "proto3"; |
- protoc命令会按照proto文件中声明的message的格式构造传输对象。gRPC的服务器端和客户端都遵守protocal buffer协议,在客户端会序列化请求对象,在服务端反序列化请求对象,服务器端处理完成之后,序列化响应对象,客户端再反序列化响应对象。所以共同遵守protocal buff 协议让客户端和服务器端可以方便地进行通信,即使最后客户端和服务器端是用不同的语言来实现的也没有关系。
protobuf语法
简单介绍
- 以.proto结尾
- Message命名采用驼峰命名方式,字段命名采用小写字母加下划线分隔方式
- 结构定义可以包含:message、service、enum
- 这里使用 proto3:不支持 proto2 的 required 和自定义
[default = ...]。未设置的普通数值字段默认为 0,字符串为空串;业务默认值要在应用中处理。前文 protoc 3.11.4 的示例不使用 optional,较新 proto3 对 optional 的支持需按编译器版本确认。
1 | syntax = "proto3"; // |
更多使用方式可以参见 Proto3 官方语法指南,也可以阅读下面的参考文章,但要区分 proto2 和 proto3。
参考链接
Go-micro
什么是go-micro
go-micro是一个框架,提供了分布式开发所需要的核心需求,包括RPC和基于事件驱动的通信。设计理念是可插拔。
Go-micro特点
- 服务发现:自动服务注册和命名解析。服务发现是微服务开发中的核心,当服务A要与服务B协作时,它得知道服务B在哪里。目前默认的服务发现机制是组播multicast DNS (mdns,组播),是一种零配置网络。
- 负载均衡:在服务发现的基础上构建客户端的负载均衡。当我们查找一个服务发现它有多个节点时,我们需要一种机制来决定最终路由到哪一个节点。默认使用random hashed load balancing来提供服务的负载均衡。如果出现问题,那么go-micro会尝试使用其他节点。
- 消息编码:基于内容类型动态编码消息,客户端和服务器端将会使用基于内容类型的编解码器来对Go语言的类型进行无缝隙的编解码。客户端可以编码并发送各种类型额消息,客户端和服务器端默认能够处理这些消息,默认包含 protobuf and json。
- 请求/相应:RPC通信是基于双向信息流的请求和相应。go-micro提供一种同步的抽象。一个发送给服务的请求会被自动的解析、负载均衡、拨号、转成字节流。默认传输是通过gRPC。
- 异步信息:发布订阅机制在异步通信和事件驱动架构中非常重要,事件通知在微服务开发中占有重要地位。默认的消息传递系统是http事件消息代理。
- 可插拔:Go Micro为各个组件定义了接口,只要实现相应的接口,就可以替换内部的技术实现。更多插件请参考 Go Micro 插件仓库,其中包含多个大版本,本文的 v2 项目需要选择对应版本的目录和使用说明。
go-micro通信流程
- Server监听客户端的调用,对Brocker推送过来的信息进行处理。并且Server端需要向Register注册自己的存在或消亡,这样Client才能知道自己的状态
- Register服务的注册的发现,Client端从Register中得到Server的信息,然后每次调用都根据算法选择一个的Server进行通信,当然通信是要经过编码/解码,选择传输协议等一系列过程的
- 如果有需要通知所有的Server端可以使用Brocker进行信息的推送,Brocker 信息队列进行信息的接收和发布
go-micro接口
go-micro之所以可以高度订制和他的框架结构是分不开的,go-micro由8个关键的interface组成,每一个interface都可以根据自己的需求重新实现,这8个主要的inteface也构成了go-micro的框架结构

go-micro 接口详解
Transort通信接口
通信相关接口
1 | type Socket interface { |
Codec编码接口
编解码,底层也是protobuf
1 | type Codec interface { |
1.1.3. Registry注册接口
服务注册发现的实现:etcd、consul、mdns、kube-DNS、zk
1 | type Registry interface { |
Selector负载均衡
根据不同算法请求主机列表
1 | type Selector interface { |
Broker发布订阅接口
pull push watch
1 | type Broker interface { |
Client客户端接口
1 | type Client interface { |
Server服务端接口
1 | type Server interface { |
Serveice接口
1 | type Service interface { |
总结
看了上面那么多概念,我们可以稍微做一下梳理和总结。
- 我们对业务需求进行梳理划分,分解一个一个的单一职责的任务,我们分别通过一个微服务来实现对应的任务。
- go-micro是一个可以用来实现微服务的框架,设计理念是可插拔,什么意思呢,就是组件可以随时替换,有多种实现方式。go-micro的整理设计逻辑如下图所示。

- 微服务在实现过程中是有一定的技术要求的。
- 服务注册与发现:用户想调用一个服务,必须首先找到这个服务,所以对于一个服务而言,就必须在开启时要进行注册,go-micro让Registry来负责这个任务,而Registry有多种实现方式,可以参见下表,而我们搭建环境的时候就用的etcd。
- 要进行负载均衡。用户在找同一个服务的时候可能会有多个节点实现这个服务,所以需要根据相应的负载均衡机制进行节点选择。这部分就由Selector来负责。
- 要进行消息编解码,不同的service在调用的时候是需要传递数据的,数据在编码和解码上要有统一的规则,从而进行序列化和反序列化。编解码支持json和protobuff。这部分的编解码工作由Codec来负责。我们在用go-micro编写微服务时,我们会按照protobuf的语法来编写proto file,然后通过protoc,protoc-gen-go,protoc-gen-mico来生成对应的消息对象以及相应服务的API.
- 要进行通信:这部分由transort来负责。
- Broker主要对异步信息进行处理
4.这几部分具体有哪些实现呢?可以看Go Micro plugins这个库中的插件集合,下面按接口类型列出了一些例子。
| Directory | Description |
|---|---|
| Broker | PubSub messaging; NATS, NSQ, RabbitMQ, Kafka |
| Client | RPC Clients; gRPC, HTTP |
| Codec | Message Encoding; BSON, Mercury |
| Micro | Micro Toolkit Plugins |
| Registry | Service Discovery; Etcd, Gossip, NATS |
| Selector | Load balancing; Label, Cache, Static |
| Server | RPC Servers; gRPC, HTTP |
| Transport | Bidirectional Streaming; NATS, RabbitMQ |
| Wrapper | Middleware; Circuit Breakers, Rate Limiting, Tracing, Monitoring |
- 对我们而言如何使用go-micro呢?
- 根据服务需求来写好proto file
- 根据proto file 生成对应的传输对象以及服务端和客户端的api
- 编写服务器端和客户端代码
- 执行服务器端和客户端代码
最后,我们可以通过命令行参数、环境变量或代码配置,选择各个接口使用的组件。具体方式可以查看Go Micro 插件使用说明。