我最近一直在研究领域驱动设计,并且必须说这种类型的架构设计触发了我的某些东西。当我尝试将其概念应用于我的 Go 项目时,我遇到了一些障碍。以下是一些示例方法,但我非常不确定要使用哪种方法。
项目结构摘录:
??? api/
??? cmd/
??? internal/
| ??? base/
| | ??? eid.go
| | ??? entity.go
| | ??? value_object.go
| ??? modules/
| | ??? realm/
| | | ??? api/
| | | ??? domain/
| | | | ??? realm/
| | | | | ??? service/
| | | | | ??? friendly_name.go
| | | | | ??? realm.go
| | | | | ??? realm_test.go
| | | | …Run Code Online (Sandbox Code Playgroud) 我目前正在用 Go 编写一个服务,我需要处理多个租户。我已经决定使用单一数据库共享表方法,使用“tenant_id”鉴别器进行租户分离。
该服务的结构如下:
gRPC server -> gRPC Handlers -
\_ Managers (SQL)
/
HTTP/JSON server -> Handlers -
Run Code Online (Sandbox Code Playgroud)
两台服务器,一台 gRPC(管理)和一台 HTTP/JSON(公共 API),每台服务器都运行在自己的 go-routine 中,并带有各自的处理程序,可以利用不同管理器的功能。管理器(我们称之为“库存管理器”),都生活在不同的根级包中。据我所知,这些是我的域实体。
对此,我有几个问题:
我找不到任何支持多个租户的 Go ORM。在 sqlx 包之上编写我自己的包是一个有效的选择吗?
未来的其他服务也需要多租户支持,所以我想我无论如何都必须创建一些库/包。
今天,我通过使用公共 API 服务器的 ResolveTenantBySubdomain 中间件来解析租户。然后,我将解析后的租户 ID 放在随调用发送给经理的上下文值中。在管理器的不同方法中,我从上下文值中获取租户 ID。然后将其与每个 SQL 查询/执行调用一起使用,或者如果租户 ID 丢失或无效则返回错误。我什至应该为此目的使用上下文吗?
解决gRPC服务器上的租户,我相信我必须使用UnaryInterceptor函数进行中间件处理。由于 gRPC API 接口只能被其他后端服务访问,我猜在这里不需要通过子域进行解析。但是我应该如何嵌入租户 ID?在标题中?
真的希望我问的是正确的问题。问候,卡尔。
在下面的代码示例中,我使用正则表达式从给定的URL中提取子域名。该示例有效,但我认为我在编译正则表达式时(主要是在插入“ virtualHost”变量的地方)未正确完成操作。有什么建议么?
package main
import (
"fmt"
"regexp"
)
var (
virtualHost string
domainRegex *regexp.Regexp
)
func extractSubdomain(host string) string {
matches := domainRegex.FindStringSubmatch(host)
if matches != nil && len(matches) > 1 {
return matches[1]
}
return ""
}
func init() {
// virtualHost = os.GetEnv("VIRTUAL_HOST")
virtualHost = "login.localhost:3000"
domainRegex = regexp.MustCompile(`^(?:https?://)?([-a-z0-9]+)(?:\.` + virtualHost + `)*$`)
}
func main() {
// host := req.host
host := "http://acme.login.localhost:3000"
if result := extractSubdomain(host); result != "" {
fmt.Printf("Subdomain detected: %s\n", result)
return …Run Code Online (Sandbox Code Playgroud)