目录
- 前言
- 1,关于grpc微服务
- 2,修改生成代码
- 3,相关的goframe的grpc配置
- 4,总结
前言
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/108971807
未经博主允许不得转载。
博主CSDN地址是:https://blog.csdn.net/freewebsys
博主掘金地址是:https://juejin.cn/user/585379920479288
博主知乎地址是:https://www.zhihu.com/people/freewebsystem
1,关于grpc微服务
项目参考:
https://grpc.io/docs/languages/go/quickstart/
需要protoc 工具直接进行安装即可:
# 手动安装 gf 工具:
git clone https://github.com/gogf/gf && cd gf/cmd/gf && go install
# 安装工具
sudo apt install -y protobuf-compiler
protoc --version
libprotoc 3.12.4
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
项目地址:
https://github.com/gogf/gf-demo-grpc
然后就可以执行 pb 命令啦
make pb 最后显示done! 执行成功:
$ make pb
/usr/bin/protoc --proto_path=/data/home/test/go/src/gf-demo-grpc/manifest/protobuf --go_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api --go-grpc_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api /data/home/test/go/src/gf-demo-grpc/manifest/protobuf/pbentity/user.proto
/usr/bin/protoc --proto_path=/data/home/test/go/src/gf-demo-grpc/manifest/protobuf --go_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api --go-grpc_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api /data/home/test/go/src/gf-demo-grpc/manifest/protobuf/user/v1/user.proto
done!
然后编写 proto 文件,也是特别的简单:
参考文档:
https://juejin.cn/post/6978474549025177608
user.proto
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
syntax = "proto3";
package pbentity;
option go_package = "github.com/gogf/gf-demo-grpc/api/pbentity";
import "google/protobuf/timestamp.proto";
message User {
uint32 Id = 1 ; // User ID
string Passport = 2 ; // User Passport
string Password = 3 ; // User Password
string Nickname = 4 ; // User Nickname
google.protobuf.Timestamp CreateAt = 5 ; // Created Time
google.protobuf.Timestamp UpdateAt = 6 ; // Updated Time
google.protobuf.Timestamp DeleteAt = 7 ; // Deleted Time
}
user api proto,来一个简单的,只有一个服务的方法
// protoc --go_out=plugins=grpc:. *.proto
syntax = "proto3";
package user;
option go_package = "gf-demo-grpc/api/user/v1";
service User{
rpc Create(CreateReq) returns (CreateRes) {}
}
message CreateReq {
string Passport = 1; // v: required
string Password = 2; // v: required
string Nickname = 3; // v: required
}
message CreateRes {
string Data = 1; // v: required
}
2,修改生成代码
goframe 默认会创建一个controller 类似的服务,其实是 gprc 的服务:
package user
import (
"context"
v1 "github.com/gogf/gf-demo-grpc/api/user/v1"
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
)
type Controller struct {
v1.UnimplementedUserServer
}
func Register(s *grpcx.GrpcServer) {
v1.RegisterUserServer(s.Server, &Controller{})
}
func (*Controller) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}
但是要修改下,默认grpc 直接返回了一个未实现代码的异常:
return nil, gerror.NewCode(gcode.CodeNotImplemented)
修改成:
func (*Controller) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
g.Log().Printf(ctx, `Create user get Nickname : %+v`, req.Nickname)
res = &v1.CreateRes{}
res.Data = "OK"
return res, nil
}
然后再修改下测试方法:
package test
import (
"fmt"
"testing"
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/test/gtest"
v1 "github.com/gogf/gf-demo-grpc/api/user/v1"
)
func Test_Create(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
ctx = gctx.GetInitCtx()
conn = grpcx.Client.MustNewGrpcClientConn("demo")
user = v1.NewUserClient(conn)
)
for i := 1; i <= 10; i++ {
res, err := user.Create(ctx, &v1.CreateReq{
Passport: fmt.Sprintf(`passport-%d`, i),
Nickname: fmt.Sprintf(`nickname-%d`, i),
})
if err != nil {
g.Log().Fatalf(ctx, `create user failed: %+v`, err)
} else {
g.Log().Printf(ctx, `create user success : %+v`, res.Data)
}
}
})
}
执行 10 次:
结果:
2023-06-06 11:44:26.456 {003338c60bf5651781952122252686fb} create user success : OK
可以获得 grpc 返回的 data 数据。
也可以通过直连的方式请求数据:
host := "localhost:8000"
ctx := gctx.GetInitCtx()
conn, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials()) )
g.Log().Print(ctx, `create ChatMessage response `, err)
user = v1.NewUserClient(conn)
为啥会想直连的方式呢,因为有可能需要在外网给别人提供服务呢。
同时可以使用nginx做负载均衡即可,直接使用grpc_pass 反向代理,和代理其他服务类似。
其他参考:https://juejin.cn/post/7179907227031994405
upstream grpc_servers {
server 192.168.1.101:8000;
server 192.168.1.102:8000;
}
location / {
grpc_pass grpc://grpc_servers:8000;
}
3,相关的goframe的grpc配置
配置参考:
https://goframe.org/pages/viewpage.action?pageId=80488218
其中的 config.yaml 配置:
# GRPC Server.
#
grpc:
address: ":8000" # 自定义服务监听地址
name: "demo"
logPath: ""
logStdout: true
errorStack: true
errorLogEnabled: true
errorLogPattern: "error-{Ymd}.log"
accessLogEnabled: true
accessLogPattern: "access-{Ymd}.log"
然后在 main 中启动了服务:
package main
import (
"github.com/gogf/gf-demo-grpc/internal/controller/user"
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
)
func main() {
// cmd.Main.Run(gctx.New())
s := grpcx.Server.New()
user.Register(s)
s.Run()
}
4,总结
grpc 的服务确实比其他服务开发麻烦一点点。
主要是proto工具的安装和配置。
但是掌握了之后就发现也是非常的方便的,同时可以支持多种语言的互相调用。
同时有了goframe 的工具集成,更容易了,直接帮忙把配置服务。
都帮忙写了,剩下就可以去编写业务逻辑了,非常方便。值得推荐。
本文的原文连接是:
https://blog.csdn.net/freewebsys/article/details/108971807