1. 客户端参数存在repeated 参数注意点

proto

  1. syntax = "proto3";
  2. option go_package=".;proto";
  3. service Greeter{
  4. rpc SayHello(HelloRequest) returns (HelloReply){}
  5. }
  6. message HelloRequest{
  7. string name =1;
  8. repeated int32 id = 2;
  9. }
  10. message HelloReply{
  11. string message = 1;
  12. }

客户端服务端

Go 客户端

  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "google.golang.org/grpc"
  6. "grpc_demo/proto"
  7. )
  8. func main() {
  9. conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
  10. if err!=nil {
  11. fmt.Println("net.Dial err"+err.Error())
  12. }
  13. c := proto.NewGreeterClient(conn)
  14. hello_res :=&proto.HelloRequest{
  15. Name: "hello name 2 ",
  16. }
  17. hello_res.Id = []int32{1,2,3,4,5}
  18. //r,err := c.SayHello(context.Background(),&proto.HelloRequest{Name:"hello name",Id: []int32{1,2,3}})
  19. r,err := c.SayHello(context.Background(),hello_res)
  20. if err!=nil{
  21. panic(err)
  22. }
  23. fmt.Println(r.Message)
  24. // 输出 name is hello name 2 id is [1 2 3 4 5]
  25. defer conn.Close()
  26. }

Go 服务端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s id is %v",res.Name,res.Id),
    },nil
}

func main()  {
    g:=grpc.NewServer()
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

Python 客户端

需要注意的是如果参数中存在数组类型,那么参数赋值形式要么直接赋值,要么使用内置的append 或者extend方法

from grpc_demo.proto import helloworld_pb2_grpc,helloworld_pb2
import grpc
if __name__ == '__main__':
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        hello_request = helloworld_pb2.HelloRequest()
        hello_request.name = "你好name"
        hello_request.id.extend([1,2])
        # or hello_request.id.append(1)
        # hello_request.id = [1,2,3] 这种形式是错误的
        # resp = stub.SayHello(helloworld_pb2.HelloRequest(name="你好name",id=[1,2,3]))
        resp = stub.SayHello(hello_request)
        print(resp.message)

Python 服务端

from grpc_demo.proto import helloworld_pb2, helloworld_pb2_grpc
import grpc
from concurrent import futures


class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message=f" name: {request.name} id = {request.id}")


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

2. option go_package 作用

如 option go_package=”./common/proto/v1;v1”; 表示将文件生成在当前proto文件下的/common/proto/v1中 且包名为 v1(对go有效),有利于包管理
image.png
image.png

3. proto文件引入其他proto文件

Python 版本

新建base.proto文件

base.proto

syntax = "proto3";

message Empty {
string name=1;

}
message Pong {
string name=1;
}

helloworld.proto

syntax = "proto3";
option  go_package="./;proto";
import "base.proto";
service Greeter{

        rpc SayHello(HelloRequest) returns (HelloReply){}
        rpc Ping(Empty) returns(Pong){}
}

message HelloRequest{
string name =1;
repeated int32 id=2;
}

message HelloReply{
string message = 1;
}

注意需要修改生成文件的包名(python)

客户端

from grpc_demo.proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

if __name__ == '__main__':
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        resp = stub.SayHello(helloworld_pb2.HelloRequest(name="你好name",id=[1,2,3]))
        resp1 = stub.Ping(helloworld_pb2_grpc.base__pb2.Empty(name="name11"))
        print(resp.message)
        print(resp1,"-----")
        # 输出 
        #  name: 你好name id = [1, 2, 3]
           name: " name is name11"
           -----

服务端

from grpc_demo.proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc


class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message=f" name: {request.name} id = {request.id}")
    def Ping(self, request, context):
        return helloworld_pb2.base__pb2.Pong(name=f" name is {request.name}")


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

Go 版本

base.proto

syntax = "proto3";

message Empty {
string name=1;

}
message Pong {
string name=1;
}

helloworld.proto

syntax = "proto3";
option  go_package=".;proto";
import "base.proto";
service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}
  rpc Ping(Empty) returns(Pong){}
}

message HelloRequest{
  string name =1;
  repeated int32 id = 2;
}

