基础介绍
微服务是一种分布式系统架构,它将一个大型的单体应用拆分为多个互相协作的小型服务,每个服务都有自己的职责、数据和通信方式。
Go 语言是一种高性能、简洁、易用的编程语言,它具有原生的并发支持、跨平台编译、丰富的标准库和工具链等特点,非常适合开发微服务。
考虑因素
用 Go 实现微服务的良好架构需要考虑以下几个方面:
- 服务拆分:根据业务领域、功能模块、数据隔离等原则,将单体应用拆分为多个独立的微服务,每个微服务都有自己的代码仓库、部署单元和运行时环境。
- 服务通信:选择合适的通信协议和方式,如 HTTP/RESTful、gRPC/Protobuf、MQ/Event 等,实现服务间的高效、可靠、安全的数据交换。
- 服务监控:采用 Prometheus/Grafana 等工具,收集和展示服务的各项指标,如响应时间、错误率、资源利用率等,及时发现和解决问题。
实现框架
用 Go 实现微服务的良好架构还可以借助一些成熟的框架和工具,如 lstio, Go-kit, Go-zero, Kratos, Go-micro 等,它们提供了丰富的功能和组件,可以快速搭建和管理微服务。
- Istio 是一个开源的服务网格,它可以透明地覆盖在现有的分布式应用上,提供统一和高效的方式来保障、连接和监控服务。 Istio 可以实现负载均衡、服务间的认证和监控等功能,而无需修改应用代码。Istio 还可以简化部署的复杂性,它使用了扩展版的 Envoy 作为数据平台,Envoy 管理了 Istio 服务网格中的所有入站和出站流量。
- Go-kit 是一个用于构建微服务的编程工具包,它解决了分布式系统开发中的常见问题和应用框架方面的挑战,让您可以专注于提供业务价值。
- Go-zero 是一个基于 Go 语言的微服务框架,它内置了许多工程实践,旨在确保繁忙服务的稳定性,并且已经为数千万用户提供了服务。Go-zero 包含了一个简洁的 API 描述语法和代码生成工具 goctl。
- Kratos 是一个基于 Go 语言的微服务框架,它提供了一套完整的解决方案,包括 API 定义、代码生成、服务治理、配置管理、日志追踪等功能,让您可以快速地开发高质量的微服务。Kratos 的设计原则是保持简洁、高可用、高并发、易扩展、故障导向编程、业务逻辑开发友好。
- Go-micro 是一个用于分布式系统开发的框架,它提供了 RPC 和事件驱动通信等核心需求。Go-micro 还抽象了分布式系统的细节,提供了如身份验证、负载均衡、故障转移、同步和异步通信等的主要特征。
基本流程
以 go-micro 为例,用 go-micro 构建一个微服务的流程一般包括如下的步骤:
- 安装工具和依赖,包括 protoc, protoc-gen-go, protoc-gen-micro 等,用于生成 protobuf 和 go-micro 的代码。
- 使用 micro new 的命令创建一个基本的微服务项目,它包含了一些模板文件和目录结构。
- 根据业务需求修改 proto 文件中定义的服务和消息,并在 handler 和 subscriber 目录中实现相应的逻辑。
- 最后,使用 go run main.go 或者 make run 命令运行微服务并使用 micro call 或者自定义的客户端程序调用它。
下面是一个简单的样例,它实现了一个 Greeter 服务,用于向客户端返回问候语。首先,我们创建一个 greet.proto 文件,定义 Greeter 服务和 Request 和 Response 消息:
syntax = "proto3";
package greet;
service Greeter {
rpc Greet(Request) returns (Response) {}
}
message Request {
string name = 1;
}
message Response {
string msg = 1;
}
然后,我们使用 protoc 命令生成对应的 go-micro 代码:
protoc --proto_path=. --micro_out=. --go_out=. greet.proto
这会在当前目录下生成 greet.pd.go 和 greet.pb.micro.go 两个文件。接下来,我们在 handler 目录下创建一个 greeter.go 文件,实现 Greeter 服务的 Greet 方法:
package handler
type Greeter struct{}
func (g *Greeter) Greet(ctx context.Context, req *greet.Request, rsp *greet.Response) error {
log.Info("Received Greeter.Greet request")
rsp.Msg = fmt.Sprintf("Hello %s", req.Name)
return nil
}
最后,我们在 main.go 文件中注册 Greeter 服务并启用它:
package main
func main() {
service := micro.NewService(
micro.Name("go.micro.service.greeter"),
micro.Version("latest"),
)
service.Init()
greet.RegisterGreeterHandler(service.Server(), new(handler.Greeter))
if err := service.Run(); err != nil {
log.Fatal(err)
}
}
运行 go run main.go 命令后,我们就可以看到 Greeter 服务已经启动,并注册到了默认的 consul 注册中心。我们可以使用 micro call 命令调用 Greeter 服务的的 Greet 方法:
micro call go.micro.service.greeter Greeter.Greet '{"name": "Bing"}'
{
"msg": "Hello Bing"
}
多微服务
以上实例仅呈现了单一微服务的实现,当我们有多个微服务需要使用,并且各个微服务互相都是可见的,这就涉及到了微服务的注册和发现的问题。
- 首先,我们需要使用 go-micro 框架来创建和注册各个微服务,每个微服务都需要有一个唯一的名称和地址,以便于被发现和调用。
- 其次,使用 consul 或者其他支持的注册中心来存储和管理我们的微服务信息,包括名称、地址、版本、元数据等等。
- 然后,借助 go-micro 的 client 和 selector 接口来发现和调用其他微服务,client 接口提供欧尼了高级别的请求/响应和通知功能,selector 接口提供了负载均衡和故障转移功能。
- 最后,利用 go-micro 的 codec 和 transport 接口来编解码和传输信息,codec 接口支持多种数据格式,如 protobuf, json, msgpack 等,transport 接口支持多种通信协议,如 HTTP, gRPC, NATS 等等。