golang示例
server
package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
com "xxx.site/myself/grpc-common"
)
var (
GitHash = "Unkown"
CompileTime = "Unkown"
port = flag.Int("port", 8411, "默认端口")
)
// 定义服务端中间件
func middleware(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
log.Printf("middleware ctx:%v", ctx)
log.Printf("middleware req:%v", req)
log.Printf("middleware info:%v", info)
log.Printf("middleware handler:%v", handler)
resp, err = handler(ctx, req)
log.Printf("middleware resp:%v", resp)
log.Printf("middleware err:%v", err)
return
}
type MathServer struct {
com.UnimplementedMathServer
}
// 各种信息都通过ctx中valueCtx传递进来
// 由不同包获取转换
func (ms *MathServer) Add(ctx context.Context, req *com.AddReq) (*com.AddRsp, error) {
log.Printf("ctx:%v, req:%v", ctx, req)
if client, ok := peer.FromContext(ctx); ok {
log.Printf("client:%v", client)
}
if ic, ok := metadata.FromIncomingContext(ctx); ok {
log.Printf("ic:%v", ic)
}
if oc, ok := metadata.FromOutgoingContext(ctx); ok {
log.Printf("oc:%v", oc)
}
if oc, ok := metadata.FromOutgoingContext(ctx); ok {
log.Printf("oc:%v", oc)
}
sts := grpc.ServerTransportStreamFromContext(ctx)
log.Printf("sts:%v", sts)
return &com.AddRsp{
Result: req.Left + req.Right,
}, nil
}
func main() {
flag.Parse()
// ct, err := credentials.NewServerTLSFromFile(
// "grpc.xxx.site.pem",
// "grpc.xxx.site.key",
// )
// if err != nil {
// log.Fatalf("tls file;%v", err)
// }
// tcp表示优先使用ipv6,其次ipv4,两者都能用
l, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalf("fail listen tcp %d", *port)
}
// 安装中间件
s := grpc.NewServer(
// 默认没有采用安全传输ssl,tls
// 增加证书认证
//grpc.Creds(ct),
grpc.UnaryInterceptor(middleware),
)
com.RegisterMathServer(s, &MathServer{})
log.Printf(
"githash:%v, compile:%v,listen:%v",
GitHash,
CompileTime,
l.Addr())
err = s.Serve(l)
if err != nil {
log.Fatalf("fail server:%v", err)
}
}
client
package main
import (
"context"
"flag"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
com "xxx.site/myself/grpc-common"
)
var (
GitHash = "unknown"
CompileTime = "unknown"
// addr = flag.String("addr", "dns:///grpc.xxx.site", "默认服务端端口")
addr = flag.String("addr", "127.0.0.1:8411", "默认服务端端口")
)
// 定义客户端中间件
func middleware(ctx context.Context, method string,
req, reply interface{}, c *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
log.Printf("middleware ctx:%v", ctx)
log.Printf("middleware method:%v", method)
log.Printf("middleware req:%v", req)
log.Printf("middleware reply:%v", reply)
log.Printf("middleware conn:%v", c)
log.Printf("middleware invoker:%v", invoker)
for pos, opt := range opts {
log.Printf("middleware pos:%v, opt:%v", pos, opt)
}
err := invoker(ctx, method, req, reply, c, opts...)
log.Printf("middleware err:%v", err)
return err
}
func main() {
flag.Parse()
// ct, err := credentials.NewClientTLSFromFile("grpc.xxx.site.pem", "grpc.xxx.site")
// if err != nil {
// log.Fatalf("err:%v", err)
// }
conn, err := grpc.Dial(
*addr,
// 采用禁用安全传输,即没有ssl/tls
grpc.WithTransportCredentials(insecure.NewCredentials()),
// 采用证书,注意跨平台,linux amd64/apple m1芯片之间可能不能通讯
// grpc.WithTransportCredentials(ct),
// 安装中间件
grpc.WithUnaryInterceptor(middleware),
grpc.WithTimeout(time.Minute),
)
if err != nil {
log.Fatalf("dial:%v, %v", *addr, err)
}
defer conn.Close()
client := com.NewMathClient(conn)
req := com.AddReq{
Left: 10,
Right: 20,
}
resp, err := client.Add(context.Background(), &req)
if err != nil {
log.Fatalf("add fail:%v", err)
}
log.Printf("resp:%v", resp.Result)
}
proto
syntax = "proto3";
option go_package = "./;common";
service Math {
rpc Add(AddReq)returns(AddRsp){}
}
message AddReq {
int64 left = 1;
int64 right = 2;
}
message AddRsp {
int64 result = 1;
}
#!/bin/bash
#--go-grpc_out表示启动protoc-gen-go-grpc插件
# --openapiv2_out 表示产生swagger.json
protoc --go_out=. --go-grpc_out=. *.proto
nginx
...
server_names_hash_bucket_size 64;
server {
listen 443 ssl http2;
server_name grpc.xxx.site;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_certificate grpc.xxx.site.pem;
ssl_certificate_key grpc.xxx.site.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
# grpc_pass localhost:9000; 等价于 grpc://127.0.0.1:8411 等价于 [::]:8411;
# To use gRPC over SSL,就要带上grpcs:
grpc_pass grpcs://[xxx]:8411;
client_max_body_size 200M;
}
}
...