zoukankan      html  css  js  c++  java
  • RabbitMQ 使用 Policies HTTP API 绑定和解绑 DLX

     需求:

    exchange 和 queue 都能重复声明不会影响已有数据,但是 DLX 只能在 queue 第一次创建的时候一起定义,否则运行时就需要通过 WEB UI 或者 rabbitmqctl set_policy 命令行指令来添加 DLX。如果对已经存在的 queue 使用 java API 的方式添加 DLX 绑定则会报错。而我在写demo时定义了默认的 exchange 和 queue,所以希望默认的 dlx 也能通过 java API 方式重复声明。

    解决方案:

    去官网找了一些 HTTP API 资料,但官网只给出 SET_POLICY 方式,相应的 HTTP API 没有给出具体示例。于是根据已有资料中一些其他的 HTTP API 的规则、WEB UI 中 Policies 接口的存在,还有 SET_POLISY DLX 的规律,猜测 DLX policy HTTP API 的调用方式,最后比较简单地试出了 DLX HTTP API 的调用方式。

    代码会跟随 RabbitMQ 的某个小demo不久后会正式分享到 github,现在就直接贴代码吧。

    Policies HTTP 设置 DLX 代码:

    PS:DELETE 方法中 pattern 为 ""(空字符串)就可以了。这里没有完全优化。

     1 private static final String DEFAULT_DLX_URL = "http://192.168.33.50:15672/api/policies/%2f/DLX"
     2 
     3 public static void declareDlxForDefaultQueueViaHttpClient(boolean bind) {
     4         HttpEntityEnclosingRequestBase request;
     5         if (bind) {
     6             request = new HttpPut(DEFAULT_DLX_URL);
     7         } else {
     8             request = new HttpDeleteWithEntity(DEFAULT_DLX_URL);
     9         }
    10         CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    11         Credentials credentials = new UsernamePasswordCredentials(DEFAULT_USERNAME, DEFAULT_USER_PWD);
    12         // 这里可以用 AuthScope.ANY 替代。表示任何 URL domain 都使用同一个 AUTH
    13         credentialsProvider.setCredentials(new AuthScope(DEFAULT_HOST, DEFAULT_MANAGEMENT_PORT), credentials);
    14         // BasicAuth 验证由 HttpClient API 来处理
    15         CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build();
    16         JSONObject dlxJson = new JSONObject();
    17         dlxJson.put("pattern", "origin\..*");
    18         JSONObject definition = new JSONObject();
    19         definition.put("dead-letter-exchange", "origin.dlx");
    20         dlxJson.put("definition", definition);
    21         dlxJson.put("apply-to", "queues");
    22         StringEntity entity = new StringEntity(dlxJson.toString(), ContentType.APPLICATION_JSON);
    23         // 有些方法不能带请求体,所以请求体不能放到 HttpClient API 里
    24         request.setEntity(entity);
    25         try {
    26             CloseableHttpResponse httpResponse = httpClient.execute(request);
    27             int statusCode = httpResponse.getStatusLine().getStatusCode();
    28             HttpEntity responseEntity = httpResponse.getEntity();
    29             String responseBody = responseEntity == null ? "empty response body" : EntityUtils.toString(responseEntity);
    30             log.info("IN declare DLX for DEFAULT QUEUE:request method=" + request.getMethod()
    31                     + ", statusCode=" + statusCode + ", responseBody=" + responseBody);
    32         } catch (IOException e) {
    33             e.printStackTrace();
    34         }
    35     }

    模拟 HttpPut 构造 HttpDeleteWithEntity 代码:

     1 public class HttpDeleteWithEntity extends HttpEntityEnclosingRequestBase {
     2 
     3     public final static String METHOD_NAME = "DELETE";
     4 
     5     public HttpDeleteWithEntity() {
     6         super();
     7     }
     8 
     9     public HttpDeleteWithEntity(final URI uri) {
    10         super();
    11         setURI(uri);
    12     }
    13 
    14     /**
    15      * @throws IllegalArgumentException if the uri is invalid.
    16      */
    17     public HttpDeleteWithEntity(final String uri) {
    18         super();
    19         setURI(URI.create(uri));
    20     }
    21 
    22     @Override
    23     public String getMethod() {
    24         return METHOD_NAME;
    25     }
    26 }

    pom.xml 代码:

     1 <dependencies>
     2         <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
     3         <dependency>
     4             <groupId>org.apache.httpcomponents</groupId>
     5             <artifactId>httpclient</artifactId>
     6             <version>4.5.10</version>
     7         </dependency>
     8 
     9         <dependency>
    10             <groupId>com.alibaba</groupId>
    11             <artifactId>fastjson</artifactId>
    12             <version>1.2.62</version>
    13         </dependency>
    14 
    15         <dependency>
    16             <groupId>junit</groupId>
    17             <artifactId>junit</artifactId>
    18             <version>4.12</version>
    19             <scope>test</scope>
    20         </dependency>
    21 
    22         <dependency>
    23             <groupId>com.rabbitmq</groupId>
    24             <artifactId>amqp-client</artifactId>
    25             <version>5.4.3</version>
    26             <scope>compile</scope>
    27         </dependency>
    28 
    29         <dependency>
    30             <groupId>org.projectlombok</groupId>
    31             <artifactId>lombok</artifactId>
    32             <version>1.18.10</version>
    33             <scope>provided</scope>
    34         </dependency>
    35 
    36         <!--logback 日志框架,只需要引入这个-->
    37         <dependency>
    38             <groupId>ch.qos.logback</groupId>
    39             <artifactId>logback-classic</artifactId>
    40             <version>1.2.3</version>
    41         </dependency>
    42     </dependencies>
    maven dependencies

    需要注意:

    当 DLX 关系存在或不存在时,API 的返回稍微有点不同,某些情况需要额外判断,如上面代码中对 responseEntity 的判断。

    用 POSTMAN 来模拟 policies set dlx:

    图1:因为我单独建了一个 collection,默认当前 collection 下所有请求都使用 Basic Auth 并自动把 username 和 password 都填了。所以没有设置这个默认选项的同学手动选一下,图中位置下拉框选中 Basic Auth,填上 RabbitMQ management 管理账号就可以了

    PS:注意 HTTP 方法要选择 PUT。

     图2:header 设置,这是发完请求后才截图的,可以看到 temporary headers 里面有 Authorization ~

    图3:body 设置

    嗯,在 POSTMAN 里面发个请求比在 java 程序里跑个 test 方法快多了。

    参考资料:

    https://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2013-May/027573.html

    RabbitMQ 官网 DLX 和 HTTP API 相关参考:

      https://www.rabbitmq.com/parameters.html

      https://www.rabbitmq.com/dlx.html

    HttpClient:https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html#d4e1023

    HttpDelete 缺失 Set Entity 方法相关解决办法参考:https://stackoverflow.com/questions/43241436/java-http-delete-with-request-body

    Basic Auth 作为一种 http header 的基本原理:https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring#maven

  • 相关阅读:
    iOS--异步下载
    linux搭建ftp服务器
    hexo常用命令
    Markdown入门
    Markdown 语法和 MWeb 写作使用说明
    vi/vim
    微信聊天机器人
    .vimrc
    配置双机
    python学习笔记(一)
  • 原文地址:https://www.cnblogs.com/christmad/p/11832495.html
Copyright © 2011-2022 走看看