Go微服务八 Go-gGRPC 不同端口提供rpc和http服务

598 次浏览次阅读
没有评论

[微服务六] 略有不同。

以商品详情场景解释本篇和 [微服务六] 还有 [微服务七] 的不同之处

微服务六: 不同端口同时支持 rpc 和 http。

​ 场景: 商品服务 -> 商品库存等

​ 商品服务 -> 商品库存提供 rpc: 端口(9001) 客户端可以通过 rpc 调用商品库存 rpc 接口服务,

此时客户端可能没有使用 rpc,只会 http api 调用的形式。这个时候客户端也可以通过 http, 调用用商品库存 rpc 接口提供的 http: 端口(8001)

相当于一个商品库存,通过基于 protobuf 协议封装的 grpc 即提供了 rpc 又提供了 http,而且端口还不同,这样也可以,在基于 protobuf 封装 rpc 的时候,加一个 options 参数,使用对应的路由实现。但是有一点不方便,不管是 rpc 还是 http api 变动都需要使用 proto 重新生成对应的 *.pb.go 文件,增加维护成本,如果调用方不支持 rpc 可以使用此方式

微服务七:同一个端口支持 grpc 和 http

​ 场景: 商品服务 -> 商品库存、商品详情、商品列表等

​ 商品服务 -> 商品库存 rpc 接口端口(9001) 客户端可以通过 rpc 调用商品库存 rpc 接口,但不能通过 http 调用商品库存 rpc 服务接口. 但是此时商品服务可能还存在一些其他的 api,比如商品详情、商品列表等,此时不想通过封装 rpc 供客户端调用,想通过简单的 http api 方式供客户端使用,但是又不想一个商品服务同时暴漏两个端口,可以采用此方法。比方客户端可以通过 http 调用商品服务另外提供的 api,端口也是 9001

不建议, 最好还是分别使用不同的端口,端口对应独立的服务

本篇文章: 不同端口提供 rpc 和 http

​ 场景: 商品服务 -> 商品库存、商品详情、商品列表等
商品服务 -> 商品库存只提供 rpc 但是商品详情和商品列表不提供 rpc 只提供 http api,端口又不同

目录结构

Go 微服务八  Go-gGRPC 不同端口提供 rpc 和 http 服务

一 创建项目

mkdir demo

cd demo && go mod init demo && go get google.golang.org/grpc && touch generate_pb && chmod +x generate_pb

mkdir demo-server && mkdir demo-client

cd demo-server && mkdir pb && mkdir proto && mkdir rpcServices && touch main.go

cd demo-client && touch main.go

二 代码编写

rpcDemoService.proto

syntax = "proto3";

package pb;

option go_package = "../pb";

message GetUserInfoRequest {int32 id = 1;}

message GetUserInfoResponse {
  string name = 1;
  int32 age = 2;
}

service RpcDemoService {rpc GetUserInfo(GetUserInfoRequest) returns (GetUserInfoResponse){}}

generate_pb

cd proto && protoc --go_out=plugins=grpc:../pb rpcDemoService.proto

执行./generate_pb, 会在 pb 目录闲生成 *.pb.go 文件

rpcDemoService.go

package rpcServices

import (
    "context"
    "demo/demo-server/pb"
)

type RpcDemoService struct{}

func (rd *RpcDemoService) GetUserInfo(ctx context.Context, r *pb.GetUserInfoRequest) (*pb.GetUserInfoResponse, error) {
    return &pb.GetUserInfoResponse{
        Name: "demo",
        Age:  18,
    }, nil
}

main.go

package main

import (
    "demo/demo-server/pb"
    "demo/demo-server/rpcServices"
    "flag"
    "log"
    "net"
    "net/http"

    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

var grpcPort string
var httpPort string

func init() {flag.StringVar(&grpcPort, "g", "8001", "gRPC 启动端口号 ")
    flag.StringVar(&httpPort, "h", "9001", "HTTP 启动端口号 ")
    flag.Parse()}

//RunHttpServer
func RunHttpServer(port string) error {serveMux := http.NewServeMux()
    serveMux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {_, _ = w.Write([]byte(`pong`))
    })

    return http.ListenAndServe(":"+port, serveMux)
}

//RunGrpcServer
func RunGrpcServer(port string) error {s := grpc.NewServer()
    pb.RegisterRpcDemoServiceServer(s, new(rpcServices.RpcDemoService))
    reflection.Register(s)
    lis, err := net.Listen("tcp", ":"+port)
    if err != nil {return err}

    return s.Serve(lis)
}

func main() {errs := make(chan error)
    go func() {err := RunHttpServer(httpPort)
        if err != nil {errs <- err}
    }()
    go func() {err := RunGrpcServer(grpcPort)
        if err != nil {errs <- err}
    }()

    select {
    case err := <-errs:
        log.Fatalf("Run Server err: %v", err)
    }
}

cd demo-client

main.go

package main

import (
    "context"
    "demo/demo-server/pb"
    "fmt"

    "google.golang.org/grpc"
)

func main() {conn, err := grpc.Dial(":8001", grpc.WithInsecure())
    if err != nil {panic(err)
    }
    defer conn.Close()

    demoServiceClient := pb.NewRpcDemoServiceClient(conn)
    result, err := demoServiceClient.GetUserInfo(context.Background(), &pb.GetUserInfoRequest{Id: 10,})
    if err != nil {panic(err)
    }

    fmt.Println(result)
}

测试 grpc

执行

cd demo-server
go run main.go

postman 或者 curl 访问 127.0.0.1:9001/ping

Go 微服务八  Go-gGRPC 不同端口提供 rpc 和 http 服务

测试 http

执行

cd demo-client && go run main.go

Go 微服务八  Go-gGRPC 不同端口提供 rpc 和 http 服务

修改 demo-server/main.go 结合 echo 框架支持 restful api

package main

import (
    "demo/demo-server/pb"
    "demo/demo-server/rpcServices"
    "flag"
    "log"
    "net"
    "net/http"

    "github.com/labstack/echo"

    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

var grpcPort string
var httpPort string

func init() {flag.StringVar(&grpcPort, "g", "8001", "gRPC 启动端口号 ")
    flag.StringVar(&httpPort, "h", "9001", "HTTP 启动端口号 ")
    flag.Parse()}

//RunHttpServer
func RunHttpServer(port string) {//serveMux := http.NewServeMux()
    //serveMux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {//  _, _ = w.Write([]byte(`pong`))
    //})
    //
    //return http.ListenAndServe(":"+port, serveMux)
    e := echo.New()
    e.GET("/ping", func(c echo.Context) error {return c.JSON(http.StatusOK, "pong...")
    })
    e.Logger.Fatal(e.Start(":" + port))
}

//RunGrpcServer
func RunGrpcServer(port string) error {s := grpc.NewServer()
    pb.RegisterRpcDemoServiceServer(s, new(rpcServices.RpcDemoService))
    reflection.Register(s)
    lis, err := net.Listen("tcp", ":"+port)
    if err != nil {return err}

    return s.Serve(lis)
}

func main() {errs := make(chan error)
    go func() {RunHttpServer(httpPort)
    }()
    go func() {err := RunGrpcServer(grpcPort)
        if err != nil {errs <- err}
    }()

    select {
    case err := <-errs:
        log.Fatalf("Run Server err: %v", err)
    }
}
正文完
 0
评论(没有评论)