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

OSCHINA-MIRROR/zuoqi200-TarsGo

Клонировать/Скачать
README.zh.md 50 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 08.06.2025 21:13 bbeb55c

Документация Tarsgo

О проекте

  • Tarsgo — это высокопроизводительный фреймворк RPC, основанный на языке программирования Golang и использующий протокол Tars. С ростом популярности контейнерных технологий, таких как Docker, Kubernetes и etcd, язык Go стал широко распространенным. Механизм многопоточности Go (goroutines) делает его идеальным выбором для разработки масштабируемых и высокопроизводительных серверных приложений. Go сочетает в себе производительность, близкую к C/C++, и удобство разработки, подобное Python. В Tencent часть разработчиков, работающих на C++, постепенно переходит на Go. Фреймворк RPC Tars уже поддерживает C++/Java/Nodejs/Php, и его интеграция с Go становится неизбежной. В ответ на просьбы пользователей мы представили Tarsgo, который уже используется в проектах Tencent Maps, MyApp, Internet+, и других.
  • Для получения информации о структуре и концепциях Tars, прочитайте введение в Tars.## Основные функции
  • Инструмент Tars2go: автоматическое создание и преобразование файлов Tars в Go, включая реализацию RPC-сервера и клиента на Go.
  • Библиотеки сериализации и десериализации Tars на Go.
  • Поддержка сервера для отправки пульса, статистики, обработки пользовательских команд, базового логирования.
  • Поддержка клиента для прямого подключения и маршрутизации, автоматического переподключения, регулярного обновления состояния узлов и поддержки протоколов UDP/TCP.
  • Поддержка удаленного логирования.
  • Поддержка отправки данных мониторинга.
  • Поддержка групп set.
  • Поддержка Protocol Buffers, подробнее см. pb2tarsgo.## Установка
  • Для установки OSS и других базовых служб, см. документацию по установке.
  • Для быстрой установки, см. быстрое развертывание.
  • Требуется Go 1.9.x или выше, см. https://golang.org/doc/install.
  • Установка: go get -u github.com/TarsCloud/TarsGo/tars

Быстрый старт

Показатели производительности

  • Для просмотра показателей производительности, см. tars_go_performance.md.

Использование

1 Сервер

  • Ниже приведен полный пример, демонстрирующий, как использовать Tarsgo для создания сервера.

1.1 Определение интерфейса

В папке $GOPATH/src создайте файл Tars, например hello.tars, в директории $GOPATH/src/TestApp/TestServer/hello.tars. Для получения дополнительной информации о протоколе Tars, см. https://github.com/TarsCloud/TarsTup/blob/master/docs-en/tars_tup.md.

module TestApp
{
interface Hello
{
    int test();
    int testHello(string sReq, out string sRsp);
};
};

1.2 Компиляция определения интерфейса

1.2.1 Сборка tars2go

Компиляция и установка инструмента tars2go

go install $GOPATH/src/github.com/TarsCloud/TarsGo/tars/tools/tars2go
1.2.2 Компиляция tars-файла и преобразование в go-файл
tars2go --outdir=./vendor hello.tars

1.3 Реализация интерфейса

package main

import (
    "github.com/TarsCloud/TarsGo/tars"

    "TestApp"
)

type HelloImp struct {
}

// Реализация интерфейса Test
func (imp *HelloImp) Test() (int32, error) {
    return 0, nil 
}

// Реализация интерфейса TestHello
``````go
func (imp *HelloImp) TestHello(in string, out *string) (int32, error) {
    *out = in
    return 0, nil 
}


func main() { // Инициализация служб
    imp := new(HelloImp)                                    // Создание реализации
    app := new(TestApp.Hello)                               // Создание и инициализация приложения Tars
    cfg := tars.GetServerConfig()                           // Получение объекта конфигурации сервера
    app.AddServant(imp, cfg.App+"."+cfg.Server+".HelloObj") // Регистрация служб
    tars.Run()
}

Описание:

  • HelloImp — это структура, в которой вы реализуете интерфейсы Hello и Test. Обратите внимание, что Test и Hello должны начинаться с заглавной буквы, чтобы быть экспортированными. Это единственное отличие от определения в tars-файле.
  • TestApp.Hello — это структура, созданная инструментом tars2go, и она находится в файле ./vendor/TestApp/Hello_IF.go. В этом файле содержится пакет TestApp, который соответствует модулю TestApp в tars-файле.
  • tars.GetServerConfig() используется для получения конфигурации сервера.
  • cfg.App + "." + cfg.Server + ".HelloObj" — это имя объекта, связанного с службой, которое используется клиентом для доступа к серверу.

1.4 Конфигурация сервера

