9

我们正在使用多租户的ServiceStack创建 API。我们想做基于 DNS 的负载平衡和路由,而不是通过反向代理(如 nginx 或 haproxy)来拼接。

我们有具有租户参数的请求 DTO。ServiceStack(及其 SwaggerFeature)允许我们定义自定义路由,并记录 DTO,以便我们可以从路径、查询、标题或正文中读取值。

我们如何(最好)连接事物,以便 DTO 属性也可以从主机名模式中读取值?那么,让 Route 从匹配的主机名和路径中获取值?

我们希望有这样的网址

  • https://{tenant}.{DNS zone for environment}/{rest of path with tokens}

此外 - DNS 区域将根据我们所处的环境而有所不同 - 对于我们使用的非生产环境(例如)testing-foobar.com和我们使用的生产环境real-live.com。理想情况下,我们可以通过单个路由声明来支持两者(我们更喜欢在运行时装饰 Request DTO 而不是命令式声明AppHost.Init)。

4

1 回答 1

3

就在本周,我在一个现有的多租户系统上解决了这个问题,该系统使用 .NET 安全主体来处理用户权限和租户。我使用自定义 ServiceRunner 来选择租户并设置安全性。您对多租户的方法是不同的,但使用 ServiceRunner 似乎仍然是一种有效的方法。

你最终会得到这样的东西:

public class MyServiceRunner<T> : ServiceRunner<T>
{
    public MyServiceRunner(IAppHost appHost, ActionContext actionContext)
        : base(appHost, actionContext)
    {}

    public override void BeforeEachRequest(IRequestContext requestContext, T request)
    {
        // Set backend authentication before the requests are processed.
        if(request instanceof ITenantRequest)
        {
            Uri uri = new Uri(requestContext.AbsoluteUri);
            string tenant = uri.Host; // Or whatever logic you need...
            ((ITenantRequest).Tenant = tenant;
        }
    }
}

public class MyAppHost : AppHostBase
{
    public MyAppHost() : base("My Web Services", typeof(MyService).Assembly) { }

    public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
    {
        return new MyServiceRunner<TRequest>(this, actionContext);
    }

    public override void Configure(Container container)
    {
        ...
    }
}

也许请求过滤方法在某种程度上更好,但这对我们有用。

于 2013-10-24T08:34:36.333 回答