Мульти-аренда в Голанге - PullRequest
       42

Мульти-аренда в Голанге

0 голосов
/ 28 сентября 2018

В настоящее время я пишу сервис в Go, где мне нужно иметь дело с несколькими арендаторами.Я остановился на использовании единой базы данных, метода общих таблиц, использующего декриминатор tenant_id для разделения клиентов.

Сервис структурирован следующим образом:

gRPC server -> gRPC Handlers -
                              \_ Managers (SQL)
                              /
HTTP/JSON server -> Handlers -

Два сервера, один gRPC(администрация) и один HTTP / JSON (общедоступный API), каждый из которых работает в своей собственной подпрограмме и со своими соответствующими обработчиками, которые могут использовать функциональные возможности различных менеджеров.Менеджеры (давайте назовем одного «инвентаря-менеджера»), все живут в разных пакетах корневого уровня.Насколько я понимаю, это мои доменные сущности.

В связи с этим у меня есть несколько вопросов:

  1. Я не могу найти ни одного ORM для Go, который поддерживает несколько арендаторов изтам.Является ли мой собственный вариант поверх пакета sqlx допустимой опцией?

  2. Другие сервисы в будущем также потребуют поддержки мультитенантов, поэтому я предполагаю, что мне придется создать некоторую библиотеку/ пакет в любом случае.

  3. Сегодня я разрешаю арендаторов с помощью промежуточного программного обеспечения ResolveTenantBySubdomain для общедоступного сервера API.Затем я помещаю решенный идентификатор арендатора в значение контекста, которое отправляется с вызовом менеджеру.Внутри разных методов в менеджере я получаю идентификатор клиента из значения контекста.Затем он используется с каждым вызовом SQL-запроса / exec или возвращает ошибку, если отсутствует или неверный идентификатор клиента.Должен ли я даже использовать контекст для этой цели?

  4. Разрешение клиента на сервере gRPC, я считаю, что для обработки промежуточного программного обеспечения мне нужно использовать функцию UnaryInterceptor.Поскольку доступ к интерфейсу API gRPC будет доступен только другим внутренним службам, я думаю, что разрешение по поддомену здесь не нужно.Но как мне вставить идентификатор арендатора?В шапке?

Очень надеюсь, что я задаю правильные вопросы.С уважением, Карл.

1 Ответ

0 голосов
/ 28 сентября 2018

Я не могу найти ни одного ORM для Go, который поддерживает несколько арендаторов.Является ли мой собственный вариант поверх пакета sqlx верным вариантом?

ORM в Go - спорная тема!Некоторые пользователи Go любят их, другие ненавидят их и предпочитают писать SQL вручную.Это вопрос личных предпочтений.Запрашивать конкретные рекомендации по библиотекам здесь не по теме, и в любом случае я не знаю ни одной мультитенантной библиотеки ORM - но ничто не мешает вам использовать оболочку sqlx (я ежедневно работаю в системе, котораяделает именно это).

Другие службы в будущем также потребуют поддержки мультитенантов, поэтому я думаю, что мне все равно придется создать какую-нибудь библиотеку / пакет.

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

Сегодня я разрешаю арендаторов с помощьюиспользование промежуточного программного обеспечения ResolveTenantBySubdomain для публичного сервера API.Затем я помещаю решенный идентификатор арендатора в значение контекста, которое отправляется с вызовом менеджеру.Внутри разных методов в менеджере я получаю идентификатор клиента из значения контекста.Затем он используется с каждым вызовом SQL-запроса / exec или возвращает ошибку, если отсутствует или неверный идентификатор клиента.Должен ли я даже использовать контекст для этой цели?

context.Context в основном касается отмены, а не распространения запроса.Хотя ваше использование допустимо в соответствии с документацией для функции WithValue, широко считается неприятным запахом кода для использования пакета context в настоящее времяреализовано для передачи значений.Вместо того, чтобы использовать неявное поведение, в котором отсутствует безопасность типов и многие другие свойства, почему бы не быть явным в сигнатуре функции ваших нижестоящих слоев данных, передавая идентификатор клиента соответствующим вызовам функций?

РазрешениеАрендатор на сервере gRPC, я считаю, что я должен использовать функцию UnaryInterceptor для обработки промежуточного программного обеспечения.Поскольку доступ к интерфейсу API gRPC будет доступен только другим внутренним службам, я думаю, что разрешение по поддомену здесь не нужно.Но как мне вставить идентификатор арендатора?В шапке?[sic]

Библиотека gRPC не учитывает ваш выбор дизайна.Можно использовать значение заголовка (для передачи идентификатора клиента в качестве параметра «ambient» в запрос) или явно добавить параметр идентификатора клиента в каждый вызов удаленного метода, для которого он требуется.

Обратите внимание, что передача идентификатора клиентатаким образом между вашими службами создается внешнее доверие между ними - если служба A делает запрос службы B и аннотирует его идентификатором клиента, вы предполагаете, что служба A выполнила необходимые проверки контроля доступа для проверки пользователяэтого арендатора действительно делает запрос.В этой простой модели нет ничего, что мешало бы мошеннической службе C запрашивать у службы B информацию о некотором произвольном идентификаторе арендатора.В альтернативной реализации будет реализована более сложная политика «никто не доверяет», в соответствии с которой каждой службе предоставляется достаточная информация об управлении доступом для принятия собственного решения о том, должен ли выполняться конкретный запрос, относящийся к конкретному арендатору.

...