DevGang
Авторизоваться

Micro в действии, часть 2: полное руководство по Bootstrap 

Это вторая статья в серии статей «Micro в действии», посвященной Micro. Мы шаг за шагом создадим микросервис и объясним особенности Micro на этом пути. Мы начнем с основных понятий и тем, а затем перейдем к расширенным функциям.

Макет проекта

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

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

Компоновка проекта следующая:

.
├── main.go
├── generate.go
├── plugin.go
├── proto/hello
│   └── hello.proto
│   └── hello.pb.go
│   └── hello.pb.micro.go
├── handler
│   └── hello.go
├── subscriber
│   └── hello.go
├── Dockerfile
├── README.md
├── .gitignore
└── go.mod

Вот список файлов в проекте:

  1. main.go - главный файл проекта, который будет подробно описан позже.
  2. generate.go - содержит только одну строку //go:generate make proto которая интегрируется с go generate. Убедитесь, что она будет вызываться автоматически во время выполнения go generate
  3. plugins.go - этот файл в настоящее время пуст. Согласно соглашению Micro, здесь рекомендуется управлять всем импортом плагинов, которые будут использоваться позже.
  4. proto/hello/hello.proto - файл определения службы gRPC, который определяет службу RPC с именем Hello. В этом сервисе заявлены 3 типичных метода RPC: одинарный RPC, серверный потоковый RPC и двунаправленный потоковый RPC.
  5. proto/hello/hello.pb.go - исходный файл golang, созданный protoc из вышеупомянутого файла .proto
  6. proto/hello/hello.pb.micro.go - исходный файл golang, созданный с помощью protoc-gen-micro. Это еще больше упрощает работу разработчика. Он определяет интерфейсы HelloSerivce и HelloHandler. Последний - это интерфейс, который нам нужен для реализации и завершения нашей бизнес-логики.
  7. handler/hello.go - файл, в котором реализована бизнес-логика. Он определяет объект Hello, реализующий интерфейс HelloHandler.
  8. subscriber/hello.go - файл, который реализует асинхронную подписку и обработку сообщений. Он показывает два разных способа обработки сообщений: один - с помощью метода объекта, а другой - с помощью функции.
  9. Dockerfile - определяет, как создавать Docker образы.
  10. Makefile - определяет несколько общих задач, компиляцию, тестирование, сборку образа Docker и т.д.
  11. README.md - содержит основную информацию о проекте
  12. .gitignore - игнорировать hello-service по умолчанию
  13. go.mod - файл модуля Go

Примечание: папка proto имеет особое значение. Хотя нет никаких технических ограничений, по соглашению Micro, папка proto в корневом каталоге каждого проекта используется для хранения «интерфейсных» файлов. Это включает как интерфейсы, которые проект должен предоставить внешнему миру, так и другие интерфейсы, от которых зависит проект. Например, предположим, что нам нужно полагаться на другую службу foo для реализации бизнес-логики. Затем мы создадим папку с именем proto/foo и поместим в нее три файла foo.proto, foo.pb.go, foo.pb.micro.go.

Объяснение для Bootstrap

Давайте посмотрим на процесс начальной загрузки main.go:

package main

import (
   "github.com/micro/go-micro/v2"
   log "github.com/micro/go-micro/v2/logger"

   "hello/handler"
   "hello/subscriber"

   hello "hello/proto/hello"
)

func main() {
   // New Service
   service := micro.NewService(
      micro.Name("com.foo.service.hello"),
      micro.Version("latest"),
   )

   // Initialise service
   service.Init()

   // Register Handler
   hello.RegisterHelloHandler(service.Server(), new(handler.Hello))

   // Register Struct as Subscriber
   micro.RegisterSubscriber("com.foo.service.hello", service.Server(), new(subscriber.Hello))

   // Run service
   if err := service.Run(); err != nil {
      log.Fatal(err)
   }
}

Код примерно разделен на 4 части: импорт зависимостей, создание и инициализация службы, регистрация обработчиков бизнес-обработки и запуск службы.

Импорт зависимостей

Отдельно стоит пояснить только одну строчку кода в этой части:

hello "hello/proto/hello"

Мы устанавливаем явное имя пакета hello на hello/proto/hello. Это также соглашение Micro: установить явные имена пакетов для всех пакетов импорта интерфейса. Это позволяет избежать использования исходного имени пакета импортированного кода. На практике, если вы не сделаете специальных настроек, имя пакета автоматически сгенерированного кода будет относительно длинным. Возьмем к примеру hello.pb.go, имя его пакета com_foo_srv_hello. Очевидно, что установка явного имени пакета - лучший выбор.

Создание и инициализация сервисов

// New Service
service := micro.NewService(
   micro.Name("com.foo.srv.hello"),
   micro.Version("latest"),
)

Мы используем метод micro.NewService(opts …Option) Service для создания сервиса. Этот метод принимает в качестве параметра micro.Option, затем создает и возвращает экземпляр micro.Service

По-видимому micro.Option, это ключ к управлению сервисом. В приведенном выше примере кода используются параметры для указания имени службы и номера версии соответственно.

В настоящее время доступно 29 опций для управления всеми аспектами службы. Некоторые параметры можно указывать несколько раз для формирования эффекта наложения (будет описано позже).

Однако документации для таких важных опций нет. Если вы хотите учиться, копание исходного кода - единственный способ. И большая часть исходного кода не имеет комментариев, что еще больше усложняет изучение.

Хотя эта статья не является исчерпывающим справочным руководством для Micro, я решил перечислить все 29 вариантов Micro v2.4.0 и объяснить их один за другим, как показано ниже. Поскольку эти параметры очень важны для понимания и использования Micro, и нет другого материала, на который можно было бы ссылаться.

  1. micro.Name(n string) Option -  Укажите имя службы. Обычно соглашение об именах $namespace. $type. $name. $namespace представляет пространство имен проекта и $type тип службы (например, gRPC и веб). Тип службы gRPC обычно сокращается до srv. После запуска экземпляра службы это имя будет автоматически зарегистрировано в Registry, что станет основой для обнаружения службы. По умолчанию это go.micro.serverПримечание: Следовательно, этот параметр необходимо указать, иначе все узлы будут использовать одно и то же имя по умолчанию, что приведет к путанице.
  2. micro.Version(v string) Option - Укажите версию сервиса. Значение по умолчанию - это форматированная строка с момента запуска. при правильном выборе номера версии в сочетании с правильностью Selector мы можем реализовать элегантное обновление с вращением, выпуск в оттенках серого, A/B-тестирование и многие другие операции.
  3. micro.Address(addr string) Option - Задает адрес службы gRPC. По умолчанию используется адрес localhost в сочетании со случайным портом. Поскольку клиенты обнаруживают службы через Registry, случайный порт не влияет на это обнаружение. Однако на практике часто указывается фиксированный номер порта, что будет полезно для работы и контроля безопасности.
  4. micro.RegisterTTL(t time.Duration) Option - Укажите TTL регистрационной информации службы в реестре. Значение по умолчанию - 1 минута.
  5. micro.RegisterInterval(t time.Duration) Option - Определяет интервал, через который служба сообщает о своем состоянии в реестр. Значение по умолчанию - 30 секунд. Эти два параметра, относящиеся к реестру, помогают избежать «неверной регистрационной информации», когда служба обнаруживает непредвиденный простой.
  6. micro.WrapHandler(w …server.HandlerWrapper) Option - Обернуть обработчик службы. Он концептуально похож на Gin Middleware и централизованно контролирует поведение обработчика. Обертку можно применять на нескольких уровнях, а порядок выполнения - снаружи внутрь (пример будет представлен в следующей статье).
  7. micro.WrapSubscriber(w …server.SubscriberWrapper) Option - Аналогичен WrapHandler, за исключением того, что он используется для обертывания подписчиков в асинхронном обмене сообщениями.
  8. micro.WrapCall(w …client.CallWrapper) Option - Оборачивает каждый вызов метода от клиента.
  9. micro.WrapClient(w …client.Wrapper) Option - Обернуть клиента службы, может применяться на нескольких уровнях, и порядок выполнения - изнутри наружу.
  10. micro.BeforeStart(fn func() error) Option - Установите несколько функций обратного вызова перед запуском службы.
  11. micro.BeforeStop(fn func() error) Option - Установите несколько функций обратного вызова до остановки службы.
  12. micro.AfterStart(fn func() error) Option - Установите несколько функций обратного вызова после запуска службы.
  13. micro.AfterStop(fn func() error) Option - Установить несколько функций обратного вызова после остановки службы
  14. micro.Action(a func(*cli.Context)) Option - Обрабатывать аргументы командной строки. Поддерживает подкоманды и флаги. см микро / CLI для получения подробной информации
  15. micro.Flags(flags …cli.Flag) Option - Обрабатывать флаги командной строки. см микро / CLI для получения подробной информации
  16. micro.Cmd(c cmd.Cmd) Option - Определяет объект обработки командной строки. Созданный по умолчанию этот объект поддерживает несколько переменных среды по умолчанию и параметры командной строки. По сути, это встроенный набор cli.Flag. Примечание. Что касается поддержки командной строки, у Micro есть как преимущества, так и недостатки одновременно. Преимущество в том, что он предоставляет множество параметров по умолчанию, что может сэкономить время разработчиков. Недостатком является то, что этот дизайн сильно инвазивен для пользовательских программ: среда требует, чтобы разработчики обрабатывали свои аргументы командной строки единообразно в соответствии с micro/cli. В противном случае программа сообщит об ошибке и не сможет работать. Например, если мы выполним ./hello-service --foo=bar, мы получим ошибоку: Incorrect Usage. Flag provided but not defined: --foo=bar. К счастью, micro.Cmd может решить проблему, вызванную навязчивостью. Если существующий проект хочет представить Micro и у него уже есть собственный механизм обработки командной строки, то вам необходимо использовать его для переопределения поведения по умолчанию (при потере возможностей обработки командной строки по умолчанию). Что касается обработки из командной строки, дальнейшее объяснение будет предоставлено позже в этой статье.
  17. micro.Metadata(md map[string]string) Option - Укажите метаданные службы. Метаданные часто используются для тегирования и группировки сервисов, реализации пользовательской стратегии балансировки нагрузки и т.д.
  18. micro.Transport(t transport.Transport) Option - Укажите транспортный протокол, по умолчанию - HTTP
  19. micro.Selector(s selector.Selector) Option - Укажите селектор узла для реализации различных стратегий загрузки. По умолчанию - случайный выбор
  20. micro.Registry(r registry.Registry) Option - Укажите, какой Registry используется для обнаружения службы. По умолчанию используется mDNS-based Registry
  21. micro.Server(s server.Server) Option - Укажите индивидуальный Server, если сервер по умолчанию не соответствует вашим требованиям. По умолчанию rpcServer
  22. micro.HandleSignal(b bool) Option - Включает автоматическую установку обработчика сигналов, который перехватывает TERM, INT и QUIT. По умолчанию true
  23. micro.Context(ctx context.Context) Option - Укажите начальный контекст службы. По умолчанию это значение context.BackGround(), которое можно использовать для управления сроком службы и т.д.
  24. micro.Client(c client.Client) Option - Укажите клиента службы. По умолчанию rpcClient
  25. micro.Broker(b broker.Broker) Option - Укажите брокер сообщений, используемый pub/sub. По умолчанию - HTTP-брокер
  26. micro.Profile(p profile.Profile) Option - Профиль, который будет использоваться для профиля отладки
  27. micro.Tracer(t trace.Tracer) Option - Tracer устанавливает трассировщик для службы
  28. micro.Auth(a auth.Auth) Option - Auth устанавливает авторизацию для службы. (согласно официальному Slask этот API недостаточно стабилен, не готов к продакшену на v2.4.0)
  29. micro.Config(c config.Config) Option - Config устанавливает конфигурацию для службы

Таким образом, указав соответствующий параметр Option, можно настроить поведение службы. Например, чтобы изменить TTL регистрационной информации службы:

