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

OSCHINA-MIRROR/andeyalee-erpc

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README_ZH.md 33 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 14.03.2025 03:24 8f67b36

eRPC GitHub release Report card GitHub issues GitHub closed issues GoDoc View examples

View Go网络编程群

eRPC

eRPC — это эффективный, масштабируемый и простой в использовании фреймворк RPC.

Подходит для использования в областях RPC, микросервисов, долгоживущих соединений типа Point-to-Point, IM и игр. ### Установка

  • версия Go ≥ 1.11
  • установка
GO111MODULE=on go get -u -v -insecure github.com/andeya/erpc/v7
  • импорт
import "github.com/andeya/erpc/v7"

Основные характеристики

  • Использует peer для предоставления одинакового API-интерфейса серверу и клиенту
  • Предоставляет многослойные абстракции, такие как:
    • peer
    • сессия/сокет
    • маршрутизатор
    • обработчик/контекст
    • сообщение
    • протокол
    • кодировка
    • фильтр передачи
    • плагин
  • Поддерживает плавное перезапускание и закрытие
  • Совместим с форматами сообщений HTTP:
    • Состоит из двух частей: Header и Body
    • Header включает метаданные такого же формата, как HTTP-заголовки
    • Body поддерживает пользовательские кодеки, аналогичные Content-Type, реализованы следующие:
      • Protobuf
      • Thrift
      • JSON
      • XML
      • Form
      • Plain
    • Поддерживает типы сообщений push, call-reply и другие
  • Поддерживает пользовательские протоколы сообщений и предлагает некоторые распространённые реализации:
    • rawproto — по умолчанию высокопроизводительный двоичный протокол
    • jsonproto — протокол сообщений JSON
    • pbproto — протокол сообщений Protobuf
    • thriftproto — протокол сообщений Thrift
    • httproto — протокол сообщений HTTP
  • Высокооптимированная производительная слой передачи данных
    • Использует неблокирующие сокеты и многоканальное мониторинг I/O
    • Поддерживает установку размера буфера I/O для сокета - Поддерживает установку максимального размера сообщения при чтении (если превышено, соединение отключается)
      • Поддерживает управление файловым дескриптором соединения
    • Поддерживает различные сетевые типы:
      • tcp
      • tcp4
      • tcp6
      • unix
      • unixpacket
      • kcp
      • quic
      • Другие
        • websocket
        • evio
    • Предоставляет богатую систему плагинов, уже реализованы:
      • аутентификация
      • привязка
      • сердцебиение
      • игнорирование регистра символов (метод службы)
      • перегрузка
      • прокси (для неизвестного метода службы)
      • безопасность
    • Сильная гибкая система логирования:
      • Подробные данные журнала, поддерживают вывод подробной информации входящих и исходящих данных
      • Поддерживают установку пороговых значений для предупреждений медленных операций
      • Поддерживают создание пользовательских компонентов журнала
    • Клиентская сессия поддерживает автоматическое восстановление после разрыва соединения### Тест производительности Самотестирование
    • Одна служба и один клиентский процесс выполняются на одной машине
    • Процессор: Intel Xeon E312xx (Sandy Bridge) 16 ядер 2.53 ГГц
    • Оперативная память: 16 ГБ
    • Операционная система: Linux 2.6.32-696.16.1.el6.centos.plus.x86_64, CentOS 6.4
    • Версия Go: 1.9.2
    • Размер сообщения: 581 байт
    • Кодировка сообщения: protobuf
    • Отправка 1 000 000 сообщений
    • erpc | Параллельные клиента | Среднее значение (мс) | Медиана (мс) | Максимальное значение (мс) | Минимальное значение (мс) | Частота транзакций (TPS) | | ------------------- | -------------------- | ------------ | ------------------------- | ------------------------ | ----------------------- | | 100 | 1 | 0 | 16 | 0 | 75505 | | 500 | 9 | 11 | 97 | 0 | 52192 | | 1000 | 19 | 24 | 187 | 0 | 50040 | | 2000 | 39 | 54 | 409 | 0 | 42551 | | 5000 | 96 | 128 | 1148 | 0 | 46367 |
    • erpc/socket | Параллельный клиент | Среднее значение (мс) | Медиана (мс) | Максимальное значение (мс) | Минимальное значение (мс) | Частота транзакций (TPS) | | ------------------- | -------------------- | ----------- | -------------------------- | -------------------------- | ------------------------- | | 100 | 0 | 0 | 14 | 0 | 225682 | | 500 | 2 | 1 | 24 | 0 | 212630 | | 1000 | 4 | 3 | 51 | 0 | 180733 || 2000 | 8 | 6 | 64 | 0 | 183351 | | 5000 | 21 | 18 | 651 | 0 | 133886 | Сравнение тестов