message HelloReply{
  string message = 1;
}

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"

)
func main()  {
    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)

    r,err := c.SayHello(context.Background(),&proto.HelloRequest{Name:"hello name",Id: []int32{1,2,3}})
    r1,_ := c.Ping(context.Background(),&proto.Empty{Name: "empty name"})
    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    fmt.Println(r1)
    // 输出 
    // name is hello name id is [1 2 3]
       name:"pong name is empty name"  
    defer conn.Close()
}

服务端

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s id is %v",res.Name,res.Id),
    },nil
}
func (this *Server) Ping(ctx context.Context,res *proto.Empty)(resp *proto.Pong,err error){
    return &proto.Pong{
        Name: fmt.Sprintf("pong name is %s",res.Name),
    },nil
}
func main()  {
    g:=grpc.NewServer()
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

4. message 嵌套

直接嵌套在message里面

proto

syntax = "proto3";
option  go_package=".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}

message HelloRequest{
  string name =1;
  repeated int32 id=2;
}

message HelloReply{
  string message = 1;
  message Result {
    string code=1;
    string msg=2;
  }
  repeated Result data =2;
}

Python

客户端

from proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

if __name__ == '__main__':
    with grpc.insecure_channel("127.0.0.1:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        resp = stub.SayHello(helloworld_pb2.HelloRequest(name="你好name",id=[1,2,3]))
        print(resp.message)
        print("----------------")
        for i in resp.data:
            print(i.code,"++",i.msg)

输出
name: 你好name id = [1, 2, 3]
————————
111 ++ success
000 ++ fail

服务端

from proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc

a = helloworld_pb2.HelloReply.Result()
a.code = "111"
a.msg = "success"

b = helloworld_pb2.HelloReply.Result()
b.code = "000"
b.msg = "fail"


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message=f" name: {request.name} id = {request.id}",
                                         data=[a,b])


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

注意点
image.png

Go

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"

)
func main()  {
    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)

    r,err := c.SayHello(context.Background(),&proto.HelloRequest{Name:"hello name",Id: []int32{1,2,3}})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    fmt.Println(r.Data) 
    // 输出
    name is hello name
    [code:"11"  msg:"success" code:"00"  msg:"fail"]

    defer conn.Close()
}

服务端

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    rs:=[]*proto.HelloReply_Result{
        &proto.HelloReply_Result{Code: "11",Msg: "success"},
        &proto.HelloReply_Result{Code: "00",Msg: "fail"},
    }
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s",res.Name),
        Data: rs,
    },nil
}

func main()  {
    g:=grpc.NewServer()
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

注意点
image.png

数据类型在message之外

proto

syntax = "proto3";
option  go_package = ".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}

message HelloRequest{
  string name = 1;
  repeated int32 id = 2;
}
message Result {
  string code = 1;
  string msg = 2;
}
message HelloReply{
  string message = 1;

  repeated Result data = 2;
}

Python

客户端

from proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

if __name__ == '__main__':
    with grpc.insecure_channel("127.0.0.1:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        resp = stub.SayHello(helloworld_pb2.HelloRequest(name="你好name",id=[1,2,3]))
        print(resp.message)
        print("----------------")
        for i in resp.data:
            print(i.code,"++",i.msg)

输出
image.png

服务端

from proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc

a = helloworld_pb2.Result()
a.code = "111"
a.msg = "success"

b = helloworld_pb2.Result()
b.code = "000"
b.msg = "fail"


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        return helloworld_pb2.HelloReply(message=f" name: {request.name} id = {request.id}",
                                         data=[a,b])


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

注意点
image.png

Go

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"

)
func main()  {
    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)

    r,err := c.SayHello(context.Background(),&proto.HelloRequest{Name:"hello name",Id: []int32{1,2,3}})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    fmt.Println(r.Data)

    defer conn.Close()
}

输出
image.png

服务端

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    rs:=[]*proto.Result{
        &proto.Result{Code: "11",Msg: "success"},
        &proto.Result{Code: "00",Msg: "fail"},
    }
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s",res.Name),
        Data: rs,
    },nil
}

