Служба фиктивного сервера протокола GRPC

задняя часть контрольная работа
Служба фиктивного сервера протокола GRPC

PowerMock — это реализация Mock Server, которая поддерживает интерфейсы протоколов HTTP и gRPC и предоставляет гибкие функции подключаемых модулей. Этот инструмент предназначен для разработчиков, у которых есть требования к имитации интерфейса для внешнего интерфейса, серверной части, тестирования и т. д. Его также можно развернуть в качестве общей службы имитации в архитектуре шлюза или платформе управления API для реализации таких функций, как переход на более раннюю версию и интерфейс. насмешливый.

адрес проекта

Адрес проекта: PowerMock

Функции

В качестве фиктивного сервера PowerMock имеет следующие основные функции:

  1. служба поддержкиHTTP-протоколипротокол gRPCМакет интерфейса.
  2. Поддержка конфигурацииJavascriptи другие языки сценариев для динамической генерации ответов.
  3. Поддерживает настройку нескольких ответов на интерфейс ипо условиюдифференцировать.
  4. Поддержка условий совпадениянесколько операторов(И/ИЛИ/>/= и т. д.).
  5. Поддерживает возврат статических данных, а такжеполевые случайные данные.
  6. служба поддержкиплагинФункции, другие механизмы сопоставления или Mock-движки могут быть реализованы путем написания плагинов.
  7. При этом предоставляются интерфейсы HTTP и gRPC, а MockAPI может быть реализован динамически.CRUD.
  8. Готовое хранилище Redis и поддержкаСвободно расширяйте другие механизмы хранения, такие как MySQL и т. д.
  9. Поддерживаются как 32-битные, так и 64-битные windows/darwin/linux.
  10. Независимо от языка, любой проект, использующий протокол HTTP или протокол gRPC, может использовать этот инструмент.

Пример

Более продвинутое использование

Этот пример можно найти вобразец коданайти соответствующую информацию В этом примере должна использоваться версия powermock v8 для полной поддержки функций Javascript.

В качестве примера возьмем следующую конфигурацию:

uniqueKey: "advanced_example"
path: "/examples.greeter.api.Greeter/Hello"
method: "POST"
cases:
  - condition:
      simple:
        items:
          - operandX: "$request.header.uid"
            operator: "<="
            operandY: "1000"
    response:
      simple:
        header:
          x-unit-id: "3"
          x-unit-region: "sh"
        trailer:
          x-api-version: "1.3.2"
        body: |
          {"timestamp": "1111", "message": "This message will only be returned when uid <= 1000", "amount": "{{ $mock.price }}"}
  - condition:
      simple:
        items:
          - operandX: "$request.header.uid"
            operator: ">"
            operandY: "1000"
    response:
      script:
        lang: "javascript"
        content: |
          (function(){
              function random(min, max){
                  return parseInt(Math.random()*(max-min+1)+min,10);
              }
              return {
                  code: 0,
                  header: {
                      "x-unit-id": (request.header["uid"] % 5).toString(),
                      "x-unit-region": "bj",
                  },
                  trailer: {
                      "x-api-version": "1.3.2",
                  },
                  body: {
                      timestamp: Math.ceil(new Date().getTime() / 1000),
                      message: "this message is generated by javascript, your uid is: " + request.header["uid"],
                      amount: random(0, 5000),
                  },
              }
          })()

Эта конфигурация определяетMockAPI, для сопоставления всех путей как/examples.greeter.api.Greeter/Hello, методPOSTЗапрос, который содержит два сценария, может достичь этого эффекта:

1. Состояние Сценарий 1

Когда заголовок запросаuid <= 1000Время:

  • Напишите в шапке ответа:
x-unit-id: "3"
x-unit-region: "sh"
  • Напишите в ответном трейлере:
x-api-version: "1.3.2"
  • Напишите в теле ответа:
{"timestamp": "1111", "message": "This message will only be returned when uid <= 1000", "amount": "{{ $mock.price }}"}

один из них{{ $mock.price }}магическая переменная, используемая для возврата случайных данных о цене. В итоге клиент получаетResponse BodyПохожий на:

{
	"timestamp": "1111",
	"message": "This message will only be returned when uid <= 1000",
	"amount": 7308.4
}

2. Сценарий условий 2

Когда заголовок запросаuid > 1000, ответ возвращается путем выполнения следующего сценария Javascript:

(function(){
    function random(min, max){
        return parseInt(Math.random()*(max-min+1)+min,10);
    }
    return {
        code: 0,
        header: {
            "x-unit-id": (request.header["uid"] % 5).toString(),
            "x-unit-region": "bj",
        },
        trailer: {
            "x-api-version": "1.3.2",
        },
        body: {
            timestamp: Math.ceil(new Date().getTime() / 1000),
            message: "this message is generated by javascript, your uid is: " + request.header["uid"],
            amount: random(0, 5000),
        },
    }
})()

В этом сценарии код, заголовок, трейлер и тело ответа генерируются в соответствии с заголовком запроса и некоторыми встроенными или пользовательскими функциями. Тело ответа, полученное конечным клиентом, похоже на:

{
	"timestamp": 1622093545,
	"message": "this message is generated by javascript, your uid is: 2233",
	"amount": 314
}

Он описывает относительно сложную сцену. Конечно, ваши потребности могут быть относительно простыми. Для настоящего боя давайте начнем с Hello World!

2. Начнем с Hello World

Этот пример можно найти вобразец коданайти соответствующую информацию

Сначала создайте файл конфигурации:

log:
    pretty: true
    level: debug
grpcmockserver:
    enable: true
    address: 0.0.0.0:30002
    protomanager:
        protoimportpaths: [ ]
        protodir: ./apis
httpmockserver:
    enable: true
    address: 0.0.0.0:30003
apimanager:
    grpcaddress: 0.0.0.0:30000
    httpaddress: 0.0.0.0:30001
pluginregistry: { }
plugin:
    simple: { }
    grpc: { }
    http: { }
    script: { }
    redis:
        enable: false
        addr: 127.0.0.1:6379
        password: ""
        db: 0
        prefix: /powermock/

Поместите скомпилированный PowerMock в тот же каталог, что и файл конфигурации, созданный выше, например:

➜ ls -alh
total 45M
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:18 .
drwxrwxrwx 1 storyicon storyicon 4.0K May 24 11:43 ..
-rwxrwxrwx 1 storyicon storyicon  546 May 27 14:16 config.yaml
-rwxrwxrwx 1 storyicon storyicon  45M May 27 14:18 powermock

затем выполнить

➜ ./powermock serve --config.file config.yaml

Если конфликтов портов нет, вы уже должны увидеть, что служба запущена!

1. Сначала смоделируйте HTTP-интерфейс

В указанном выше каталоге создайте файл с именем apis.yaml:

uniqueKey: "hello_example_http"
path: "/hello"
method: "GET"
cases:
    - response:
          simple:
              header:
                  x-unit-id: "3"
                  x-unit-region: "sh"
              trailer:
                  x-api-version: "1.3.2"
              body: |
                  hello world!

Затем запустите:

➜ ./powermock load --address=127.0.0.1:30000 apis.yaml
2:32PM INF start to load file component=main file=load.go:59
2:32PM INF mock apis loaded from file component=main count=1 file=load.go:64
2:32PM INF start to save api component=main file=load.go:76 host= method=GET path=/hello uniqueKey=hello
2:32PM INF succeed! component=main file=load.go:89

Таким образом создается MockAPI, который мы описываем.

пройти черезcurlили запросы вашего браузераhttp://127.0.0.1:30003/hello, вы можете видеть, что привет мир вернулся к нам!

➜ curl http://127.0.0.1:30003/hello -i
HTTP/1.1 200 OK
Content-Type: application/json
X-Unit-Id: 3
X-Unit-Region: sh
Date: Thu, 27 May 2021 06:36:28 GMT
Content-Length: 12

hello world!

2. Смоделируйте другой интерфейс gRPC

В указанном выше каталоге создайте каталог apis, чтобы вся структура каталогов выглядела так:

➜  ls -alh
total 45M
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:42 .
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:37 ..
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:23 apis
-rwxrwxrwx 1 storyicon storyicon 1.8K May 27 14:32 apis.yaml
-rwxrwxrwx 1 storyicon storyicon  546 May 27 14:16 config.yaml
-rwxrwxrwx 1 storyicon storyicon  45M May 27 14:18 powermock

Создадим наш Greeter.proto в директории apis:

syntax = "proto3";

package examples.greeter.api;
option go_package = "github.com/bilibili-base/powermock/examples/helloWorld/apis;apis";

service Greeter {
    rpc Hello(HelloRequest) returns (HelloResponse);
}

