消息_消息队列 - CSDN
精华内容
参与话题
  • 消息中间件(一)MQ详解及四大MQ比较

    万次阅读 多人点赞 2018-08-29 22:26:55
    一、消息中间件相关知识 1、概述 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息...

    一、消息中间件相关知识

    1、概述

    消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。

     

    2、消息中间件的组成

          2.1 Broker

    消息服务器,作为server提供消息核心服务

          2.2 Producer

    消息生产者,业务的发起方,负责生产消息传输给broker,

          2.3 Consumer

    消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理

          2.4 Topic

    主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的       广播

          2.5 Queue

    队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收

          2.6 Message

    消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

     

    3 消息中间件模式分类

          3.1 点对点

    PTP点对点:使用queue作为通信载体 

    说明: 
    消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。 
    消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

    3.2 发布/订阅

    Pub/Sub发布订阅(广播):使用topic作为通信载体 

    说明: 
    消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

    queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。 
    topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝。

     

    4 消息中间件的优势

          4.1 系统解耦

    交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。

          4.2 提高系统响应时间

    例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送几个逻辑才能完成;通过MQ架构设计,就可将紧急重要(需要立刻响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,供消费者处理。

          4.3 为大数据处理架构提供服务

    通过消息作为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。

          4.4 Java消息服务——JMS

    Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。 
    JMS中的P2P和Pub/Sub消息模式:点对点(point to point, queue)与发布订阅(publish/subscribe,topic)最初是由JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)。

     

    5 消息中间件应用场景

           5.1 异步通信

    有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

          5.2 解耦

    降低工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,可以独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

          5.3 冗余

    有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

          5.4 扩展性

    因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。便于分布式扩容。

          5.5 过载保护

    在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量无法提取预知;如果以为了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

          5.6 可恢复性

    系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

          5.7 顺序保证

    在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。

          5.8 缓冲

    在任何重要的系统中,都会有需要不同的处理时间的元素。消息队列通过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流经过系统的速度。以调节系统响应时间。

          5.9 数据流处理

    分布式系统产生的海量数据流,如:业务日志、监控数据、用户行为等,针对这些数据流进行实时或批量采集汇总,然后进行大数据分析是当前互联网的必备技术,通过消息队列完成此类数据收集是最好的选择。

     

    6 消息中间件常用协议

          6.1 AMQP协议

    AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。 
    优点:可靠、通用

          6.2 MQTT协议

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。 
    优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

          6.3 STOMP协议

    STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。 
    优点:命令模式(非topic\queue模式)

          6.4 XMPP协议

    XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。 
    优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

          6.5 其他基于TCP/IP自定义的协议

    有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。

     

    7 常见消息中间件MQ介绍

          7.1 RocketMQ

    阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,目前主要多用于订单交易系统。

    具有以下特点:

    • 能够保证严格的消息顺序
    • 提供针对消息的过滤功能
    • 提供丰富的消息拉取模式
    • 高效的订阅者水平扩展能力
    • 实时的消息订阅机制
    • 亿级消息堆积能力

    官方提供了一些不同于kafka的对比差异: 
    https://rocketmq.apache.org/docs/motivation/

          7.2 RabbitMQ

    使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。

          7.3 ActiveMQ

    Apache下的一个子项目。使用Java完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少量代码就可以高效地实现高级应用场景。可插拔的传输协议支持,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

          7.4 Redis

    使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

          7.5 Kafka

    Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具有以下特性:

    • 快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
    • 高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
    • 高堆积:支持topic下消费者较长时间离线,消息堆积量大;
    • 完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
    • 支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

          7.6 ZeroMQ

    号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中经常使用,偏重于实时数据通信场景。ZMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,开发成本高。因此ZeroMQ具有一个独特的非中间件的模式,更像一个socket library,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序本身就是使用ZeroMQ API完成逻辑服务的角色。但是ZeroMQ仅提供非持久性的队列,如果down机,数据将会丢失。如:Twitter的Storm中使用ZeroMQ作为数据流的传输。

    ZeroMQ套接字是与传输层无关的:ZeroMQ套接字对所有传输层协议定义了统一的API接口。默认支持 进程内(inproc) ,进程间(IPC) ,多播,TCP协议,在不同的协议之间切换只要简单的改变连接字符串的前缀。可以在任何时候以最小的代价从进程间的本地通信切换到分布式下的TCP通信。ZeroMQ在背后处理连接建立,断开和重连逻辑。

    特性:

    • 无锁的队列模型:对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。
    • 批量处理的算法:对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。
    • 多核下的线程绑定,无须CPU切换:区别于传统的多线程并发模式,信号量或者临界区,zeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销。

     

    二、主要消息中间件的比较

     

    综合选择RabbitMq 

    展开全文
  • 通俗易懂讲消息队列

    千次阅读 2020-03-05 17:00:21
    一、什么是消息队列? 消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。 消息队列,一般我们会简称它为MQ(Message Queue),嗯...

    一、什么是消息队列?

    消息队列不知道大家看到这个词的时候,会不会觉得它是一个比较高端的技术,反正我是觉得它好像是挺牛逼的。

    消息队列,一般我们会简称它为MQ(Message Queue),嗯,就是很直白的简写。

    我们先不管消息(Message)这个词,来看看队列(Queue)。这一看,队列大家应该都熟悉吧。

    队列是一种先进先出的数据结构。

    什么是消息队列?

     

    在Java里边,已经实现了不少的队列了:

    什么是消息队列?

     

    那为什么还需要消息队列(MQ)这种中间件呢???其实这个问题,跟之前我学Redis的时候很像。Redis是一个以key-value形式存储的内存数据库,明明我们可以使用类似HashMap这种实现类就可以达到类似的效果了,那还为什么要Redis?《Redis合集》

    • 到这里,大家可以先猜猜为什么要用消息队列(MQ)这种中间件,下面会继续补充。

    消息队列可以简单理解为:把要传输的数据放在队列中

    什么是消息队列?

     

    )

    科普:

    • 把数据放到消息队列叫做生产者
    • 从消息队列里边取数据叫做消费者

    二、为什么要用消息队列?

    为什么要用消息队列,也就是在问:用了消息队列有什么好处。我们看看以下的场景

    2.1 解耦

    现在我有一个系统A,系统A可以产生一个userId

    什么是消息队列?

     

    然后,现在有系统B和系统C都需要这个userId去做相关的操作

    什么是消息队列?

     

    写成伪代码可能是这样的:

    public class SystemA {
     // 系统B和系统C的依赖
     SystemB systemB = new SystemB();
     SystemC systemC = new SystemC();
     // 系统A独有的数据userId
     private String userId = "Java3y";
     public void doSomething() {
     // 系统B和系统C都需要拿着系统A的userId去操作其他的事
     systemB.SystemBNeed2do(userId);
     systemC.SystemCNeed2do(userId);
     
     }
    }
    

    结构图如下:

    什么是消息队列?

     

    ok,一切平安无事度过了几个天。

    某一天,系统B的负责人告诉系统A的负责人,现在系统B的SystemBNeed2do(String userId)这个接口不再使用了,让系统A别去调它了

    于是,系统A的负责人说"好的,那我就不调用你了。",于是就把调用系统B接口的代码给删掉了

    public void doSomething() {
     // 系统A不再调用系统B的接口了
     //systemB.SystemBNeed2do(userId);
     systemC.SystemCNeed2do(userId);
    }
    

    又过了几天,系统D的负责人接了个需求,也需要用到系统A的userId,于是就跑去跟系统A的负责人说:"老哥,我要用到你的userId,你调一下我的接口吧"

    于是系统A说:"没问题的,这就搞"

    什么是消息队列?

     

    然后,系统A的代码如下:

    public class SystemA {
     // 已经不再需要系统B的依赖了
     // SystemB systemB = new SystemB();
     
     // 系统C和系统D的依赖
     SystemC systemC = new SystemC();
     SystemD systemD = new SystemD();
     // 系统A独有的数据
     private String userId = "Java3y";
     public void doSomething() {
     
     // 已经不再需要系统B的依赖了
     //systemB.SystemBNeed2do(userId);
     // 系统C和系统D都需要拿着系统A的userId去操作其他的事
     systemC.SystemCNeed2do(userId);
     systemD.SystemDNeed2do(userId);
     }
    }
    

    时间飞逝:

    • 又过了几天,系统E的负责人过来了,告诉系统A,需要userId。
    • 又过了几天,系统B的负责人过来了,告诉系统A,还是重新掉那个接口吧。
    • 又过了几天,系统F的负责人过来了,告诉系统A,需要userId。
    • …...

    于是系统A的负责人,每天都被这给骚扰着,改来改去,改来改去.......

    还有另外一个问题,调用系统C的时候,如果系统C挂了,系统A还得想办法处理。如果调用系统D时,由于网络延迟,请求超时了,那系统A是反馈fail还是重试??

    最后,系统A的负责人,觉得隔一段时间就改来改去,没意思,于是就跑路了。

    然后,公司招来一个大佬,大佬经过几天熟悉,上来就说:将系统A的userId写到消息队列中,这样系统A就不用经常改动了。为什么呢?下面我们来一起看看:

    什么是消息队列?

     

    系统A将userId写到消息队列中,系统C和系统D从消息队列中拿数据。这样有什么好处

    • 系统A只负责把数据写到队列中,谁想要或不想要这个数据(消息),系统A一点都不关心
    • 即便现在系统D不想要userId这个数据了,系统B又突然想要userId这个数据了,都跟系统A无关,系统A一点代码都不用改。
    • 系统D拿userId不再经过系统A,而是从消息队列里边拿。系统D即便挂了或者请求超时,都跟系统A无关,只跟消息队列有关

    这样一来,系统A与系统B、C、D都解耦了。

    2.2 异步

    我们再来看看下面这种情况:系统A还是直接调用系统B、C、D

    什么是消息队列?

     

    代码如下:

    public class SystemA {
     SystemB systemB = new SystemB();
     SystemC systemC = new SystemC();
     SystemD systemD = new SystemD();
     // 系统A独有的数据
     private String userId ;
     public void doOrder() {
     
     // 下订单
     userId = this.order();
     // 如果下单成功,则安排其他系统做一些事 
     systemB.SystemBNeed2do(userId);
     systemC.SystemCNeed2do(userId);
     systemD.SystemDNeed2do(userId);
     }
    }
    

    假设系统A运算出userId具体的值需要50ms,调用系统B的接口需要300ms,调用系统C的接口需要300ms,调用系统D的接口需要300ms。那么这次请求就需要50+300+300+300=950ms

    并且我们得知,系统A做的是主要的业务,而系统B、C、D是非主要的业务。比如系统A处理的是订单下单,而系统B是订单下单成功了,那发送一条短信告诉具体的用户此订单已成功,而系统C和系统D也是处理一些小事而已。

    那么此时,为了提高用户体验和吞吐量,其实可以异步地调用系统B、C、D的接口。所以,我们可以弄成是这样的:

    什么是消息队列?

     

    系统A执行完了以后,将userId写到消息队列中,然后就直接返回了(至于其他的操作,则异步处理)。

    • 本来整个请求需要用950ms(同步)
    • 现在将调用其他系统接口异步化,只需要100ms(异步)

    (例子可能举得不太好,但我觉得说明到点子上就行了,见谅。)

    2.3削峰/限流

    我们再来一个场景,现在我们每个月要搞一次大促,大促期间的并发可能会很高的,比如每秒3000个请求。假设我们现在有两台机器处理请求,并且每台机器只能每次处理1000个请求。

    什么是消息队列?

     

    那多出来的1000个请求,可能就把我们整个系统给搞崩了...所以,有一种办法,我们可以写到消息队列中:

    什么是消息队列?

     

    系统B和系统C根据自己的能够处理的请求数去消息队列中拿数据,这样即便有每秒有8000个请求,那只是把请求放在消息队列中,去拿消息队列的消息由系统自己去控制,这样就不会把整个系统给搞崩。

    三、使用消息队列有什么问题?

    经过我们上面的场景,我们已经可以发现,消息队列能做的事其实还是蛮多的。

    说到这里,我们先回到文章的开头,"明明JDK已经有不少的队列实现了,我们还需要消息队列中间件呢?"其实很简单,JDK实现的队列种类虽然有很多种,但是都是简单的内存队列。为什么我说JDK是简单的内存队列呢?下面我们来看看要实现消息队列(中间件)可能要考虑什么问题

    3.1高可用

    无论是我们使用消息队列来做解耦、异步还是削峰,消息队列肯定不能是单机的。试着想一下,如果是单机的消息队列,万一这台机器挂了,那我们整个系统几乎就是不可用了。

    什么是消息队列?

     

    所以,当我们项目中使用消息队列,都是得集群/分布式的。要做集群/分布式就必然希望该消息队列能够提供现成的支持,而不是自己写代码手动去实现。

    3.2 数据丢失问题

    我们将数据写到消息队列上,系统B和C还没来得及取消息队列的数据,就挂掉了。如果没有做任何的措施,我们的数据就丢了

    什么是消息队列?

     

    学过Redis的都知道,Redis可以将数据持久化磁盘上,万一Redis挂了,还能从磁盘从将数据恢复过来。同样地,消息队列中的数据也需要存在别的地方,这样才尽可能减少数据的丢失。

    那存在哪呢?

    • 磁盘?
    • 数据库?
    • Redis?
    • 分布式文件系统?

    同步存储还是异步存储?

    3.3消费者怎么得到消息队列的数据?

    消费者怎么从消息队列里边得到数据?有两种办法:

    • 生产者将数据放到消息队列中,消息队列有数据了,主动叫消费者去拿(俗称push)
    • 消费者不断去轮训消息队列,看看有没有新的数据,如果有就消费(俗称pull)

    3.4其他

    除了这些,我们在使用的时候还得考虑各种的问题:

    • 消息重复消费了怎么办啊?
    • 我想保证消息是绝对有顺序的怎么做?
    • ……..

    虽然消息队列给我们带来了那么多的好处,但同时我们发现引入消息队列也会提高系统的复杂性。市面上现在已经有不少消息队列轮子了,每种消息队列都有自己的特点,选取哪种MQ还得好好斟酌

    展开全文
  • 消息中心(系统消息)实现

    万次阅读 2019-03-17 15:36:33
    用户能即时的收到来自系统或者其他用户发来的消息,在web界面右下角弹窗提醒,用户还能标记消息是否已阅状态。 即时通讯 概念:即时通讯(实时通信,Instant Messaging,简称IM)是一个实时通信系统,允许两人或...
    • 需求

    用户能即时的收到来自系统或者其他用户发来的消息,在web界面右下角弹窗提醒,用户还能标记消息是否已阅状态。

    • 即时通讯

    概念:即时通讯(实时通信,Instant Messaging,简称IM)是一个实时通信系统,允许两人或多人使用网络实时的传递文字消息、文件、语音与视频交流。

    即时通讯有多方面的应用:即时消息、群组聊天、游戏、系统控制、地理定位、中间件和云计算、数据同步、网络语音通话、身份服务。

    • 为什么使用即时通讯

    情景:

    “我们已经到了吗?”,车后面的小孩儿问道,“没,还没有到”,一个成年人回答到。过了一会儿,小孩儿问道:“我们现在到了吗?”。这种时间短但频率高的重复性交换是一个轮询系统的真实例子:小孩儿不知道汽车什么时候到达目的地,这样他经常向开车的成年人确认。那就是,小孩儿正在轮询信息。通常成年人回复不会花太长时间:“当我们到那儿的时候,我会告诉你”。在这个例子中,这有助于和小孩儿一起旅行的成年人保持头脑清楚;在英特网上,它具有节省带宽和服务器资源的双重目的(不会再有“它变化了吗?”,“没,还没有”的交换),并且确保订阅人接收到更新和网络传递给他们的信息是一样的,而不是只有在下次由订阅人轮询来源。这跟我们平常基于“请求响应”方式来开发网站的理念不同,它属于”发布订阅”的概念,或者说“推送”的概念。

     

    • XMPP

    可扩展通讯与表示协议(XMPP)是一项用于实时通讯的开放技术。它使用可扩展标记

    语言(xml)作为交换信息的基本格式。所谓协议,就是实现即时通讯的一组约定。

    XMPP可以提供以下核心服务:信道加密、认证、出席、联络清单、一对一消息、多方通讯消息、通知、服务发现、能力广告、结构化数据表单、工作流管理、对等网络媒体会话。

    1XMPP 的 client-server 架构

    XMPP,在本质上,是一种 XML 流技术。当你准备开始和 XMPP 服务器会话,你打开一

    个长时间在线的 TCP 连接,然后和服务器协商一个 XML 流(服务器也同样也打开一个流,

    例如在每个方向有一个流)。是免费的、开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。 Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器可支持上万并发用户。

     

    XML 流 例子:

    C: <stream:stream>

    C: <presence/>

    C: <iq type="get">

    <query xmlns="jabber:iq:roster"/>

    </iq>

    S: <iq type="result">

    <query xmlns="jabber:iq:roster">

    <item jid="suke@skh.whu.edu.cn/>

    <item jid="gmz@skh.whu.edu.cn"/>

    <item jid="beta@skh.whu.edu.cn"/>

    </query>

    </iq>

    C: <message from="suke@skh.whu.edu.cn"

    to="beta@skh.whu.edu.cn">

    <body>Off with his head!</body>

    </message>

    S: <message from="lj@skh.whu.edu.cn"

    to="cyl@skh.whu.edu.cn ">

    <body>You are all pardoned.</body></message>

    C: <presence type="unavailable"/>

    C: </stream:stream>

    • XMPP的实现

    服务端:djabberd、ejabberd、jabberd、jabberd2、Prosody、Tigase等。

    openfire

    是免费的、开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。 Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器可支持上万并发用户。

    客户端(桌面版):Coccinella、Jeti、Psi、Swift、Tkabber等(类似于rtx、qq、tim、微信

    Spark

    Spark 是一个面向商业的客户端,并和 Openfire 服务器紧密关联。除了和 Openfire 服务器 的 集 成 外 , 它 也 提 供 了 半 专 有 的 音 频 和 视 频 通 讯 能 力 。 许 可 证 : LGPL 。 网 址 :http://www.igniterealtime.org/projects/spark/。

     

    客户端(web):Jabbear、JWChat、SparkWeb等(类似于wechat网页版)

    工具库:

    Smack(java)

    Smack 是一个非常流行、全功能的库,用于编写客户端、机器人和其他的应用程序。它

    由创建了 Openfire 服务器和 Spark 客户端的开发者编写。许可证: Apache。网址:

    http://www.igniterealtime .org/projects/smack/。

     

    Strophe(JavaScript)

    Strophe 是一个具有良好文档化的库,用于开发 XMPP 客户端,包括强大的 TLS 和 SASL支持。Strophe 有两种形式:C(libstrophe)和 JavaScript(strophejs)。许可证:GPL。网址:http://code.stanziq.com/strophe/。

    • 消息中心实现

    数据库设计

    活动图

    提交信息:标题(内容)、类型、附加属性(url、数据)、业务标识、发送方信息、接受方信息等。发送方信息、接受方信息包含用户名、系统标识。

    中间件:可选。比如可以是spring cloud的Feign、spring cloud stream、rabbitmq。考虑到消息的高并发性,推荐使用消息中间件spring cloud stream、rabbitmq。

    信息处理:对提交的信息进行验证、存储等。

    发送消息:使用smack api与openfire交互,将消息发送给相应的客户端。实现已封装在simba-component-xmpp包中。

    消息中心发送逻辑关键代码:

    自定义拓展节点MessageXMPP

    <messageCenter>    --消息中心

    <infoId>5376228f-abca-4353-ae00-e4042f96903a</infoId>    --消息主体id

    <type>1</type>    --消息类型

    <url>/</url>    --附加属性

    <appSn>xfgl</appSn>    --消息来源应用标识

    </messageCenter>

    simba-component-xmpp关键代码:

    创建链接

    发送消息

    消息提醒:消息接收者的web界面右下角出现窗口提醒消息。

    Strophe.js关键代码:

    添加消息监听处理器

    connection.addHandler(function(message));

    登录认证

    connection.connect(jid, pwd, function(status));

     

    阅读消息:用户点击消息。

    更新消息状态:更新状态位。

    其他处理:可选。可根据不同的消息类型,进行不同的处理。如通知服务调用者当前消息已阅读。

     

     

     

    展开全文
  • 消息推送方案

    千次阅读 2018-11-09 17:20:29
    对于需要即使通知用户的业务,例如告警等,需要消息推送功能,保证通知的及时性。   应用场景需求 消息推送涉及到消息的发送和接收,即方案既要能在后端中使用,也要能在前端和移动端使用,所以需要能适配java 和...
    • 目的

    对于需要即使通知用户的业务,例如告警等,需要消息推送功能,保证通知的及时性。

     

    • 应用场景需求

    消息推送涉及到消息的发送和接收,即方案既要能在后端中使用,也要能在前端和移动端使用,所以需要能适配java 和 javaScript 语言。

     

    • 选择方案

        常规思路如下三种:

    轮询(Pull)方式:客户端定时向服务器发送询问消息,一旦服务器有变化则立即同步消息。

    推送(Push)方式:移动终端现在服务器端注册并告知关注的消息主体,服务器获得相关的消息之后,根据主体主动推送给移动终端。

    常连接方式:移动终端与服务器端保持常连接,保证消息下发的及时性。

     

    通过检索分析,选择使用push方式,并且使用MQTT协议来实现。此协议开销小,能高效地使用网络,也是物联网选择使用的一个协议。并且由于使用较多,说明资料相对来说比较丰富,便于开发使用。

    消息中转代理服务使用Apache的开源工具 ActiveMQ Artemis, 它是一个多协议消息中转服务,支持STOMP, AMQP, MQTT, Openwire, SSL, and WebSockets。

    服务端和客户端之间通过发布和订阅方式来实现消息推送,消息的中转即通过Artemis来实现。

     

     

     

     

     

     

     

    MQTT协议针对消息传送提供三种服务质量:

    “至多一次”

    消息根据底层因特网协议网络尽最大努力进行传递。 可能会丢失消息。

    “至少一次”

    保证消息抵达,但可能会出现重复。

    “刚好一次”

    确保只收到一次消息。

    因此我们可以根据具体的业务需要来设置服务质量参数QoS,同时通过主题Topic来区分不同的业务来推送给不同的用户。

     

     

    关于中转服务器的选择,分析了三种服务器,都是开源项目,分别为Apache的 Apollo 、Artemis 还有国内的EMQ, 其中Apollo 操作虽然简洁,但是已经很久没有更新维护了,而国内的EMQ 从使用来看不如Apache的便利,并且其使用Erlang语言开发,非常规开发语言,对于后期使用维护不太方便。综合来看,Artemis的功能比较完备,并且版本一直有在更新维护,使用的是Java语言开发,遇到问题可以从开源社区寻求获取解决方案。

     

    中转消息服务器Artemis信息显示页面

    连接会话:

     

    服务器使用情况:

     

     

     

     

    • 具体使用流程

     

     

     

     

     

     

     

     

    五:参考文档

     

    1、消息中转服务Artemis 说明:

    http://activemq.apache.org/artemis/

    其开源项目代码地址:

    https://github.com/apache/activemq-artemis

     

    1. 后台Java(包括App)使用库和代码参考:

    https://github.com/eclipse/paho.mqtt.java

    https://github.com/eclipse/paho.mqtt.android

     

    1. 前台JavaScript使用库和代码参考:

    https://github.com/eclipse/paho.mqtt.javascript

    注意使用对应的库,来进行对应的调用,其JS库有两个版本:

    @namespace Paho

    @namespace Paho.MQTT

     

    1. MQTT 协议说明:

    https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html

    中文翻译版本:

    https://mcxiaoke.gitbooks.io/mqtt-cn/content/mqtt/01-Introduction.html

     

    1. 各种代理服务

    https://github.com/mqtt/mqtt.github.io/wiki/brokers

     

    展开全文
  • 即每发送一个消息,同步落盘后才返回生产者消息发送成功,即生产者收到确认发送消息成功,才继续之后操作,这样只要生产者得到了消息发送生成的返回,事后除了硬盘损坏,都可以保证不会消息丢失。 2、同步落盘怎么...
  • windows 消息代码大全

    2019-06-24 16:17:25
    windows消息代码 WM_NULL =$0000 // WM_CREATE =$0001 //应用程序创建一个窗口 WM_DESTROY = $0002 //一个窗口被销毁 WM_MOVE = $0003 //移动一个窗口 WM_SIZE= $0005 //改变一个窗口的大小 WM_ACTIVATE= $0006 //...
  • windows消息传递机制详解

    千次阅读 2018-01-31 19:14:56
    林炳文Evankaka原创作品。...  Windows是一个消息(Message)...应用程序想要实现的功能由消息来触发,并且靠对消息的响应和处理来完成。必须注意的是,消息并非是抢占性的,无论事件的缓急,总是按照到达的先后派对,
  • 支付宝将转账的消息投递到RabbitMQ, 余额宝通过监听RibbitMQ的消息队列获得消息, 然后通过应答队列告诉支付宝消息已经消费 遇到的问题 1. 当余额宝获取到消息之后, 可能转账失败, 消息队列不会关心余额宝是否...
  • 消息队列的两种模式

    万次阅读 多人点赞 2015-12-01 16:37:34
    Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。 点对点与发布订阅最初是由JMS定义的。...
  • handler机制的原理

    万次阅读 多人点赞 2012-10-03 13:39:21
    Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。 1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。 2)Handler: 你可以构造Handler对象来与Looper...
  • JMS学习三(ActiveMQ消息的可靠性)

    万次阅读 2020-05-02 10:46:47
    下面我们来学习一下消息接受确认和发送持久化消息消息的过期、消息的选择器和消息的优先级。 一、消息接收确认 1、jms消息只有在被确认之后才认为成功消费了这条消息消息的成功消费通常包括三个步骤:(1)、...
  • RabbitMQ简介与概念

    万次阅读 2019-04-02 18:08:10
    AMQP ———高级消息队列协议,也是一个消息代理的规范,兼容JMS。 RabbitMQ是AMQP的实现 AMQP 中消息的路由过程和 Java 开发者熟悉的 JMS 存在一些差别,AMQP 中增加了Exchange 和 Binding 的角色。生产者把消息...
  • JMS学习六(ActiveMQ消息传送模型)

    万次阅读 2020-05-02 10:43:44
    JMS学习六(ActiveMQ消息传送模型) ActiveMQ 支持两种截然不同的消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布 /订阅模型),分别称作:PTP Domain 和Pub/Sub Domain。 一、PTP消息传送模型 1、PTP...
  • RTMP规范简单分析

    万次阅读 多人点赞 2014-08-24 19:26:13
    当RTMP协议在互联网中传输数据的时候,消息会被拆分成更小的单元,称为消息块(Chunk)。 1 消息 消息是RTMP协议中基本的数据单元。不同种类的消息包含不同的Message Type ID,代表不同的功能。RTMP协议中一共规定了...
  • windows消息消息队列详解

    万次阅读 2009-10-16 11:40:00
    windows消息消息队列 与基于MS - DOS的应用程序不同,Windows的应用程序是事件(消息)驱动的。它们不会显式地调用函数(如C运行时库调用)来获取输入,而是等待windows向它们传递输入。 windows系统把应用程序的...
  • 大规模分布式消息中间件简介

    万次阅读 2010-10-27 18:44:00
    其中,服务器之间消息通讯这种功能广泛应用于这些中间件中,于是,将这种面向消息的中间件(Message Oriented Middleware,MOM)抽象出来,形成通用的消息中间件,成为业内主流。目前消息中间件的标准主要有:JMS和...
  • 深入浅出JMS(一)--JMS基本概念

    万次阅读 多人点赞 2015-06-30 22:47:22
    摘要:JMS(JAVA Message Service,java消息服务)API是一个消息服务的标准或者说是规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。它使分布式通信耦合度更低,消息服务更加可靠以及异步性。
  • RabbitMQ-消息应答和消息持久化

    万次阅读 2019-01-28 10:56:27
    1.消息应答 Ack (Message Acknowledgement) 消息应答默认打开 false autoAck = true (自动确认模式) 一旦rabbitMQ将消息分发给消费者,就会从内存中删除 这种情况下,如果消费者未处理完消息就异常结束,则...
  • MFC 应用程序中处理消息的顺序

    万次阅读 2009-06-23 15:52:00
    1.AfxWndProc() 该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc() 该函数负责保存消息(保存的内容主要是消息标识符和消息参数)供应用程序以后使用,然后调用WindowProc()...
  • 如何查看在rabbitMQ里面堆积的消息

    万次阅读 2018-12-17 20:34:31
    回顾上一节的内容,通过配置了stream来对MQ的简单的封装,主要定义接口,里面定义input以及output来绑定交换机,获取消息通道MessageChannel以及订阅通道SubscribableChannel对象,而消费端配置@streamListener 来...
1 2 3 4 5 ... 20
收藏数 2,069,271
精华内容 827,708
关键字:

消息