1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/teamlint-nrpc

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README.md 12 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 06.03.2025 06:08 334f5fa

NRPC

Статус сборки

NRPC — это фреймворк RPC, основанный на NATS.

С помощью файлов .proto генерируются клиентская и серверная части NRPC, а также обработчики сообщений NATS MsgHandler.

Почему использовать NATS?

На основе модели Request-Reply NATS можно получить ряд преимуществ перед gRPC:

  • Минимальная система открытия служб: Клиентам и серверам достаточно знать узел соединения NATS-кластера; клиентам не требуется дополнительное открытие служб.
  • Простое балансирование нагрузки: Каждый микросервис подключается к одному и тому же кластеру NATS, используя группы очередей NATS Queue Groups для случайной обработки входящих запросов, что позволяет избежать использования дополнительных балунсеров нагрузки.

Конечно, при очень высокой нагрузке сам кластер NATS может стать узким местом. Также некоторые продвинутые возможности, такие как потоковая обработка и расширенная аутентификация, могут отсутствовать, но NRPC упрощает сложность операций, поэтому он остаётся отличным выбором для средних по размеру приложений.

NRPC успешно используется в SaaS продукте OpsDash и демонстрирует хорошие результаты.

ОбзорС NRPC прилагается плагин компилятора протоколов protobuf protoc-gen-nrpc, который сгенерирует код из файлов .proto.

Допустим, имеется файл .proto, например: helloworld.proto, тогда можно воспользоваться следующими командами:

$ ls
helloworld.proto
$ protoc --go_out=. --nrpc_out=. helloworld.proto
$ ls
helloworld.nrpc.go	helloworld.pb.go	helloworld.proto

Сгенерированный файл .pb.go создается стандартным плагином Go и содержит определения сообщений, файл .nrpc.go создается плагином NRPC и содержит определения сервисных интерфейсов, а также код для вызова клиентской и серверной частей, а также обработчики сообщений NATS.

Структура кода:

Модель RPC

Вызовы

Режим запрос-ответ

Стандартный режим

Сервер подписывается на сообщение, клиент отправляет сообщение запроса для получения ответа.

Режим потока ответов

В этом режиме после установления соединения между клиентом и сервером, последний продолжает отправлять сообщения клиенту. Метод клиента создает обратный вызов для чтения сообщений от сервера до завершения передачи данных.Пример:

Определение Proto:

option (nrpc.packageSubjectParams) = "instance"; // Параметры темы пакета

service SvcCustomSubject {
	option (nrpc.serviceSubject) = 'custom_subject'; // Уникальная тема сервиса
	rpc MtStreamedReply(StringArg) returns (SimpleStringReply) {
  		option (nrpc.streamedReply) = true;
	}
}

Имплементация серверной части:

func (s BasicServerImpl) MtStreamedReply(ctx context.Context, req *StringArg, send func(rep *SimpleStringReply)) error {
	if req.GetArg1() == "please fail" {
		panic("Failing")
	}
	if req.GetArg1() == "very long call" {
		select {
			case <-ctx.Done():
				return ctx.Err()
			case <-time.After(time.Minute):
				time.Sleep(time.Minute)
				return nil
		}
	}
	time.Sleep(time.Second)
	send(&SimpleStringReply{Reply: "msg1"})
	time.Sleep(250 * time.Millisecond)
	send(&SimpleStringReply{Reply: "msg2"})
	time.Sleep(250 * time.Millisecond)
	send(&SimpleStringReply{Reply: "msg3"})
	time.Sleep(250 * time.Millisecond)
	return nil
}

Вызов клиента:

client := NewSvcCustomSubjectClient(c, "default") // default — значение параметра темы пакета
err := client.MtStreamedReply(context.Background(), &StringArg{Arg1: "arg"}, func(ctx context.Context, rep *SimpleStringReply) {
	fmt.Println("получено", rep)
	resChan <- rep.GetReply()
})

Результат:

получено reply:"msg1"
получено reply:"msg2"
получено reply:"msg3"

Режим без ответа

Клиент отправляет сообщение, сервер реализует логику обработки сообщения, но не возвращает никакого значения.

Определение Proto:

option (nrpc.packageSubjectParams) = "instance"; // Параметры темы пакета

service SvcCustomSubject {
	option (nrpc.serviceSubject) = 'custom_subject'; // Уникальная тема сервиса
	rpc MtRequestNoReply(StringArg) returns (nrpc.NoReply) {}
}
```**Имплементация серверной части:**
```go
func (s BasicServerImpl) MtRequestNoReply(ctx context.Context, req *StringArg) {
	s.t.Log("Отправлю в MtRequestNoReply")
	s.t.Logf("клиент отправил сообщение = %v\n", *req)
	// TODO: Обработать сообщение от клиента. Для длительных задач можно создать NoRequest API и здесь отправить клиенту сообщение, которое он будет использовать для дальнейшей обработки, например:
	s.handler.MtNoRequestPublish("default", &SimpleStringReply{Reply: "Привет"})
}

