【问题标题】:ServiceStack AppHost Is a Singleton?ServiceStack AppHost 是单例吗?
【发布时间】:2013-04-06 11:16:47
【问题描述】:

我一直在评估 ServiceStack,到目前为止,我已经卖得差不多了 - 但我有一个要求,我认为会破坏交易。

我基本上需要多个 AppHost 派生实例。第一个很好地旋转,但其余的都失败了,因为“AppHostBase.Instance 已设置”。

这是否意味着如果我希望多个主机(在不同的 Uris 上)位于不同的可执行文件中?如果是这样的话,那就太令人失望了,因为这个库在其他方面都是完美的,除了这个限制。

如果我错了,谁能指出我的解决方案?

请允许我详细说明一下。我们计划在整个网络中提供许多服务。我的意图是将它们设计为单独的服务,然后在托管类中“托管”。托管类本身是用于管理目的的服务,并且具有启动和停止服务的能力。它们在网络上是“可发现的”。我们可以在不同时间或随意启动和关闭不同机器上的服务。

我的计划是为这些事情使用服务堆栈,并能够在任何机器和任何“主机”上以临时方式创建和销毁服务。我唯一遇到的问题是 AppHost 只被初始化一次。

显然我做错了什么,所以任何关于如何在同一个可执行文件中托管多个服务的信息都会很棒:)

【问题讨论】:

  • 所以你想要来自同一个进程的不同端口号上的多个服务?使用 Servicestack 的 Route 属性,我的软件上有四个端点:http://+:12000/route1、http://+:12000/route2 等。
  • @Brannon,个别服务可以随时消失和重新出现。不确定这是否会有所帮助。出于这个原因,它们也在自己的自己的 URI 上,并且可以在网络的一个点消失并出现在另一个点上。目录服务用于发现事物的位置。

标签: c# servicestack


【解决方案1】:

为了回答这个问题,我添加了新的 Modularizing servicesPhysical project structure wiki 页面,以突出构建和模块化 ServiceStack 服务的不同方式,我将重复听到这些方式以提高可发现性:

正如您所发现的,ServiceStack 对每个应用程序域都有一个单个应用程序主机。正如您可以从名称中推断的那样,Host 项目的作用是作为绑定所有服务具体依赖项、插件、过滤器和服务所需的所有其他内容的管道。在您的 AppHost.Configure() 方法中初始化所有内容后,您的服务配置应该是不可变的。 Physical project structure wiki page wiki 显示了典型解决方案的推荐物理项目结构。

在多个程序集中模块化服务

虽然您只能拥有 1 个 AppHost,但可以通过在 AppHostBase 构造函数中提供程序集来将服务分布在多个程序集中,例如:

public class AppHost : AppHostBase
{
    //Tell Service Stack the name of your application and which assemblies to find your web services
    public AppHost() : base("Hello ServiceStack!", 
       typeof(ServicesFromDll1).Assembly, ServicesFromDll2).Assembly /*, etc */) { }

    public override void Configure(Container container) {}
}

您还可以通过覆盖 CreateServiceManager 来提供自己的策略来发现和解析 ServiceStack 应自动连接的服务类型,例如:

public class AppHost : AppHostBase
{
    public AppHost() : base("Hello ServiceStack!", typeof(ServicesFromDll1).Assembly) { }
    public override void Configure(Container container) {}

    //Provide Alternative way to inject IOC Container + Service Resolver strategy
    protected virtual ServiceManager CreateServiceManager(params Assembly[] assembliesWithServices)
    {       
        return new ServiceManager(new Container(),
            new ServiceController(() => assembliesWithServices.ToList().SelectMany(x => x.GetTypes())));
    }
}

在插件中封装服务

一种模块化服务的方法是将它们封装在Plugins 中,这允许您手动注册服务、自定义路由、过滤器、内容类型、允许自定义以及您的模块需要的任何其他内容。

为了说明这一点,我们将展示一个基本的Auth Feature 示例的样子:

public class BasicAuthFeature : IPlugin 
{
    public string HtmlRedirect { get; set; }   //User-defined configuration

    public void Register(IAppHost appHost)
    {
        //Register Services exposed by this module
        appHost.RegisterService<AuthService>("/auth", "/auth/{provider}");
        appHost.RegisterService<AssignRolesService>("/assignroles");
        appHost.RegisterService<UnAssignRolesService>("/unassignroles");

        //Load dependent plugins
        appHost.LoadPlugin(new SessionFeature());
    }
}

将所有内容都封装在一个插件中,您的用户可以通过以下方式轻松地在您的 AppHost 中启用它们:

Plugins.Add(new BasicAuthFeature { HtmlRedirect = "~/login" });

Physical Project Structure

请参阅此earlier answer,了解对项目进行物理布局的推荐方式。

【讨论】:

  • 非常感谢您的及时回复。我无法可视化其他程序集中的服务类是什么。显然它们不是从 AppHost 派生的。因此,我还假设所有服务都有一个 Uri,但是路由是根据传递的类型确定的?我认为这可能是一个完美的解决方案。另外,我可以在以后注册这些组件,还是他们必须在施工时完成?如果没有,我可以解决它。
  • 所有服务的单一 URI?您指定将安装 ServiceStack 的 /root 的位置,然后所有服务都来自该根,但它们可以具有任何自定义 url 结构。是的,必须在构造时指定程序集(构造发生在 App_Start 中的任何位置),而 AppHost.Configure() 中的所有其他配置。您可以使用如上所示的appHost.RegisterService&lt;T&gt;("/path") 手动注册服务。
  • 非常感谢您的回复。出于某种原因,我仍然无法想象我的一项服务如何“上线”然后可以“下线”,或者有效地取消注册。在构建时向 AppHost 提供程序集实际上不是问题,因为配置文件是在启动时处理的,我知道所有可能提前提供服务的程序集。只是想看看这是如何工作的。非常感谢,继续为社区提供如此出色、自给自足、轻量级和高性能的解决方案:)
猜你喜欢
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 2013-07-02
  • 2023-03-08
  • 2012-08-02
  • 1970-01-01
相关资源
最近更新 更多