JavaEE08-异步消息

异步消息

消息队列

点对点模式, 消息队列中的每一条消息只能有一个接收者接收. 如果有多个接收者监听队列, 那么一条消息由哪个接收者接收到是不确定的. 例如排队机.

主题

发布/订阅模式, 发布者发布消息到主题, 主题的订阅者都会收到消息的副本. 例如期刊订阅.

异步消息和同步调用

发送消息完成后不等待消息处理结果. 调用者不需要等待被调用者完成操作. 同步的本质是把被调用者纳入到调用者的时间序列中.
消息的发送者接收者位置独立. 调用者不需要知道被调用者的位置, 例如URL, IP/端口等等. 但是需要知道消息代理(消息队列/主题)的地址.
消息不依赖于接收者的实现方式. 调用者只需要发送消息(具有一定的格式), 无序依赖被调用者采用的具体的技术协议, 如HTTP, TCP, RPC, REST等等. 但是需要符合消息代理(消息队列/主题)的协议.
消息代理确保消息不丢失. 被调用者的可用性基本不影响调用者, 但是消息代理(消息队列/主题)的可用性直接影响调用者.
总之异步消息是以数据格式为规范的系统协作范式.
同步调用是以过程调用为范式的系统协作范式. 同步调用可以确保调用已经完成, 异步消息不保证消息何时被处理.

RabbitMQ

RabbitMQ实现了AMQP. RabbitMQ采用erlang语言实现. 消息的发送者和接收者可以采用不同的语言实现.

安装

下载安装erlang_win64_20.3
下载安装RabbitMQ
或者在百度网盘https://pan.baidu.com/s/18D_48VjCQUPzTZIWWofCrA
安装完成后启动RabbitMQ服务

编程

参考http://www.rabbitmq.com/getstarted.html编写程序.

下载
java-amqp-client
SLF4J API
SLF4J Simple
后, 把上述3个jar文件加入要编写的项目中.
编写发送端文件Send.java

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Send {

  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    String message = "Hello World! 世界, 你好!";
    channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
    System.out.println(" [x] Sent '" + message + "'");

    channel.close();
    connection.close();
  }
}

编写接收端文件Recv .java

import com.rabbitmq.client.*;

import java.io.IOException;

public class Recv {

  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

    Consumer consumer = new DefaultConsumer(channel) {
      @Override
      public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
          throws IOException {
        String message = new String(body, "UTF-8");
        System.out.println(" [x] Received '" + message + "'");
      }
    };
    channel.basicConsume(QUEUE_NAME, true, consumer);
  }
}

项目文件结构

JavaEE08-异步消息_第1张图片

运行结果

运行Recv.java
JavaEE08-异步消息_第2张图片
运行Send.java
JavaEE08-异步消息_第3张图片
Recv接收到信息
JavaEE08-异步消息_第4张图片

使用在其它主机上部署的RabbitMQ

RabbitMQ的默认用户guest只能使用localhost上的RabbitMQ服务器. 如果要使用其它主机上的RabbitMQ服务器, 需要在RabbitMQ服务器上配置用户名和口令, 完成用户的认证. 配置用户的权限(访问控制列表), 完成用户的授权. 这样, 在客户端使用(用IP地址或域名)指定的RabbitMQ服务器时, 需要提供用户名和口令, RabbitMQ完成用户身份认证, 根据用户的权限, 判断用户是否可以访问和可以如何访问这个RabbitMQ服务器, 完成访问控制.

在RabbitMQ服务器上增加用户

例如在一个部署在Linux(Ubuntu18.4)主机上的RabbitMQ服务器上增加用户u00, 口令为p00

sudo rabbitmqctl add_user u00 p00

执行结果:

~$ sudo rabbitmqctl add_user u00 p00
Adding user "u00" ...

查看RabbitMQ服务器的用户列表

sudo rabbitmqctl list_users

执行结果:

~$ sudo rabbitmqctl list_users
Listing users ...
u00     []
guest   [administrator]

配置用户的访问权限

例如在一个部署在Linux主机上的RabbitMQ服务器上为用户u00授予全部权限

sudo rabbitmqctl set_permissions -p / u00 '.*' '.*' '.*'

执行结果:

~$ sudo rabbitmqctl set_permissions -p / u00 '.*' '.*' '.*'
Setting permissions for user "u00" in vhost "/" ...

查看RabbitMQ服务器的用户权限列表

sudo rabbitmqctl list_permissions

执行结果:

~$ sudo rabbitmqctl list_permissions
Listing permissions for vhost "/" ...
guest   .*      .*      .*
u00     .*      .*      .*

程序的变化

在程序中设置主机的IP地址, 用于连接RabbitMQ服务器的用户名和口令。
把Send.java和Recv.java中的

        factory.setHost("localhost");

替换为

        factory.setHost("10.0.2.15");
        factory.setUsername("u00");
        factory.setPassword("p00");

重新运行Send.java和Recv.java, 可以得到和原来同样的运行结果.

在windows上部署RabbitMQ的注意事项

  • 注意事项1:
    对于Windows10, erlang_20.3, rabbitmq-server-3.7.5需要手工复制erlang的cookie文件到用户目录下, 以保持cookie一致. 否则rabbitmqctl命令不能正确执行. 也就是需要把C:\Windows\System32\config\systemprofile.erlang.cookie文件复制到当前用户目录下, 即目录C:\Users\当前用户名\
  • 注意事项2:
    在window上执行以管理员权限执行设置用户u00具有全部权限的命令为 rabbitmqctl set_permissions -p / u00 .* .* .*
    注意不要加’号.

你可能感兴趣的:(JavaEE)