创建proto中间文件
go get google.golang.org/protobufgo get google.golang.org/grpcE:\protoc\bingo install google.golang.org/protobuf/cmd/protoc-gen-go
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; // 商品库存
}
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
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\
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}"
};
}
}
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\protoc --grpc-gateway_out=logtostderr=true:services .\pbfiles\Prod.proto -I .\pbfiles\
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接口