Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
dapeng committed Jun 19, 2024
1 parent 361dc1c commit 45cd26e
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 3 deletions.
5 changes: 4 additions & 1 deletion docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,11 @@ module.exports = {
text: '分布式锁 + 分布式缓存',
link: '/zh/guide/redis',
}, {
text: 'cron 格式的任务',
text: '配置定时任务',
link: '/zh/guide/schedule.md',
}, {
text: '使用gRPC',
link: '/zh/guide/grpc.md',
}],
}, {
text: "效率提升",
Expand Down
2 changes: 1 addition & 1 deletion docs/zh/goners/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ next: ../
|redis|封装`github.com/gomodule/redigo/redis`,用于操作redis,提供redis缓存和redis分布式锁的功能|[利用redis提供分布式锁和分布式缓存](../guide/redis.md)|
|schedule|封装`github.com/robfig/cron/v3`,提供定时任务的能力|[用cron表达式配置定时任务](https://goner.fun/zh/guide/schedule.html)|
|urllib|封装`github.com/imroc/req/v3`,提供http调用能力|-|
|grpc|提供开发grpc服务端和客户端的能力|-|
|grpc|提供开发grpc服务端和客户端的能力|[使用gRPC](https://goner.fun/zh/guide/grpc.html)|
|cmux|封装`github.com/soheilhy/cmux`,是统一端口可以提供混合服务的能力|-|
|zap|封装`go.uber.org/zap`,实现`gone.Logger`日志接口,可以替换`logrus`实现更高效的日志输出|-|
|viper|封装`github.com/spf13/viper`,用于替换配置接口默认实现,可以支持丰富的配置文件格式|-|
Expand Down
208 changes: 208 additions & 0 deletions docs/zh/guide/grpc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
---
sidebar: auto
prev: ./schedule
next: ./auto-gen-priest
---

# 使用gRPC
首先创建一个grpc目录,在这个目录中初始化一个golang mod:
```bash
mkdir grpc
cd grpc
go mod init grpc
```

## 编写proto文件,生成golang代码
- 编写协议文件
定义一个简单的Hello服务,包含一个Say方法
文件名:proto/hello.proto
```proto
syntax = "proto3";
option go_package="/proto";
package Business;
service Hello {
rpc Say (SayRequest) returns (SayResponse);
}
message SayResponse {
string Message = 1;
}
message SayRequest {
string Name = 1;
}
```
- 生成golang代码

```bash
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/hello.proto
```
> 其中,protoc的安装参考[Protocol Buffer 编译器安装](https://blog.csdn.net/waitdeng/article/details/139248507)

## 编写服务端代码
文件名:server/main.go
```go
package main

import (
"context"
"github.com/gone-io/gone"
"github.com/gone-io/gone/goner"
"github.com/gone-io/gone/goner/cmux"
"google.golang.org/grpc"
"grpc/proto"
"log"
)

type server struct {
gone.Flag
proto.UnimplementedHelloServer // 嵌入UnimplementedHelloServer
}

// 重载协议中定义的服务
func (s *server) Say(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
log.Printf("Received: %v", in.GetName())
return &proto.SayResponse{Message: "Hello " + in.GetName()}, nil
}

// 实现 gone_grpc.Service接口的RegisterGrpcServer方法,该方法在服务器启动时会被自动调用
func (s *server) RegisterGrpcServer(server *grpc.Server) {
proto.RegisterHelloServer(server, s)
}

func main() {
gone.
Prepare(func(cemetery gone.Cemetery) error {
_ = cmux.Priest(cemetery) // 注册cmux,可以让gRPC服务 和 HTTP服务共享一个端口

_ = goner.GrpcServerPriest(cemetery) // 注册gRPC服务器

cemetery.Bury(&server{}) // 注册gRPC服务
return nil
}).
// 启动服务
Serve()
}
```

## 注册客户端
文件名:client/main.go
```go
package main

import (
"context"
"fmt"
"github.com/gone-io/gone"
"github.com/gone-io/gone/goner"
"google.golang.org/grpc"
"grpc/proto"
"log"
)

type helloClient struct {
gone.Flag
proto.HelloClient // 嵌入HelloClient

host string `gone:"config,server.host"`
port string `gone:"config,server.port"`
}

// 实现 gone_grpc.Client接口的Address方法,该方法在客户端启动时会被自动调用
// 该方法的作用是告诉客户端gRPC服务的地址
func (c *helloClient) Address() string {
return fmt.Sprintf("%s:%s", c.host, c.port)
}

// 实现 gone_grpc.Client接口的Stub方法,该方法在客户端启动时会被自动调用
// 在该方法中,完成 HelloClient的初始化
func (c *helloClient) Stub(conn *grpc.ClientConn) {
c.HelloClient = proto.NewHelloClient(conn)
}

func main() {
gone.
Prepare(func(cemetery gone.Cemetery) error {
_ = goner.GrpcClientPriest(cemetery) // 注册gRPC客户端注册器Goner

cemetery.Bury(&helloClient{}) //注册我们的实现的helloClient
return nil
}).
Run(func(in struct {
hello *helloClient `gone:"*"`// 在Run方法的参数中,注入 helloClient
}) {
// 调用Say方法,给服务段发送消息
say, err := in.hello.Say(context.Background(), &proto.SayRequest{Name: "gone"})
if err != nil {
log.Printf("er:%v", err)
return
}
log.Printf("say result: %s", say.Message)
})
}
```

## 编写配置文件
文件名:config/default.properties
```properties
# 设置grpc服务的端口和host
server.port=9001
server.host=127.0.0.1

# 设置客户端使用的grpc服务端口和host
server.grpc.port=${server.port}
server.grpc.host=${server.host}
```


## 测试
- 先运行服务端:
```bash
go run server/main.go
```
程序等待请求,屏幕打印内容:
```log
2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:84||Register gRPC service *main.server
2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:88||gRPC server now listen at 127.0.0.1:9001
```

- 然后,另外开窗口启动客户端:
```bash
go run client/main.go
```
程序执行完退出,屏幕打印内容如下:
```log
2024-06-19 22:06:20.713|INFO|/Users/jim/works/gone-io/gone/goner/grpc/client.go:59||register gRPC client *main.helloClient on address 127.0.0.1:9001
2024/06/19 22:06:20 say result: Hello gone
```

- 回到服务端窗口,可以看到服务器接收到请求,新打印一行日志:
```log
2024/06/19 22:06:08 Received: gone
```

## 总结
在Gone中使用gRPC,需要完成以下几步:
- 编写服务端
1. 编写服务端Goner,匿名嵌入proto协议生成代码的 默认实现
2. 重载proto文件中定义的接口方法,编写提供服务的具体业务逻辑
3. 实现`gone_grpc.Service`接口的`RegisterGrpcServer`方法,在该方法中完成服务注册
4. 将 服务端Goner 注册到 Gone框架
5. 启动服务

- 编写客户端
1. 编写客户端Goner,嵌入proto协议生成代码的客户端接口
2. 实现`gone_grpc.Client`接口的`Address``Stub`方法,`Address`方法返回服务端地址,`Stub`初始化客服端接口
3. 将 客户端Goner 注册到 Gone框架
4. 启动客户端,调用客服端接口方法

本文的代码开源在 [Gone-io/grpc](https://github.com/gone-io/gone/tree/main/example/grpc)
2 changes: 1 addition & 1 deletion docs/zh/guide/schedule.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
sidebar: auto
prev: ./redis
next: ./auto-gen-priest
next: ./grpc
---

# 用cron表达式配置定时任务
Expand Down

0 comments on commit 45cd26e

Please sign in to comment.