go语言grpc框架实战-01-客户端和服务端双向认证,借助grpc-gateway支持grpc和http服务
创建proto中间文件
-
protobuf(protocol buffer)特点
性能高、压缩好、传输快、维护方便,一些第三方rpc库都会支持protobuf -
下载protobuf
go get google.golang.org/protobuf
注意:如果先下载grpc会默认下载protobuf
go get google.golang.org/grpc
-
安装protoc编译器,将proto文件编译成指定语言的代码文件(通用编译器)
下载网址
protoc-3.20.1-win64.zip -
下载解压后将protoc.exe所在的bin目录添加到系统环境变量当中去
E:\protoc\bin
-
安装protobuf的编译器插件protoc-gen-go,等下我们执行protoc命令时就会自动调用这个插件生成go代码
go install google.golang.org/protobuf/cmd/protoc-gen-go
-
安装goland的proto插件(goland 2022.1默认安装了grpc和proto的支持)
-
创建中间文件 hello.proto
syntax="proto3"; // 使用的proto 3的版本
package services; // 生成go文件的包名
option go_package="../services"; // 指定生成go文件所在当前文件的路径
message ProdRequest{
int32 prod_id = 1; // 传入的商品id
}
message ProdResponse{
int32 prod_stock = 1; // 商品库存
}
- 执行命令生成Prod.pb.go文件
protoc --go_out=services .\pbfiles\Prod.proto
- 文件目录
创建grpc服务并运行
- 原Prod.proto文件增加一个服务
service ProdService{ // 获取商品库存服务
rpc GetProdStock(ProdRequest) returns (ProdResponse);
}
- 生成支持grpc的Prod.pb.go文件还需要下载安装一个插件protoc-gen-go-grpc.exe
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
-
重新生成Prod.pb.go文件
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\
-
自行实现GetProdStock服务接口,在services目录创建文件:ProdService.go
package services
import (
"context"
)
type ProdService struct {
UnimplementedProdServiceServer
}
func (ProdService) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error) {
return new(ProdResponse), nil
}
- 根目录创建server.go文件
package main
import (
"google.golang.org/grpc"
"grpc_test/services"
"net"
)
func main() {
// NewServer 创建一个未注册服务且尚未开始接受请求的 gRPC 服务器。
rpcServer := grpc.NewServer()
// 将当前产品服务注册到grpc服务当中去
services.RegisterProdServiceServer(rpcServer, new(services.ProdService))
// 监听套接字
listener, _ := net.Listen("tcp", ":8080")
// grpc服务器通过传入的监听套接字接收请求,开始基于http2.0提供服务
rpcServer.Serve(listener)
}
自签证书,服务加入证书验证
使用自签ca server client证书和双向认证
客户端和服务端各自使用各自的证书,同时使用ca证书进行验签
参考文档
双向认证下rpc-gateway的使用(同时提供rpc和http接口)
- 安装
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
go mod tidy
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go install
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
- 修改我们的Prod.proto文件,增加http接口支持
syntax = "proto3"; // 使用的proto 3的版本
package services; // 生成go文件的包名
option go_package = "../services"; // 指定生成go文件所在当前文件的路径
import "google/api/annotations.proto"; // 新增加的
message ProdRequest{
int32 prod_id = 1; // 传入的商品id
}
message ProdResponse{
int32 prod_stock = 1; // 商品库存
}
service ProdService{// 获取商品库存服务
rpc GetProdStock(ProdRequest) returns (ProdResponse) {
option (google.api.http) = { // 新增加的
get : "/v1/prod/{prod_id}"
};
}
}
-
将相关的proto文件拷贝到我们的本地,如图
-
执行protoc命令,重新生成Prod.pb.go文件
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\
-
生成Prod.pb.gw.go文件
protoc --grpc-gateway_out=logtostderr=true:services .\pbfiles\Prod.proto -I .\pbfiles\
-
server.go代码提供grpc服务
点击查看代码
package main
import (
"google.golang.org/grpc"
"grpc_test/helper"
"grpc_test/services"
"net"
)
func main() {
creds := helper.GetServerCreds()
// NewServer 创建一个未注册服务且尚未开始接受请求的 gRPC 服务器。
rpcServer := grpc.NewServer(grpc.Creds(creds))
// 将当前产品服务注册到grpc服务当中去
services.RegisterProdServiceServer(rpcServer, new(services.ProdService))
// 监听套接字
listener, _ := net.Listen("tcp", ":8080")
//// grpc服务器接收请求,开始提供服务
rpcServer.Serve(listener)
}
- httpserver.go代码提供http服务
点击查看代码
package main
import (
"context"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"grpc_test/helper"
"grpc_test/services"
"log"
"net/http"
)
func main() {
gwmux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithTransportCredentials(helper.GetClientCreds())}
// endpoint: 是grpc服务器的地址
err := services.RegisterProdServiceHandlerFromEndpoint(context.Background(), gwmux, "127.0.0.1:8080", opts)
if err != nil {
log.Fatal(err.Error())
}
httpServer := http.Server{Addr: "127.0.0.1:8081", Handler: gwmux}
httpServer.ListenAndServe()
}
浏览器访问试试吧:http://127.0.0.1:8081/v1/prod/38
同时grpc客户端访问也可以,至此,借助grpc-gateway完成了同时提供grpc和http接口