当前位置:网站首页>Grpc: implement grpc proxy

Grpc: implement grpc proxy

2022-06-24 01:48:00 Trespass

Introduce

How does this article describe rk-boot Quickly build gRPC agent .

What is? gRPC agent ?

gRPC Agent will accept gRPC request , And forward to others according to the user policy gRPC service . There are not many application scenarios , For example, according to the environmental parameters , Forward the request to a different gRPC service .

install

go get github.com/rookie-ninja/rk-boot
go get github.com/rookie-ninja/rk-grpc

Quick start

Use rk-boot Starting up gRPC The agency has a limitation . Only requests sent in code form , To be represented .grpc-gateway perhaps grpcurl Form requests are temporarily not supported .

at present ,rk-boot Support 3 In the strategy .

  • headerBased: adopt gRPC In request Metadata Value to determine the proxy destination .
  • pathBased: Determine the proxy destination through the request path .
  • ipBased: By remote IP Address to determine the proxy destination .

In the following example , We start three services .

  • proxy(8080): Agency service , according to headerBased Strategy , forward rk.api.v1.RkCommonService.Healthy Ask to test In service .
  • test(8081): Test domain gRPC service , Accept proxy Acting as a proxy for incoming requests .
  • client: Go to proxy Service delivery rk.api.v1.RkCommonService.Healthy request .

1. establish proxy/boot.yaml & proxy/main.go

monitor 8080 port ,proxy The service does not implement any gRPC Method , If gRPC Requested Metadata Contained in the domain:test, Will forward .

The proxy defaults from proxy.rules.dest Select an address to forward .

  • boot.yaml
---
grpc:
  - name: greeter                        # Required
    port: 8080                           # Required
    enabled: true                        # Required
    proxy:
      enabled: true                      # Optional, enable proxy server
      rules:
        - type: headerBased              # Optional, options:[headerBased, pathBased, ipBased]
          headerPairs: ["domain:test"]   # Optional, header pairs separated by colon(:)
          dest: ["localhost:8081"]       # Optional, destinations
    interceptors:
      loggingZap:
        enabled: true
  • main.go
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"github.com/rookie-ninja/rk-boot"
	_ "github.com/rookie-ninja/rk-grpc/boot"
)

// Application entrance.
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// Bootstrap
	boot.Bootstrap(context.Background())

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

2. establish test/boot.yaml & test/main.go

monitor 8081 port .

start-up CommonService service , receive Proxy The agent came here rk.api.v1.RkCommonService.Healthy request .

  • boot.yaml
---
grpc:
  - name: greeter                     # Required
    port: 8081                        # Required
    enabled: true                     # Required
    commonService:
      enabled: true                   # Optional, default: false
    interceptors:
      loggingZap:
        enabled: true
  • main.go
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"github.com/rookie-ninja/rk-boot"
	_ "github.com/rookie-ninja/rk-grpc/boot"
)

// Application entrance.
func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// Bootstrap
	boot.Bootstrap(context.Background())

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

3.client/main.go

Sent request metadata in , add to domain:test, Give Way proxy Agent request .

// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"fmt"
	api "github.com/rookie-ninja/rk-grpc/boot/api/third_party/gen/v1"
	"github.com/rookie-ninja/rk-grpc/interceptor/context"
	"github.com/rookie-ninja/rk-grpc/interceptor/log/zap"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
	"log"
)

// In this example, we will create a simple gRpc client and enable RK style logging interceptor.
func main() {
	// ********************************************
	// ********** Enable interceptors *************
	// ********************************************
	opts := []grpc.DialOption{
		grpc.WithChainUnaryInterceptor(
			rkgrpclog.UnaryClientInterceptor(),
		),
		grpc.WithInsecure(),
		grpc.WithBlock(),
	}

	// 1: Create grpc client
	conn, client := createCommonServiceClient(opts...)
	defer conn.Close()

	// 2: Wrap context, this is required in order to use bellow features easily.
	ctx := rkgrpcctx.WrapContext(context.Background())
	// Add header to make proxy request to test server
	ctx = metadata.AppendToOutgoingContext(ctx, "domain", "test")

	// 3: Call server
	if resp, err := client.Healthy(ctx, &api.HealthyRequest{}); err != nil {
		rkgrpcctx.GetLogger(ctx).Fatal("Failed to send request to server.", zap.Error(err))
	} else {
		rkgrpcctx.GetLogger(ctx).Info(fmt.Sprintf("[Message]: %s", resp.String()))
	}
}