Окружение Частота транзакций Средняя задержка Задержка P99
**[Подробнее](https://github.com/andeya/rpc-benchmark)** - Время работы процессора в виде "огоньков" erpc/socket ![](https://github.com/andeya/erpc/raw/master/doc/erpc_socket_profile_torch.png) **[файл SVG](https://github.com/andeya/erpc/raw/master/doc/erpc_socket_profile_torch.svg)** - Информация о стеке вызовов в виде "огоньков" erpc/socket ![](https://github.com/andeya/erpc/raw/master/doc/erpc_socket_heap_torch.png) **[файл SVG](https://github.com/andeya/erpc/raw/master/doc/erpc_socket_heap_torch.svg)** ## Пример кода ### server.go ```go package main```go import ( "fmt" "time" "github.com/andeya/erpc/v7" )

func main() { defer erpc.FlushLogger() // грациозное завершение go erpc.GraceSignal()

// серверный узел
srv := erpc.NewPeer(erpc.PeerConfig{
	CountTime:   true,
	ListenPort:  9090,
	PrintDetail: true,
})
// srv.SetTLSConfig(erpc.GenerateTLSConfigForServer())

// маршрутизатор
srv.RouteCall(new(Math))

// широковещательная рассылка каждые 5 секунд
go func() {
	for {
		time.Sleep(time.Second * 5)
		srv.RangeSession(func(sess erpc.Session) bool {
			sess.Push(
				"/push/status",
				fmt.Sprintf("это широковещательное сообщение, время сервера: %v", time.Now()),
			)
			return true
		})
	}
}()

// прослушивание и обслуживание
srv.ListenAndServe()

}

// Обработчик математических операций type Math struct { erpc.CallCtx }

// Add обрабатывает запрос на сложение func (m *Math) Add(arg *[]int) (int, *erpc.Status) { // тест метаданных erpc.Infof("автор: %s", m.PeekMeta("author"))

// суммирование
var r int
for _, a := range *arg {
	r += a
}

// ответ
return r, nil

}