...
// New Service
service := micro.NewService(
   micro.Name("foo.bar"),
   micro.Version("v1.0"),
   // change default TTL value
   micro.RegisterTTL(5 * time.Minute),
   ...
)
...

Примечание. Большинство из вышеперечисленных параметров можно указать несколькими способами. Жесткое кодирование в исходном файле - лишь один из способов. Фактически, Micro рекомендует пользователям указывать параметры через переменные среды, поскольку это обеспечивает большую гибкость. Взяв micro.RegisterTTL в качестве примера, мы можем указать его во время выполнения через переменную среды $ MICRO_REGISTER_TTL=value или флаг командной строки --register_ttl=value (значение в секундах). Для этих встроенных опций в настоящее время нет документации. Выполнение ./hello-service -h покажет их краткое описание. Если вы хотите узнать все подробности, раскопайте источник newCmd сами. В последующих статьях этой серии эта тема будет более подробно раскрыта.

После создания вы можете инициализировать службу:

// Initialize service
service.Init()

Метод service.Init может принимать одни и те же параметры, как и micro.NewService. Таким образом, вышеуказанные 29 вариантов также могут быть использованы в service.Init. Они имеют одинаковый эффект, но различаются только по времени.

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

// Initialize service
service.Init(
   // print log after start
   micro.AfterStart(func() error {
      log.Infof("service listening on %s!",
         service.Options().Server.Options().Address,
      )
      return nil
   }),
)

Регистрация бизнес-обработчиков

// Register Handler
hello.RegisterHelloHandler(service.Server(), new(handler.Hello))

// Register Struct as Subscriber
micro.RegisterSubscriber("com.foo.service.hello", service.Server(), new(subscriber.Hello))

Только после регистрации обработчика наш бизнес-код может действительно предоставлять услуги внешнему миру. Вот две типичные операции регистрации:

  1. Зарегистрируйте обработчик gRPC. Создайте объект handler.Hello и зарегистрируйте его на Server. Поскольку handler.Hello реализует интерфейс HelloHandler, его можно передать hello.RegisterHelloHandler, иначе произойдет ошибка. Несколько Handlers могут быть зарегистрированы для выполнения Server различных бизнес-функций.
  2. Зарегистрируйте объект обработки сообщений. Первый параметр - это тема сообщения, второй параметр - это Server, а третий параметр - объект обработки сообщения.

Подробнее об асинхронном обмене сообщениями мы поговорим позже в специальной статье.

Запустить сервис

if err := service.Run(); err != nil {
      log.Fatal(err)
}

На этом этапе служба наконец запускается

Проверить статус выполнения

Как упоминалось в предыдущей статье, инструмент командной строки micro можно использовать для проверки и управления службами во время выполнения. Давай попробуем.

После запуска службы запустите micro web:

$ micro web


2020-04-02 17:16:48  level=info service=web HTTP API Listening on [::]:8082
2020-04-02 17:16:48  level=info service=web Starting [service] go.micro.web
2020-04-02 17:16:48  level=info service=web Server [grpc] Listening on [::]:60537
2020-04-02 17:16:48  level=info service=web Registry [mdns] Registering node: go.micro.web-dc1270ba-8b1f-4f05-92ec-57fb450efaaa

Как видите, сервер прослушивает локальный хост, порт 8082.

Примечание. Порт 8082 является значением по умолчанию и может быть изменен с помощью переменных среды или флага командной строки.

Затем посетите http://127.0.0.1:8082/service/com.foo.service.hello, чтобы просмотреть статус службы. Ниже скриншот:

На картинке выше мы можем просмотреть различную информацию об услуге:

  1. Наименование услуги
  2. Список сервисных узлов. Если несколько узлов работают одновременно, вы увидите их все.
  3. Информация о каждом узле: версия, уникальный идентификатор, адрес, метаданные и т.д.
  4. Конечные точки. Определение службы, имя службы gRPC, имя метода, информация о параметрах, тип данных и т.д.

Так различный статус выполнения службы могут быть легко проверены micro web

Источник:

#Golang
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

Оплатив хостинг 25$ в подарок вы получите 100$ на счет

Получить