繁体   English   中英

嵌入式AMQP Java Broker

[英]Embedded AMQP Java Broker

我正在尝试为连接到RabbitMQ代理的Scala / Java应用程序创建集成测试。 为了达到这个目的,我想要一个能够在每次测试之前开始和停止的AMQP的嵌入式代理。 最初我尝试将ActiveMQ作为嵌入式代理引入AMQP,但是应用程序使用RabbitMQ只能说AMQP版本0.9.3而ActiveMQ需要AMQP版本1.0。

我可以使用另一个嵌入式代理来代替ActiveMQ吗?

一个完全内存的解决方案。 根据需要更换spring.*属性。

<dependency>
  <groupId>org.apache.qpid</groupId>
  <artifactId>qpid-broker</artifactId>
  <version>6.1.1</version>
  <scope>test</scope>
</dependency>
public class EmbeddedBroker {
  public void start() {
    Broker broker = new Broker();
    BrokerOptions brokerOptions = new BrokerOptions();
    brokerOptions.setConfigProperty("qpid.amqp_port", environment.getProperty("spring.rabbitmq.port"));
    brokerOptions.setConfigProperty("qpid.broker.defaultPreferenceStoreAttributes", "{\"type\": \"Noop\"}");
    brokerOptions.setConfigProperty("qpid.vhost", environment.getProperty("spring.rabbitmq.virtual-host"));
    brokerOptions.setConfigurationStoreType("Memory");
    brokerOptions.setStartupLoggedToSystemOut(false);
    broker.startup(brokerOptions);
  }
}

添加initial-config.json作为资源:

{
  "name": "Embedded Test Broker",
  "modelVersion": "6.1",
  "authenticationproviders" : [{
    "name": "password",
    "type": "Plain",
    "secureOnlyMechanisms": [],
    "users": [{"name": "guest", "password": "guest", "type": "managed"}]
  }],
  "ports": [{
    "name": "AMQP",
    "port": "${qpid.amqp_port}",
    "authenticationProvider": "password",
    "protocols": [ "AMQP_0_9_1" ],
    "transports": [ "TCP" ],
    "virtualhostaliases": [{
      "name": "${qpid.vhost}",
      "type": "nameAlias"
    }]
  }],
  "virtualhostnodes" : [{
    "name": "${qpid.vhost}",
    "type": "Memory",
    "virtualHostInitialConfiguration": "{ \"type\": \"Memory\" }"
  }]
}

我已经开发了一个包装器,用于下载,提取,启动和管理RabbitMQ,因此它可以像任何JVM项目控制的嵌入式服务一样工作。

看看: https//github.com/AlejandroRivera/embedded-rabbitmq

它很简单:

EmbeddedRabbitMqConfig config = new EmbeddedRabbitMqConfig.Builder()
    .version(PredefinedVersion.V3_5_7)
    .build();
EmbeddedRabbitMq rabbitMq = new EmbeddedRabbitMq(config);
rabbitMq.start();
...
rabbitMq.stop();

适用于Linux,Mac和Windows。

以下是OrangeDog提出的适用于Qpid Broker 7.x的解决方案,灵感来自于此

添加qpid 7.x作为测试依赖项。 在7.x中,这些已经在核心+插件中分离,具体取决于您的需要。 对于RabbitMQ AMQP版本,您需要qpid-broker-plugins-amqp-0-8-protocol并且要运行内存(足以进行集成测试),请使用qpid-broker-plugins-memory-store

pom.xml

...
<properties>
    ...
    <qpid-broker.version>7.0.2</qpid-broker.version>
</properties>

<dependencies>
    ...
    <dependency>
        <groupId>org.apache.qpid</groupId>
        <artifactId>qpid-broker-core</artifactId>
        <version>${qpid-broker.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.qpid</groupId>
        <artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
        <version>${qpid-broker.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.qpid</groupId>
        <artifactId>qpid-broker-plugins-memory-store</artifactId>
        <version>${qpid-broker.version}</version>
        <scope>test</scope>
    </dependency>
</dependecies>
...

使用硬编码的用户/密码添加代理配置,并将默认的内存虚拟主机映射到默认端口(5672):

qpid-config.json

{
  "name": "EmbeddedBroker",
  "modelVersion": "7.0",
  "authenticationproviders": [
    {
      "name": "password",
      "type": "Plain",
      "secureOnlyMechanisms": [],
      "users": [{"name": "guest", "password": "guest", "type": "managed"}]
    }
  ],
  "ports": [
    {
      "name": "AMQP",
      "port": "${qpid.amqp_port}",
      "authenticationProvider": "password",
      "virtualhostaliases": [
        {
          "name": "defaultAlias",
          "type": "defaultAlias"
        }
      ]
    }
  ],
  "virtualhostnodes": [
    {
      "name": "default",
      "defaultVirtualHostNode": "true",
      "type": "Memory",
      "virtualHostInitialConfiguration": "{\"type\": \"Memory\" }"
    }
  ]
}

定义junit ExternalResource并声明为ClassRule (或者在IT @BeforeClass@AfterClass方法中启动和关闭嵌入式代理):

EmbeddedAMQPBroker.java

public class EmbeddedAMQPBroker extends ExternalResource {

    private final SystemLauncher broker = new SystemLauncher();

    @Override
    protected void before() throws Throwable {
        startQpidBroker();
        //createExchange();
    }

    @Override
    protected void after() {
        broker.shutdown();
    }

    private void startQpidBroker() throws Exception {
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("type", "Memory");
        attributes.put("initialConfigurationLocation", findResourcePath("qpid-config.json"));
        broker.startup(attributes);
    }

    private String findResourcePath(final String fileName) {
        return EmbeddedAMQPBroker.class.getClassLoader().getResource(fileName).toExternalForm();
    }
}

整合测试:

public class MessagingIT{
    @ClassRule
    public static EmbeddedAMQPBroker embeddedAMQPBroker = new EmbeddedAMQPBroker();

    ...
}

我不知道任何嵌入式RabbitMQ服务器,所以我认为你有几个选项可以解决这个问题:

  1. 您的RabbitMQ服务器不需要存在于CI服务器上,您可以启动一个新的服务器,即CI rabbitmq服务器。 如果你不能自己带一个,你可以看看CloudAMQP 今天的免费套餐提供:每月1M条消息,20条并发连接,100条队列,10,000条排队消息。 对您的CI流程来说足够了。

  2. 如果您的测试只是针对RabbitMQ进行单元测试,那么您可以模拟您的RabbitMQ消息生成。 这就是我们在一些单元测试中所做的。 我们只是检查一个特定的操作使方法调用产生一个特定的消息,但我们嘲笑它,所以我们实际上不发布消息。 然后,我们通过使用我们创建的特定消息显式调用使用者方法来测试每个使用者。

您可以尝试Apache QPid Java代理 这可以用作嵌入式代理。

Scala中的安装程序在另一个SO问题中描述 - 独立Apache Qpid(amqp)Junit测试的示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM