REST

连接 > 协议 > REST

ActiveMQ Classic 实现了一个面向 REST 的消息 API,它允许任何支持 Web 的设备使用常规的 HTTP POST 或 GET 来发布或消费消息。

如果您有兴趣直接从 Web 浏览器发送消息,您可能想查看我们的 AjaxWebSockets 支持,或尝试 运行 REST 示例

REST 到 JMS 的映射

要发布消息,请使用 HTTP POST。要消费消息,请使用 HTTP DELETE 或 GET。

ActiveMQ Classic 具有一个 Servlet,它负责处理 HTTP 和 ActiveMQ Classic 分发器之间的集成。

注意:以下示例需要在 URL 上进行 Servlet 映射。有关没有 Servlet 映射的发布方法,请参见后面的示例。

您可以将 URI 映射到 Servlet,然后使用 URI 的相对部分作为主题或队列名称。例如,您可以使用 HTTP POST 到

http://www.acme.com/orders/input

这将把 HTTP POST 的内容发布到 JMS 上的 orders.input 队列中。 

类似地,您可以对上述 URL 执行 HTTP DELETE GET 以从同一队列中读取。在这种情况下,我们将 ActiveMQ Classic 中的 MessageServlet 映射到 URI

http://www.acme.com/queue

并将其配置为接受 URI 作为队列目标。我们也可以做类似的事情来支持主题目标。

我们可以使用 HTTP 会话来表示唯一的发布者或消费者。

请注意,严格的 REST 要求 GET 是一种只读操作;因此严格来说,我们不应该使用 GET 来允许人们消费消息。虽然我们允许这样做,因为它在一定程度上简化了 HTTP/DHTML/Ajax 集成。

对于更清晰的简单传输协议到不同语言的映射,您可能希望查看 Stomp.

默认配置

在 5.8 版本之前,REST API 是 Web 示例 的一部分,并映射到 https://127.0.0.1:8161/demo/message URL。从 5.8 版本开始,该 API 默认情况下在 https://127.0.0.1:8161/api/message URL 上可用。此外,从 5.8 版本开始,Web 服务器默认情况下是安全的(有关更多信息,请参见 Web 控制台),因此在尝试使用它时请牢记这一点。以下示例将假定新的 API 位置和安全的 Web 服务器。

生产

您可以通过向服务器发送 POST 请求来进行生产,例如

curl -u admin:admin -d "body=message" https://127.0.0.1:8161/api/message/TEST?type=queue

注意:如果未指定类型参数,则默认情况下会创建一个主题。要将默认值更改为队列,请在 webapps/demo/WEB-INF/web.xml 中使用 init 参数初始化 Servlet,

如下所示

<servlet>
  <servlet-name>MessageServlet</servlet-name>  
  <servlet-class>org.apache.activemq.web.MessageServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
  <init-param>
     <param-name>topic</param-name>
     <param-value>false</param-value>
  </init-param>
</servlet>

备用生产语法

支持使用 URL 编码参数的备用发布语法;以下是一些示例: 

# Send to queue orders.input:
curl -XPOST -d "body=message" http://admin:admin@localhost:8161/api/message?destination=queue://orders.input
 
# Send to topic orders.input:
curl -XPOST -d "body=message" http://admin:admin@localhost:8161/api/message?destination=topic://orders.input

消息大小限制

默认情况下,消息的大小限制为 100,000 个字符,以防止可能出现内存不足的情况。可以通过将 init 参数 maxMessageSize 设置为您选择的任何值来修改此值。将该值设置为 -1 将禁用限制。

要更改该值,请修改 webapps/api/WEB-INF/web.xml 文件,如下所示

<servlet>
    <servlet-name>MessageServlet</servlet-name>
    <servlet-class>org.apache.activemq.web.MessageServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>

    <init-param>
        <param-name>maxMessageSize</param-name>
        <param-value>-1</param-value>
    </init-param>
</servlet>

超时

从队列中读取时,我们可能没有消息。我们可以使用超时查询参数来指示我们愿意等待消息到达的时间。这使我们能够轮询或阻塞,直到消息到达。

将其与 HTTP 1.1 保持活动套接字和管道处理结合使用,我们可以高效地访问通过 HTTP 的 JMS。