func main()  {
    g:=grpc.NewServer()
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

注意点
image.png

5. enum 枚举类型

proto

syntax = "proto3";
option  go_package = ".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}
enum Gender {
  Male = 0;
  Female = 1;
}
message HelloRequest{
  string name = 1;
  repeated int32 id = 2;
  Gender sex = 3;
}

message Result {
  string code = 1;
  string msg = 2;
}
message HelloReply{
  string message = 1;

  repeated Result data = 2;
}

image.png

Python

会生成全局变量
image.png

客户端

from proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

if __name__ == '__main__':
    with grpc.insecure_channel("127.0.0.1:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        resp = stub.SayHello(helloworld_pb2.HelloRequest(name="你好name",id=[1,2,3],
                                                         sex=helloworld_pb2.Male))
        print(resp.message)
        print("----------------")
        for i in resp.data:
            print(i.code,"++",i.msg)

注意点
image.png

服务端

from proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc

a = helloworld_pb2.Result()
a.code = "111"
a.msg = "success"

b = helloworld_pb2.Result()
b.code = "000"
b.msg = "fail"


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        print(request.sex)
        return helloworld_pb2.HelloReply(message=f" name: {request.name} id = {request.id}",
                                         data=[a,b])


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

Go

会生成全局变量
image.png

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"

)
func main()  {
    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)

    r,err := c.SayHello(context.Background(),
        &proto.HelloRequest{Name:"hello name",
            Id: []int32{1,2,3},Sex: proto.Gender_Female})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    fmt.Println(r.Data)

    defer conn.Close()
}

注意点
image.png

服务端

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    rs:=[]*proto.Result{
        &proto.Result{Code: "11",Msg: "success"},
        &proto.Result{Code: "00",Msg: "fail"},
    }
    fmt.Println(fmt.Sprintf("Gender is %v",res.Sex))
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s",res.Name),
        Data: rs,
    },nil
}

func main()  {
    g:=grpc.NewServer()
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

注意点
image.png
输出
Gender is Female

6 . map 类型

proto

syntax = "proto3";
option  go_package = ".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}

message HelloRequest{
  string name = 1;
  repeated int32 id = 2;
  map<string,string> mp = 3;
}

message Result {
  string code = 1;
  string msg = 2;
}
message HelloReply{
  string message = 1;

  repeated Result data = 2;
}

Python

客户端

具体参数设置
image.png

服务端

输出查看
image.png

Go

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "grpc_demo/proto"

)
func main()  {
    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)

    r,err := c.SayHello(context.Background(),
        &proto.HelloRequest{Name:"hello name",
            Id: []int32{1,2,3},
            Mp:map[string]string{"name":"zhangsan",
                "age":"14"}})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    fmt.Println(r.Data)

    defer conn.Close()
}

注意点
image.png

服务端

雷同  
输出即可
Mp is map[age:14 name:zhangsan]

7. grpc metadata信息

proto

syntax = "proto3";
option  go_package = ".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}

message HelloRequest{
  string name = 1;

}

message HelloReply{
  string message = 1;
}

Python

客户端

from proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

if __name__ == '__main__':
    with grpc.insecure_channel("127.0.0.1:50051") as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        resp = stub.SayHello.with_call(
            helloworld_pb2.HelloRequest(name='myname'),
            metadata=(
                ('name', 'zhangsan'),
                ('password', '123456')
            )
        )
        print(resp[0].message)

服务端

from proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        for key, value in context.invocation_metadata():
            print('Received initial metadata: key=%s value=%s' % (key, value))

        return helloworld_pb2.HelloReply(message=f" name: {request.name}")


if __name__ == '__main__':
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

输出
Received initial metadata: key=name value=zhangsan
Received initial metadata: key=password value=123456
Received initial metadata: key=user-agent value=grpc-python/1.33.2 grpc-c/13.0.0 (windows; chttp2)

Go

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    "grpc_demo/proto"

)
func main()  {

    md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})
    // md 
    //md := metadata.Pairs(
    //    "key1", "val1",
    //    "key1", "val1-2",
    //    "key2", "val2",
    //)
    ctx := metadata.NewOutgoingContext(context.Background(), md)

    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure())
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)
    r,err := c.SayHello(ctx,
        &proto.HelloRequest{Name:"hello name"})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    defer conn.Close()
}