### Клиент
```go
package main

import (
	"time"
	"github.com/andeya/erpc/v7"
)

func main() {
	defer erpc.SetLoggerLevel("ERROR")()
	cli := erpc.NewPeer(erpc.PeerConfig{})
	defer cli.Close()
	// cli.SetTLSConfig(&tls.Config{InsecureSkipVerify: true})
	cli.RoutePush(new(Push))
	sess, stat := cli.Dial(":9090")
	if !stat.OK() {
		erpc.Fatalf("%v", stat)
	}
	var result int
	stat = sess.Call("/math/add",
		[]int{1, 2, 3, 4, 5},
		&result,
		erpc.WithAddMeta("author", "andeya"),
	).Status()
	if !stat.OK() {
		erpc.Fatalf("%v", stat)
	}
	erpc.Printf("результат: %d", result)
	erpc.Printf("Ожидание получения push в течение 10 секунд... ")
	time.Sleep(time.Second * 10)
}

// Обработчик push
type Push struct {
	erpc.PushCtx
}

// Push обрабатывает сообщение '/push/status'
func (p *Push) Status(arg *string) *erpc.Status {
	erpc.Printf("%s", *arg)
	return nil
}
```[Дополнительные примеры](https://github.com/andeya/erpc/blob/master/examples)

## Использование
**ЗАМЕЧАНИЕ:**  
- Лучше всего установить ограничение размера пакета при чтении: `SetReadLimit`.  
- По умолчанию ограничение размера пакета при чтении составляет 1 ГБ.

### Пример конечной точки Peer (сервер или клиент)
```go
// Запуск сервера
var peer1 = erpc.NewPeer(erpc.PeerConfig{
ListenPort:  9090, // для роли сервера
})
peer1.Listen()

// Запуск клиента
var peer2 = erpc.NewPeer(erpc.PeerConfig{})
var sess, err = peer2.Dial("127.0.0.1:8080")

Встроенные правила отображения ServiceMethod

  • По умолчанию используются следующие правила отображения имени структуры или метода в имя службы (HTTPServiceMethodMapper):
    • AaBb -> /aa_bb
    • ABcXYz -> /abc_xyz
    • Aa__Bb -> /aa_bb
    • aa__bb -> /aa_bb
    • ABC__XYZ -> /abc_xyz
    • Aa_Bb -> /aa/bb
    • aa_bb -> /aa/bb
    • ABC_XYZ -> /abc/xyz
erpc.SetServiceMethodMapper(erpc.HTTPServiceMethodMapper)

Маппинг структур или методов в служебные методы RPC (RPCServiceMethodMapper):

- `AaBb` -> `AaBb`
- `ABcXYz` -> `ABcXYz`
- `Aa__Bb` -> `Aa_Bb`
- `aa__bb` -> `aa_bb`
- `ABC__XYZ` -> `ABC_XYZ`
- `Aa_Bb` -> `Aa.Bb`
- `aa_bb` -> `aa.bb`
- `ABC_XYZ` -> `ABC.XYZ`
erpc.SetServiceMethodMapper(erpc.RPCServiceMethodMapper)

Шаблон Call-Struct интерфейса

type Aaa struct {
    erpc.CallCtx
}
func (x *Aaa) XxZz(arg *<T>) (<T>, *erpc.Status) {
    ...
    return r, nil
}

Регистрация в корневом маршруте:

// регистрация вызова маршрута
// HTTP отображение: /aaa/xx_zz
// RPC отображение: Aaa.XxZz
peer.RouteCall(new(Aaa))
// или регистрация вызова маршрута
// HTTP отображение: /xx_zz
// RPC отображение: XxZz
peer.RouteCallFunc((*Aaa).XxZz)
```### Шаблон call-function интерфейса

```go
func XxZz(ctx erpc.CallCtx, arg *<T>) (<T>, *erpc.Status) {
    ...
    return r, nil
}

Регистрация в корневом маршруте:

// регистрация вызова маршрута
// HTTP отображение: /xx_zz
// RPC отображение: XxZz
peer.RouteCallFunc(XxZz)

Шаблон push-struct интерфейса

type Bbb struct {
    erpc.PushCtx
}
func (b *Bbb) YyZz(arg *<T>) *erpc.Status {
    ...
    return nil
}

Регистрация в корневом маршруте:

// регистрация обработчика отправки
// HTTP отображение: /bbb/yy_zz
// RPC отображение: Bbb.YyZz
peer.RoutePush(new(Bbb))
// или регистрация обработчика отправки
// HTTP отображение: /yy_zz
// RPC отображение: YyZz
peer.RoutePushFunc((*Bbb).YyZz)

Шаблон push-function интерфейса

// YyZz регистрация обработчика
func YyZz(ctx erpc.PushCtx, arg *<T>) *erpc.Status {
    ...
    return nil
}

Регистрация в корневом маршруте:

// регистрация обработчика отправки
// HTTP отображение: /yy_zz
// RPC отображение: YyZz
peer.RoutePushFunc(YyZz)

Шаблон unknown-call-function интерфейса

func XxxUnknownCall(ctx erpc.UnknownCallCtx) (interface{}, *erpc.Status) {
    ...
    return r, nil
}

Регистрация в корневом маршруте:

// регистрация маршрута неизвестного вызова: /*
peer.SetUnknownCall(XxxUnknownCall)

Шаблон unknown-push-function интерфейса

func XxxUnknownPush(ctx erpc.UnknownPushCtx) *erpc.Status {
    ...
    return nil
}

Регистрация в корневом маршруте:```go

// регистрация маршрута неизвестной отправки: /* peer.SetUnknownPush(XxxUnknownPush)


### Пример плагинов
```go
// NewIgnoreCase возвращает плагин игнорирующего регистра.
func NewIgnoreCase() *ignoreCase {
    return &ignoreCase{}
}
type ignoreCase struct{}
var (
    _ erpc.PostReadCallHeaderPlugin = new(ignoreCase)
    _ erpc.PostReadPushHeaderPlugin = new(ignoreCase)
)
func (i *ignoreCase) Name() string {
    return "ignoreCase"
}
func (i *ignoreCase) PostReadCallHeader(ctx erpc.ReadCtx) *erpc.Status {
    // Динамическое преобразование пути в нижний регистр
    ctx.UriObject().Path = strings.ToLower(ctx.UriObject().Path)
    return nil
}
func (i *ignoreCase) PostReadPushHeader(ctx erpc.ReadCtx) *erpc.Status {
    // Динамическое преобразование пути в нижний регистр
    ctx.UriObject().Path = strings.ToLower(ctx.UriObject().Path)
    return nil
}

Регистрация примеров операций и плагинов в маршруте

// добавление группы маршрутов
group := peer.SubRoute("test")
// регистрация в группе тест
group.RouteCall(new(Aaa), NewIgnoreCase())
peer.RouteCallFunc(XxZz, NewIgnoreCase())
group.RoutePush(new(Bbb))
peer.RoutePushFunc(YyZz)
peer.SetUnknownCall(XxxUnknownCall)
peer.SetUnknownPush(XxxUnknownPush)

Конфигурационные данные

type PeerConfig struct {
    Network            string        `yaml:"network"              ini:"network"              comment:"Сеть; tcp, tcp4, tcp6, unix, unixpacket, kcp или quic"`
    LocalIP            string        `yaml:"local_ip"             ini:"local_ip"             comment:"Локальный IP"`
    ListenPort         uint16        `yaml:"listen_port"          ini:"listen_port"          comment:"Порт прослушивания; для роли сервера"`
    DialTimeout        time.Duration `yaml:"dial_timeout"         ini:"dial_timeout"         comment:"По умолчанию максимальное время ожидания соединения; для роли клиента; ns, µs, ms, s, m, h"`
}
``````markdown
    RedialTimes        int32         `yaml:"redial_times"         ini:"redial_times"         comment:"Максимальное количество попыток повторной установки соединения после его непредвиденного разрыва; без ограничений при отрицательном значении; для роли клиента"`
     RedialInterval     time.Duration `yaml:"redial_interval"      ini:"redial_interval"      comment:"Интервал между попытками повторной установки соединения; по умолчанию 100 мс; для роли клиента; ns, µs, ms, s, m, h"`
     DefaultBodyCodec   string        `yaml:"default_body_codec"   ini:"default_body_codec"   comment:"ID типа дефолтного кодека для тела сообщения"`
     DefaultSessionAge  time.Duration `yaml:"default_session_age"  ini:"default_session_age"  comment:"Длительность сессии по умолчанию"`
 }
 
 ```Продолжительность `yaml:"default_session_age"  ini:"default_session_age"  comment:"Максимальный срок действия сессии по умолчанию, если меньше либо равно 0, то нет ограничения времени; ns, µs, ms, s, m, h"`
     DefaultContextAge  time.Duration `yaml:"default_context_age"  ini:"default_context_age"  comment:"Максимальный срок действия контекста запроса по умолчанию, если меньше либо равно 0, то нет ограничения времени; ns, µs, ms, s, m, h"`
     SlowCometDuration  time.Duration `yaml:"slow_comet_duration"  ini:"slow_comet_duration"  comment:"Пороговое значение для оповещения о медленной операции; ns, µs, ms, s..."`
     PrintDetail        bool          `yaml:"print_detail"         ini:"print_detail"         comment:"Отображение содержимого и метаданных или нет"`
     CountTime          bool          `yaml:"count_time"           ini:"count_time"           comment:"Подсчет затраченного времени или нет"`
 }
