首页 > 其他分享 >架构设计:系统间通信(19)——MQ:消息协议(上)

架构设计:系统间通信(19)——MQ:消息协议(上)

时间:2024-09-24 09:19:41浏览次数:12  
标签:架构设计 协议 19 XMPP Stomp 间通信 命令 消息 客户端

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

1、概述

从本文开始,我们介绍另一类型的系统间通讯及输:MQ消息队列。首先我们将讨论几种常用消息队列协议的基本原理和工作方式,包括MQTT、XMPP、Stomp、AMQP、OpenWire等。然后在这个基础上介绍两款MQ产品:ActiveMQ和RabbitMQ,它们是现在业务系统中应用广泛的消息队列软件。包括他们的安装、运行、支持协议、集群化和调用方式。

当然,在这个过程中我们还会提到其他的消息队列协议(或者实现),例如微软JBossMQ、MSMQ、商业化产品WebSphere MQ、Oracle高级队列(AQ)等。 我们还会讨论这些眼花缭乱的协议、软件、程序库之间的关系 。

随后我们会花一些篇幅,讨论现在新兴的消息队列Kafka和ZeroMQ。它们的应用越来越广泛,尤其在大数据的采集方面。最后我们将使用消息队列搭建一个高性能的日志采集系统,作为实战。

2、基本概念

2-1、消息

首先有三个基本概念在开篇前我们需要进行讨论:消息、消息协议、消息队列。 消息既是信息的载体 这个描述相信各位读者都能够明白。 为了让消息发送者和消息接收者都能够明白消息所承载的信息 (消息发送者需要知道如何构造消息;消息接收者需要知道如何解析消息) ,它们就需要按照一种统一的格式描述消息,这种统一的格式称之为消息协议 。所以, 有效的消息一定具有某一种格式;而没有格式的消息是没有意义的 。

而消息从发送者到接收者的方式也有两种。一种我们可以称为 即时消息通讯 ,也就是说消息从一端发出后(消息发送者)立即就可以达到另一端(消息接收者),这种方式的具体实现就是我们已经介绍过的RPC(当然单纯的http通讯也满足这个定义);另一种方式称为 延迟消息通讯 ,即 消息从某一端发出后,首先进入一个容器进行临时存储,当达到某种条件后,再由这个容器发送给另一端。 这个容器的一种具体实现就是 消息队列 。

2-2、知识结构

消息队列和已经介绍过的RPC相同的是:无论是RPC也好,消息队列也好他们都建立在网络IO模型基础上(我们已经介绍过多种网络IO模型)。先进的网络IO模型将赋予MQ协议优异的性能表现(当然,性能也不仅仅取决于网络IO模型)。

202307292152447421.png

从上图可以看到, 某一种消息通讯软件(或者叫做程序库)的实现都建立在“协议”基础上 :RMI程序库建立在RMI协议上(RMI协议是JAVA规范协议的一部分) ,属于一种“即时消息通讯”;RabbitMQ和Qpid消息通讯软件的设计依据是AMQP协议,属于一种“延迟消息通讯”。

虽然消息协议存在“私有协议”和“开放协议”之分(是否向行业开放消息规范文档、是否允许某个组织更改协议),虽然某一个软件(程序库)不一定只支持一种协议(例如ActiveMQ实现了多种消息协议),虽然某一种协议也不一定只有一种软件(程序库)实现(例如能够支持webservice协议的程序库就有Codehaus XFire、Apache CXF、Jboss RESTEasy等), 但是这并不影响“某一种消息通讯软件(或者叫做程序库)的实现都建立在“协议”基础上”的概念,反而是这个基本概念加强了。

3、消息协议

那么要理解消息队列,我们就应该从这些支持“延迟消息通讯”的消息协议开始讨论。这个小节我们首先为各位读者介绍几种使用的消息协议,他们是XMPP、Stomp和AMQP。为了承接后文我们讲解的MQ软件,这三个协议中我们又着重讲解AMQP协议。

3-1、XMPP协议

3-1-1、定义

XMPP is the Extensible Messaging and Presence Protocol, a set of open technologies for instant messaging, presence, multi-party chat, voice and video calls, collaboration, lightweight middleware, content syndication, and generalized routing of XML data.

以上内容引用自XMPP官网,这个定义已经可以清楚表明XMPP协议的用途和特性。XMPP的前身是Jabber,一个开源形式组织制定的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。

XMPP基于XML,用于IM系统的开发。国内比较流行的XMPP服务器叫做Openfire,它使用MINA作为下层的网络IO框架(不是MINA2是MINA1);国外用的比较多的XMPP服务器叫做Tigase,它的官网号称单节点可以支撑50万用户在线,集群可以支持100万用户在线:(http://projects.tigase.org/

Cluster with over 1mn online users . 500k online users on a single machine

当然如果读者所在公司需要开发IM系统,除了使用现成的XMPP服务器以外,还需要实现了XMPP协议的客户端或者开发包(以便进行扩展开发)。您可以在XMPP官网查看到XMPP官方推荐的开发包,各种语言的支持基本上都有:https://xmpp.org/software/

笔者曾参与过某几款IM系统的开发(包括自己创业的项目),总的来说XMPP协议本身是不错的选择,但是学习起来会耗费相当的时间,并且某些XMPP客户端、服务器端或者程序库并没有这些开发团队宣传的那么稳定好用。 所以如果您的公司需要进行IM系统的开发,那么创立私有的消息协议也会是一个不错的选择 。

3-1-2、协议通讯过程示例

为了让各位读者对XMPP协议有一个感性认识,这里我们给出一个XMPP协议处理“IM用户登录”操作的过程(XMPP的登录方式分为有用户密码和无用户密码两种方式,这里我们介绍无密码登录方式)。

XMPP协议本身细节比较丰富,这里我们只讨论登录操作,如果读者有兴趣可以下载全套的XMPP官方规范文档进行研究(XMPP | The universal messaging standard):

202307292152458732.png

通过上图可以看到,XMPP协议中的xml片段。这里出现了几个XMPP协议中的关键信息,例如:

  • stream标记:通讯流标记,是指XMPP的客户端或者服务器端向对方发起的通讯请求(或者响应)。通讯流并不携带正真的内容信息,指示表明客户端和服务器端发生了一次交互。stream的属性包括:to、from、id、xml:lang、version等。
  • iq标记:iq标记是Info/Query的简称(你可以理解成查询信息请求),一般是一组的形式出现,由客户端发起查询请求,由服务器端返回查询结果。由于查询请求的类型不一样,iq标记中可以嵌入的子标记就有很多。例如,可以嵌入bind标记,表明某个用户和jid的绑定关系;可以嵌入多个item标记,表明查询得到的这个用户的好友信息(如下)。
    <iq to='[email protected]/someresource' type='result' id='roster'>  
        <query xmlns='jabber:iq:roster'>  
            <item jid='[email protected]' name='someone1'/>  
            <item jid='[email protected]' name='someone2'/>  
        </query>  
    </iq>
  • jid标记:jid(JabberID)是XMPP协议中标示,它用来标示XMPP网络中的各个XMPP实体(实体可以是某一个用户、某一个服务器、某一个聊天室),规范格式如下:
    jid = [ node "@" ] domain [ "/" resource ]
  • 还有未出现的message、presence标记:message是实体内容标记,记录了聊天的真实内容;presence标记表示了XMPP用户的服务状态(离线,在线、忙碌等)。示例如下:
    <message to="[email protected]/someresource" type="chat"> 
        <body>helloword。。。</body> 
    </message>

3-2、Stomp协议

3-2-1、定义

Stomp协议,英文全名Streaming Text Orientated Message Protocol,中文名称为 ‘流文本定向消息协议’。是一种以纯文本为载体的协议(以文本为载体的意思是它的消息格式规范中没有类似XMPP协议那样的xml格式要求,你可以将它看作‘半结构化数据’)。目前Stomp协议有两个版本:V1.1和V1.2。

一个标准的Stomp协议包括以下部分:命令/信息关键字、头信息、文本内容。如下图所示:

202307292152468773.png

以下为一段简单的协议信息示例:

    CONNECT
    accept-version:1.2
    someparam1:value1
    someparam2:value2
    
    this is conntecon ^@

上面的示例中,我们使用了Stomp协议的CONNECT命令,它的意思为连接到Stomp代理端,并且携带了要求代理端的版本信息和两个自定义的K-V信息(请注意’^@’符号,STOMP协议中用它来表示NULL)。

Stomp协议中有两个重要的角色:STOMP客户端与任意STOMP消息代理(Broker)。如下图所示:

202307292152475744.png

看了上面的示意图后有的读者可能会问:为什么称为Stomp消息代理,而不称为Stomp消息服务?因为Stomp Broker只是负责接受和存储客户端发来的消息、只是按照客户端要求的路径转发消息,只是管理客户端连接和订阅:它并不负责根据消息内容做任何业务处理。所以将它称为消息代理端更贴切。

由于Stomp协议的结构如此简单,以至于任何理解Stomp协议命令格式的技术人员都可以开发Stomp的代理端或者Stomp的客户端,并将自己满足Stomp协议的系统轻松接入另一个同样满足Stomp协议的第三方系统(例如activeMQ) 。

3-2-2、基本命令/返回信息

和介绍XMPP协议的方式类似,为了让读者对Stomp协议有进一步的认识,本小节我们介绍Stomp协议的基本命令和代理端返回的信息种类,并且列举一些实例进行使用讲解。

在Stomp协议中,主要有以下命令/返回信息(有的文章中也称一个完整的信息为帧)。这些命令/返回信息构成了Stomp协议的主体,并能够支持您的Stomp客户端和Stomp代理端完成连接、发送、订阅、事务、响应的整个操作过程。这些命令/返回是:

  • CONNECT/STOMP命令 : 客户端通过使用CONNECT命令,连接到Stomp代理端。如果使用STOMP命令,那么Stomp代理端的版本必须是1.2。
  • CONNECTED信息 :当Stomp代理端收到客户端发送来的Connect命令并且处理成功后,将向这个客户端返回CONNECTED状态信息;如果这个过程中出现任何问题,还可能返回ERROR信息
  • SEND 发送命令 :客户端使用SEND命令,向某个指定位置(代理端上的一个虚拟路径)发送内容。这样在这个路径上订阅了消息事件的其它客户端,将能够收到这个消息。
  • SUBSCRIBE 订阅命令 :客户端使用SUBSCRIBE订阅命令,向Stomp服务代理订阅某一个虚拟路径上的监听。这样当其它客户端使用SEND命令发送内容到这个路径上时,这个客户端就可以收到这个消息。在使用SUBSCRIBE时,有一个重要的ACK属性。这个ACK属性说明了Stomp服务代理端发送给这个客户端的消息是否需要收到一个ACK命令,才认为这个消息处理成功了。如下所示:
    SUBSCRIBE
    id:XXXXXXXXX
    destination:/test
    ack:client
    
    ^@

以上SUBSCRIBE命令信息说明,客户端订阅的虚拟位置是test。且命令信息中ack属性为client,说明当客户端收到消息时,必须向代理端发送ack命令,代理端才认为这个消息处理成功了(ack的值只有三种:auto(默认)、client和client-individual)。

  • UNSUBSCRIBE 退订命令 :客户端使用这个命令,取消对某个路径上消息事件的监听。如果客户端给出的路径之前就没有被这个客户端订阅,那么这个命令执行无效。
  • MESSAGE 信息 :当客户端在某个订阅的位置收到消息时,这个消息将通过MESSAGE关键字进行描述。类似以下信息就是从代理端拿到的消息描述:
    MESSAGE
    redelivered:true
    message-id:ID:localhost-34450-1457321490460-4:24:-1:1:1
    destination:/test
    timestamp:1457331607873
    expires:0
    priority:4
    
    2345431457331607861
  • BEGIN 开始事务命令 : Stomp协议支持事务模式,在这种模式下,使用Send命令从某个客户端发出的消息,在没有使用COMMIT正式提交前,这些消息是不会真正发送给Stomp代理端的。 BEGIN命令就是用于开启事务。注意,一个事务中可以有一条消息,也可以有多条消息 。
  • COMMIT 提交命令 : 当完成事务中的信息定义后,使用该命令提交事务。 只有使用COMMIT命令后,在某一个事务中的一条或者多条消息才会进入Stomp代理端的队列 (订阅了事件的其它客户端才能收到这些消息)。
  • ABORT 取消/终止事务命令 :很明显,这个命令用于取消/终止当前还没有执行COMMIT命令的事务。
  • ACK 确认命令 :当客户端使用SUBSCRIBE命令进行订阅时,如果在SUBSCRIBE命令中制定ack属性为client,那么这个客户端在收到某条消息(id为XXXX)后,必须向Stomp代理端发送ACK命令,这样代理端才会认为消息处理成功了; 如果Stomp客户端在断开连接之前都没有发送ACK命令,那么Stomp代理端将在这个客户端断开连接后,将这条消息发送给其它客户端 。
    ACK
    id:MESSAGE ID
    
    ^@
复制代码

请注意head部分的id属性,传递的id属性是之前收到的MESSAGE信息的id标示。

  • NACK 不确认命令 :同样是以上的SUBSCRIBE命令的状态下,如果这时Stomp客户端向Stomp代理端发送NACK信息,证明这条消息在这个客户端处理失败。 Stomp代理端将会把这条消息发送给另一个客户端(无论当前的客户端是否断开连接) 。
  • DISCONNECT 断开命令 :这个命令将断开Stomp客户端与Stomp代理端的连接。

标签:架构设计,协议,19,XMPP,Stomp,间通信,命令,消息,客户端
From: https://blog.csdn.net/smart_an/article/details/142473336

相关文章

  • 架构设计:系统间通信(18)——服务治理与Dubbo 下篇(继续分析)
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......
  • 【刷题笔记】2019 CSP-S
    2019CSP-S题目整理A-格雷数思路简介思路很简单,如果编号在中点的左边那么就输出0,否则输出1,同时还要改变编号。代码实现#include<bits/stdc++.h>#definemaxn80usingnamespacestd;typedef__int128int1;int1n,k;__int128read(){ charch=getchar(); __int128......
  • LGP1901 题解
    原题链接:P1901发射站难度:Easy。注意到"最近的且比它高",容易想到用单调栈维护每个能量发射站左右第一个比它高的,最后统计答案即可。具体的令f[i][0/1]表示能量发射站\(i\)右边/左边第一个\(h_x>h_i\)的位置\(x\)。用单调栈从左向右扫一遍,得到f[i][0]。用单调栈从右......
  • 9.19
    今天完成开学考试,本次考试的题目是一个《河北省重大技术需求征集》的基本信息填报功能。本次提供前端页面的代码。涉及到的必填选项以及字数限制都有很好的效果。<template><div><div><divclass="card"style="margin-bottom:10px"><el-inputv-model......
  • 2024.8.19 模拟赛 24
    模拟赛总是忘记保存怎么办难得挂分。T1ANDandSUM签到题,如果两数按位与结果为\(a\),那么它们的二进制重复为\(1\)的位一定就是\(a\)的二进制为\(1\)的位置,所以它们相加的值至少是\(2a\)。并且不够的差值只能在\(a\)二进制为零的位置补(否则会有进位),所以判\((s-2a)......
  • AI 大模型计算机科学家群英传:明斯基(Marvin Lee Minsky,1927年—2016年)
    AI大模型计算机科学家群英传:明斯基(MarvinLeeMinsky,1927年—2016年)作者:禅与计算机程序设计艺术/ZenandtheArtofComputerProgramming1.背景介绍1.1问题的由来人工智能(ArtificialIntelligence,AI)作为一门横跨计算机科学、认知科学、数学等多个学科的交叉学......
  • [GXYCTF2019]BabySQli
    这题查看源码后发现一个php文件问了ai后发现MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5是一段base32编码,经过base32解码,base64解码后的结果是select*fromuserwhereusername='$name'很明显是一个sql语句,在us......
  • 信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取
    信息学奥赛复赛复习01-CSP-J2019-01-字符、字符数组、字符串、string、字符串读取PDF文档公众号回复关键字:2024092312019CSP-J题目1数字游戏[题目描述]小K同学向小P同学发送了一个长度为8的01字符串来玩数字游戏,小P同学想要知道字符串中究竟有多少个1。注......
  • 中国土地利用覆盖和变化数据集(1980-2021)
       该数据集通过融合森林资源清查数据和20种遥感土地利用产品,重建生成了1980-2015年中国森林覆盖数据集,空间分辨率为1×1公里。并且在此基础上进一步获得高精度森林覆被信息和土地利用覆盖数据集相融合,生成了中国1980-2021年土地利用覆盖和变化数据集,空间分辨率为10×10公......
  • 31927 – Application Development with .NET
    Assignment-1Spring20241FacultyofEngineeringandInformationTechnologySchoolofComputerScience31927–ApplicationDevelopmentwith.NET32998-.NETApplicationDevelopmentSPRING2024ASSIGNMENT1–SPECIFICATIONDuedateMonday23September2......