服务端

image.png
输出
map[:authority:[127.0.0.1:8080] content-type:[application/grpc] key1:[val1] key2:[val2] user-agent:[grpc-go/1.33.2]] true

8 grpc拦截器

proto

syntax = "proto3";
option  go_package = ".;proto";

service Greeter{

  rpc SayHello(HelloRequest) returns (HelloReply){}

}

message HelloRequest{
  string name = 1;

}

message HelloReply{
  string message = 1;
}

Python

客户端

from proto import helloworld_pb2_grpc,helloworld_pb2
import grpc

class DefaultInterceptor(grpc.UnaryUnaryClientInterceptor):
    def intercept_unary_unary(self, continuation, client_call_details, request):
        from datetime import datetime
        start = datetime.now()
        res = continuation(client_call_details,request)
        print((datetime.now()-start).microseconds/1000)
        return res



if __name__ == '__main__':
    defaultintercept = DefaultInterceptor()
    with grpc.insecure_channel("127.0.0.1:50051") as channel:
        intecept = grpc.intercept_channel(channel,defaultintercept)
        stub = helloworld_pb2_grpc.GreeterStub(intecept)
        resp = stub.SayHello.with_call(
            helloworld_pb2.HelloRequest(name='myname'),
            metadata=(
                ('name', 'zhangsan'),
                ('password', '123456')
            )
        )
        print(resp[0].message)

image.png

服务端

from proto import helloworld_pb2, helloworld_pb2_grpc
from concurrent import futures
import grpc


class Greeter(helloworld_pb2_grpc.GreeterServicer):

    def SayHello(self, request, context):
        for key, value in context.invocation_metadata():
            print('Received initial metadata: key=%s value=%s' % (key, value))

        return helloworld_pb2.HelloReply(message=f" name: {request.name}")

class LogInterceptor(grpc.ServerInterceptor):
    def intercept_service(self, continuation, handler_call_details):

        print("请求结束")
        resp = continuation(handler_call_details)
        print("请求结束")
        return resp


if __name__ == '__main__':
    interceptor = LogInterceptor()
    # 实例化server
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10),interceptors=[interceptor])
    # 注册逻辑到server
    helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
    # 启动
    server.add_insecure_port('127.0.0.1:50051')
    server.start()
    server.wait_for_termination()

image.png

Go

客户端

package main
import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    "grpc_demo/proto"
    "time"
)
func main()  {
    intercaptor:=func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error{
        start:=time.Now()
        err:=invoker(ctx,method,req,reply,cc,opts...)
        fmt.Printf("耗时%s\n",time.Since(start))
        fmt.Println(err)
        return err
    }
    opt:=grpc.WithUnaryInterceptor(intercaptor)
    md := metadata.New(map[string]string{"key1": "val1", "key2": "val2",})
    ctx := metadata.NewOutgoingContext(context.Background(), md)

    conn,err:=grpc.Dial("127.0.0.1:8080",grpc.WithInsecure(),opt)
    if err!=nil {
    fmt.Println("net.Dial err"+err.Error())
    }
    c := proto.NewGreeterClient(conn)
    r,err := c.SayHello(ctx,
        &proto.HelloRequest{Name:"hello name"})

    if err!=nil{
        panic(err)
    }
    fmt.Println(r.Message)
    defer conn.Close()
}

image.png

服务端

package main

import (
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/metadata"
    "grpc_demo/proto"
    "net"
)

type Server struct {

}

func (this *Server) SayHello(ctx context.Context,res *proto.HelloRequest)(resp *proto.HelloReply,err error){
    // 接收metadata信息
    md, ok := metadata.FromIncomingContext(ctx)
    fmt.Println(md,ok)
    return &proto.HelloReply{
        Message: fmt.Sprintf("name is %s",res.Name),

    },nil
}

