【问题标题】:RabbitMQ: Injecting the connection factoryRabbitMQ:注入连接工厂
【发布时间】:2012-11-01 16:23:50
【问题描述】:

我正在尝试为我正在编写的一对 Windows 服务设置 RabbitMQ,以便以快速可靠的方式促进它们之间的通信。但是,我在尝试设置主要的 Windows 服务引擎时遇到了问题,这些引擎需要建立与 RabbitMQ 服务器的连接才能完成它们的工作。

基本上,RabbitMQ 的 .NET 客户端中的ConnectionFactory 对象不是抽象的,也没有实现任何接口。我看不到使用像 StructureMap 这样的 IoC 容器来注入此类的明显方法。甚至文档中的代码示例也只是公然显示newing,就像这样:

 ConnectionFactory factory = new ConnectionFactory();
 factory.Uri = "amqp://user:pass@hostName:port/vhost";
 IConnection conn = factory.CreateConnection();

向我展示的解决方案是将整个工厂推到服务的主要 OnStartOnStop 函数中,这真的很难测试,而且无论如何也没有太大的兴趣。但是,这给我留下了一个单一的IConnection 用于服务,所以如果该连接以任何方式断开,服务将无法恢复并且必须简单地退出。如果主引擎可以看到工厂,它可以简单地产生一个新的连接并继续。但是除非我注入它,否则如果不连接到现有服务器就无法测试主引擎!

这里有什么我遗漏的吗?我不考虑的任何其他选择?我该如何注入这个工厂,如果我不能,我如何限制损失?

编辑:另外,作为事后的想法,如果有人对主要开发团队对类似更改的接受程度有很好的了解,我很高兴对 RabbitMQ 的 .NET 客户端进行更改以在此实现一个接口这。我很乐意做出贡献,但我最不想做的事情是让我的程序在一些自定义版本的 RabbitMQ 上运行,从而首先消除使用第三方库的主要好处。

【问题讨论】:

    标签: c# .net dependency-injection rabbitmq


    【解决方案1】:

    RabbitMQ C# 客户端是一个低级纯 AMQP 实现,您可能希望将其包装在更高级别的抽象中,然后将其注册到您的 IoC 容器中。

    EasyNetQ,对基本客户端的更高层次的抽象,实现了一个持久的 AMQP 连接,在连接丢失(通过网络问题或服务器反弹)后重新连接,并重建所有当前订阅。欢迎您使用任何您认为有用的代码。

    简而言之,就是将连接管理封装在某种PersistentConnection 类中,然后注册每个订阅with some code to rebuild them after a successful reconnect

    我已经写了a blog post 关于连接 EasyNetQ、Windsor IoC 容器和 TopShelf 的文章。我已经成功地使用这种技术来构建基于 RabbitMQ 的 Windows 服务。

    【讨论】:

    • 我将热切地对此进行调查。如果它和我希望的一样好,我会在这里改变接受的答案,当然要向 M Afifi 道歉。
    • 当尝试通过 NuGet 包安装时,EasyNetQ 坚持认为我已经引用了 RabbitMQ.Client 的较新版本,即使我完全取消了旧引用。知道为什么吗?
    • “EasyNetQ 坚持我已经在引用更新的版本。”你能更具体一点吗?是运行时程序集绑定问题,还是 NuGet 抱怨?
    • 抱歉 - NuGet 正在抱怨。我看到的具体输出是:Successfully installed 'RabbitMQ.Client 2.8.6'. Successfully installed 'Newtonsoft.Json 4.5.10'. Successfully installed 'EasyNetQ 0.8.1.37'. Install failed. Rolling back... Already referencing a newer version of 'RabbitMQ.Client'.
    • 值得注意的是(事后我突然想到)NuGet 安装了一些类似的程序集而没有任何抱怨。例如,它可以很好地安装 Burrow。我的项目中有 Burrow 作为权宜之计,但看起来 EasyNetQ 有更多我想使用的东西。
    【解决方案2】:

    棘手的部分是它看起来像根据documentation ConnectionFactory 没有实现任何接口。

    所以你真的可以实现自己的,比如,

    public interface IConnectionFactory
    {
        ConnectionFactory Get();
        ConnectionFactory Get(string uri);
    }
    
    public class ConnectionFactoryCreator : IConnectionFactory
    {
        public ConnectionFactory Get(
            string uri = "amqp://user:pass@hostName:port/vhost")
        {
            return new ConnectionFactory
            {
                Uri = uri
            };
        }
    }
    

    对于您最终使用它的课程,

    public class RabbitMQUserClass
    {
        public ConnectionFactory ConnectionFactory {get; private set;}
        public RabbitMQUserClass(IConnectionFactory connectionFactory)
        {
            ConnectionFactory = connectionFactory.Get();
        }
    }
    

    【讨论】:

    • 我希望它记录在案,我非常不喜欢这个解决方案,但你是绝对正确的,这是我对目前情况的唯一追索权。感谢您的宝贵时间并感谢您的帮助。
    猜你喜欢
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    相关资源
    最近更新 更多