精华内容
下载资源
问答
  • 消息中间件MQ与RabbitMQ面试题(2020最新版)

    万次阅读 多人点赞 2020-03-01 11:11:21
    MQ的优点消息队列有什么优缺点?RabbitMQ有什么优缺点?你们公司生产环境用的是什么消息中间件?Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?MQ 有哪些常见问题?如何解决这些问题?什么是RabbitMQ?...

    Java面试总结(2021优化版)已发布在个人微信公众号【技术人成长之路】,优化版首先修正了读者反馈的部分答案存在的错误,同时根据最新面试总结,删除了低频问题,添加了一些常见面试题,对文章进行了精简优化,欢迎大家关注!😊😊

    【技术人成长之路】,助力技术人成长!更多精彩文章第一时间在公众号发布哦!

    Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,MyBatis,数据库,中间件等,包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大部分知识。欢迎大家阅读,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,在此表示感激不尽。文章持续更新中…

    序号内容链接地址
    1Java基础知识面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390612
    2Java集合容器面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588551
    3Java异常面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390689
    4并发编程面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104863992
    5JVM面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390752
    6Spring面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397516
    7Spring MVC面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397427
    8Spring Boot面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397299
    9Spring Cloud面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397367
    10MyBatis面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/101292950
    11Redis面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/103522351
    12MySQL数据库面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104778621
    13消息中间件MQ与RabbitMQ面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588612
    14Dubbo面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390006
    15Linux面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588679
    16Tomcat面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397665
    17ZooKeeper面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397719
    18Netty面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/104391081
    19架构设计&分布式&数据结构与算法面试题(2020最新版)https://thinkwon.blog.csdn.net/article/details/105870730

    为什么使用MQ?MQ的优点

    简答

    • 异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。
    • 应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。
    • 流量削锋 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。
    • 日志处理 - 解决大量日志传输。
    • 消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

    详答

    主要是:解耦、异步、削峰。

    解耦:A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。

    就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。

    异步:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。

    削峰:减少高峰时期对服务器压力。

    消息队列有什么优缺点?RabbitMQ有什么优缺点?

    优点上面已经说了,就是在特殊场景下有其对应的好处解耦异步削峰

    缺点有以下几个:

    系统可用性降低

    本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;

    系统复杂度提高

    加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。

    一致性问题

    A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

    所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

    你们公司生产环境用的是什么消息中间件?

    这个首先你可以说下你们公司选用的是什么消息中间件,比如用的是RabbitMQ,然后可以初步给一些你对不同MQ中间件技术的选型分析。

    举个例子:比如说ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。

    但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。

    然后你可以说说RabbitMQ,他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。

    另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。

    而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。

    除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。

    但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。

    然后可以聊聊RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。

    而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。

    另外就是Kafka。Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。

    但是Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。

    因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。但是在传统的MQ中间件使用场景中较少采用。

    Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

    ActiveMQRabbitMQRocketMQKafkaZeroMQ
    单机吞吐量比RabbitMQ低2.6w/s(消息做持久化)11.6w/s17.3w/s29w/s
    开发语言JavaErlangJavaScala/JavaC
    主要维护者ApacheMozilla/SpringAlibabaApacheiMatix,创始人已去世
    成熟度成熟成熟开源版本不够成熟比较成熟只有C、PHP等版本成熟
    订阅形式点对点(p2p)、广播(发布-订阅)提供了4种:direct, topic ,Headers和fanout。fanout就是广播模式基于topic/messageTag以及按照消息类型、属性进行正则匹配的发布订阅模式基于topic以及按照topic进行正则匹配的发布订阅模式点对点(p2p)
    持久化支持少量堆积支持少量堆积支持大量堆积支持大量堆积不支持
    顺序消息不支持不支持支持支持不支持
    性能稳定性一般较差很好
    集群方式支持简单集群模式,比如’主-备’,对高级集群模式支持不好。支持简单集群,'复制’模式,对高级集群模式支持不好。常用 多对’Master-Slave’ 模式,开源版本需手动切换Slave变成Master天然的‘Leader-Slave’无状态集群,每台服务器既是Master也是Slave不支持
    管理界面一般较好一般

    综上,各种对比之后,有如下建议:

    一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;

    后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;

    不过现在确实越来越多的公司会去用 RocketMQ,确实很不错,毕竟是阿里出品,但社区可能有突然黄掉的风险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。

    所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。

    如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。

    MQ 有哪些常见问题?如何解决这些问题?

    MQ 的常见问题有:

    1. 消息的顺序问题
    2. 消息的重复问题

    消息的顺序问题

    消息有序指的是可以按照消息的发送顺序来消费。

    假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到 S2,如果要保证 M1 先于 M2 被消费,怎么做?

    img

    解决方案:

    (1)保证生产者 - MQServer - 消费者是一对一对一的关系

    img

    缺陷:

    • 并行度就会成为消息系统的瓶颈(吞吐量不够)
    • 更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞的问题。 (2)通过合理的设计或者将问题分解来规避。
    • 不关注乱序的应用实际大量存在
    • 队列无序并不意味着消息无序 所以从业务层面来保证消息的顺序而不仅仅是依赖于消息系统,是一种更合理的方式。

    消息的重复问题

    造成消息重复的根本原因是:网络不可达。

    所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?

    消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。

    什么是RabbitMQ?

    RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的消息中间件

    rabbitmq 的使用场景

    (1)服务间异步通信

    (2)顺序消费

    (3)定时任务

    (4)请求削峰

    RabbitMQ基本概念

    • Broker: 简单来说就是消息队列服务器实体
    • Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
    • Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
    • Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
    • Routing Key: 路由关键字,exchange根据这个关键字进行消息投递
    • VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。
    • Producer: 消息生产者,就是投递消息的程序
    • Consumer: 消息消费者,就是接受消息的程序
    • Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务

    由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。

    RabbitMQ的工作模式

    一.simple模式(即最简单的收发模式)

    img

    1.消息产生消息,将消息放入队列

    2.消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。

    二.work工作模式(资源的竞争)

    img

    1.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。

    三.publish/subscribe发布订阅(共享资源)

    img

    1、每个消费者监听自己的队列;

    2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。

    四.routing路由模式

    img

    1.消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息;

    2.根据业务功能定义路由字符串

    3.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。

    4.业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误;

    五.topic 主题模式(路由模式的一种)

    img

    1.星号井号代表通配符

    2.星号代表多个单词,井号代表一个单词

    3.路由功能添加模糊匹配

    4.消息产生者产生消息,把消息交给交换机

    5.交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费

    (在我的理解看来就是routing查询的一种模糊匹配,就类似sql的模糊查询方式)

    如何保证RabbitMQ消息的顺序性?

    拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。

    消息如何分发?

    若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。通过路由可实现多消费的功能

    消息怎么路由?

    消息提供方->路由->一至多个队列消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。通过队列路由键,可以把队列绑定到交换器上。消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);

    常用的交换器主要分为一下三种:

    fanout:如果交换器收到消息,将会广播到所有绑定的队列上

    direct:如果路由键完全匹配,消息就被投递到相应的队列

    topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符

    消息基于什么传输?

    由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。

    如何保证消息不被重复消费?或者说,如何保证消息消费时的幂等性?

    先说为什么会重复消费:正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;

    但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。

    针对以上问题,一个解决思路是:保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性;

    比如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过;

    假设你有个系统,消费一条消息就往数据库里插入一条数据,要是你一个消息重复两次,你不就插入了两条,这数据不就错了?但是你要是消费到第二次的时候,自己判断一下是否已经消费过了,若是就直接扔了,这样不就保留了一条数据,从而保证了数据的正确性。

    如何确保消息正确地发送至 RabbitMQ? 如何确保消息接收方消费了消息?

    发送方确认模式

    将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID。

    一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。

    如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确认)消息。

    发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

    接收方确认机制

    消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ 才能安全地把消息从队列中删除。

    这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。保证数据的最终一致性;

    下面罗列几种特殊情况

    • 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
    • 如果消费者接收到消息却没有确认消息,连接也未断开,则 RabbitMQ 认为该消费者繁忙,将不会给该消费者分发更多的消息。

    如何保证RabbitMQ消息的可靠传输?

    消息不可靠的情况可能是消息丢失,劫持等原因;

    丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息;

    生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息;

    transaction机制就是说:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。然而,这种方式有个缺点:吞吐量下降;

    confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;

    rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;

    如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

    消息队列丢数据:消息持久化。

    处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。

    这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。

    这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

    那么如何持久化呢?

    这里顺便说一下吧,其实也很容易,就下面两步

    1. 将queue的持久化标识durable设置为true,则代表是一个持久的队列
    2. 发送消息的时候将deliveryMode=2

    这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据

    消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可!

    消费者在收到消息之后,处理消息之前,会自动回复RabbitMQ已收到消息;

    如果这时处理消息失败,就会丢失该消息;

    解决方案:处理消息成功后,手动回复确认消息。

    为什么不应该对所有的 message 都使用持久化机制?

    首先,必然导致性能的下降,因为写磁盘比写 RAM 慢的多,message 的吞吐量可能有 10 倍的差距。

    其次,message 的持久化机制用在 RabbitMQ 的内置 cluster 方案时会出现“坑爹”问题。矛盾点在于,若 message 设置了 persistent 属性,但 queue 未设置 durable 属性,那么当该 queue 的 owner node 出现异常后,在未重建该 queue 前,发往该 queue 的 message 将被 blackholed ;若 message 设置了 persistent 属性,同时 queue 也设置了 durable 属性,那么当 queue 的 owner node 异常且无法重启的情况下,则该 queue 无法在其他 node 上重建,只能等待其 owner node 重启后,才能恢复该 queue 的使用,而在这段时间内发送给该 queue 的 message 将被 blackholed 。

    所以,是否要对 message 进行持久化,需要综合考虑性能需要,以及可能遇到的问题。若想达到 100,000 条/秒以上的消息吞吐量(单 RabbitMQ 服务器),则要么使用其他的方式来确保 message 的可靠 delivery ,要么使用非常快速的存储系统以支持全持久化(例如使用 SSD)。另外一种处理原则是:仅对关键消息作持久化处理(根据业务重要程度),且应该保证关键消息的量不会导致性能瓶颈。

    如何保证高可用的?RabbitMQ 的集群

    RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。

    单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的?,没人生产用单机模式

    普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。

    镜像集群模式:这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。

    如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

    消息积压处理办法:临时紧急扩容:

    先修复 consumer 的问题,确保其恢复消费速度,然后将现有 cnosumer 都停掉。
    新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
    然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
    接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
    等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。
    MQ中消息失效:假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会直接搞丢。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。

    mq消息队列块满了:如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个,都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。

    设计MQ思路

    比如说这个消息队列系统,我们从以下几个角度来考虑一下:

    首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?

    其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。

    其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。

    能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。

    展开全文
  • 想查看微信好友撤回的消息?Python帮你搞定

    万次阅读 多人点赞 2019-12-01 13:50:59
    要说微信最让人恶心的发明,消息撤回绝对能上榜。 比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?...

    要说微信最让人恶心的发明,消息撤回绝对能上榜。

    比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?于是你打算问问她发了什么,结果她回一句"没什么"。这一回复,让你的好奇心更加强烈了,顿时就感觉消息撤回这一功能就是用来折磨人的。

    那么有没有什么办法能够知道你心爱的她(他)到底撤回了什么呢?不要着急,Python帮你搞定。

    模块介绍

    本篇文章将用Python实现微信的防撤回功能,针对微信操作,Python有一个十分强大的库:itchat。相信没有使用过也有所耳闻吧。官方是这样描述它的:

    Project description
    itchat is a open souce wechat api project for personal account.
    
    It enables you to access your personal wechat account through command line.
    

    翻译过来就是:itchat是一个针对个人帐户的开放式微信api项目,它使您可以通过命令行访问您的个人微信帐户。

    既然是针对微信的开发,我们就离不开这个模块的协助,所以,首先下载该模块:

    pip install itchat
    

    也可以在开发工具Pycharm中直接导入该模块,Pycharm会提示你下载。

    模块初体验

    考虑到应该有些人从来没有使用过该模块,这里对该模块进行一个简单的入门。

    1、如何登陆微信

    既然要操作微信,那么摆在我们面前的问题就是如何登录微信,登录微信非常简单,直接看代码:

    import itchat
    
    itchat.login()
    

    没错,一句代码即可完成登录,运行之后就会弹出一个二维码,扫描之后在手机上授权登录,控制台就会提示是否登录成功。

    Login successfully as Y
    

    这样就说明登录成功了。

    这里需要注意一个问题,就是你会发现每次运行程序都要扫描二维码登录,这样未免太麻烦,有没有办法只扫描一次,以后就自动登录了呢?这当然是可以的。

    import itchat
    
    itchat.auto_login(hotReload=True)
    

    通过函数名也能知道该方法可以实现自动登录,运行程序,扫码登录之后会在项目路径下创建一个itchat.pkl文件,该文件用于存储登录的状态,所以千万不要动它,如果你想换一个微信账号登录,就要先把这个文件删除,因为该文件记录的是上一个微信的状态,删除之后即可登录。

    需要注意:这种方式只能保证你在短时间内无需重复登录,时间长了,还是需要重新扫码登录的。

    进行到这里,有些人可能会发现自己的微信登录不上的情况,据我所知,有些新注册的微信和长期不使用的微信是无法登录网页版微信的,所以这里也会导致登录不上。如果登录不上,那也是没有办法的,下面的内容也就没有意义了。

    2、获取好友列表

    登录上微信之后,我们来用一用itchat模块提供的一些api,比如获取好友列表。

    import itchat
    
    itchat.auto_login(hotReload=True)
    friends = itchat.get_friends()  # 好友列表
    print(friends)
    

    使用get_friends()函数即可获取到好友列表的所有好友信息,包括昵称、备注名、地址、个性签名、性别等等。

    这里我随意地复制了一个好友的个人信息,当然由于隐私问题,这里的部分信息我用"*"号代替了,我们重点是分析一下这些信息的内容。比如最开始的UserName,这是用户的唯一标识,相当于身份证号码,你的每个好友都会有这样一个标识,每个好友之间肯定都是不一样的;然后是NickName,这是好友的昵称;HeadImgUrl是好友的头像地址;RemarkName是你对好友的备注名;Province是省份等等,这里就不一一介绍了,感兴趣的话可以自己去了解一下。

    3、如何发送消息给好友

    如何发送一条消息给指定的好友呢?也非常简单:

    import itchat
    
    itchat.auto_login(hotReload=True)
    itchat.send('Hello World', toUserName='@f9e42aafa1175b38b60a0be4d651a34c77f2528d9b7784e7aaf415090eca8fa6')
    

    此时的UserName就派上用场了,也就是好友的唯一标识,这样,我们就给该标识对应的好友发送了一条消息,所以,我们可以这样改进程序:

    import itchat
    
    itchat.auto_login(hotReload=True)
    friends = itchat.get_friends()
    nickName = '诚信通授权渠道商-老曾'
    for i in friends:
        if '诚信通授权渠道商-老曾' == i['NickName']:
            itchat.send('Hello World', toUserName=i['UserName'])
            break
    
    

    这样,就可以指定发送给任意好友,通过好友的昵称在好友列表中进行检索,找到的话,就获取该好友的UserName,然后发送消息,也可以通过对好友的备注名(RemarkName)查找,大家可以自己尝试。

    4、装饰器

    关于itchat模块还有很多功能,这里就不作过多讲解了,我们只讲关于这次程序的知识点,这里是最后一个内容,装饰器。

    关于装饰器,一时半会还讲不清楚,这里只是简单介绍一下,装饰器的作用就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。

    例如现在有一个函数fun(),你并不知晓函数的实现原理,你肯定也不能去修改这个函数的代码,而你需要给该函数添加一个输出开始运行时间和结束运行时间的功能,该如何实现呢?这个时候就可以使用装饰器。

    import time
     
    def show_time(fun):
        def inner():
            print(time.time())
            fun()
            print(time.time())
        return inner   
     
    @show_time
    def fun():
        pass
     
    fun()
    
    

    该如何理解这段程序呢?首先@show_time即是使用一个装饰器show_time,此时会将装饰的函数,也就是fun()作为参数传递给装饰器show_time(),我们知道函数作为返回值的话,执行的其实是该函数,所以程序会执行内部函数inner(),此时输出开始运行时间,然后调用fun()函数(原有的功能不能丢),最后输出结束运行时间。这样就通过装饰器实现了一个函数的功能扩展,这也是典型的面向切面编程思想。

    如何获取好友发送的消息

    准备工作做完了,接下来就进入正题了,对于上面的知识点,大家一定要掌握,如果不懂的话,接下来的代码你可能会很懵。

    首先,我们看看该如何获取到好友发送的消息。

    import itchat
    
    itchat.auto_login(hotReload=True)
    
    
    @itchat.msg_register(itchat.content.TEXT)
    def resever_info(msg):
        print(msg)
    
    
    itchat.run() #保持运行
    
    

    itchat模块提供了@itchat.msg_register装饰器来监听消息,比如这里我们自定义了一个resever_info()函数,并用装饰器对消息进行监听,装饰器中传入了itchat.content.TEXT类型,这样监听的就是文本消息,监听到输入之后,装饰器就会将文本消息传入resever_info()的参数中。所以,msg就是监听到的消息内容。

    对于@itchat.msg_register装饰器,它不仅可以监听文本,还可以监听语音、图片、地图、名片、视频等等,为了方便,这里我们导入itchat模块下的content模块中的全部内容,因为这些消息类型都是在该模块下声明的。

    TEXT       = 'Text'
    MAP        = 'Map'
    CARD       = 'Card'
    NOTE       = 'Note'
    SHARING    = 'Sharing'
    PICTURE    = 'Picture'
    RECORDING  = VOICE = 'Recording'
    ATTACHMENT = 'Attachment'
    VIDEO      = 'Video'
    FRIENDS    = 'Friends'
    SYSTEM     = 'System'
    
    INCOME_MSG = [TEXT, MAP, CARD, NOTE, SHARING, PICTURE,
        RECORDING, VOICE, ATTACHMENT, VIDEO, FRIENDS, SYSTEM]
    
    

    还有要注意的地方,最后记得调用itchat的run()函数,保持程序运行,否则程序就直接结束了。

    接下来我们就可以测试一下了,我让我的好友发了一条消息给我,控制台就输出了如下内容:
    在这里插入图片描述

    内容很多,我们只挑重要的看。例如FromUserName,这是发送者的标识;ToUserName,这是接收者的标识;Content,这当然就是文本内容了;CreateTime,这是发送时间;注意最后的两个值:Type,这是消息类型,这里是文本类型Text,然后Text也是文本内容,所以如果想取出好友发送的消息内容的话,用Content和Text都可以。分析过后,取出内容就很简单了:

    import itchat
    import time
    from itchat.content import *  # 导入itchat下的content模块
    
    itchat.auto_login(hotReload=True)
    
    
    @itchat.msg_register(TEXT)
    def resever_info(msg):
        info = msg['Text']  # 取出文本消息
        info_type = msg['Type']  # 取出消息类型
        fromUser = itchat.search_friends(userName=msg['FromUserName'])['NickName']
        ticks = msg['CreateTime']  # 获取信息发送的时间
        time_local = time.localtime(ticks)
        dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)  # 格式化日期
        print("发送人:" + fromUser + '\n消息类型:' + info_type + '\n发送时间:' + dt + '\n消息内容:' + info)
    
    
    itchat.run()
    
    

    这里用到了time模块,用于格式化日期。

    为了测试方便,我就自己发了一条消息给别人,自己发的消息也是会被监听的,看运行结果:

    发送人:Y
    消息类型:Text
    发送时间:2019-11-28 16:19:13
    消息内容:土鳖
    
    

    再来试试语音和图片能获取到吗?我们回到刚才的代码:

    import itchat
    from itchat.content import *  # 导入itchat下的content模块
    
    itchat.auto_login(hotReload=True)
    
    
    @itchat.msg_register(TEXT)
    def resever_info(msg):
        print(msg)
    
    
    itchat.run()
    
    

    运行之后,发送语音和图片试试,不管怎么发,控制台就是没反应,这是当然的了,我们还没对语音和图片进行监听呢,修改代码:

    import itchat
    from itchat.content import *  # 导入itchat下的content模块
    
    itchat.auto_login(hotReload=True)
    
    
    @itchat.msg_register([TEXT, PICTURE, RECORDING])	#添加了对图片和语音的监听
    def resever_info(msg):
        print(msg)
    
    
    itchat.run()
    
    

    再运行试试,先发送一张图片,再发送一段语音,控制台输出了两段内容,由于篇幅过长,就不贴出来了,无非还是那些信息,发送者,接收者,日期,消息内容等等,这里只需注意图片和语音的内容:

    'Type': 'Picture', 'Text': <function get_download_fn.<locals>.download_fn at 0x0000000003574158>
    'Type': 'Recording', 'Text': <function get_download_fn.<locals>.download_fn at 0x0000000002CFED08>
    
    

    这是一段地址,通过它我们就能够将图片和语音保存起来。

    如何保存好友发送的图片和语音

    下面我们对好友发送的图片和语音进行保存。

    import itchat
    import os
    from itchat.content import *  # 导入itchat下的content模块
    
    itchat.auto_login(hotReload=True)
    temp = 'C:/Users/Administrator/Desktop/CrawlerDemo' + '/' + '撤回的消息'
    # 如果不存在该文件夹,就创建
    if not os.path.exists(temp):
        os.mkdir(temp)
    
    
    @itchat.msg_register([TEXT, PICTURE, RECORDING])
    def resever_info(msg):
        info = msg['Text']  # 取出文本消息
        info_type = msg['Type']  # 取出消息类型
        name = msg['FileName']  # 取出语音(图片)文件名
    
        if info_type == 'Recording':
            # 保存语音
            info(temp + '/' + name)
        elif info_type == 'Picture':
            # 保存图片
            info(temp + '/' + name)
    
    
    itchat.run()
    
    

    运行起来,然后发送一张图片和一条语音,就会在指定目录下生成两个文件:
    在这里插入图片描述

    如何监听好友撤回了消息

    到这里,我们其实已经完成了消息监听,只需要稍加修改即可,但是这个程序是有缺陷的,因为不是所有消息我们都需要去保存的,好友正常发送过来的消息我们直接就能看到,保存下来不是多此一举吗?我们的目的是想知道好友撤回了什么内容,这就涉及到如何监听好友是否撤回了消息这一问题了。其实也非常简单,Content模块为我们提供了NOTE类型,该类型指的是系统消息。

    所以我们可以自定义一个函数用来监听系统消息:

    import itchat
    from itchat.content import *  # 导入itchat下的content模块
    
    
    itchat.auto_login(hotReload=True)
    
    @itchat.msg_register(NOTE)
    def note_info(msg): # 监听系统消息
        print(msg)
    
    
    itchat.run()
    
    

    运行程序,我们撤回一条消息测试一下,输出结果如下:

    ......
    'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': '', 'EncryChatRoomId': '', 'IsOwner': 0}>, 'Type': 'Note', 'Text': '你撤回了一条消息'}
    ......
    
    

    这里截取了部分内容,会发现,撤回消息的文本内容为"你撤回了一条消息",所以要想知道好友是否撤回了消息就非常简单了,判断msg['Text'] == '你撤回了一条消息'即可。

    实现微信防撤回程序

    关于程序每个步骤的代码到这里就分析完了,接下来是对所有代码的汇总,也是整个程序的完整代码:

    import itchat
    from itchat.content import *
    import os
    import time
    import xml.dom.minidom	# 解析xml模块
    
    # 这是保存撤回消息的文件目录(如:图片、语音等),这里已经写死了,大家可以自行修改
    temp = 'C:/Users/Administrator/Desktop/CrawlerDemo' + '/' + '撤回的消息'
    if not os.path.exists(temp):
        os.mkdir(temp)
    
    itchat.auto_login(True)	# 自动登录
    
    dict = {}	# 定义一个字典
    
    
    # 这是一个装饰器,给下面的函数添加新功能
    # 能够捕获好友发送的消息,并传递给函数参数msg
    @itchat.msg_register([TEXT, PICTURE, FRIENDS, CARD, MAP, SHARING, RECORDING, ATTACHMENT, VIDEO])  # 文本,语音,图片
    def resever_info(msg):
        global dict	# 声明全局变量
    
        info = msg['Text']  # 取出消息内容
        msgId = msg['MsgId']  # 取出消息标识
        info_type = msg['Type']  # 取出消息类型
        name = msg['FileName']  # 取出消息文件名
        # 取出消息发送者标识并从好友列表中检索
        fromUser = itchat.search_friends(userName=msg['FromUserName'])['NickName']
        ticks = msg['CreateTime']  # 获取信息发送的时间
        time_local = time.localtime(ticks)
        dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)  # 格式化日期
        # 将消息标识和消息内容添加到字典
        # 每一条消息的唯一标识作为键,消息的具体信息作为值,也是一个字典
        dict[msgId] = {"info": info, "info_type": info_type, "name": name, "fromUser": fromUser, "dt": dt}
        
    
    @itchat.msg_register(NOTE)  # 监听系统提示
    def note_info(msg):
        # 监听到好友撤回了一条消息
        if '撤回了一条消息' in msg['Text']:
            # 获取系统消息中的Content结点值
            content = msg['Content']
            # Content值为xml,解析xml
            doc = xml.dom.minidom.parseString(content)
            # 取出msgid标签的值
            result = doc.getElementsByTagName("msgid")
            # 该msgId就是撤回的消息标识,通过它可以在字典中找到撤回的消息信息
            msgId = result[0].childNodes[0].nodeValue
            # 从字典中取出对应消息标识的消息类型
            msg_type = dict[msgId]['info_type']
            if msg_type == 'Recording':	# 撤回的消息为语音
                recording_info = dict[msgId]['info']  # 取出消息标识对应的消息内容
                info_name = dict[msgId]['name'] # 取出消息文件名
                fromUser = dict[msgId]['fromUser'] # 取出发送者
                dt = dict[msgId]['dt'] # 取出发送时间
                recording_info(temp + '/' + info_name) # 保存语音
                # 拼接提示消息
                send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回了一条语音'
                itchat.send(send_msg, 'filehelper') # 将提示消息发送给文件助手
                # 发送保存的语音
                itchat.send_file(temp + '/' + info_name, 'filehelper')
                del dict[msgId] # 删除字典中对应的消息
                print("保存语音")
            elif msg_type == 'Text':
                text_info = dict[msgId]['info'] # 取出消息标识对应的消息内容
                fromUser = dict[msgId]['fromUser'] # 取出发送者
                dt = dict[msgId]['dt'] # 取出发送时间
                # 拼接提示消息
                send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回内容:' + text_info
                # 将提示消息发送给文件助手
                itchat.send(send_msg, 'filehelper')
                del dict[msgId] # 删除字典中对应的消息
                print("保存文本")
            elif msg_type == 'Picture':
                picture_info = dict[msgId]['info'] # 取出消息标识对应的消息内容
                fromUser = dict[msgId]['fromUser'] # 取出发送者
                dt = dict[msgId]['dt'] # 取出发送时间
                info_name = dict[msgId]['name'] # 取出文件名
                picture_info(temp + '/' + info_name) # 保存图片
                # 拼接提示消息
                send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回了一张图片'
                itchat.send(send_msg, 'filehelper') # 将图片发送给文件助手
                # 发送保存的语音
                itchat.send_file(temp + '/' + info_name, 'filehelper')
                del dict[msgId] # 删除字典中对应的消息 
                print("保存图片")
    
    
    itchat.run()
    
    

    这样,一个完整的防撤回程序就完成了,如果你对于前面的铺垫能够掌握得很好的话,这个程序对你来说就是小菜一碟,每一句代码的注释我都有写,应该很容易看懂。

    测试程序

    到了激动人心的测试环节,我们来测试一下这个程序是否编写成功了。

    在这里插入图片描述

    我向我的好友发送了三条消息,分别是文本、图片和语音,接着我一一撤回,然后,微信程序就自动向文件传输助手发送了三条消息:
    在这里插入图片描述

    到这里,这个程序就基本完成了。你们在测试的时候也可以叫自己的好友、同学发给你几条消息,然后撤回看看是否能够成功获取到撤回的消息。

    撤回的消息发给别人肯定不行,这样不仅泄露了隐私,也会骚扰到别人,所以这里我选择将撤回的消息发送给文件传输助手,如何将消息发送给文件传输助手也很简单:

    itchat.send(send_msg, toUserName='filehelper')
    
    

    toUserName传入filehelper即可,这样,如果对方撤回了消息,你就可以前往文件传输助手查看对方究竟撤回了什么。

    说说我遇到的一些坑

    这个程序说它难,其实并不难,但我也在编写的过程中遇到了一些坑,一开始我是一条消息一条消息地进行测试,发现程序是正常的,但我连续撤回几条消息,却发现程序出现了Bug。比如我一开始发送了一张图片和一段文字,结果我撤回这两条消息后,得到的却是两段文字。后面我才醒悟过来,是后面的消息覆盖了前面的消息,导致了这个结果,所以在程序中,我定义了一个字典,用于存放好友输入的消息,当监听到消息被撤回时,就通过撤回消息产生的内容中的msgId去和字典中的匹配,匹配到的就是被撤回的消息,然后进行操作即可。

    使用教程

    想使用该程序非常简单,实现微信防撤回程序节点下有程序的完整代码,直接复制粘贴到你自己的python文件,然后运行该文件即可,运行后会产生一个二维码,用手机验证登录即可。
    当然,你也可以选择将该程序打包成可执行的exe文件,这样运行更加方便,打包方式:
    首先打开cmd窗口,下载pyinstaller模块,有的话就不用下载了,下载指令:pip insall pyinstaller,此时我们通过cmd窗口进入到python文件目录,比如我这里
    在这里插入图片描述
    那就进入到该目录下:
    在这里插入图片描述
    然后执行下面这条指令:

    pyinstaller -F wechat.py
    

    后面是需要打包的文件名,执行命令后,就会在文件同级目录下生成一个dist文件夹。
    在这里插入图片描述
    进入该文件夹,就看到我们的.exe文件了,然后双击执行即可。

    最后

    这个程序目前只实现了监听好友的文本、图片、语音类型的消息,对于其它类型的消息,还有群聊的消息都是无法监听到的,感兴趣的话大家可以自己试着实现一下。

    因为自己也是刚刚接触这个模块,文中的程序可能会出现一些意想不到的Bug,但目前我测试来看是没有问题的,如有问题,欢迎评论区留言。

    展开全文
  • 大型网站架构之分布式消息队列

    万次阅读 多人点赞 2016-01-26 08:48:40
    大型网站架构之分布式消息队列   以下是消息队列以下的大纲,本文主要介绍消息队列概述,消息队列应用场景和消息中间件示例(电商,日志系统)。 本次分享大纲 消息队列概述消息队列应用场景消息中间件示例...

    大型网站架构之分布式消息队列

     

    以下是消息队列以下的大纲,本文主要介绍消息队列概述,消息队列应用场景和消息中间件示例(电商,日志系统)。

    本次分享大纲

    1. 消息队列概述
    2. 消息队列应用场景
    3. 消息中间件示例
    4. JMS消息服务
    5. 常用消息队列
    6. 参考(推荐)资料
    7. 本次分享总结

    一、消息队列概述

    消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。

    目前在生产环境,使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。

    二、消息队列应用场景

    以下介绍消息队列在实际应用中常用的使用场景。异步处理,应用解耦,流量削锋和消息通讯四个场景。

    2.1异步处理

    场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种1.串行的方式;2.并行方式。

    (1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。(架构KKQ:466097527,欢迎加入)

     

    (2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

     

    假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

    因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)。

     

    小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?

    引入消息队列,将不是必须的业务逻辑,异步处理。改造后的架构如下:

     

    按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。

    2.2应用解耦

    场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图:(架构KKQ:466097527,欢迎加入)

     

    传统模式的缺点:

    1)  假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;

    2)  订单系统与库存系统耦合;

    如何解决以上问题呢?引入应用消息队列后的方案,如下图:

     

    • 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。
    • 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。
    • 假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦。

    2.3流量削锋

    流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。

    应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

    1. 可以控制活动的人数;
    2. 可以缓解短时间内高流量压垮应用;

     

    1. 用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;
    2. 秒杀业务根据消息队列中的请求信息,再做后续处理。

    2.4日志处理

    日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下:(架构KKQ:466097527,欢迎加入)

     

    • 日志采集客户端,负责日志数据采集,定时写受写入Kafka队列;
    • Kafka消息队列,负责日志数据的接收,存储和转发;
    • 日志处理应用:订阅并消费kafka队列中的日志数据;

    以下是新浪kafka日志处理应用案例:

    转自(http://cloud.51cto.com/art/201507/484338.htm)

     

    (1)Kafka:接收用户日志的消息队列。

    (2)Logstash:做日志解析,统一成JSON输出给Elasticsearch。

    (3)Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能。

    (4)Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因。

    2.5消息通讯

    消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

    点对点通讯:

     

    客户端A和客户端B使用同一队列,进行消息通讯。

    聊天室通讯:

     

    客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。实现类似聊天室效果。

    以上实际是消息队列的两种消息模式,点对点或发布订阅模式。模型为示意图,供参考。

    三、消息中间件示例

    3.1电商系统

     

    消息队列采用高可用,可持久化的消息中间件。比如Active MQ,Rabbit MQ,Rocket Mq。(1)应用将主干逻辑处理完成后,写入消息队列。消息发送是否成功可以开启消息的确认模式。(消息队列返回消息接收成功状态后,应用再返回,这样保障消息的完整性)

    (2)扩展流程(发短信,配送处理)订阅队列消息。采用推或拉的方式获取消息并处理。

    (3)消息将应用解耦的同时,带来了数据一致性问题,可以采用最终一致性方式解决。比如主数据写入数据库,扩展应用根据消息队列,并结合数据库方式实现基于消息队列的后续处理。

    3.2日志收集系统

     

    分为Zookeeper注册中心,日志收集客户端,Kafka集群和Storm集群(OtherApp)四部分组成。

    • Zookeeper注册中心,提出负载均衡和地址查找服务;
    • 日志收集客户端,用于采集应用系统的日志,并将数据推送到kafka队列;
    • Kafka集群:接收,路由,存储,转发等消息处理;

    Storm集群:与OtherApp处于同一级别,采用拉的方式消费队列中的数据;

    四、JMS消息服务

    讲消息队列就不得不提JMS 。JMS(JAVA Message Service,java消息服务)API是一个消息服务的标准/规范,允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。它使分布式通信耦合度更低,消息服务更加可靠以及异步性。

    在EJB架构中,有消息bean可以无缝的与JM消息服务集成。在J2EE架构模式中,有消息服务者模式,用于实现消息与应用直接的解耦。

    4.1消息模型

    在JMS标准中,有两种消息模型P2P(Point to Point),Publish/Subscribe(Pub/Sub)。

    4.1.1 P2P模式

     

    P2P模式包含三个角色:消息队列(Queue),发送者(Sender),接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。

     

    P2P的特点

    • 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
    • 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列
    • 接收者在成功接收消息之后需向队列应答成功

     

    如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式。(架构KKQ:466097527,欢迎加入)

    4.1.2 Pub/sub模式

     

    包含三个角色主题(Topic),发布者(Publisher),订阅者(Subscriber) 。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。

    Pub/Sub的特点

    • 每个消息可以有多个消费者
    • 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
    • 为了消费消息,订阅者必须保持运行的状态。

     

    为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。

    如果希望发送的消息可以不被做任何处理、或者只被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。

    4.2消息消费

    在JMS中,消息的产生和消费都是异步的。对于消费来说,JMS的消息者可以通过两种方式来消费消息。

    (1)同步

    订阅者或接收者通过receive方法来接收消息,receive方法在接收到消息之前(或超时之前)将一直阻塞;

    (2)异步

    订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。

     

    JNDI:Java命名和目录接口,是一种标准的Java命名系统接口。可以在网络上查找和访问服务。通过指定一个资源名称,该名称对应于数据库或命名服务中的一个记录,同时返回资源连接建立所必须的信息。

    JNDI在JMS中起到查找和访问发送目标或消息来源的作用。(架构KKQ:466097527,欢迎加入)

    4.3JMS编程模型

    (1) ConnectionFactory

    创建Connection对象的工厂,针对两种不同的jms消息模型,分别有QueueConnectionFactory和TopicConnectionFactory两种。可以通过JNDI来查找ConnectionFactory对象。

    (2) Destination

    Destination的意思是消息生产者的消息发送目标或者说消息消费者的消息来源。对于消息生产者来说,它的Destination是某个队列(Queue)或某个主题(Topic);对于消息消费者来说,它的Destination也是某个队列或主题(即消息来源)。

    所以,Destination实际上就是两种类型的对象:Queue、Topic可以通过JNDI来查找Destination。

    (3) Connection

    Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装)。Connection可以产生一个或多个Session。跟ConnectionFactory一样,Connection也有两种类型:QueueConnection和TopicConnection。

    (4) Session

    Session是操作消息的接口。可以通过session创建生产者、消费者、消息等。Session提供了事务的功能。当需要使用session发送/接收多个消息时,可以将这些发送/接收动作放到一个事务中。同样,也分QueueSession和TopicSession。

    (5) 消息的生产者

    消息生产者由Session创建,并用于将消息发送到Destination。同样,消息生产者分两种类型:QueueSender和TopicPublisher。可以调用消息生产者的方法(send或publish方法)发送消息。

    (6) 消息消费者

    消息消费者由Session创建,用于接收被发送到Destination的消息。两种类型:QueueReceiver和TopicSubscriber。可分别通过session的createReceiver(Queue)或createSubscriber(Topic)来创建。当然,也可以session的creatDurableSubscriber方法来创建持久化的订阅者。

    (7) MessageListener

    消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。EJB中的MDB(Message-Driven Bean)就是一种MessageListener。

     

    深入学习JMS对掌握JAVA架构,EJB架构有很好的帮助,消息中间件也是大型分布式系统必须的组件。本次分享主要做全局性介绍,具体的深入需要大家学习,实践,总结,领会。

    五、常用消息队列

    一般商用的容器,比如WebLogic,JBoss,都支持JMS标准,开发上很方便。但免费的比如Tomcat,Jetty等则需要使用第三方的消息中间件。本部分内容介绍常用的消息中间件(Active MQ,Rabbit MQ,Zero MQ,Kafka)以及他们的特点。

    5.1 ActiveMQ

    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

    ActiveMQ特性如下:

    ⒈ 多种语言和协议编写客户端。语言: Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP

    ⒉ 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)

    ⒊ 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性

    ⒋ 通过了常见J2EE服务器(如 Geronimo,JBoss 4,GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上

    ⒌ 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA

    ⒍ 支持通过JDBC和journal提供高速的消息持久化

    ⒎ 从设计上保证了高性能的集群,客户端-服务器,点对点

    ⒏ 支持Ajax

    ⒐ 支持与Axis的整合

    ⒑ 可以很容易得调用内嵌JMS provider,进行测试

    5.2 RabbitMQ

    RabbitMQ是流行的开源消息队列系统,用erlang语言开发。RabbitMQ是AMQP(高级消息队列协议)的标准实现。支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX,持久化。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    结构图如下:(架构KKQ:466097527,欢迎加入)

    几个重要概念:

    Broker:简单来说就是消息队列服务器实体。

      Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。

      Queue:消息队列载体,每个消息都会被投入到一个或多个队列。

      Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。

      Routing Key:路由关键字,exchange根据这个关键字进行消息投递。

      vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。

      producer:消息生产者,就是投递消息的程序。

      consumer:消息消费者,就是接受消息的程序。

      channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。

    消息队列的使用过程,如下:

    (1)客户端连接到消息队列服务器,打开一个channel。

    (2)客户端声明一个exchange,并设置相关属性。

    (3)客户端声明一个queue,并设置相关属性。

    (4)客户端使用routing key,在exchange和queue之间建立好绑定关系。

    (5)客户端投递消息到exchange。

    exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。

    5.3 ZeroMQ

    号称史上最快的消息队列,它实际类似于Socket的一系列接口,他跟Socket的区别是:普通的socket是端到端的(1:1的关系),而ZMQ却是可以N:M 的关系,人们对BSD套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏蔽了这些细节,让你的网络编程更为简单。ZMQ用于node与node间的通信,node可以是主机或者是进程。

    引用官方的说法: “ZMQ(以下ZeroMQ简称ZMQ)是一个简单好用的传输层,像框架一样的一个socket library,他使得Socket编程更加简单、简洁和性能更高。是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。ZMQ的明确目标是“成为标准网络协议栈的一部分,之后进入Linux内核”。现在还未看到它们的成功。但是,它无疑是极具前景的、并且是人们更加需要的“传统”BSD套接字之上的一 层封装。ZMQ让编写高性能网络应用程序极为简单和有趣。”

    特点是:

    • 高性能,非持久化;
    • 跨平台:支持Linux、Windows、OS X等。
    • 多语言支持; C、C++、Java、.NET、Python等30多种开发语言。
    • 可单独部署或集成到应用中使用;
    • 可作为Socket通信库使用。

    与RabbitMQ相比,ZMQ并不像是一个传统意义上的消息队列服务器,事实上,它也根本不是一个服务器,更像一个底层的网络通讯库,在Socket API之上做了一层封装,将网络通讯、进程通讯和线程通讯抽象为统一的API接口。支持“Request-Reply “,”Publisher-Subscriber“,”Parallel Pipeline”三种基本模型和扩展模型。

     

    ZeroMQ高性能设计要点:

    1、无锁的队列模型

       对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。

    2、批量处理的算法

       对于传统的消息处理,每个消息在发送和接收的时候,都需要系统的调用,这样对于大量的消息,系统的开销比较大,zeroMQ对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。

    3、多核下的线程绑定,无须CPU切换

       区别于传统的多线程并发模式,信号量或者临界区, zeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销。

    5.4 Kafka

    Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。 对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群机来提供实时的消费。

    Kafka是一种高吞吐量的分布式发布订阅消息系统,有如下特性:

    • 通过O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以TB的消息存储也能够保持长时间的稳定性能。(文件追加的方式写入数据,过期的数据定期删除)
    • 高吞吐量:即使是非常普通的硬件Kafka也可以支持每秒数百万的消息。
    • 支持通过Kafka服务器和消费机集群来分区消息。
    • 支持Hadoop并行数据加载。

     

    Kafka相关概念

    • Broker

    Kafka集群包含一个或多个服务器,这种服务器被称为broker[5]

    • Topic

    每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)

    • Partition

    Parition是物理上的概念,每个Topic包含一个或多个Partition.

    • Producer

    负责发布消息到Kafka broker

    • Consumer

    消息消费者,向Kafka broker读取消息的客户端。

    • Consumer Group

    每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。

     

    一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用。

    六、参考资料

    以下是本次分享参考的资料和推荐大家参考的资料。

     

    参考资料(可参考资料):

    (1)Jms

    http://blog.sina.com.cn/s/blog_3fba24680100r777.html

    http://blog.csdn.net/jiuqiyuliang/article/details/46701559(深入浅出JMS(一)--JMS基本概念)

    (2)RabbitMQ

    http://baike.baidu.com/link?url=s2cU-QgOsXan7j0AM5qxxlmruz6WEeBQXX-Bbk0O3F5jt9Qts2uYQARxQxl7CBT2SO2NF2VkzX_XZLqU-CTaPa

    http://blog.csdn.net/sun305355024sun/article/details/41913105

    (3)Zero MQ

    http://www.searchtb.com/2012/08/zeromq-primer.html

    http://blog.csdn.net/yangbutao/article/details/8498790

    http://wenku.baidu.com/link?url=yYoiZ_pYPCuUxEsGQvMMleY08bcptZvwF3IMHo2W1i-ti66YXXPpLLJBGXboddwgGBnOehHiUdslFhtz7RGZYkrtMQQ02DV5sv9JFF4LZnK

    (4)Kafka

    http://baike.baidu.com/link?url=qQXyqvPQ1MVrw9WkOGSGEfSX1NHy4unsgc4ezzJwU94SrPuVnrKf2tbm4SllVaN3ArGGxV_N5hw8JTT2-lw4QK

    http://www.infoq.com/cn/articles/apache-kafka/

    http://www.mincoder.com/article/3942.shtml

    已分享的电子资料(在群文件中)

    (1)Active MQ

     

    (2)Kafka

     

    (3)Notify

     

    七、本次分享总结

    以上是本周的分享,主要讲解了消息队列概述,常用消息队列应用场景(异步处理,应用解耦,流量削锋,日志处理和消息通讯),JMS Java消息服务,以及目前流行的几款消息队列介绍。最后演示了两个使用消息中间件的架构。

    因为时间关系,有些讲解的不细致,大家可以问下度娘/Google,希望本次分享对大家有帮助。

    本次是春节前最后一次分享,我们的分享年后会继续,明年会继续《大型网站架构系列》,并会增加《一步一步学架构系列》。具体时间和分享内容会以QQ群公告的方式通知大家。感谢大家的关注。

    分享是快乐的,也是个人成长的过程。文章一般是自己的学习总结,工作经验,不足之处在所难免,请大家指正,共同进步。建立了一个以架构为中心的KK群466097527 ,欢迎大家加入。专注大型分布式网站架构,大数据,架构模式,设计模式。

     

    原文:http://www.cnblogs.com/itfly8/p/5155983.html

    展开全文
  • 5G消息

    万次阅读 2020-12-29 10:21:06
    什么是5G消息 在讲5G消息之前,我们先来聊聊RCS,循序渐进,一层一层的剥开5G消息的神秘面纱。 “5G消息”,其实和5G并没有什么关系。它既不是5G特有的功能,也不是5G时代新开发出来的业务。它的真实身份,是...

    什么是5G消息

    三大运营商联手,针对微信公众号共同研发反制利器——5G消息

     

    在讲5G消息之前,我们先来聊聊RCS,循序渐进,一层一层的剥开5G消息的神秘面纱。

    “5G消息”,其实和5G并没有什么关系。它既不是5G特有的功能,也不是5G时代新开发出来的业务。它的真实身份,是2008年就已经诞生的RCS业务。RCS,全称是Rich Communication Suite,即富媒体通讯套件

    什么是“富媒体(Rich Media)”?传统电话只有语音,传统短信只有文本。而“富媒体”,包括文本、语音、图片、视频、动画、表情、位置等多种媒体形式。我们天天在用的微信公众号,就是一种富媒体通信工具。

    RCS,也被称为融合通信。所谓“融合”,既可以理解为多种媒体形式融合,也可以理解为IP业务和传统电信网业务的融合。5G消息就是相当于给RCS穿了一件新衣服。关于RCS的前世今生,我们下一篇文章再讲。

    在这流量红利时代,腾讯早已布好局。早在2013年8月5日微信正式推出微信公众平台(公众号)后,将更多的公域流量变成了私域流量,自己闷声发大财。越来越多的企业用户接入微信公众平台,也就导致越来越多的个人用户使用公众号,将原本属于短信的公域流量变成了属于微信的私域流量。同年,三大运营商的短信发送量下降。随着时间的推移,使用微信公众号的人越来越多,与之相反,三大运营商的短彩发送量也越来越低。为了反制腾讯,今年,三大运营商强强联手,将多年之前的RCS再次拿出来,升级为5G消息,用以抢夺流量市场。

    5G消息白皮书

    早在今年4月8日,中国移动、中国电信、中国联通携手11家合作伙伴(终端企业及通讯领域企业)共同发布《5G消息白皮书》,华为、小米、OPPO 、VIVO、魅族等手机终端厂商积极响应,并承诺5G机型将全面适配5G消息服务!三大运营商联合发布一份白皮书,充分说明它们对5G消息业务的一致看好。那么,运营商下定决心大力发展的5G消息,究竟是什么呢?

      通俗的讲,5G消息更像是短信和彩信的升级版,在5G时代,是运营商的一种基础电信增值服务。短信时代,只能传输纯文本;彩信时代,可以传输音视频等富媒体内容,然后5G消息融合了短彩,在此基础上,新增以卡片的方式将多种媒体内容呈现给终端用户。传统的短信保留着2G电路域的业务形态和体验,5G消息则基于IP技术实现业务体验的飞跃,支持的媒体格式更多,表现形式更丰富。

      趁着5G时代的快车,5G消息时代已经来临,全球运营商已达成广泛共识:传统短信业务难以满足当前交流的需求,急需升级到富媒体消息业务,也就是5G消息业务。根据白皮书的介绍,5G消息多种媒体格式,包括文本、图片和音视频以及调用手机硬件支持等,更像是一个功能齐全的微信公众号。相关业务主要分为两大类:一是个人用户和个人用户之间的交互消息,另一个是企业用户与个人用户之间的交互消息(侧重)。

    三大运营商联手,针对微信公众号共同研发反制利器——5G消息

     

    应用场景

    距离白皮书发布已过去半年之久,目前三大运营商及各大终端厂商已经为中国的5G消息建立了良好的生态环境。下面我们就来展示一些具体的应用场景。

    1、P2P消息,个人用户交互场景(暂未商用)

    2、A2P消息,通知服务类场景

    三大运营商联手,针对微信公众号共同研发反制利器——5G消息

    如中国移动话费账单通知、订阅短信号内容推送等

    3、P2A,品牌服务类场景,由用户主动上行触发。商家通过消息服务平台被智能对接给用户,解决需求或提供服务。

     

     

    5G消息的核心产品:Chatbot

    Chatbot (聊天机器人)。利用人工智能新技术,如语音识别,语义分析等,随时响应用户并提供发送、接收、解析、处理等消息服务,是一种集成程度更高、可代替App的全新人机交互服务模式。RCS消息利用Chatbot平台聚合商户,通过RCS消息通道满足商户与客户的交流,可以根据聊天场景为用户提供智能的个性化服务。Chatbot打造消息服务新入口,完成一站式的业务体验和人机交互,将短信互联网化,为商户创造更多业务拓展与服务场景,打造新入口、新平台、新渠道。

    三大运营商联手,针对微信公众号共同研发反制利器——5G消息

     

    也就是说,针对P2A或者A2P的最终表现形式就是Chatbot,Chatbot承载着所有消息内容,是用户与商家交互的第一窗口。终端短信APP原生支持,无需下载任何软件,相比于微信公众号,Chatbot的消息更易于被用户查看和接收。

    展开全文
  • 消息中间件(一)MQ详解及四大MQ比较

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

    万次阅读 2018-04-27 13:24:28
    于是通过自己的摸索与测试,终于通过自己的方法组起TLV消息,并通过socket发送出去。在这里,希望和大家交流一下有关TLV的知识,写的不好的地方,请指正。 TLV结构体 struct TLV_HEAD // tlv消息头 { int ...
  • 消息队列的使用场景

    万次阅读 多人点赞 2016-03-04 10:26:20
    一、消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。 目前在生产环境,...
  • 文章目录消息描述规范字段字段类型字段名常量编译消息文件关于std_msgs 参考:http://wiki.ros.org/msg ros使用一套简化的消息描述语言来描述ros节点所发布的数据。ros工具可以根据消息描述为消息类型生成不同目标...
  • androidpn消息推送

    千次下载 热门讨论 2012-07-04 16:32:15
    androidpn消息推送 其中包含客户端 服务器端包含tomcat和jetty版本
  • Android消息推送

    千次下载 热门讨论 2013-04-17 12:02:48
    Android消息推送 支持离线消息 Android消息推送 支持离线消息
  • 我在《项目中为什么要使用消息队列》中列举了两个使用消息队列的例子。 (1)收银系统,确认收款成功,通过MQ通知给物流系统发货。 (2)消费积分,用户每消费一笔给用户增加一定积分,京东豆,信用卡积分,2020年...
  • 常用消息队列对比

    万次阅读 2017-03-08 17:00:56
    作为中间件,消息队列是分布式应用间交换信息的重要组件。消息队列可驻留在内存或磁盘上, 队列可以存储消息直到它们被应用程序读走。通过消息队列,应用程序可以在不知道彼此位置的情况下独立处理消息,或者在处理...
  • rabbitmq消息发送确认和消费消息手动删除消息
  • RabbitMQ之消息确认机制(事务+Confirm)

    万次阅读 多人点赞 2017-02-17 16:33:09
    在使用RabbitMQ的时候,我们可以通过消息持久化操作来解决因为服务器的异常奔溃导致的消息丢失,除此之外我们还会遇到一个问题,当消息的发布者在将消息发送出去之后,消息到底有没有正确到达broker代理服务器呢?...
  • RabbitMQ之消息持久化

    万次阅读 多人点赞 2017-03-08 16:53:06
    消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保证消息可靠性的呢——消息持久化。 为了保证RabbitMQ在退出或者crash等异常情况下数据没有丢失,需要将queue,exchange和Message都持久化。 queue的...
  • 消息队列使用的四种场景介绍

    万次阅读 多人点赞 2017-04-18 10:55:09
    消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题 实现高性能,高可用,可伸缩和最终一致性架构 使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ ...
  • 一、RocketMQ 支持 3 种消息发送方式 : 1、同步消息(sync message ) producer向 broker 发送消息,执行 API 时同步等待, 直到broker 服务器返回发送结果 。 2、异步消息(async message) producer向 broker ...
  • “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息...
  • 消息总线VS消息队列

    万次阅读 多人点赞 2015-02-18 17:30:22
    消息队列跟消息总线进行了对比,并说明了对于企业应用,封装消息总线的必要性。
  • 简单消息,异步消息,同步消息辨析

    千次阅读 2016-12-02 10:35:26
    简单消息,异步消息,同步消息辨析 附例子
  • 微信脚本自动发消息 即将还有几个小时放假,约朋友一起玩,灵光一闪,能不能写个微信自动发消息来提醒朋友的插件呢。尝试了一下。结果可行 如果对你有帮助麻烦给个赞,鼓励一下。话不多说,贴代码 var appElement = ...
  • 用Python实现自动发消息,自定义内容,太省事了!

    万次阅读 多人点赞 2021-08-16 11:27:22
    有时候让了解放双手,让电脑来帮我们自动发一些我们想要发的消息,挺省力的,比如说白天写好了演讲稿,晚上要在群里进行文字演讲,那么我们就可以用脚本来实现自动复制、粘贴和发送文字的功能,从而解放我们自己,...
  • 小伙伴们,好久不见,之前一直忙需求,好久没写博客了,企业微信于今年六月底新增了群机器人消息接口,虽然这个机器人的功能还不是很完善,但是总体来说呢跟企业微信发送应用消息差不多,企业微信发送应用消息在这 ...
  • RocketMQ事务消息实战

    万次阅读 多人点赞 2018-07-31 19:19:05
       我们以一个订单流转流程来举例,例如订单子系统创建订单,需要将订单数据下发到其他子...   3、MQ消费者消费消息,发送远程RPC服务调用,完成订单数据的同步。    1、方案一    方案弊端:  ...
  • ⭐️UI自动化控制微信发送或转发图片消息

    万次阅读 多人点赞 2021-09-18 22:42:18
    在前面《UI自动化轻松解决微信手工群发消息的烦恼》一文中,我演示了如果使用python发送文本消息。前段时间有群友询问: 虽然之前觉得太简单懒得做,但今天周末又想起这个问题,考虑到很多网友不知道如何实现,所以...
  • 前一篇文章里我们已经把微信公众平台接口中消息及相关操作都进行了封装,本章节将主要介绍如何接收微信服务器发送的消息并做出响应。 明确在哪接收消息 从微信公众平台接口消息指南中可以了解到,当用户向公众...
  • RocketMq发送延迟消息

    万次阅读 2019-05-25 10:59:51
    对于消息中间件来说,producer将消息发送到mq的服务器,但并不期望这条消息马上被消费,而是推迟到当前时间点之后的某个时间点后再投递到queue中让consumer进行消费,延迟消息的使用场景很多,一种比较常见的场景...
  • 延迟消息的五种实现方案

    万次阅读 多人点赞 2021-01-12 12:09:06
    针对延迟消息,本文分享五种不同的实现方案,并逐一讨论各种方案的大致实现和优缺点。
  • app消息推送及监听系统消息点击

    万次阅读 2020-08-11 15:55:45
    //创建本地消息,这个可以通过判断服务器端是否有新消息推送,获取到推送消息之后,创建本地推送消息 plus.push.addEventListener(“click”, function(msg) { //content: ( String ) 必选 消息显示的内容,在系统...
  • HTTP消息

    万次阅读 2020-08-14 21:14:47
    HTTP消息 请求头 响应头 成功响应 重定向 客户端响应 服务端响应 0850875)] 服务端响应

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,601,814
精华内容 1,040,725
关键字:

消息