Клиентский вызов:```go // Client subscribes to a message c1 := NewSvcCustomSubjectClient(conn, "default") arg := "[client.sync]req-noreply -> [server]process -> [server]publish to client" // Creating a synchronous subscriber for messages sub, err := c1.MtNoRequestSubscribeSync() // Subscription method created in the NoRequest mode if err != nil { t.Fatal(err) } defer sub.Unsubscribe() err = c1.MtRequestNoReply(&StringArg{Arg1: arg}) // Client's NoReply method if err != nil { t.Fatal(err) } // Getting the message reply, err := sub.Next(10 * time.Second) if err != nil { t.Fatal(err) }


#### Mode without request (NoRequest)

The server publishes messages and the client subscribes to them.

- Server generates

  The server **does not create interface methods**, but instead creates a method `RPCMethodName + Publish` used for publishing messages.

- Client generates

  - Method `RPCMethodName + Subject` for obtaining the message topic,
  - Method `RPCMethodName + Subscribe` for asynchronous subscription to the topic,
  - Method `RPCMethodName + SubscribeSync` for synchronous subscription to the topic,
  - Method `RPCMethodName + SubscribeChan` for subscribing through a channel.

**Protocol Proto**:

```protobuf
option (nrpc.packageSubjectParams) = "instance"; // Package subject parameters

service SvcCustomSubject {
	rpc MtNoRequest(nrpc.NoRequest) returns (SimpleStringReply) {}
}

Server implementation:

Since the server does not create interface methods, there is no need for specific implementation. Instead, the server creates a method RPCMethodName + Publish.

Client call:

The client directly subscribes to the message topic for its processing, supporting synchronous, asynchronous, and subscription through a channel.```go // Client subscribes to a message c1 := NewSvcCustomSubjectClient(conn, "default") repChan := make(chan string) // Creating an asynchronous subscriber for messages sub, err := c1.MtNoRequestSubscribe(func(reply *SimpleStringReply) { defer close(repChan) repChan <- reply.GetReply() }) if err != nil { t.Fatal(err) } defer sub.Unsubscribe() // Getting the message for rep := range repChan { t.Log(rep) }


### Protocol Parameters Protobuf

- nrpc.Void — empty parameter

  Does not change the call mode; the server returns a value with errors.

- nrpc.NoReply — changes the call mode
  The client uses the PUB model, and the server does not return anything (no errors).

- nrpc.NoRequest — changes the call mode, does not create interface methods
  The server uses the PUB model for publishing messages, method signature `RPCMethodName + Publish`.
  The client subscribes to messages,

  - subscription method `RPCMethodName + Subscribe[Sync|Chan]`,
  - method for obtaining the subject of the message `RPCMethodName + Subject`.

## Characteristics

For detailed information, follow these links:

- [Load Balancing](https://github.com//nrpc/wiki/Load-Balancing)
- [Metrics Monitoring](https://github.com/teamlint/nrpc/wiki/Metrics-Instrumentation)
  using [Prometheus](https://github.com/prometheus/prometheus)

## Installation

### Installing the Proto protocol

[Download](https://github.com/protocolbuffers/protobuf) and install the protobuf protocol compiler

### Installing the protoc plugin for Go

```shell
$ go install google.golang.org/protobuf/cmd/protoc-gen-go

Installing the protoc plugin for NRPC

$ go get github.com/teamlint/nrpc/protoc-gen-nrpc
```

## Примеры

Компиляция и запуск сервера примера `greeter_server`:

```shell
$ go get github.com/teamlint/nrpc/examples/helloworld/greeter_server
$ greeter_server
Сервер работает, ^C завершает работу.
```

Компиляция и запуск клиента примера `greeter_client`:

```shell
$ go get github.com/teamlint/nrpc/examples/helloworld/greeter_client
$ greeter_client
Приветствие: Hello world
```

## Дополнительная информация

Узнайте, как использовать файлы .proto для описания сервисов gRPC, [здесь](https://grpc.io/docs/guides/concepts.html).
Дополнительная информация о NATS доступна на [официальном сайте NATS](https://nats.io/).

## Статус проекта
На данный момент поддерживаются только Go-модули.

Исходная версия была создана командой RapidLoop, а расширена и доработана командой Teamlint.

## Запланированные задачи

- Реализация времени ожидания запроса в клиенте NRPC или использование CallOption или контекста
- Переработка protoc-gen-nrpc с использованием [protogen](google.golang.org/protobuf/compiler/protogen)
- Поддержка динамического вызова различных клиентов через Hub, передача параметров пакета?

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/teamlint-nrpc.git
git@api.gitlife.ru:oschina-mirror/teamlint-nrpc.git
oschina-mirror
teamlint-nrpc
teamlint-nrpc
master