java消息中间件

大型系统的演变必然的发展方向是分布式,而在分布式系统中应用与应用之间互相连接越来越紧密,在应用之间的消息传递就像家常便饭般普遍。使用Java消息中间件处理异步消息成为了分布式系统中的必修课。

1.为什么要使用消息中间件

我们模拟这样一个场景:小明所在公司发展壮大,他们开发的商城系统新增了需求,需要在用户登录成功之后,给用户发个短信,告诉用户登录成功。ok,这个需求很合理,于是小明在登录接口中新增了发送短信的代码。没过几天,产品经理又找到小明,告诉他,用户登录成功之后还要给用户账号增加积分,积分换礼品来保证用户粘度。ok,这个需求很合理,然后小明又改造了登录接口,增加了登录成功修改积分的功能。很不幸,没过几天,产品经理又找到小明,咱们这个系统需要在用户登录成功之后将记录用户登录时间以便于当用户超过三天未登录时发送短信通知(骚扰用户?哈哈)。ok!,虽然这个需求还是很合理,于是小明又很傻很天真的将登录接口改造。小明正沾沾自喜之时,测试小姐姐找上门来了,表示登录所耗时间长,用户体验不行(这不废话么,一个登录接口中包含了那么多功能,不慢才怪呢)。这下小明傻眼了,该怎么办呢?
在上面模拟的场景中,我们可以发现登录接口中包含了太多的功能,并且都是同步的。这明显违反了程序设计中的单一设计原则,以及开闭原则。那我们应该如何解决小明的难题呢?没错,用异步处理。此处我们引入消息中间件。

2.什么是消息中间件

简单来说,利用高效可靠的异步消息传递机制来实现消息的发送和接收。

3. 消息中间件应用场景

还是上面那个示例,当我们使用消息中间件进行改造之后,我们可以用如下草图进行示意:
image.png

这样登录接口就变得很纯粹,仅仅实现登录功能,其他的功能采用消息中间件异步处理了。
我们从本例中至少能发现使用消息中间件的一个好处:解耦。这对系统的维护是有莫大的好处的。

4.关于消息中间件的两个规范

网上总结的很好,此处粘贴进行记录:

1.JMS
java消息服务(Java Message Service)即JMS,是一个Java平台中关于面向消息中间件的api,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信
2.AMQP
AMQP(advanced message queuing protocol)是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制
常见消息中间件

activeMQ(支持多语言,实现jms1.1,j2ee1.4规范),RabbitMQ(支持更多语言,基于AMQP规范),kafka(高吞吐量,分布式,分区,O(1)磁盘顺序提供消息持久化)
image.png

JMS中的两种消息模式对比

在jms规范中有队列模式和主题模式。
这两种模式区别在于,队列模式只能被消费者消费一次,即点对点模式,每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
主题模式也被称为发布订阅模式,每个消息都可以有多个消费者,我们生活中最常见的微信公众号其实就是一个最常见的主题模式有木有。微信公众号发布一段消息,订阅了该公众号的用户就可以看到该消息。

JMS代码示例

消息生产者类

public class AppQueueProducer {
    public static final String url = "tcp://localhost:61616";
    public static final String queueName = "queue-test";

    public static void main(String[] args) throws JMSException {

        //1. 创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);

        //2. 创建连接
        Connection connection = activeMQConnectionFactory.createConnection();

        //3. 启动连接
        connection.start();

        //4. 创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5. 创建目标,为队列模式
        Destination destination = session.createQueue(queueName);//队列模式
     // Destination destination = session.createTopic(toppicName);//主题模式

        //6. 创建一个生产者
        MessageProducer producer = session.createProducer(destination);

        //7. 发送消息
        Stream.iterate(1, x -> x + 1).limit(100).map(y -> {
            try {
                //8. 创建消息
                TextMessage textMessage = session.createTextMessage("test" + y);
                //9. 发布消息
                producer.send(textMessage);

                return "发送消息:" + textMessage.getText();
            } catch (JMSException e) {
                e.printStackTrace();
                return e.getMessage();
            }
        }).forEach(System.out::println);

        //关闭连接
        connection.close();
    }
}

消息消费者类

public class AppQueueConsumer {
    public static final String url="tcp://localhost:61616";
    public static final String queueName="queue-test";

    public static void main(String[] args) throws JMSException {
        //1. 创建工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(url);

        //2. 创建连接
        Connection connection = activeMQConnectionFactory.createConnection();

        //3. 连接启动
        connection.start();

        //4. 创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5. 创建目标
        Destination destination=session.createQueue(queueName);//队列模式
      //Destination destination=session.createTopic(toppicName);//主题模式

        //6. 创建消费者
        MessageConsumer consumer = session.createConsumer(destination);

        //7. 创建消息监听
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
               TextMessage textMessage= (TextMessage) message;
                try {
                    System.out.println("接收到消息:"+textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

我们启动队列模式下的消息生产者,然后启动三个消息消费者实例,我们会发现,在队列模式下,三个实例是均匀消费消息的,如下图
image.png
image.png
image.png

我们启动主题模式下的消息生产者,然后启动三个消息消费者实例,我们发现此时并没有接收到消息,原因在于消息消费者启动订阅之后,前面生产的消息已经发布了,此时他不能被后面的消息消费者发现。我们要先启动消息消费者,然后再启动消息生产者,我们发现三个消息消费者都完整接收到了消息发布者发布的100条消息。
消息中间件难的不是代码,而是思想。如何使用消息中间件让我们的系统更加健壮合理这才是我们需要真正思考的地方!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容

  • 中间件 非底层操作系统软件,非业务应用软件,不能直接给最终用户使用和带来价值的软件。 消息中间件 关注于数据的发送...
    wch853阅读 1,019评论 0 0
  • 为什么使用消息中间件 消息中间件作用:解耦服务调用。松耦合。 使用中间件,不用等调用的服务处理完才返回结果。提高效...
    Hey_Shaw阅读 1,069评论 0 16
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,654评论 18 139
  • 人来人往红尘过, 潮起潮落有缘错。 昨夜小楼月梅花, 暖茶对饮珠帘落。
    果然全身阅读 309评论 10 18
  • 14章记载以色列民过红海的奇妙经历,属神的子民人生处处都有神迹。 逾越节的那个晚上,埃及地满了哀...
    玛哈念跳舞阅读 5,014评论 0 0