显然,如果您的客户端是 Java,那么使用 ActiveMQ Classic 的 JMS API 是与消息代理交互最快、最有效的方式;但是,如果您没有使用 Java 或更喜欢 HTTP 的简单性,那么它应该相当有效,特别是如果您的 HTTP 客户端支持保持活动套接字和管道处理。

消费

使用 REST API 消费消息时,您必须在 GET 请求之间保持会话活动,否则您将为每个请求创建一个单独的消费者,并且由于预取限制,您后续的调用将挂起。

例如,您可以使用 wget 来消费消息,如下所示

wget --user admin --password admin --save-cookies cookies.txt --load-cookies cookies.txt --keep-session-cookies  https://127.0.0.1:8161/api/message/TEST1?type=queue

此外,如果您计划让多个消费者使用 REST,建议将预取大小设置为 1,这样所有消费者都有平等的机会获得消息。您可以在 webapps/demo/WEB-INF/web.xml 中向 MessageServlet 传递一个特殊参数来做到这一点

<servlet>
    <servlet-name>MessageServlet</servlet-name>       
    <servlet-class>org.apache.activemq.web.MessageServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
            <param-name>destinationOptions</param-name>
            <param-value>consumer.prefetchSize=1</param-value>
    </init-param>
</servlet>

webapps/demo/WEB-INF/web.xml

备用消费语法

与生产一样,还支持使用 URL 编码参数的备用消费消息语法;以下是一些示例: 

# Send to queue orders.input:
curl -XGET http://admin:admin@localhost:8161/api/message?destination=queue://orders.input
 
# Send to topic orders.input:
curl -XGET http://admin:admin@localhost:8161/api/message?destination=topic://orders.input

无会话消费

从 5.2.0 版本开始,您可以使用 clientId 参数来避免将实际 JMS 消费者存储在请求会话中。使用这种方法时,您不需要在请求之间保持会话活动,您只需要在每次使用相同的 clientId

wget --user admin --password admin https://127.0.0.1:8161/api/message/test?type=queue&clientId=consumerA

每次这样的调用都将使用相同的 JMS 消费者,并交付由代理发送给它的消息。

在 5.4.1 版本中,也可以取消订阅客户端。通过向服务器发送包含 clientIdaction=unsubscribe 参数的 POST 调用来完成此操作,例如

https://127.0.0.1:8161/demo/message/test?clientId=consumerA&action=unsubscribe

使用选择器消费

从 ActiveMQ Classic 5.4.0 版本开始,您可以在使用 REST 协议消费时使用选择器。为此,只需指定包含选择器的适当标头即可。要为消费者定义选择器,您必须在适当的 HTTP 标头中提供它。默认情况下,选择器标头名称为 selector,因此以下示例

wget  --user admin --password admin --save-cookies cookies.txt --load-cookies cookies.txt --keep-session-cookies  --header="selector: test=2" https://127.0.0.1:8161/api/message/test?type=queue

应仅消费具有设置为 2test 属性的消息。

您可以使用 WEB-INF/web.xml 中的 org.apache.activemq.selectorName Servlet 上下文属性来更改选择器标头的名称,例如

<context-param>
    <param-name>org.apache.activemq.selectorName</param-name>
    <param-value>activemq-selector</param-value>
</context-param>

有关更多信息,请查看 RestTest

使用一次性消费者消费

一次性消费允许 REST 调用接收一条消息,然后立即关闭关联的消费者。

到目前为止,所有示例都会导致 Servlet 在多个 HTTP 请求中创建和保存目标的消费者。如果不注意,这些消费者可能会导致混淆,因为消息将被分派给它们,但随后会闲置,因为消费 HTTP 会话或 clientId 无法连接以继续请求消息。解决该问题的一种方法是使用一次性消费者。 只需添加 ?oneShot=true 选项,消费者在消费完成后就会被删除;如下所示

curl -XGET http://admin:admin@localhost:8161/api/message?destination=queue://orders.input&oneShot=true

请注意,在消费者正在等待消息时中断调用,消费者可能会保留,直到服务器超时 HTTP 请求,或直到最终收到消息。

内容类型

默认情况下,消息将使用 text/xml 内容类型发送给消费者。您的基于 REST 的应用程序可能希望 JSON 响应而不是 XML 响应。在这种情况下,您可以配置 Servlet 以发送响应,方法是添加类似于以下内容的内容

<servlet>
    <servlet-name>MessageServlet</servlet-name>
    <servlet-class>org.apache.activemq.web.MessageServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
            <param-name>defaultContentType</param-name>
            <param-value>application/json</param-value>
    </init-param> 
</servlet>

到您的 WEB-INF/web.xml 中。

也可以使用请求标头来覆盖默认内容类型。指定 xml=truejson=true URL 参数,您将获得具有所需内容类型的响应。

wget --user admin --password admin https://127.0.0.1:8161/api/message/TEST?type=queue\\&clientId=A\\&json=true

安全

从 5.7.0 版本开始,REST API 可以连接到安全的代理。该 API 使用基本身份验证标头格式来获取用户名和密码信息。

例如,使用 curl,您可以执行以下操作

curl -u system:manager -d "body=message" https://127.0.0.1:8161/demo/message/TEST?type=queue

此外,您可能希望为您的连接启用 ssl。为此,只需取消注释 conf/jetty.xml 中的 SecureConnector

<bean id="SecureConnector" class="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
    <property name="port" value="8162" />
    <property name="keystore" value="file:${activemq.conf}/broker.ks" />
    <property name="password" value="password" />
</bean>

REST 管理

从 5.8 版本开始,我们为代理提供了 REST 管理 API。使用 Jolokia JMX-HTTP 桥,可以使用 REST API 访问所有代理指标(例如内存使用情况)并执行管理操作(例如清除队列)。默认情况下,管理 API 在 https://127.0.0.1:8161/api/jolokia/ URL 上公开。因此,例如,您可以使用以下命令获取基本代理数据

wget --user admin --password admin --header "Origin: https://127.0.0.1" --auth-no-challenge https://127.0.0.1:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost

或者更具体地,使用以下命令获取总的消费者数量

wget --user admin --password admin --header "Origin: https://127.0.0.1" --auth-no-challenge https://127.0.0.1:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName=localhost/TotalConsumerCount

默认情况下,ActiveMQ Classic 使用 以下 Jolokia 安全策略

<restrict>

  <!-- Enforce that an Origin/Referer header is present to prevent CSRF -->
  <cors>
    <strict-checking/>
  </cors>

  <!-- deny calling operations or getting attributes from these mbeans -->
  <deny>
    <mbean>
      <name>com.sun.management:type=DiagnosticCommand</name>
      <attribute>*</attribute>
      <operation>*</operation>
    </mbean>
    <mbean>
      <name>com.sun.management:type=HotSpotDiagnostic</name>
      <attribute>*</attribute>
      <operation>*</operation>
    </mbean>
  </deny>

</restrict>

可以通过编辑“webapps/api/WEB-INF/web.xml”并指定“jolokia-agent”Servlet 下的“policyLocation”参数来配置自定义 Jolokia 安全策略。

有关 Jolokia 安全的更多信息,请参阅其参考手册的 安全部分。像这样的 API 使得对代理进行监控和管理操作的脚本编写变得容易,另请参见 如何监控 ActiveMQ Classic

陷阱和其他琐事

  1. 缺少“body”参数

在上面的 curl POST 示例中,使用“body=…”至关重要。如果在消息正文内容前面没有指定它,Web Servlet 将尝试从请求(而不是从 -d 参数)中读取正文,这将导致以下异常

java.lang.IllegalStateException: STREAMED
at org.eclipse.jetty.server.Request.getReader(Request.java:898)
at org.apache.activemq.web.MessageServletSupport.getPostedMessageBody(MessageServletSupport.java:347)
at org.apache.activemq.web.MessageServlet.doPost(MessageServlet.java:126)
...

但是,在这种情况下,一种选择是显式指定内容类型

curl -u admin:admin -d "hello world $(date)" -H "Content-Type: text/plain" -XPOST https://127.0.0.1:8161/api/message?destination=queue://abc.def

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛徽标和 Apache ActiveMQ 项目徽标是 Apache 软件基金会的商标。版权所有 © 2024,Apache 软件基金会。根据 Apache 许可证 2.0 许可。