繁体   English   中英

高朗的多租户

[英]Multi-tenancy in Golang

我目前正在Go中编写服务,需要与多个租户打交道。 我已经决定使用一个数据库共享表方法,并使用“ tenant_id”定界符来分隔租户。

服务的结构如下:

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

两台服务器,一台gRPC(管理)和一台HTTP / JSON(公共API),每台服务器都在各自的例程中运行,并具有各自的处理程序,可以利用不同管理器的功能。 经理(让我们称其为“库存经理”),全部生活在不同的根级包中。 据我所知,这些是我的域实体。

在这方面,我有一些问题:

  1. 我找不到任何支持多个租户的ORM for Go。 在sqlx包之上编写自己的代码是否有效?

  2. 将来的其他服务也将需要多租户支持,因此我想无论如何我都必须创建一些库/包。

  3. 今天,我通过为公共API服务器使用ResolveTenantBySubdomain中间件来解决租户。 然后,我将解析的租户ID放在与调用一起发送给管理器的上下文值中。 在管理器的不同方法中,我从上下文值中获取租户ID。 然后将其与每个SQL查询/ exec调用一起使用,如果缺少或无效的租户ID,则返回错误。 我是否应该为此使用上下文?

  4. 解决gRPC服务器上的租户,我相信我必须使用UnaryInterceptor函数进行中间件处理。 由于gRPC API接口只能由其他后端服务访问,因此我认为此处不需要按子域进行解析。 但是我应该如何嵌入租户ID? 在标题中?

真的希望我问正确的问题。 问候,卡尔。

我找不到任何支持多个租户的ORM for Go。 在sqlx包之上编写自己的代码是否有效?

Go中的ORM是一个有争议的话题! 一些Go用户喜欢它们,另一些讨厌它们,并且喜欢手动编写SQL。 这是个人喜好问题。 询问特定的库建议在这里是sqlx ,无论如何,我不知道任何多租户ORM库-但是没有什么可以阻止您使用sqlx包装器的(我每天在一个工作正常的系统上工作这个)。

将来的其他服务也将需要多租户支持,因此我想无论如何我都必须创建一些库/包。

以适合您的编程和接口模式的方式从那些内部服务中抽象出这种行为是有意义的,但是这里没有更多细节可以更具体地回答。

今天,我通过为公共API服务器使用ResolveTenantBySubdomain中间件来解决租户。 然后,我将解析的租户ID放在与调用一起发送给管理器的上下文值中。 在管理器的不同方法中,我从上下文值中获取租户ID。 然后将其与每个SQL查询/ exec调用一起使用,如果缺少或无效的租户ID,则返回错误。 我是否应该为此使用上下文?

context.Context主要是关于取消,而不是请求传播。 根据WithValue函数的文档 ,尽管您的使用是可以接受的,但使用当前实现为传递值的context包,它被广泛 认为是一种不好的代码味道。 与其使用缺乏类型安全性和许多其他属性的隐式行为,不如通过将租户ID传递给相关的函数调用来在下游数据层的函数签名中显式显示?

解决gRPC服务器上的租户,我相信我必须使用UnaryInterceptor函数进行中间件处理。 由于gRPC API接口只能由其他后端服务访问,因此我认为此处不需要按子域进行解析。 但是我应该如何嵌入租户ID? 在标题中? [原文如此]

gRPC库没有考虑您的设计选择。 您可以使用标头值(将租户ID作为“环境”参数传递给请求),也可以将租户ID参数显式添加到需要它的每个远程方法调用中。

请注意,以这种方式在服务之间传递租户ID会在它们之间建立外部信任 -如果服务A提出服务B的请求并用租户ID对其进行注释,则您假定服务A已执行了必要的访问控制检查以验证用户该租户确实在提出请求。 在此简单模型中,没有什么可以阻止流氓服务C向服务B询问有关某些任意租户ID的信息。 另一种实现方式是实施更复杂的无人信任策略,从而为每个服务提供足够的访问控制信息,以就是否应满足针对特定租户的特定请求做出自己的策略决策。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM