消息_消息树 - CSDN
  • 在大型平台的分布式项目中,消息队列MQ具有重要的作用,经常用在边缘业务功能的处理中,比如日志管理【下面将以Bug日志保存为例】,因为像日志保存、新用户注册发送邮件等操作都不是主干业务,可以放在消息队列异步...

    人工智能,零基础入门!http://www.captainbed.net/inner

    一、简介

    在大型平台的分布式项目中,消息队列MQ具有重要的作用,经常用在边缘业务功能的处理中,比如日志管理【下面将以Bug日志保存为例】,因为像日志保存、新用户注册发送邮件等操作都不是主干业务,可以放在消息队列异步处理,这样可以减小项目的阻塞和压力。下面介绍的是比较常用的一个消息队列ActiveMQ

    二、项目的一般业务逻辑

    就以Bug日志保存为例,介绍一般的业务逻辑:【如下图代码示例】

    【1】写一个接口,

    【2】然后调用注入的Service的业务逻辑方法,

    【3】接口返回结果,流程结束。

    三、要用消息队列情况的业务逻辑

    【1】首先要有另外一个新的MQ项目服务器,用于接收消息,和处理消息,暴露接口出来即可,

    【2】在原先的项目业务上修改:请求MQ项目暴露出来的接口,把数据传过去,如果是传输的数据是对象得注意这个对象进行序列话【就是实现Serializable接口】

    【3】需要注意的是,原先的项目中的service的业务逻辑代码要copy到MQ项目中,到这里你可能就明白了MQ的实现原理:原先的项目就负责发送消息给MQ项目,然后MQ项目上有一套完全一样的业务处理代码,MQ项目在拿到消息后再慢慢处理消息【异步进行】,说通俗一点,就相当于将业务转移到另外一个项目。

    四、MQ项目消息端配置 

    【1】原先项目中的service方法要copy过来,还有对应的实体类也要copy一致,

    【2】写一个接收消息的接口:

    【3】生产消息的生产端【生产者】

    【4】消费消息的消费端 【消费者】

    【5】配置queue的名字

     这是简单的运用,用起来还是蛮简单的,但是要了解里面的原理还要多多学习源码。

    展开全文
  • 要说微信最让人恶心的发明,消息撤回绝对能上榜。 比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?...

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

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

    那么有没有什么办法能够知道你心爱的她(他)到底撤回了什么呢?不要着急,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,但目前我测试来看是没有问题的,如有问题,欢迎评论区留言。

    展开全文
  • 大型网站架构之分布式消息队列   以下是消息队列以下的大纲,本文主要介绍消息队列概述,消息队列应用场景和消息中间件示例(电商,日志系统)。 本次分享大纲 消息队列概述消息队列应用场景消息中间件示例...

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

     

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

    本次分享大纲

    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

    展开全文
  • 周末测试了一下RabbitMQ的性能,RabbitMQ是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。个人认为,在互联网开发...
    周末测试了一下RabbitMQ的性能,RabbitMQ是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。个人认为,在互联网开发中,使用消息队列,更多的因为在高并发环境下,由于来不及同步处理,请求会发生堵塞,所以我们需要一个队列服务来进行异步的处理,在这种场景下,只要队列服务满足最基本的Push/Pop已经足够了。

    Redis是一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持list数据结构的操作,所以完全可以当做一个轻量级的队列服务来使用。

    本文简单对比了Redis作为消息队列和RabbitMQ的性能表现情况。

    测试环境
    1. 硬件环境:在个人笔记本上测试,Server和Client使用同一台机器,硬件信息如下

    Processor : Inter(R) Core(TM)2 Duo CPU P8400 @2.26GHz
    RAM : 4.00GB
    Operating System : 32-bit Ubuntu 10.10
    2. 软件化境:RabbitMQ和Redis的Server启动都是用默认配置,客户端使用Java,JVM启动使用默认参数:

    RabbitMQ Server 2.2.0
    RabbitMQ Java Client 2.2.0

    Redis 2.0 Stable
    Jedis
    对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。

    入队性能对比
    四种不同大小的数据入队性能对比(RPS):



    测试结果:



    可以看到对于入队操作,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis慢的无法忍受。

    出队性能对比
    四种不同大小的数据出队对比(PRS):



    测试结果:



    可以看到对于出队操作,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

    Redis入队和出队对比
    针对Redis入队和出队对比(RPS):



    测试数据:



    不管数据大小,Redis的出队性能都表现的非常优秀,而入队性能在数据比较大时,慢的无法忍受。

    RabbitMQ入队和出队对比
    针对RabbitMQ的入队和出队对比(RPS):



    测试数据:



    不管数据大小,RabbitMQ的入队和出队性能都保持一个均衡的状态,但总体上,出队性能远低于入队性能。

    总结
    总体看来,Redis比较适合在Web场景下作为队列服务使用,但当数据比较大的时候,入队性能有些问题,也可能是我配置上不正确,所以还需要进一步研究。而RabbitMQ本身支持太多的协议,不适合在Web环境中使用。另外有一个MySQL的插件Q4M,可以使用SQL语法来操作消息队列,只不过性能表现怎么样,还需要进一步测试。
    展开全文
  • Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序...
  • 最近几天发现手机QQ很安静,一个消息都没有,这不正常,万一有什么紧急事情呢(比如:佳人有约、基友搞基哈哈哈),收不到消息,就不好了。 尝试用别的QQ发一条消息试试,还真是接收不到,只有打开QQ才能查看消息,...
  • 已经有几位读者抱怨“柳峰只用到文本消息作为示例,从来不提图文消息,都不知道图文消息该如何使用”,好吧,我错了,原本以为把基础API封装完、框架搭建好,再给出一个文本消息的使用示例,大家就能够照猫画虎的,...
  • posix消息队列与system v消息队列的差别: (1)对posix消息队列的读总是返回最高优先级的最早消息,对system v消息队列的读则可以返回任意指定优先级的消息。 (2)当往一个空队列放置一个消息时,posix消息队列...
  • 下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处。 一、什么是消息队列 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,...
  • 1、消息队列(以下简称MQ)天生就是处理高并发的有力工具,因为他可以把一个完整的流程拆为多部分,并发进行,或者不是很重要的步骤模块延迟进行。大家所熟悉的是消息队列在大基数用户项目的注册模块和电商项目的...
  • 本文大概围绕如下几点进行阐述:为什么使用消息队列?使用消息队列有什么缺点?消息队列如何选型?如何保证消息队列是高可用的?如何保证消息不被重复消费?如何保证消费的可靠性传输?如何保证消息的顺序性?我们围绕...
  • 消息队列使用场景为什么会需要消息队列(MQ)? 解耦 在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。...
  • 情景引入 情景分析 ...本模块主要讲解关于消息中间件的相关基础知识,也是方便我们后面的学习。...非操作系统软件,非业务应用软件,不是直接给最终...百度百科解释:消息中间件利用高效可靠的消息传递机制进行平...
  • 说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! ... 一丶概论 公众号接收与发送消息 ...如果公众号类型为服务号(订阅号只能使用普通消息接口),可以在公众平台网站中申请认证...
  • “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息...
  • Redis不仅可作为缓存服务器,还可用作消息队列。它的列表类型天生支持用作消息队列。如下图所示:  由于Redis的列表是使用双向链表实现的,保存了头尾节点,所以在列表头尾两边插取元素都是非常快的。  所以可以...
  • 在使用RabbitMQ的时候,我们可以通过消息持久化操作来解决因为服务器的异常奔溃导致的消息丢失,除此之外我们还会遇到一个问题,当消息的发布者在将消息发送出去之后,消息到底有没有正确到达broker代理服务器呢?...
  • 有个需求:APP用户产生某个操作,需要让后台管理系统部分人员感知(表现为一个页面消息)。最早版本是后台管理系统轮训,每隔一段时间轮训一次,由于消息重要,每隔几秒就查一次。这样做明显很不雅!会消耗大量资...
  • 在我们做微信公众号开发时,发送模板消息往往是必不可少的功能。今天我们就来说说吧! 1、申请模板消息 首先我们应该知道,模板消息是需要申请的。这个申请就其本身来说是很easy的(我前一天晚上申请的,显示需要2...
  • 消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法。对于消息队列的操作,我们可以类比为这么一个过程:假如 A 有个东西要给 B,因为某些原因 A 不能当面直接给 B,这时候他们需要借助第三方托管...
1 2 3 4 5 ... 20
收藏数 2,011,178
精华内容 804,471
热门标签
关键字:

消息