【问题标题】:Multi tenant implementations of the same endpoint同一端点的多租户实现
【发布时间】:2020-08-27 01:53:03
【问题描述】:

我有一个用 Go 编写的 API 服务器,它为不同的租户做一些工作。 我有许多端点应该根据调用它的租户实现不同的代码,例如:

s.GET("/api/orders", a.getOrders)

将调用 a.getOrders 处理程序,该处理程序在其工作后将为所有租户返回相同的 JSON 结构,但获取数据的实现可能不同(有时对于租户我需要调用另一个 Web 服务,另一个我需要查询不同的数据库表等...)。 我正在考虑为每个租户创建不同的包,所以我将有一个common(用于常见实现)、tenanta(用于租户 A 特定实现)、tenantbtenantc 等等。 ..现在,我的问题是:处理“重定向”的最佳方式是什么? 我能想到的第一件事(也可能是坏事)是在我的 a.getOrders 处理程序中放置一个开关,并从会话或 url 解析 tenantID

switch tenantID {
   case "tenanta":
       tenanta.getOrders()
   case "tenantb":
       tenantb.getOrders()
   case "tenantc":
       tenantc.getOrders()
   default:
       common.getOrders()
}

显然,它可能会变得非常快(目前我必须处理 20 多个租户)。 有没有更好的方法来处理这种情况?

谢谢

【问题讨论】:

  • 租户地图?

标签: api rest go multi-tenant


【解决方案1】:

你可以做一个租户界面,比如

type tenant interface{
    getOrders() Orders
}

现在您可以声明实现此接口的任意数量的租户

package main

import (
    "fmt"
)

type tenant interface {
    getOrders()
}

type TenantA struct {
}

func (t TenantA) getOrders() {
    fmt.Println("Tenant A")
}

var tenantMap = map[string]tenant{
    "T-A": TenantA{},
}

func main() {
    fmt.Println("Hello")
    teneantTest := "T-A"
    
    curTeneant, ok := tenantMap[teneantTest]
    if !ok {
        fmt.Println("Not Found")
        return
    }
    
    curTeneant.getOrders()
}

现在您的所有租户都遵循相同的界面,如果所有租户都定义了最少的功能集,这将是编译时可测试的

这也将导致更清晰的抽象

【讨论】:

  • 非常感谢,这意味着如果只有一个租户实现自己的代码,我应该为所有其他租户定义空函数?
  • 不,你不应该在界面中添加那个功能,界面应该有什么共同点,如果有帮助也接受答案?
最近更新 更多