tars.GetServerConfig() возвращает конфигурацию сервера, которая определена следующим образом:

type serverConfig struct {
	Node      string
	App       string
	Server    string
	LogPath   string
	LogSize   string
	LogLevel  string
	Version   string
	LocalIP   string
	BasePath  string
	DataPath  string
	Config    string
	Notify    string
	Log       string
	NetThread int
	Adapters  map[string]adapterConfig
}
```	Container   string
 	Isdocker    bool
 	Enableset   bool
 	Setdivision string
 }
 ```- Node: локальный адрес tarsnode, используется только при развертывании на платформе Tars.
 - APP: имя приложения.
 - Server: имя сервиса.
 - LogPath: путь для сохранения логов.
 - LogSize: размер для переключения логов.
 - LogLevel: уровень для переключения логов.
 - Version: версия Tarsg.
 - LocalIP: локальный IP-адрес.
 - BasePath: базовый путь для двоичных файлов.
 - DataPath: путь для хранения кэшированных файлов.
 - Config: центр конфигурации для получения конфигураций, например, tars. tarsconfig. ConfigObj
 - Notify: центр уведомлений для отправки отчетов, например, tars. tarsnotify. NotifyObj
 - Log: удалённый центр логов, например, tars. tarslog. LogObj
 - NetThread: резервный поток Go для управления получением и отправкой пакетов.
 - Adapters: специфическая конфигурация для каждого адаптера.
 - Container: резервное поле для будущего использования, используется для хранения имени контейнера.
 - Isdocker: резервное поле для будущего использования, используется для указания, запущен ли сервис в контейнере.
 - Enableset: если используется set, то значение True.
 - Setdivision: указывает, какой set используется, например, gray. sz. *Вот пример конфигурации сервера:
 ```xml
 <tars>
   <application>
       enableset=Y
       setdivision=gray. sz. *
     <server>
        node=tars. tarsnode. ServerObj@tcp -h 10. 120. 129. 226 -p 19386 -t 60000
        app=TestApp
        server=HelloServer
        localip=10. 120. 129. 226
        local=tcp -h 127. 0. 0. 1 -p 20001 -t 3000
        basepath=/usr/local/app/tars/tarsnode/data/TestApp. HelloServer/bin/
        datapath=/usr/local/app/tars/tarsnode/data/TestApp. HelloServer/data/
        logpath=/usr/local/app/tars/app_log/
 ```       logsize=10М
        config=tars. tarsconfig. ConfigObj
        notify=tars. tarsnotify. NotifyObj
        log=tars. tarslog. LogObj
        #тайм-аут для деактивации, мс.
        deactivating-timeout=2000
        logLevel=DEBUG
     </server>
   </application>
 </tars>
 ```#### 1.5 Адаптер
Адаптер связывает IP и порт для каждого объекта. В примере реализации серверного кода, 
`app.AddServant(imp, cfg.App + "." + cfg.Server + ".HelloObj")` выполняет настройку и связывает реализацию адаптера для `HelloObj`. Пример полной конфигурации адаптера приведен ниже:

```xml
<tars>
  <application>
    <server>
       <!-- each adapter configuration -->
       <TestApp.HelloServer.HelloObjAdapter>
            <!-- allow Ip for white list -->
            allow
            <!-- ip and port to listen on -->
            endpoint=tcp -h 10.120.129.226 -p 20001 -t 60000
            <!-- handlegroup -->
            handlegroup=TestApp.HelloServer.HelloObjAdapter
            <!-- max connection -->
            maxconns=200000
            <!-- portocol, only tars for now -->
            protocol=tars
            <!-- max capbility in handle queue -->
            queuecap=10000
            <!-- timeout in ms for the request in the queue -->
            queuetimeout=60000
            <!-- servant -->
            servant=TestApp.HelloServer.HelloObj
            <!-- threads in handle server side implement code. goroutine for golang -->
            threads=5
       </TestApp.HelloServer.HelloObjAdapter>
    </server>
  </application>
</tars>

1.6 Запуск сервераСледующая команда используется для запуска сервера:

./HelloServer --config=config.conf