func createCommonServiceClient(opts ...grpc.DialOption) (*grpc.ClientConn, api.RkCommonServiceClient) {
	// 1: Set up a connection to the server.
	conn, err := grpc.DialContext(context.Background(), "localhost:8080", opts...)
	if err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}

	// 2: Create grpc client
	client := api.NewRkCommonServiceClient(conn)

	return conn, client
}

4. Folder structure

$ tree
.
├── client
│   ├── go.mod
│   └── main.go
├── proxy
│   ├── boot.yaml
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── test
    ├── boot.yaml
    ├── go.mod
    └── main.go

3 directories, 9 files

5. start-up proxy,test

$ go run proxy/main.go
$ go run test/main.go

6. verification

start-up client/main.go

  • client End log
2021-11-13T02:14:33.598+0800    INFO    client/main.go:45       [Message]: fields:{key:"healthy" value:{bool_value:true}}

------------------------------------------------------------------------
endTime=2021-11-13T02:14:33.597875+08:00
startTime=2021-11-13T02:14:33.59247+08:00
elapsedNano=5405233
timezone=CST
ids={"eventId":"7ffe293d-24f4-42b3-9325-64bde414912c"}
app={"appName":"rk","appVersion":"","entryName":"grpc","entryType":"grpc"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"grpcMethod":"Healthy","grpcService":"rk.api.v1.RkCommonService","grpcType":"unaryClient","remoteIp":"localhost","remotePort":"8080"}
error={}
counters={}
pairs={}
timing={}
remoteAddr=localhost:8080
operation=/rk.api.v1.RkCommonService/Healthy
resCode=OK
eventStatus=Ended
EOE
  • proxy End log

proxy Terminal grpcType yes streamServer.

------------------------------------------------------------------------
endTime=2021-11-13T02:14:33.597337+08:00
startTime=2021-11-13T02:14:33.593252+08:00
elapsedNano=4085300
timezone=CST
ids={"eventId":"f32f7895-a4b2-4c8c-bedc-1d4733db78a7"}
app={"appName":"rk-demo","appVersion":"master-2c9c6fd","entryName":"greeter","entryType":"GrpcEntry"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"grpcMethod":"Healthy","grpcService":"rk.api.v1.RkCommonService","grpcType":"streamServer","gwMethod":"","gwPath":"","gwScheme":"","gwUserAgent":""}
error={}
counters={}
pairs={}
timing={}
remoteAddr=127.0.0.1:58441
operation=/rk.api.v1.RkCommonService/Healthy
resCode=OK
eventStatus=Ended
EOE
  • test End log

test Terminal grpcType yes unaryServer.

------------------------------------------------------------------------
endTime=2021-11-13T02:14:33.596967+08:00
startTime=2021-11-13T02:14:33.59692+08:00
elapsedNano=47149
timezone=CST
ids={"eventId":"6eb9b10a-153a-4955-85b0-f227e3ec54b2"}
app={"appName":"rk-demo","appVersion":"master-2c9c6fd","entryName":"greeter","entryType":"GrpcEntry"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"grpcMethod":"Healthy","grpcService":"rk.api.v1.RkCommonService","grpcType":"unaryServer","gwMethod":"","gwPath":"","gwScheme":"","gwUserAgent":""}
error={}
counters={}
pairs={"healthy":"true"}
timing={}
remoteAddr=10.8.0.2:58443
operation=/rk.api.v1.RkCommonService/Healthy
resCode=OK
eventStatus=Ended
EOE

pathBased Strategy

It can be modified by boot.yaml File modification agent policy .

---
grpc:
  - name: greeter                                         # Required
    port: 8080                                            # Required
    enabled: true                                         # Required
    proxy:
      enabled: true                                       # Optional, enable proxy server
      rules:
        - type: pathBased                                 # Optional, options:[headerBased, pathBased, ipBased]
          paths: ["/rk.api.v1.RkCommonService/Healthy"]   # Optional, gRPC method, support golang regex.
          dest: ["localhost:8081"]                        # Optional, destinations

ipBased Strategy

It can be modified by boot.yaml File modification agent policy .

proxy.rules.ips Support CIDR.

---
grpc:
  - name: greeter                    # Required
    port: 8080                       # Required
    enabled: true                    # Required
    proxy:
      enabled: true                  # Optional, enable proxy server
      rules:
        - type: ipBased              # Optional, options:[headerBased, pathBased, ipBased]
          ips: ["127.0.0.0/24"]      # Optional, remote Ips, support CIDR.
          dest: ["localhost:8081"]   # Optional, destinations
原网站

版权声明
本文为[Trespass ]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/11/20211113033516565r.html