message HelloRequest {
    string message = 2;
}

message HelloResponse {
    string message = 2;
}

Теперь вся структура каталогов выглядит так:

.
├── apis
│   └── greeter.proto
├── apis.yaml
├── config.yaml
└── powermock

повторите нашpowermockЧтобы загрузить наш недавно написанный прото-файл:

➜ ./powermock serve --config.file config.yaml
2:55PM INF starting load proto from: ./apis component=main.gRPCMockServer.protoManager file=service.go:102
2:55PM INF api loaded component=main.gRPCMockServer.protoManager file=service.go:131 name=/examples.greeter.api.Greeter/Hello

Вы можете видеть в журнале запуска, что наш недавно созданный прото-файл был загружен в PowerMock.

Измените наш файл apis.yaml следующим образом:

uniqueKey: "hello_example_http"
path: "/hello"
method: "GET"
cases:
    - response:
          simple:
              header:
                  x-unit-id: "3"
                  x-unit-region: "sh"
              trailer:
                  x-api-version: "1.3.2"
              body: |
                  hello world!

---

uniqueKey: "hello_example_gRPC"
path: "/examples.greeter.api.Greeter/Hello"
method: "POST"
cases:
    - response:
          simple:
              header:
                  x-unit-id: "3"
                  x-unit-region: "sh"
              trailer:
                  x-api-version: "1.3.2"
              body: |
                  {"message": "hello world!"}

Как видите, в него добавлен MockAPI с именем «hello_example_gRPC», и мы загружаем его с помощью следующей команды:

➜ powermock load --address=127.0.0.1:30000  apis.yaml
3:06PM INF start to load file component=main file=load.go:59
3:06PM INF mock apis loaded from file component=main count=2 file=load.go:64
3:06PM INF start to save api component=main file=load.go:76 host= method=GET path=/hello uniqueKey=hello_example_http
3:06PM INF start to save api component=main file=load.go:76 host= method=POST path=/examples.greeter.api.Greeter/Hello uniqueKey=hello_example_gRPC
3:06PM INF succeed! component=main file=load.go:89

При этом наш MockAPI добавляется в PowerMock.

Если в вашей среде есть такие инструменты, как BloomRPC, вы можете сначала загрузить Greeter.proto через BloomRPC, а затем вызвать127.0.0.1:30002:

hello_world_bloomrpc.png

Как видите, вызов успешно возвращает «hello world». Если вы используете язык программирования для вызова, возьмите в качестве примера golang, вызовите его с помощью следующего кода.PowerMock:

func main() {
	fmt.Println("starting call mock server")
	conn, err := grpc.Dial("127.0.0.1:30002", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	client := apis.NewGreeterClient(conn)

	var header, trailer metadata.MD
	startTime := time.Now()
	resp, err := client.Hello(context.TODO(), &apis.HelloRequest{
		Message: "hi",
	}, grpc.Header(&header), grpc.Trailer(&trailer))
	if err != nil {
		panic(err)
	}
	fmt.Printf("[elapsed] %d ms \r\n", time.Since(startTime).Milliseconds())
	fmt.Printf("[headers] %+v \r\n", header)
	fmt.Printf("[trailer] %+v \r\n", trailer)
	fmt.Printf("[response] %+v \r\n", resp.String())
}

Вывод журнала таков:

starting call mock server
[elapsed] 2 ms
[headers] map[content-type:[application/grpc] x-unit-id:[3] x-unit-region:[sh]]
[trailer] map[x-api-version:[1.3.2]]
[response] message:"This message will only be returned when uid <= 1000"

Как видите, наш интерфейс был успешно смоделирован!

Установить

Установить через Go

Установите обычную версию без поддержки Javascript:

go install github.com/bilibili-base/powermock/cmd/powermock

Установите версию V8, которая поддерживает Javascript:

go install github.com/bilibili-base/powermock/cmd/powermock-v8

Нестандартная версия

Если вам не нужны пользовательские плагины,Нестандартная версияИдеально подходит для вас.

Компилировать с Makefile

Что, если выlinux/darwin/wslпользователям рекомендуется использовать makefile для установки:

➜ git clone https://github.com/bilibili-base/powermock
➜ cd powermock
➜ make build_linux_v8
➜ make build_linux
➜ make build_darwin
➜ make build_windows

Конечно, вы также можете скомпилировать напрямую:

➜ cd ./cmd/powermock
➜ go install
➜ go build .