- Added package.json to manage development scripts. - Updated restart-services.ps1 to call the new dev script for starting services. - Refactored start-admin.ps1, start-backend.ps1, start-frontend.ps1, and start-mcp.ps1 to utilize the dev script for starting respective services. - Enhanced stop-services.ps1 to improve process termination logic by matching command patterns.
174 lines
4.0 KiB
Markdown
174 lines
4.0 KiB
Markdown
---
|
||
title: "Go使用gRPC进行通信"
|
||
description: RPC是远程过程调用的简称,是分布式系统中不同节点间流行的通信方式。
|
||
date: 2022-05-26T14:17:33+08:00
|
||
draft: false
|
||
slug: go-grpc
|
||
image:
|
||
categories:
|
||
- Go
|
||
tags:
|
||
- Go
|
||
- gRPC
|
||
---
|
||
|
||
# 安装`gRPC`和`Protoc`
|
||
|
||
## 安装`protobuf`
|
||
|
||
```bash
|
||
go get -u google.golang.org/protobuf
|
||
go get -u google.golang.org/protobuf/proto
|
||
go get -u google.golang.org/protobuf/protoc-gen-go
|
||
```
|
||
|
||
|
||
|
||
## 安装`Protoc`
|
||
|
||
```shell
|
||
# 下载二进制文件并添加至环境变量
|
||
https://github.com/protocolbuffers/protobuf/releases
|
||
```
|
||
|
||
安装`Protoc`插件`protoc-gen-go`
|
||
|
||
```shell
|
||
# go install 会自动编译项目并添加至环境变量中
|
||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||
```
|
||
|
||
```shell
|
||
#protoc-gen-go 文档地址
|
||
https://developers.google.com/protocol-buffers/docs/reference/go-generated
|
||
```
|
||
|
||
# 创建`proto`文件并定义服务
|
||
|
||
## 新建 `task.proto`文件
|
||
|
||
```shell
|
||
touch task.proto
|
||
```
|
||
|
||
## 编写`task.proto`
|
||
|
||
```protobuf
|
||
// 指定proto版本
|
||
syntax = "proto3";
|
||
// 指定包名
|
||
package task;
|
||
// 指定输出 go 语言的源码到哪个目录和 包名
|
||
// 主要 目录和包名用 ; 隔开
|
||
// 将在当前目录生成 task.pb.go
|
||
// 也可以只填写 "./",会生成的包名会变成 "----"
|
||
option go_package = "./;task";
|
||
|
||
// 指定RPC的服务名
|
||
service TaskService {
|
||
// 调用 AddTaskCompletion 方法
|
||
rpc AddTaskCompletion(request) returns (response);
|
||
}
|
||
|
||
// RPC TaskService服务,AddTaskCompletion函数的请求参数,即消息
|
||
message request {
|
||
uint32 id = 1;//任务id
|
||
string module = 2;//所属模块
|
||
int32 value = 3;//此次完成值
|
||
string guid = 4;//用户id
|
||
}
|
||
// RPC TaskService服务,TaskService函数的返回值,即消息
|
||
message response{
|
||
|
||
}
|
||
```
|
||
|
||
## 使用`Protoc`来生成Go代码
|
||
|
||
```bash
|
||
protoc --go_out=. --go-grpc_out=. <要进行生成代码的文件>.proto
|
||
# example
|
||
protoc --go_out=. --go-grpc_out=. .\task.proto
|
||
```
|
||
|
||
这样生成会生成两个`.go`文件,一个是对应消息`task.pb.go`,一个对应服务接口`task_grpc.pb.go`。
|
||
|
||
在`task_grpc.pb.go`中,在我们定义的服务接口中,多增加了一个私有的接口方法:
|
||
`mustEmbedUnimplementedTaskServiceServer()`
|
||
|
||
# 使用`Go`监听`gRPC`服务端及客户端
|
||
|
||
## 监听服务端
|
||
|
||
并有生成的一个`UnimplementedTaskServiceServer`结构体来实现了所有的服务接口。因此,在我们自己实现的服务类中,需要继承这个结构体,如:
|
||
|
||
```go
|
||
// 用于实现grpc服务 TaskServiceServer 接口
|
||
type TaskServiceImpl struct {
|
||
// 需要继承结构体 UnimplementedServiceServer 或mustEmbedUnimplementedTaskServiceServer
|
||
task.mustEmbedUnimplementedTaskServiceServer()
|
||
}
|
||
|
||
func main() {
|
||
// 创建Grpc服务
|
||
// 创建tcp连接
|
||
listener, err := net.Listen("tcp", ":8082")
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
// 创建grpc服务
|
||
grpcServer := grpc.NewServer()
|
||
// 此函数在task.pb.go中,自动生成
|
||
task.RegisterTaskServiceServer(grpcServer, &TaskServiceImpl{})
|
||
// 在grpc服务上注册反射服务
|
||
reflection.Register(grpcServer)
|
||
// 启动grpc服务
|
||
err = grpcServer.Serve(listener)
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
|
||
}
|
||
|
||
func (s *TaskServiceImpl) AddTaskCompletion(ctx context.Context, in *task.Request) (*task.Response, error) {
|
||
fmt.Println("收到一个Grpc 请求, 请求参数为", in.Guid)
|
||
r := &task.Response{
|
||
}
|
||
return r, nil
|
||
}
|
||
|
||
```
|
||
|
||
然后在`TaskService`上实现我们的服务接口。
|
||
|
||
|
||
## 客户端
|
||
|
||
```go
|
||
conn, err := grpc.Dial("127.0.0.1:8082", grpc.WithInsecure())
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
defer conn.Close()
|
||
// 创建grpc客户端
|
||
client := task.NewTaskServiceClient(conn)
|
||
// 创建请求
|
||
req := &task.Request{
|
||
Id: 1,
|
||
Module: "test",
|
||
Value: 3,
|
||
Guid: "test",
|
||
}
|
||
// 调用rpc TaskService AddTaskCompletion函数
|
||
response, err := client.AddTaskCompletion(context.Background(), req)
|
||
if err != nil {
|
||
log.Println(err)
|
||
return
|
||
}
|
||
log.Println(response)
|
||
```
|
||
|
||
[本文参考](https://www.cnblogs.com/whuanle/p/14588031.html)
|