func main()  {
    intercaptor:= func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error){
        fmt.Println("接收到请求 ")
        res,err:= handler(ctx,req)
        fmt.Println("请求结束")
        return res,err
    }
    opt:=grpc.UnaryInterceptor(intercaptor)
    g:=grpc.NewServer(opt)
    s := Server{}
    proto.RegisterGreeterServer(g,&s)
    lis, err := net.Listen("tcp", fmt.Sprintf(":8080"))
    if err != nil {
        panic("failed to listen: "+err.Error())
    }
    g.Serve(lis)
}

image.png

9 grpc-gateway

proto

syntax = "proto3";
option  go_package=".;proto";
import "google/api/annotations.proto";

service DemoService {
   rpc Echo(StringMessage) returns (StringMessage) {
       option (google.api.http) = {
           post: "/v1/example/echo"
           body: "*"
       };
   }

   rpc GetMessage(Empty) returns (GETMessage) {
       option (google.api.http) = {
           get: "/v1/example/echo"

       };
   }
 }

 message StringMessage{
     string  name=1;
 }

 message Empty {
 }

 message GETMessage{
     repeated string names=1;
 }

分别生成 pd.go 和gw.go文件

github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis
protoc -I/usr/local/include -I.
-I$GOPATH/src -I$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway/v2@v2.0.1/third_party/googleapis --go_out=plugins=grpc:. *.proto
protoc -I/usr/local/include -I. -I$GOPATH/src -I$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway/v2@v2.0.1/third_party/googleapis --grpc-gateway_out=logtostderr=true:.  *.proto

server

package main

import (
    "context"
    "fmt"
    "go_demo/grpc_demo/proto"
    "log"
    "net"

    // pb "grpc_demo/proto"

    "google.golang.org/grpc"
)

const (
    port = "0.0.0.0:8080"
)

type server struct {
    proto.UnimplementedDemoServiceServer
}

func (s *server) Echo(ctx context.Context, req *proto.StringMessage) (*proto.StringMessage, error) {
    fmt.Println("请求进来了......")
    return &proto.StringMessage{Name: "123456789"}, nil
}

func (s *server) GetMessage(ctx context.Context, req *proto.Empty) (*proto.GETMessage, error) {
    return &proto.GETMessage{Names: []string{"1", "2", "4", "5"}}, nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v\n", err)
    }

    s := grpc.NewServer()
    proto.RegisterDemoServiceServer(s, &server{})

    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

client

package main

import (
    "context"
    "go_demo/grpc_demo/proto"
    "log"
    "time"

    "google.golang.org/grpc"
)

const (
    addr = "9.135.90.120:58080"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    conn, err := grpc.DialContext(ctx, addr, grpc.WithBlock(), grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v\n", err)
    }
    defer conn.Close()
    c := proto.NewDemoServiceClient(conn)

    log.Printf("echo request: wang\n")

    r, err := c.Echo(ctx, &proto.StringMessage{Name: "iiiiii"})
    if err != nil {
        log.Fatalf("could not echo: %v\n", err)
    }

    log.Printf("Echo reply: %s\n", r.GetName())
}

httpclient

package main

import (
    "context"
    "flag"
    "go_demo/grpc_demo/proto"
    "net/http"

    "github.com/golang/glog"
    "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    "google.golang.org/grpc"
)

var (
    GrpcServerEndpoint = flag.String("grpc-server-endpoint", "9.135.90.120:58080", "gRPC server demoserver")
)

func run() error {
    ctx := context.Background()
    ctx1, cancel := context.WithCancel(ctx)
    defer cancel()

    mux := runtime.NewServeMux()
    opts := []grpc.DialOption{grpc.WithInsecure()}
    err := proto.RegisterDemoServiceHandlerFromEndpoint(ctx1, mux, *GrpcServerEndpoint, opts)
    if err != nil {
        return err
    }

    return http.ListenAndServe("9.135.90.120:8081", mux)
}

func main() {

    flag.Parse()
    defer glog.Flush()

    if err := run(); err != nil {
        glog.Fatal(err)
    }
}

10 grpc异常处理

package main

import (
        "context"
        "fmt"
        "google.golang.org/grpc"
        "google.golang.org/grpc/status"
)

func main() {
        st, ok := status.FromError(err)
        if ok {
                fmt.Println(st.Code(), "-----")
                fmt.Println(st.Message(), "+++++++")
        }
}