基于Go/Grpc/kubernetes/Istio开发微服务的最佳实际尝试 - 1/3

基于Go/Grpc/kubernetes/Istio开发微服务的最佳实际尝试 - 2/3

基于Go/Grpc/kubernetes/Istio开发微服务的最佳实际尝试 - 3/3

我的项目地址:https://github.com/janrs-io/Jgrpc


转载请注明起源:https://janrs.com/ugj7

在上一部分中,咱们创立了微服务的目录构造并实现了微服务pongservice

这部分咱们持续实现一个名为pingservice的微服务,拜访上一节曾经部署好的pongservice微服务。

创立一个新的微服务非常简单,只需复制之前创立的pongservice微服务,而后做一些小改变。

我的项目构造

这部分最终的目录构造如下:

pingservice├── buf.gen.yaml├── cmd│   ├── main.go│   └── server│       ├── grpc.go│       ├── http.go│       ├── run.go│       ├── wire.go│       └── wire_gen.go├── config│   ├── client.go│   ├── config.go│   └── config.yaml├── genproto│   └── v1│       ├── gw│       │   └── pingservice.pb.gw.go│       ├── pingservice.pb.go│       └── pingservice_grpc.pb.go├── go.mod├── go.sum├── proto│   ├── buf.lock│   ├── buf.yaml│   └── v1│       ├── pingservice.proto│       └── pingservice.yaml└── service    ├── client.go    └── server.go9 directories, 21 files

开始

复制

src 目录下执行如下复制命令:

cp -R pongservice pingservice

删除 wire_gen.go

删除 pingservice/cmd/server 目录中的 wire_gen.go 文件。

批改 go.mod module

批改go.mod文件的模块,如下代码所示:

module github.com/janrs-io/Jgrpc/src/pingservice

生成 proto

删除pingservice/proto/v1目录下的pongservice.protopongservice.yaml文件以及整个genproto文件夹。

而后从新创立pingservice.protopingservice.yaml文件,代码如下:

pingservice.proto code:

syntax = "proto3";package proto.v1;option go_package = "github.com/janrs-io/Jgrpc/src/pingservice/genproto/v1";service PingService {  rpc Ping(PingRequest) returns(PingResponse){}}message PingRequest {  string msg = 1 ;}message PingResponse {  string msg = 1;}

pingservice.yaml code:

type: google.api.Serviceconfig_version: 3http:  rules:    - selector: proto.v1.PingService.Ping      get: /ping.v1.ping

批改 pingservice 目录下的 buf.gen.yaml 文件。 批改后的残缺代码如下:

version: v1plugins:  - plugin: go    out: genproto/v1    opt:      - paths=source_relative  - plugin: go-grpc    out: genproto/v1    opt:      - paths=source_relative  - plugin: grpc-gateway    out: genproto/v1/gw    opt:      - paths=source_relative      - grpc_api_configuration=proto/v1/pingservice.yaml      - standalone=true

pingservice目录下执行以下命令生成 proto 文件:

buf generate proto/v1

执行命令后,将从新生成genproto目录,并主动创立*pb.go文件。

批改 import 门路和所有代码

查看所有文件的导入,将导入门路的pongservice批改为pingservice

将所有代码的Pong/pong改为Ping/ping,直到没有谬误为止。

批改 config.yaml

批改 config 目录下的config.yaml文件。
grpc 的服务器端口更改为 50052,将 http 的服务器端口更改为 9002
grpc 的服务名改为ping-grpc,将 http 的服务名改为ping-http

批改后的残缺代码如下:

# grpc configgrpc:  host: ""  port: ":50052"  name: "ping-grpc"# http confighttp:  host: ""  port: ":9002"  name: "ping-http"

生成 generate inject

pingservice 目录中执行以下 wire 命令以从新生成依赖注入文件:

wire ./...

引入 pongservier 服务的 go.mod

咱们要在 pingservice 这个微服务中拜访 pongservicegrpc 服务,所以须要导入 pongservicego.mod

批改pingservice目录下的go.mod文件,增加导入pongservice的代码,如下:

module github.com/janrs-io/Jgrpc/src/pingservicego 1.19replace (    pongservice => ../pongservice)require (    pongservice v0.0.0    github.com/google/wire v0.5.0    github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2    github.com/spf13/viper v1.15.0    google.golang.org/grpc v1.54.0    google.golang.org/protobuf v1.30.0)// the other required package...

批改 config.yaml

批改pingservice/config目录下的config.yaml文件,增加如下代码:

# service clientclient:  pong: ":50051"

批改后的残缺代码如下:

# grpc configgrpc:  host: ""  port: ":50052"  name: "ping-grpc"# http confighttp:  host: ""  port: ":9002"  name: "ping-http"# service clientclient:  pong: ":50051"

生成 client.go

pingservice/config目录下生成client.go文件,增加如下代码:

package config// Client Client service configtype Client struct {    Pong string `json:"pong" yaml:"pong"`}

批改 config.go

Config 构造体中增加一个 Client 字段,代码如下:

Client Client `json:"client" yaml:"client"`

批改后的残缺代码如下:

package configimport (    "net/http"    "github.com/spf13/viper"    "google.golang.org/grpc")// Config Service configtype Config struct {    Grpc   Grpc   `json:"grpc" yaml:"grpc"`    Http   Http   `json:"http" yaml:"http"`    Client Client `json:"client" yaml:"client"`}// NewConfig Initial service's configfunc NewConfig(cfg string) *Config {    if cfg == "" {        panic("load config file failed.config file can not be empty.")    }    viper.SetConfigFile(cfg)    // Read config file    if err := viper.ReadInConfig(); err != nil {        panic("read config failed.[ERROR]=>" + err.Error())    }    conf := &Config{}    // Assign the overloaded configuration to the global    if err := viper.Unmarshal(conf); err != nil {        panic("assign config failed.[ERROR]=>" + err.Error())    }    return conf}// Grpc Grpc server configtype Grpc struct {    Host   string `json:"host" yaml:"host"`    Port   string `json:"port" yaml:"port"`    Name   string `json:"name" yaml:"name"`    Server *grpc.Server}// Http Http server configtype Http struct {    Host   string `json:"host" yaml:"host"`    Port   string `json:"port" yaml:"port"`    Name   string `json:"name" yaml:"name"`    Server *http.Server}

批改 client.go

批改pingservice/service目录下的client.go文件,增加如下代码:

// NewPongClient New pong service clientfunc NewPongClient(conf *config.Config) (pongclientv1.PongServiceClient, error) {    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)    defer cancel()    conn, err := grpc.DialContext(ctx, conf.Client.Pong, grpc.WithTransportCredentials(insecure.NewCredentials()))    if err != nil {        fmt.Println("dial auth server failed.[ERROR]=>" + err.Error())        return nil, err    }    client := pongclientv1.NewPongServiceClient(conn)    return client, nil}

批改后的残缺代码如下:

package serviceimport (    "context"    "fmt"    "time"    "google.golang.org/grpc"    "google.golang.org/grpc/credentials/insecure"    "github.com/janrs-io/Jgrpc/src/pingservice/config"    v1 "github.com/janrs-io/Jgrpc/src/pingservice/genproto/v1"    pongclientv1 "github.com/janrs-io/Jgrpc/src/pongservice/genproto/v1")// NewClient New service's clientfunc NewClient(conf *config.Config) (v1.PingServiceClient, error) {    serverAddress := conf.Grpc.Host + conf.Grpc.Port    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)    defer cancel()    conn, err := grpc.DialContext(ctx, serverAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))    if err != nil {        return nil, err    }    client := v1.NewPingServiceClient(conn)    return client, nil}// NewPongClient New pong service clientfunc NewPongClient(conf *config.Config) (pongclientv1.PongServiceClient, error) {    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)    defer cancel()    conn, err := grpc.DialContext(ctx, conf.Client.Pong, grpc.WithTransportCredentials(insecure.NewCredentials()))    if err != nil {        fmt.Println("dial auth server failed.[ERROR]=>" + err.Error())        return nil, err    }    client := pongclientv1.NewPongServiceClient(conn)    return client, nil}

批改 server.go

批改pingservice/service目录下的server.go文件,批改后的残缺代码如下:

package serviceimport (    "context"    "google.golang.org/grpc/grpclog"    "github.com/janrs-io/Jgrpc/src/pingservice/config"    v1 "github.com/janrs-io/Jgrpc/src/pingservice/genproto/v1"    pongclientv1 "github.com/janrs-io/Jgrpc/src/pongservice/genproto/v1")// Server Server structtype Server struct {    v1.UnimplementedPingServiceServer    pingClient v1.PingServiceClient    pongClient pongclientv1.PongServiceClient    conf       *config.Config}// NewServer New service grpc serverfunc NewServer(    conf *config.Config,    pingClient v1.PingServiceClient,    pongClient pongclientv1.PongServiceClient,) v1.PingServiceServer {    return &Server{        pingClient: pingClient,        pongClient: pongClient,        conf:       conf,    }}func (s *Server) Ping(ctx context.Context, req *v1.PingRequest) (*v1.PingResponse, error) {    pongReq := &pongclientv1.PongRequest{Msg: "request from ping service"}    pongResp, err := s.pongClient.Pong(ctx, pongReq)    if err != nil {        grpclog.Error("connect pong failed.[ERROR]=>" + err.Error())        return nil, err    }    return &v1.PingResponse{        Msg: "response ping msg:" + req.Msg + " and msg from pong service is: " + pongResp.Msg,    }, nil}

批改 wire.go

批改pingservice/cmd/serverwire.go文件,增加service.NewPongClient依赖注入。 代码如下:

service.NewPongClient

批改后的残缺代码如下:

//go:build wireinject// +build wireinjectpackage serverimport (    "github.com/google/wire"    "github.com/janrs-io/Jgrpc/src/pingservice/config"    v1 "github.com/janrs-io/Jgrpc/src/pingservice/genproto/v1"    "github.com/janrs-io/Jgrpc/src/pingservice/service")// InitServer Inject service's componentfunc InitServer(conf *config.Config) (v1.PingServiceServer, error) {    wire.Build(        service.NewPongClient,        service.NewClient,        service.NewServer,    )    return &service.Server{}, nil}

pingservice 目录下执行以下 wire 命令从新生成依赖注入文件:

如果呈现 go.mod 引入谬误,只需在 pingservice 目录中再次运行 go mod tidy
wire ./...

启动 service

别离在pongservice目录和pingservice目录下执行go run命令。

go run cmd/main.go

在浏览器中输出以下申请地址:

127.0.01:9002/ping.v1.ping?msg=best practice

所有正确的状况下返回以下 json 数据:

{    "msg": "response ping msg:best practice and msg from pong service is: response pong msg:request from ping service"}

总结

这部分咱们新建一个 pingservice 微服务,实现拜访 pongservicegrpc 服务。

置信通过这两次创立微服务的简略尝试,你肯定感觉基于GoGrpc开发微服务并不难。

在下一部分中,咱们将利用 Jenkins/Gitlab/HarborKubernets/Istio 进行 devopsCICD 部署。


转载请注明起源:https://janrs.com/ugj7