【问题标题】:Cannot inject dependencies to Azure WorkerRole object using Spring.NET无法使用 Spring.NET 将依赖项注入到 Azure WorkerRole 对象
【发布时间】:2012-05-20 07:54:11
【问题描述】:

我在使用 spring.net 4.0 和 nhibernate 3.0 为基于 ASP.net 的 Web 应用程序开发 Web 应用程序方面具有中等经验。最近我遇到了一种情况,我需要使用 spring.net 来注入属于WorkerRole 类的服务依赖项。我创建了 app.config 文件,就像我通常为 spring 使用 web.config 文件所做的那样。这是为了清楚起见。 (我已经排除了根节点)

<configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" requirePermission="false" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" requirePermission="false" />
      <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>
    <spring>
    <context>
      <!-- Application services and data access that has been previously developed and tested-->
      <resource uri="assembly://DataAccess/data-access-config.xml" />
      <resource uri="assembly://Services/service-config.xml" />
      <resource uri="AOP.xml" />
      <resource uri="DI.xml"/>
    </context>
    <parsers>
      <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
      <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
      <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
    </parsers>
  </spring>

同样是 AOP.xml

<object id="FilterServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
    <property name="proxyInterfaces" value="Domain.IFilterService"/>
    <property name="target" ref="FilterService"/>
    <property name="interceptorNames">
      <list>
        <value>UnhandledExceptionThrowsAdvice</value>
        <value>PerformanceLoggingAroundAdvice</value>
      </list>
    </property>
  </object>
</objects>

和 DI.xml

<object type="FilterMt.WorkerRole, FilterMt" >
  <property name="FilterMtService1" ref="FilterServiceProxy"/>
</object>

但是,我无法将任何依赖项注入辅助角色。有人可以让我知道我在这里做错了什么吗?是否有其他方法可以为 Windows azure 应用程序配置 Spring.net DI?

我没有收到任何配置错误,但我看到依赖项尚未注入,因为我尝试注入的属性对象仍然为空。

【问题讨论】:

    标签: azure spring.net azure-worker-roles


    【解决方案1】:

    根据我的经验,您不能在 WorkerRole 类(实现 RoleEntryPoint 的类)中注入任何东西。到目前为止,我使用Unity(我还为 Unity 构建了自己的帮助程序来帮助我注入 Azure 设置)所做的是,我拥有自己的基础架构,可以运行并由 Unity 构建,但我在代码中创建它工人角色。

    例如,我在我的 RoleEntry 点的 OnStart() 方法中初始化依赖容器,在那里我解决了我需要的任何事情。然后在我的 Run() 方法中,我在已解决的依赖项上调用一个方法。

    这是我的 RoleEntryPoint 实现的一个快速、精简的版本:

    public class WorkerRole : RoleEntryPoint
    {
        private UnityServiceHost _serviceHost;
        private UnityContainer _container;
    
        public override void Run()
        {
            // This is a sample worker implementation. Replace with your logic.
            Trace.WriteLine("FIB.Worker entry point called", "Information");
            using (this._container = new UnityContainer())
            {
                this._container.LoadConfiguration();
                IWorker someWorker = this._container.Resolve<IWorker>();
                someWorker.Start();
    
                IWorker otherWorker = this._container.Resolve<IWorker>("otherWorker");
                otherWorker.Start();
    
                while (true)
                {
                    // sleep 30 minutes. we don't really need to do anything here.
                    Thread.Sleep(1800000);
                    Trace.WriteLine("Working", "Information");
                }
            }
        }
    
        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections 
            ServicePointManager.DefaultConnectionLimit = 12;
    
            // For information on handling configuration changes
            // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    
            this.CreateServiceHost();
    
            return base.OnStart();
        }
    
        public override void OnStop()
        {
            this._serviceHost.Close(TimeSpan.FromSeconds(30));    
            base.OnStop();
        }
    
        private void CreateServiceHost()
        {
            this._serviceHost = new UnityServiceHost(typeof(MyService));
    
            var binding = new NetTcpBinding(SecurityMode.None);
            RoleInstanceEndpoint externalEndPoint =
                RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEndpoint"];
            string endpoint = String.Format(
                "net.tcp://{0}/MyService", externalEndPoint.IPEndpoint);
            this._serviceHost.AddServiceEndpoint(typeof(IMyService), binding, endpoint);
            this._serviceHost.Open();
        }
    

    如您所见,我自己的逻辑是 IWorker 接口,我可以拥有任意数量的实现,我在我的 Run() 方法中启动它们。我要做的更多是拥有一个 WCF 服务,再次完全通过 DI 和 Unity 进行配置。这是我的 IWorker 界面:

    public interface IWorker : IDisposable
    {
        void Start();
        void Stop();
        void DoWork();
    }
    

    就是这样。我的 WorkerRole 中没有任何“硬”依赖项,只有 Unity 容器。而且我的两个工人中有非常复杂的 DI,一切运行良好。

    您不能直接干预 WorkerRole.cs 类的原因是它是由 Windows Azure 基础架构而不是您自己的基础架构实例化的。您必须接受这一点,并在 WorkerRole 适当的方法中构建您的基础设施。并且不要忘记您绝不能退出/中断/返回/退出 Run() 方法。这样做会标记 Windows Azure 基础架构,表明您的代码有问题,并会触发角色回收。

    希望这会有所帮助。

    【讨论】:

    • 所以基本上WorkerRole 是组合根?
    • 谢谢阿斯塔科夫。这是解决问题的好方法。
    【解决方案2】:

    我知道这是一个老问题,但我正在经历同样的学习曲线,我想将我的发现分享给那些难以理解机制的人。

    您无法在辅助角色类中访问 DI 的原因是因为它在 IIS 之外的操作系统中的单独进程中运行。将您的 WebRole 类视为在 Windows 服务中运行。

    我对我的 MVC 网站和 WebRole 类做了一个小实验:

    public class WebRole : RoleEntryPoint
    {
        public override void Run()
        {
            while (true)
            {
                Thread.Sleep(10000);
                WriteToLogFile("Web Role Run: run, Forest, RUN!");
            }
        }
    
        private static void WriteToLogFile(string text)
        {
            var file = new System.IO.StreamWriter("D:\\tmp\\webRole.txt", true); // might want to change the filename
            var message = string.Format("{0} | {1}", DateTime.UtcNow, text);
    
            file.WriteLine(message);
            file.Close();
        }
    }
    

    这将每 10 秒(左右)向文件写入一个新字符串。现在以调试模式启动您的 Azure 站点,确保站点部署到 Azure 模拟器并且 VS 中的调试器已启动。检查站点是否正在运行并检查 WebRole 是否正在写入相关文件。

    现在在不停止 VS 调试器的情况下停止 IIS Express(或 IIS,如果您在完整安装中运行它)。您网站中的所有操作现在都已停止。但是,如果您检查临时文件,该过程仍在运行,并且您仍然每 10 秒添加新行。直到您停止调试器。

    因此,您在 Web 应用程序的内存中加载的任何内容都在 IIS 内部,而在 Worker Role 内部不可用。而且您需要从头开始重新配置您的 DI 和其他服务。

    希望这有助于人们更好地理解基础知识。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      • 2022-07-07
      • 2012-01-26
      • 1970-01-01
      相关资源
      最近更新 更多