采用go-micro,gin,etcd完成微服务开发
1.介绍
- Go Micro 是一个分布式系统开发框架。Go Micro 提供了分布式系统开发的核心需求,包括 RPC 和事件驱动的通信。Gin 是一个用 Golang 编写的 web 框架。etcd 是一个开源的分布式键值存储系统,用于可靠地存储分布式系统中的关键数据。通过Gin作为微服务的网关,通过etcd服务注册,完成各个子组件的调用
2.环境准备
- 安装 go1.20.4
- 安装 protoc、protoc-gen-go 和 protoc-gen-micro
- 安装 etcd并启动
3.编写proto文件
- 采用protoc --micro_out=. --go_out=:. .proto命令生成.pb.go和*.pb.micro.go文件
syntax = "proto3";
package user;
option go_package = "../user";
service UserService {
rpc GetUser (UserRequest) returns (Response) {}
}
message UserRequest{
int64 page = 1;
int64 size = 2;
}
message Response {
int32 code = 1;
bytes data = 2;
}
4.完成RPC服务代码的编写
- 编写UserServiceHandler的实现结构体,需要实现GetUser方法(备注:UserServiceHandler是通过protoc命令自动生成的)
- 将rpc服务注册到etcd中并返回服务器实例
- 调用RegisterUserServiceHandler函数将UserServiceHandler的实现结构体注册到服务器实例中
- 调用服务器实例的Run函数完成服务的启动
handler.go
type User struct {
dao dao.Dao //数据库实例
}
func NewUserHandler(d dao.Dao) *User {
return &User{dao: d}
}
func (u User) GetUser(ctx context.Context, request *user.UserRequest, response *user.Response) error {
return nil
}
main.go
package main
import (
"github.com/go-micro/plugins/v4/registry/etcd"
"go-micro.dev/v4"
"go-micro.dev/v4/registry"
"study/go_micro_test/proto/user"
"study/go_micro_test/user-srv/handler"
)
func main() {
userHandler := handler.NewUserHandler(daoAll)
// 使用etcd作为默认注册中心
etcdRegistry := etcd.NewRegistry(func(opt *registry.Options) {
opt.Addrs = []string{"etcd服务地址+端口号"}
})
// 创建服务,除了服务名,其它选项可加可不加,比如Version版本号、Metadata元数据等
srv := micro.NewService(
micro.Name("user"),
micro.Version("latest"),
micro.Registry(etcdRegistry), // 使用etcd注册中心
)
err := user.RegisterUserServiceHandler(srv.Server(), userHandler)
if err != nil {
return
}
err = srv.Run()
if err != nil {
return
}
}
1.编写网关服务
- 实例化gin服务
- 实例化所有路由
- 创建服务端实例并进行实例化
- 初始化所有的rpc服务便于后续直接调用,这里采用的是go-micro.dev/v4/client
- 将gin服务绑定到服务端实例中
- 启动服务端实例
main.go
package main
import (
"context"
"github.com/gin-gonic/gin"
"github.com/go-micro/plugins/v4/registry/etcd"
"go-micro.dev/v4/registry"
"go-micro.dev/v4/web"
"study/go_micro_test/api-gateway/handler/api/user"
"study/go_micro_test/api-gateway/router"
"study/go_micro_test/api-gateway/rpc"
)
func Router(router gin.IRouter) {
root := router.Group("/test")
UserRouter(root)
}
func UserRouter(root *gin.RouterGroup) {
local := root.Group("/user")
local.GET("/getUser", GetUser)
}
func GetUser(ctx *gin.Context) {
rpc.UserClient.GetUser(context.Background(), &user.UserRequest{Page: page, Size: size})
}
func main() {
engine := gin.Default()
Router(engine)
etcdRegistry := etcd.NewRegistry(func(opt *registry.Options) {
opt.Addrs = []string{"127.0.0.1:2379"}
})
webService := web.NewService(
web.Name("web"),
web.Address(":8080"),
web.Registry(etcdRegistry),
)
err := webService.Init()
if err != nil {
return
}
rpc.InitClients()
webService.Handle("/", engine)
err = webService.Run()
if err != nil {
return
}
}
client.go
package rpc
import (
"go-micro.dev/v4/client"
"study/go_micro_test/proto/user"
)
var UserClient user.UserService
func InitClients() {
cl := client.DefaultClient
UserClient = user.NewUserService("user", cl)
}