```### Оптимизация связи
- **SetMessageSizeLimit** Установка верхнего предела размера сообщения,
  если `max_size`  0, верхний предел по умолчанию равен максимальному значению `uint32`
      ```go
     func SetMessageSizeLimit(max_message_size uint32)
     ```
- **SetSocketKeepAlive** Разрешение отправки пакетов keepalive TCP системой
      ```go
     func SetSocketKeepAlive(keep_alive bool)
     ```
- **SetSocketKeepAlivePeriod** Установка частоты отправки пакетов keepalive TCP системой
      ```go
     func SetSocketKeepAlivePeriod(duration time.Duration)
     ```
- **SetSocketNoDelay** Отключение алгоритма Nagle; отключение позволяет не объединять небольшие данные в один пакет передачи; по умолчанию отключено
      ```go
     func SetSocketNoDelay(no_delay bool)
     ```
- **SetSocketReadBuffer** Установка размера буфера чтения TCP системы
      ```go
     func SetSocketReadBuffer(size int)
     ```
- **SetSocketWriteBuffer** Установка размера буфера записи TCP системы
      ```go
     func SetSocketWriteBuffer(size int)
     ```## Расширяемые пакеты
### Кодеки
| пакет                                  | импорт                                   | описание                      |
| ---------------------------------------- | ---------------------------------------- | ----------------------------- |
| [json](https://github.com/andeya/erpc/blob/master/codec/json_codec.go) | `"github.com/andeya/erpc/v7/codec"` | JSON кодек (собственный erpc)|
| [protobuf](https://github.com/andeya/erpc/blob/master/codec/protobuf_codec.go) | `"github.com/andeya/erpc/v7/codec"` | Protobuf кодек (собственный erpc)|
| [thrift](https://github.com/andeya/erpc/blob/master/codec/thrift_codec.go) | `"github.com/andeya/erpc/v7/codec"` | Thrift кодек (собственный erpc)|
| [url](https://github.com/andeya/erpc/blob/master/codec/url_codec.go) | `"github.com/andeya/erpc/v7/codec"` | Кодек для URL-кодировки              |
| [xml](https://github.com/andeya/erpc/blob/master/codec/xml_codec.go) | `"github.com/andeya/erpc/v7/codec"` | XML-кодек                          |
| [plain](https://github.com/andeya/erpc/blob/master/codec/plain_codec.go) | `"github.com/和deya/erpc/v7/codec"` | Кодек для обычного текста          |
| [form](https://github.com/andeya/erpc/blob/master/codec/form_codec.go) | `"github.com/andeya/erpc/v7/codec"` | Кодек для формы с URL-кодировкой   |

Замечено, что в последней строке есть некорректно переведенный текст `和deya`, который следует заменить на `andeya`.### плагины
| пакет                                    | импорт                                   | описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [auth](https://github.com/andeya/erpc/tree/master/plugin/auth) | `"github.com/andeya/erpc/v7/plugin/auth"` | Плагин аутентификации для проверки соединений при первом обращении |
| [binder](https://github.com/andeya/erpc/tree/master/plugin/binder) | `"github.com/andeya/erpc/v7/plugin/binder"` | Плагин проверки привязки параметров для обработчика структур |
| [heartbeat](https://github.com/andeya/erpc/tree/master/plugin/heartbeat) | `"github.com/andeya/erpc/v7/plugin/heartbeat"` | Универсальный плагин для отправки сигналов жизнедеятельности |
| [proxy](https://github.com/andeya/erpc/tree/master/plugin/proxy) | `"github.com/andeya/erpc/v7/plugin/proxy"` | Прокси-плагин для обработки неизвестных вызовов или отправок |
| [secure](https://github.com/andeya/erpc/tree/master/plugin/secure) | `"github.com/andeya/erpc/v7/plugin/secure"` | Плагин шифрования/расшифровки сообщений |
| [overloader](https://github.com/andeya/erpc/tree/master/plugin/overloader) | `"github.com/andeya/erpc/v7/plugin/overloader"` | Плагин защиты от перегрузки |### протоколы
| пакет                                    | импорт                                   | описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [rawproto](https://github.com/andeya/erpc/tree/master/proto/rawproto) | `"github.com/andeya/erpc/v7/proto/rawproto"` | Высокоэффективный протокол связи (по умолчанию в erpc) |
| [jsonproto](https://github.com/andeya/erpc/tree/master/proto/jsonproto) | `"github.com/andeya/erpc/v7/proto/jsonproto"` | Протокол связи в формате JSON         |
| [pbproto]                               | пакет                                    | импорт                                   | описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [pbproto](https://github.com/andeya/erpc/tree/master/proto/pbproto) | `"github.com/andeya/erpc/v7/proto/pbproto"` | Канал связи в формате Protocol Buffers |
| [thriftproto](https://github.com/andeya/erpc/tree/master/proto/thriftproto) | `"github.com/andeya/erpc/v7/proto/thriftproto"` | Канал связи в формате Apache Thrift    |
| [httproto](https://github.com/andeya/erpc/tree/master/proto/httproto) | `"github.com/andeya/erpc/v7/proto/httproto"` | Канал связи в формате HTTP             |

### Протоколы
| Пакет                                    | Импорт                                   | Описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [rawproto](https://github.com/andeya/erpc/tree/master/proto/rawproto) | `"github.com/andeya/erpc/v7/proto/rawproto"` | Высокоэффективный протокол связи (по умолчанию в erpc) |
| [jsonproto](https://github.com/andeya/erpc/tree/master/proto/jsonproto) | `"github.com/edneya/erpc/v7/proto/jsonproto"` | Протокол связи в формате JSON         |
| [pbproto]                               | Пакет                                    | Импорт                                   | Описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [pbproto](https://github.com/andeya/erpc/tree/master/proto/pbproto) | `"github.com/andeya/erpc/v7/proto/pbproto"` | Канал связи в формате Protocol Buffers |
| [thriftproto](https://github.com/andeya/erpc/tree/master/proto/thriftproto) | `"github.com/andeya/erpc/v7/proto/thriftproto"` | Канал связи в формате Apache Thrift    |
| [httproto](https://github.com/andeya/erpc/tree/master/proto/httproto) | `"github.com/andeya/erpc/v7/proto/httproto"` | Канал связи в формате HTTP             |### Транспортные фильтры
| пакет                                    | импорт                                   | описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [gzip](https://github.com/andeya/erpc/tree/master/xfer/gzip) | `"github.com/andeya/erpc/v7/xfer/gzip"` | Фильтр сжатия данных GZIP (собственный) |
| [md5](https://github.com/andeya/erpc/tree/master/xfer/md5) | `"github.com/andeya/erpc/v7/xfer/md5"` | Фильтр проверки целостности данных MD5 |

### Другие модули
| пакет                                    | импорт                                   | описание                                |
| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- |
| [multiclient](https://github.com/andeya/erpc/tree/master/mixer/multiclient) | `"github.com/andeya/erpc/v7/mixer/multiclient"` | Буфер соединений клиента высокой пропускной способности при передаче больших сообщений (например, загрузке файлов) |
| [websocket](https://github.com/andeya/erpc/tree/master/mixer/websocket) | `"github.com/andeya/erpc/v7/mixer/websocket"` | Интеграция eRPC с протоколом WebSocket согласно спецификации RFC 6455 |
| [evio](https://github.com/andeya/erpc/tree/master/mixer/evio) | `"github.com/andeya/erpc/v7/mixer/evio"` | Быстрый сетевой фреймворк событийного цикла, использующий слой API eRPC |
| [html](https://github.com/xiaoenai/tp-micro/tree/master/helper/mod-html) | `html "github.com/xiaoenai/tp-micro/helper/mod-html"` | Генерация HTML для HTTP клиентов |## Проекты на основе eRPC
| проект                                  | описание                                |
| ---------------------------------------- | ---------------------------------------- |
| [TP-Micro](https://github.com/xiaoenai/tp-micro) | TP-Micro — это минималистичный и мощный микросервисный фреймворк, основанный на eRPC. |
| [Pholcus](https://github.com/andeya/pholcus) | Pholcus (Паучок) — это мощный веб-скрейпер, написанный на чистом Go и поддерживающий распределённую архитектуру с высокой пропускной способностью. Программа направлена на сбор данных с интернета и предоставляет пользователям с навыками программирования на Go или JavaScript мощный инструмент для создания собственных правил. |

## Корпоративные пользователи
<a href="http://www.xiaoenai.com"><img src="https://raw.githubusercontent.com/andeya/imgs-repo/master/xiaoenai.png" height="50" alt="Shenzhen Mengzhiduo Information Technology Co., Ltd."/></a>
&nbsp;&nbsp;
<a href="https://tech.pingan.com/index.html"><img src="http://pa-tech.hirede.com/templates/pa-tech/Images/logo.png" height="50" alt="Ping An Technology"/></a>
<br/>
<a href="http://www.fun.tv"><img src="http://static.funshion.com/open/static/img/logo.gif" height="70" alt="Beijing FengXing Online Technology Co., Ltd."/></a>
&nbsp;&nbsp;
<a href="http://www.kejishidai.cn"><img src="http://simg.ktvms.com/picture/logo.png" height="70" alt="Beijing Keji Shidai Network Company"/></a>
<a href="https://www.kuaishou.com/"><img src="https://inews.gtimg.com/newsapp_bt/0/4400789257/1000" height="70" alt="KuaiShou Short Video Platform"/></a>

## Лицензионное соглашение
Проект eRPC использует лицензию Apache 2.0, которая является дружественной для коммерческого использования. [Apache2.0](https://github.com/andeya/erpc/raw/master/LICENSE)

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

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

1
https://api.gitlife.ru/oschina-mirror/andeyalee-erpc.git
git@api.gitlife.ru:oschina-mirror/andeyalee-erpc.git
oschina-mirror
andeyalee-erpc
andeyalee-erpc
master