Для полного примера конфигурации config.conf, пожалуйста, обратитесь ниже. В следующем разделе мы объясним конфигурацию клиента.```xml enableset=n setdivision=NULL node=tars.tarsnode.ServerObj@tcp -h 10.120.129.226 -p 19386 -t 60000 app=TestApp server=HelloServer localip=10.120.129.226 local=tcp -h 127.0.0.1 -p 20001 -t 3000 basepath=/usr/local/app/tars/tarsnode/data/TestApp.HelloServer/bin/ datapath=/usr/local/app/tars/tarsnode/data/TestApp.HelloServer/data/ logpath=/usr/local/app/tars/app_log/ logsize=10M config=tars.tarsconfig.ConfigObj notify=tars.tarsnotify.NotifyObj log=tars.tarslog.LogObj deactivating-timeout=2000 logLevel=DEBUG <TestApp.HelloServer.HelloObjAdapter> allow endpoint=tcp -h 10.120.129.226 -p 20001 -t 60000 handlegroup=TestApp.HelloServer.HelloObjAdapter maxconns=200000 protocol=tars queuecap=10000 queuetimeout=60000 servant=TestApp.HelloServer.HelloObj threads=5 </TestApp.HelloServer.HelloObjAdapter> locator=tars.tarsregistry.QueryObj@tcp -h 10.120.129.226 -p 17890 sync-invoke-timeout=3000 async-invoke-timeout=5000 refresh-endpoint-interval=60000 report-interval=60000 sample-rate=100000 max-sample-count=50 asyncthread=3 modulename=TestApp.HelloServer

Пользователи могут легко писать клиентский код без необходимости писать код для коммуникации, использующий определённый протокол.
#### 2.1 Пример клиента
Пожалуйста, обратитесь к следующему примеру клиента:```go

package main

import (
    "fmt"
    "github.com/TarsCloud/TarsGo/tars"
    "TestApp"
)
// tars.Communicator следует инициализировать только один раз и сделать глобальным
var comm *tars.Communicator

func main() {
    comm = tars.NewCommunicator()
    obj := "TestApp.TestServer.HelloObj@tcp -h 127.0.0.1 -p 10015 -t 60000"
    app := new(TestApp.Hello)
    comm.StringToProxy(obj, app)
    var req string = "Hello Wold"
    var res string
    ret, err := app.TestHello(req, &res)
    if err != nil {
        fmt.Println(err)
        return
    }   
    fmt.Println(ret, res)

Описание:

  • Пакет TestApp создан инструментом tars2go на основе файлов протокола Tars.
  • comm: Communicator используется для коммуникации с сервером, он должен инициализироваться только один раз и быть глобальным.
  • obj: Имя объекта, используемое для указания IP-адреса и порта сервера. Обычно перед символом "@" требуется только имя объекта.
  • app: Приложение, связанное с интерфейсом, определённым в файле Tars. В данном примере это TestApp.Hello.
  • StringToProxy: Метод StringToProxy используется для привязки имени объекта и приложения, если этого не сделать, коммуникатор не будет знать, кто коммуницирует с приложением.
  • req, res: Входные и выходные параметры, определённые в файле Tars, используются в методе TestHello.
  • app.TestHello используется для вызова метода, определённого в файле Tars, и возвращает ret и err.

2.2 Коммуникатор

Коммуникатор представляет собой набор ресурсов для отправки и получения пакетов клиентом, который в конечном итоге управляет сокетной коммуникацией каждого объекта. В одном приложении требуется только один коммуникатор.

var comm *tars.Communicator
comm = tars.NewCommunicator()
comm.SetProperty("property", "tars.tarsproperty.PropertyObj")
comm.SetProperty("locator", "tars.tarsregistry.QueryObj@tcp -h ... -p ...")
```Описание:
 > * Формат конфигурационного файла коммуникатора будет описан позже.
 > * Конфигурация коммуникатора может быть выполнена без конфигурационного файла, и все параметры имеют значения по умолчанию.
 > * Коммуникатор также может быть инициализирован напрямую методом "SetProperty".
 > * Если вам не требуется конфигурационный файл, вы должны самостоятельно настроить параметр locator. Описание свойств коммутирующего агента:
 > * locator: адрес главного сервиса должен быть в формате "ip:port". Если вам не требуется, чтобы главный сервис находил сервис, то это свойство не нужно настраивать.
 > * important async-invoke-timeout: максимальное время ожидания клиента при вызове (в миллисекундах), значение по умолчанию равно 3000.
 > * sync-invoke-timeout: в настоящее время не используется в tarsgo.
 > * refresh-endpoint-interval: интервал времени между регулярными запросами к главному сервису для получения информации (в миллисекундах), значение по умолчанию равно одной минуте.
 > * stat: адрес сервиса, вызываемого между модулями. Если это свойство не настроено, то отправленные данные будут игнорироваться.
 > * property: адрес, по которому сервис отправляет свои свойства. Если это свойство не настроено, то отправленные данные будут игнорироваться.
 > * report-interval: в настоящее время не используется в tarsgo.
 > * asyncthread: отброшено tarsgo.
 > * modulename: имя модуля, значение по умолчанию — имя исполняемого файла.Формат конфигурационного файла коммутирующего приложения следующий:
```xml
<tars>
   <application>
     <!-- Конфигурация, требуемая для прокси -->
     <client>
         <!-- Адрес -->
         locator                     = tars. tarsregistry. QueryObj@tcp -h 127. 0. 0. 1 -p 17890
         <!-- Максимальное время ожидания (в миллисекундах) для синхронных вызовов -->
         sync-invoke-timeout         = 3000
         <!-- Максимальное время ожидания (в миллисекундах) для асинхронных вызовов -->
         async-invoke-timeout        = 5000
         <!-- Максимальное время ожидания (в миллисекундах) для синхронных вызовов -->
         refresh-endpoint-interval   = 60000
         <!-- Используется для межмодульных вызовов -->
         stat                        = tars. tarsstat. StatObj
         <!-- Адрес, используемый для отчета о свойствах -->
         property                    = tars. tarsproperty. PropertyObj
         <!-- Интервал отчета времени -->
         report-interval             = 60000
         <!-- Количество потоков, обрабатывающих асинхронные ответы -->
         asyncthread                 = 3
         <!-- Имя модуля -->
         modulename                  = Test. HelloServer
     </client>
   </application>
 </tars>

2.3 Управление таймаутами

Если вы хотите использовать управление таймаутами на клиенте, используйте TarsSetTimeout в миллисекундах.

    app := new(TestApp. Hello)
    comm. StringToProxy(obj, app)
    app. TarsSetTimeout(3000)
```#### 2.4 Вызовы интерфейсов

В этом разделе подробно описано, как клиент Tars осуществляет удалённые вызовы на сервере.

Сначала кратко описаны режимы адресации клиента Tars. Затем будут описаны методы вызова клиента, включая, но не ограничиваясь, односторонними вызовами, синхронными вызовами, асинхронными вызовами, вызовами с хэшированием и т.д.

##### 2.4.1 Краткое описание режимов адресации.

Режимы адресации услуг Tars обычно делятся на два типа: имя услуги зарегистрировано на мастер-сервере, имя услуги не зарегистрировано на мастер-сервере. Мастер — это специализированный сервис имен, используемый для регистрации информации о узлах сервиса (роутинг сервис).

Добавление имени услуги в сервис имен осуществляется через платформу управления операциями.

Для услуг, не зарегистрированных на мастер-сервере, можно разделить на прямую адресацию, то есть перед вызовом услуги необходимо указать IP-адрес поставщика услуги. Клиенту необходимо указать конкретный адрес объекта HelloObj при вызове услуги, то есть Test.HelloServer.HelloObj@tcp -h 127.0.0.1 -p 9985

Test.HelloServer.HelloObj: Имя объекта

tcp: Протокол TCP

-h: Указание адреса хоста, здесь это 127.0.0.1

-p: порт, здесь это 9985Если HelloServer запущен на двух серверах, то инициализация приложения выглядит следующим образом:
obj := "Test.HelloServer.HelloObj@tcp -h 127.0.0.1 -p 9985:tcp -h 192.168.1.1 -p 9983"
app := new(TestApp.Hello)
comm.StringToProxy(obj, app)
Адрес `HelloObj` устанавливается для адресов двух серверов. В этом случае запросы будут распределяться между двумя серверами (можно указать метод распределения, но это не рассматривается здесь). Если один из серверов выключен, запросы будут автоматически перенаправлены на другой сервер, а серверы будут регулярно перезапускаться.Для зарегистрированных в мастере сервисов, сервисы будут адресоваться по имени сервиса. Когда клиент запрашивает сервис, ему не нужно указывать конкретный адрес `HelloServer`, но при создании или инициализации коммуникатора необходимо указать адрес `registry`.

Вот пример, показывающий адрес мастера через установку параметров коммуникатора:

var *tars.Communicator comm = tars.NewCommunicator() comm.SetProperty("locator", "tars.tarsregistry.QueryObj@tcp -h ... -p ...")

Так как клиенту требуется зависеть от адреса мастера, мастер также должен обладать возможностью отказоустойчивости. Методы отказоустойчивости мастера такие же, как и выше, то есть указывается адрес двух мастеров.

##### 2.4.2. Односторонний вызов
TODO. tarsgo временно не поддерживает.

##### 2.4.3. Синхронный вызов
```go
package main

import (
    "fmt"
    "github.com/TarsCloud/TarsGo/tars"
    "TestApp"
)

var *tars.Communicator
func main() {
    comm = tars.NewCommunicator()
    obj := "TestApp.TestServer.HelloObj@tcp -h 127.0.0.1 -p 10015 -t 60000"
    app := new(TestApp.Hello)
    comm.StringToProxy(obj, app)
	var req string = "Hello Wold"
    var res string
    ret, err := app.TestHello(req, &res)
    if err != nil {
        fmt.Println(err)
        return
    }   
    fmt.Println(ret, res)
2.4.4. Асинхронный вызов

tarsgo позволяет легко использовать асинхронные вызовы с помощью goroutine. В отличие от C++, нам не нужно реализовывать обратные вызовы.

package main```go
import (
    "fmt"
    "github.com/TarsCloud/TarsGo/tars"
    "time"
    "TestApp"
)

var comm *tars.Communicator

func main() {
    comm = tars.NewCommunicator()
    obj := "TestApp.TestServer.HelloObj@tcp -h 127.0.0.1 -p 10015 -t 60000"
    app := new(TestApp.Hello)
    comm.StringToProxy(obj, app)

    go func() {
        var req string = "Hello World"
        var res string
        ret, err := app.TestHello(req, &res)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println(ret, res)
    }()

    time.Sleep(1 * time.Second)
}
```go
import (
    "fmt"
    "github.com/TarsCloud/TarsGo/tars"
    "time"
    "TestApp"
)

var comm *tars.Communicator

func main() {
    comm = tars.NewCommunicator()
    obj := "TestApp.TestServer.HelloObj@tcp -h 127.0.0.1 -p 10015 -t 60000"
    app := new(TestApp.Hello)
    comm.StringToProxy(obj, app)

    go func() {
        var req string = "Hello World"
        var res string
        ret, err := app.TestHello(req, &res)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println(ret, res)
    }()

    time.Sleep(1 * time.Second)
}
Клиент может вызвать сервер через set, настроив соответствующий конфигурационный файл, где enableset установлен в "y", а setdivision, например, установлен в "gray.sz.*". Для получения дополнительной информации обратитесь к https://github.com/TarsCloud/Tars/blob/master/docs-en/tars_idc_set.md.
Если вы хотите выполнять вызовы через set вручную, tarsgo вскоре поддержит эту функцию.

##### 2.4.6 Вызов по хешу

Поскольку могут быть развернуты несколько серверов, запросы клиента распределяются случайным образом между серверами, но в некоторых случаях требуется всегда отправлять определенные запросы на конкретный сервер. В этом случае Tars предлагает простой способ реализации, известный как вызов по хешу. Tarsgo вскоре поддержит эту функцию.### 3 Возвращаемые коды TARS
```go
// Определение возвращаемых кодов TARS-сервисом
const int TARSSERVERSUCCESS       = 0;    // Успешное выполнение серверной обработки
const int TARSSERVERDECODEERR     = -1;   // Исключение декодирования на сервере
const int TARSSERVERENCODEERR     = -2;   // Исключение кодирования на сервере
const int TARSSERVERNOFUNCERR     = -3;   // На сервере нет такой функции
const int TARSSERVERNOSERVANTERR  = -4;   // Сервер не имеет объекта Servant
const int TARSSERVERRESETGRID     = -5;   // Несоответствие состояния сервера
const int TARSSERVERQUEUETIMEOUT  = -6;   // Превышение лимита очереди сервера
const int TARSASYNCCALLTIMEOUT    = -7;   // Превышение времени ожидания асинхронного вызова
const int TARSINVOKETIMEOUT       = -7;   // Превышение времени ожидания вызова
const int TARSPROXYCONNECTERR     = -8;   // Исключение соединения прокси
const int TARSSERVEROVERLOAD      = -9;   // Перегрузка сервера, превышение длины очереди
const int TARSADAPTERNULL         = -10;  // Маршрутизация клиента пустая, сервис не существует или все сервисы недоступны
const int TARSINVOKEBYINVALIDESET = -11;  // Нарушение правил вызова set клиентом
const int TARSCLIENTDECODEERR     = -12;  // Исключение декодирования клиента
const int TARSSERVERUNKNOWNERR    = -99;  // Сервер находится в неизвестном состоянии
```### 4 Логирование
Быстрый пример использования tarsgo для переключения логов:

```go
TLOG := tars.GetLogger("TLOG")
TLOG.Debug("Debug logging")

Это создаст объект *tars.Logger, определенный в tars/util/logger, и после вызова GetLogger создаст лог-файл в Logpath, указанном в config.conf. Имя файла будет cfg.App + "." + cfg.Server + "_" + имя, и этот лог-файл будет переключаться после достижения размера 100МБ (по умолчанию), с максимальным количеством переключаемых файлов 10 (по умолчанию).


```go
TLOG := tars.GetDayLogger("TLOG", 1)
TLOG.Debug("Debug logging")

Используйте GetHourLogger("TLOG", 1) для переключения логов по часам. Если вы хотите отправлять логи на удалённый сервер, определённый в config.conf как tars.tarslog.LogObj, вам нужно будет настроить лог-сервер. Полное определение TARS файла можно найти в tars/protocol/res/LogF.tars, а сам лог-сервер можно найти в Tencent/Tars/cpp/framework/LogServer. Быстрый пример:

TLOG := GetRemoteLogger("TLOG")
TLOG.Debug("Debug logging")

Если вы хотите настроить уровень логирования, вы можете сделать это на платформе OSS, предоставляемой проектом TARS в Tencent/Tars/web.

Если вы хотите настроить свои собственные логи, вы можете найти больше информации в tars/util/logger, tars/logger.go и tars/remotelogger.go.

5 Управление сервисом

Фреймворк TARS поддерживает динамическое получение команд для обработки бизнес-логики, например, динамическое обновление конфигурации.Текущая версия tarsgo поддерживает команды управления tars.viewversion / tars.setloglevel. Пользователи могут отправлять команды управления из OSS для просмотра версии или установки уровня логирования.

Если вы хотите определить свои собственные команды управления, вы можете использовать следующий пример:

func helloAdmin(who string) (string, error) {
    return who, nil
}
tars.RegisterAdmin("tars.helloAdmin", helloAdmin)

Затем вы можете отправлять пользовательскую команду управления "tars.helloAdmin tarsgo", и tarsgo отобразит её в браузере.

Пример:

// Функция должна быть в следующем формате
type adminFn func(string) (string, error)

// Затем вы должны зарегистрировать эту функцию следующим образом

func RegisterAdmin(name string, fn adminFn)

6 Отчёт статистики

Отчёт статистики включает отправку информации о времени выполнения и других данных в tarsstat. Это не требует разработки пользователем, достаточно правильно настроить информацию при инициализации программы, чтобы автоматически отправлять отчёты (включая клиентскую и серверную части).

После вызова интерфейса отчёта клиентом, информация временно хранится в памяти, и при достижении определённого времени отправляется в tarsstat (по умолчанию каждую минуту). Временной интервал между двумя отправками называется интервалом отчёта, и в течение этого интервала выполняются операции агрегации и сравнения значений с одинаковым ключом.```go // Для ошибок ReportStat(msg, 0, 1, 0)

// Для успешных операций ReportStat(msg, 1, 0, 0)


## 7 Отчет об ошибках
Для улучшенного мониторинга, фреймворк TARS поддерживает прямую отправку информации об ошибках в tarsnotify, которую можно просмотреть на веб-странице управления.

Фреймворк предоставляет три макроса для отправки информации об ошибках различных типов:
```go
tars.reportNotifyInfo("Ошибка при получении данных из MySQL!")

Info — это строка, которую можно отправить напрямую в tarsnotify. Отправленная строка будет отображаться на странице, после чего можно будет использовать её для отправки уведомлений.

8 Мониторинг характеристик

Для удобства статистического анализа бизнес-процессов, фреймворк TARS также поддерживает отображение информации на веб-странице управления.

Текущие поддерживаемые типы статистики включают:

  • Sum(sum) // Вычисляет сумму всех отправленных значений
  • Average(avg) // Вычисляет среднее значение всех отправленных значений
  • Distribution(distr) // Вычисляет распределение всех отправленных значений, параметр — это список, который используется для вычисления вероятностного распределения для каждого интервала
  • Maximum(max) // Вычисляет максимальное значение всех отправленных значений
  • Minimum(min) // Вычисляет минимальное значение всех отправленных значений
  • Count(count) // Вычисляет количество отправленных значений
```go
    sum := tars.NewSum()
    count := tars.NewCount()
    max := tars.NewMax()
    min := tars.NewMin()
    d := []int{10, 20, 30, 50} 
    distr := tars.NewDistr(d)
    p := tars.CreatePropertyReport("testproperty", sum, count, max, min, distr)
    for i := 0; i < 5; i++ {
        v := rand.Intn(100)
        p.Report(v)
    }   
> * Регулярная отправка данных может быть настроена в конфигурации передатчика, в настоящее время отправка происходит каждую минуту;
> * Создайте функцию PropertyReportPtr: параметр createPropertyReport может быть набором любых статистических методов, в примере используется шесть статистических методов, обычно требуется только один или два;
> * Обратите внимание, что при вызове createPropertyReport необходимо создавать и сохранять созданный объект после включения службы, затем просто отправляйте объект, не создавайте его каждый раз при использовании.
### 9 Удаленное конфигурирование
Пользователи могут настроить удаленные параметры из OSS. Подробнее см. https://github.com/TarsCloud/TarsFramework/blob/master/docs-en/tars_config.md.
Приведенный ниже пример демонстрирует, как использовать этот API для получения конфигурационных файлов из удаленного источника.

```go
import "github.com/TarsCloud/TarsGo/tars"
...
cfg := tars.GetServerConfig()
remoteConf := tars.NewRConf(cfg.App, cfg.Server, cfg.BasePath)
config, _ := remoteConf.GetConfig("test.conf")

...

10 setting.go

Файл setting.go в пакете tars используется для управления производительностью и функциональностью tarsgo. Некоторые опции следует обновлять из GetServerConfig().

// количество рабочих потоков для обработки запросов клиентов
// нулевое значение означает, что нет контроля, и используется один горутина для каждого запроса клиента.
// runtime.NumCPU() обычно обеспечивает наилучшую производительность в тестах.
var MaxInvoke int = 0

const (
	// в настоящее время некоторые опции следует обновлять из удаленного конфигурирования

	// версия
	TarsVersion string = "1.0.0"

	// сервер

	AcceptTimeout time.Duration = 500 * time.Millisecond
	// нулевое значение означает, что не установлено время ожидания чтения для Conn (лучшая производительность)
	ReadTimeout time.Duration = 0 * time.Millisecond
	// нулевое значение означает, что не установлено время ожидания записи для Conn (лучшая производительность)
	WriteTimeout time.Duration = 0 * time.Millisecond
	// нулевое значение означает, что не установлено время ожидания для вызова пользовательского интерфейса (лучшая производительность)
	HandleTimeout time.Duration = 0 * time.Millisecond
	IdleTimeout   time.Duration = 600000 * time.Millisecond
	ZombileTimeout time.Duration = time.Second * 10
	QueueCap      int           = 10000000

	// клиент
	ClientQueueLen     int           = 10000
	ClientIdleTimeout  time.Duration = time.Second * 600
	ClientReadTimeout  time.Duration = time.Millisecond * 100
	ClientWriteTimeout time.Duration = time.Millisecond * 3000
	ReqDefaultTimeout  int32         = 3000
	ObjQueueMax        int32         = 10000

	// отчеты
	PropertyReportInterval time.Duration = 10 * time.Second
	StatReportInterval     time.Duration = 10 * time.Second

	// основной цикл
	MainLoopTicker time.Duration = 10 * time.Second

	// адаптер
	AdapterProxyTicker     time.Duration = 10 * time.Second
	AdapterProxyResetCount int           = 5
)
```	// значения по умолчанию для коммуникатора, обновляются из удаленного конфигурирования
	refreshEndpointInterval int = 60000
	reportInterval          int = 10000
	AsyncInvokeTimeout      int = 3000

	// настройки TCP-сети
	TCPReadBuffer  = 128 * 1024 * 1024
	TCPWriteBuffer = 128 * 1024 * 1024
	TCPNoDelay     = false
)```


### 11 Поддержка HTTP

Текущий `tar.TarsHttpMux` и встроенный `golang` `http.ServeMux` используются одинаковым образом, где параметр `pattern` используется как имя интерфейса для мониторинга данных. В будущем планируется реализовать более мощные функции маршрутизации, вдохновленные `github.com/gorilla/mux`.

Для примера реализации см. ниже:

```go
package main

import (
	"net/http"
	"github.com/TarsCloud/TarsGo/tars"
)

func main() {
	mux := &tars.TarsHttpMux{}
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello tafgo"))
	})

	cfg := tars.GetServerConfig()
	tars.AddHttpServant(mux, cfg.App+"."+cfg.Server+".HttpObj") // Регистрация HTTP-сервера
	tars.Run()
}
```


### 12 Поддержка Context

Ранее в сгенерированном клиентском коде или коде, переданном пользователем, не использовался `context`. Это затрудняло передачу информации о фреймворке, такой как IP-адрес клиента и порт, или передачу информации о вызове пользователем в фреймворк. После переработки интерфейса была добавлена поддержка `context`, что позволяет передавать все эти контекстные данные через `context`. Переработка была выполнена с полной совместимостью для старых пользовательских действий.

Использование `context` на стороне сервера```go
type ContextTestImp struct {
}
// Необходимо добавить параметр `ctx context.Context` в интерфейсе
func (imp *ContextTestImp) Add(ctx context.Context, a int32, b int32, c *int32) (int32, error) {
	// Мы можем использовать `context` для получения информации, переданной фреймворком, например, получения IP-адреса клиента
	ip, ok := current.GetClientIPFromContext(ctx)
	if !ok {
		logger.Error("Ошибка получения IP-адреса из контекста")
	}  
	return 0, nil
}
// Ранее использовался `AddServant`, теперь следует использовать `AddServantWithContext`
app.AddServantWithContext(imp, cfg.App+"."+cfg.Server+".ContextTestObj")
```

Использование `context` на стороне клиента

```golang

ctx := context.Background()
c := make(map[string]string)
c["a"] = "b" 
// Ранее использовался `app.Add` для вызова клиента, теперь следует использовать `app.AddWithContext`, чтобы передать `context` фреймворку
// Если необходимо установить `context` для запроса `tars`, можно передать дополнительные параметры, такие как `c`, где `c` является необязательным параметром, формат которого `...[string]string`
ret, err := app.AddWithContext(ctx, i, i*2, &out, c)

```
Полные примеры использования `context` на стороне сервера и клиента см. в `TarGo/examples`
```

### 13 Механизм фильтров (плагины) и zipkin opentracing
Для поддержки пользовательских плагинов мы реализовали механизм фильтров, который включает в себя серверные и клиентские фильтры.```go
// Серверный фильтр, который принимает dispatch, f (интерфейс для вызова пользовательского кода), req (пакет запроса пользователя) и resp (пакет ответа сервера)
type ServerFilter func(ctx context.Context, d Dispatch, f interface{}, req *requestf.RequestPacket, resp *requestf.ResponsePacket, withContext bool) (err error)
// Клиентский фильтр, который принимает msg (включающий информацию об obj, adapter, req и resp пакетах) и пользовательское значение таймаута
type ClientFilter func(ctx context.Context, msg *Message, invoke Invoke, timeout time.Duration) (err error)
// Регистрация серверного фильтра
//func RegisterServerFilter(f ServerFilter)
// Регистрация клиентского фильтра
//func RegisterClientFilter(f ClientFilter)
```С помощью фильтров мы можем выполнять фильтрацию запросов на стороне сервера и клиента, например, используя hook для распределённого отслеживания с использованием opentracing span.
Давайте рассмотрим пример клиентского фильтра:
```go
// Создание клиентского фильтра tars для внедрения span
func ZipkinClientFilter() tars.ClientFilter {
	return func(ctx context.Context, msg *tars.Message, invoke tars.Invoke, timeout time.Duration) (err error) {
		var pCtx opentracing.SpanContext
		req := msg.Req
		// Сначала проверяем, есть ли в контексте вызова клиента информация о вызове,
		// если есть, используем её как родительский span, если нет, создаём новый span с именем функции RPC-запроса
		if parent := opentracing.SpanFromContext(ctx); parent != nil {
			pCtx = parent.Context()
		}
		cSpan := opentracing.GlobalTracer().StartSpan(
			req.SFuncName,
			opentracing.ChildOf(pCtx),
			ext.SpanKindRPCClient,
		)
		defer cSpan.Finish()
		cfg := tars.GetServerConfig()
``````go
		// Устанавливаем информацию для span, например, IP-адрес клиента, интерфейс, метод, протокол, версию клиента и т.д.
		cSpan.SetTag("client.ipv4", cfg.LocalIP)
		cSpan.SetTag("tars.interface", req.SServantName)
		cSpan.SetTag("tars.method", req.SFuncName)
		cSpan.SetTag("tars.protocol", "tars")
		cSpan.SetTag("tars.client.version", tars.TarsVersion)
``````markdown
// Вставляем span в поле Status запроса, где Status имеет структуру map[string]string
if req.Status != nil {
	err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(req.Status))
	if err != nil {
		logger.Error("ошибка вставки span в Status:", err)
	}
} else {
	s := make(map[string]string)
	err = opentracing.GlobalTracer().Inject(cSpan.Context(), opentracing.TextMap, opentracing.TextMapCarrier(s))
	if err != nil {
		logger.Error("ошибка вставки span в Status:", err)
	} else {
		req.Status = s
	}
}
// Больше ничего не нужно изменять, инициируем клиентский вызов
err = invoke(ctx, msg, timeout)
if err != nil {
	// При ошибке вызова, записываем информацию об ошибке в span
	ext.Error.Set(cSpan, true)
	cSpan.LogFields(oplog.String("event", "error"), oplog.String("message", err.Error()))
}
``````go
		return err
	}
```Сервер также регистрирует фильтр, основная функция которого — извлечение контекста вызова из поля `status` тела запроса. Этот контекст используется как родительский span для записи информации о вызовах.

Для более подробного изучения кода обратитесь к TarsGo/tars/plugin/zipkintracing.

Полные примеры клиентской и серверной сторон для zipkin tracing доступны в TarsGo/examples: ZipkinTraceClient и ZipkinTraceServer.

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

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

1
https://api.gitlife.ru/oschina-mirror/zuoqi200-TarsGo.git
git@api.gitlife.ru:oschina-mirror/zuoqi200-TarsGo.git
oschina-mirror
zuoqi200-TarsGo
zuoqi200-TarsGo
master