「gRPC」 Gateway的实现

Golang
521
0
0
2022-09-12
标签   gRPC
gRPC Gateway的实现相应的客户端和服务端代码就已经为我们生成了
我们只需要实现服务端的接口:
// TripServiceServer is the server API for TripService service.
type TripServiceServer interface {
    GetTrip(context.Context, *GetTripRequest) (*GetTripResponse, error)
}
接口的实现:
import (
    "context"
    trippb "coolcar/proto/gen/go"
)

//type TripServiceServer interface {
//    GetTrip(context.Context, *GetTripRequest) (*GetTripResponse, error)
// }

type Service struct{}

func (*Service) GetTrip(con context.Context, req *trippb.GetTripRequest) (*trippb.GetTripResponse, error) {
    return &trippb.GetTripResponse{
    //客户请求什么Id,服务端返回什么Id
        Id: req.Id,
        Trip: &trippb.Trip{
            Statar:      "北京"
            End:         "上海",
            DurationSec: 3600,
            FeeCent:     1000,
            StatarPos: &trippb.Location{
                Latitude:  30,
                Longitude: 120,
            },
            EndPos: &trippb.Location{
                Latitude:  40,
                Longitude: 125,
            },
            PathLocations: []*trippb.Location{
                {
                    Latitude:  34,
                    Longitude: 123,
                },
                {
                    Latitude:  38,
                    Longitude: 124,
                },
            },
            Status: trippb.TripStatus_FINISHED,
        },
    }, nil
}
现在我们来实现获取行程的整个过程:
编写service端和gateway
package main

import (
    "context"
    trippb "coolcar/proto/gen/go"
    trip "coolcar/tripservice" 
    "fmt" 
    "log" 
    "net" 
    "net/http"

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

//gateway的实现
func startGRPCGatway() {
    c := context.Background()          //生成没具体内容的上下文
    c, cancel := context.WithCancel(c) //该方法将具有cancel的能力 
    defer cancel()

    //runtime.WithMarshalerOption()将Status: trippb.TripStatus_FINISHED,改为status:3
    mux := runtime.NewServeMux(runtime.WithMarshalerOption(
        runtime.MIMEWildcard, &runtime.JSONPb{
            EnumsAsInts: true, //status
            OrigName:    true, //命名
        },
    ))

    err := trippb.RegisterTripServiceHandlerFromEndpoint(
        c, //通过context去连接, 注册在runtime.NewServeMux()上面
        mux,
        ":8081",  //连接内部grpc服务端口
        []grpc.DialOption{grpc.WithInsecure()}, //grpc.WithInsecure()连接方式tcp明文,即不做安全处理
    )
    if err != nil {
        log.Fatalf("断开连接: %v", err)
    }

    //对外暴露http端口
    err = http.ListenAndServe(":8080", mux)
    if err != nil {
        log.Fatalf("连接失败: %v", err)
    }
}


//service 端
func main() {
    fmt.Println("监听开始")
    go startGRPCGatway()
    list, err := net.Listen("tcp", ":8081")
    if err != nil {
        log.Fatalf("监听失败: %v", err)
    }
    s := grpc.NewServer() //NewServer 创建一个未注册服务且尚未开始接受请求的 gRPC 服务器。
    trippb.RegisterTripServiceServer(s, &trip.Service{})
    fmt.Println("监听结束")
    fmt.Println(list)
    log.Fatal(s.Serve(list)) //s.Serve()方法不会退出

}
编写客户端:
  1. 这里也可以通过grpc进行拨号:
package main

import (
    "context"
    trippb "coolcar/proto/gen/go" 
    "fmt" 
    "log"

    "google.golang.org/grpc"
)

func main() {
  //连接gateway
    con, err := grpc.Dial("localhost:8080")
    if err != nil {
        log.Fatalf("连接失败: %v", err)
    }

    tsClient := trippb.NewTripServiceClient(con)
    res, err := tsClient.GetTrip(context.Background(), &trippb.GetTripRequest{
        Id: "trips01",
    })
    if err != nil {
        log.Fatalf("未获取到trips: %v", err)
    }
    fmt.Println(res)
}
  1. 通过浏览器:http://localhost:8080/trip?Id=trips01
这样整个流程就完了
返回结果:
id:"trips01" trip:{statar:"北京" statar_pos:{latitude:30 longitude:120} path_locations:{latitude:34 longitude:123} path_locations:{latitude:38 longitude:124} end:"上海" end_pos:{latitude:40 longitude:125} duration_sec:3600 fee_cent:1000 status:FINISHED}