掌桥专利:专业的专利平台
掌桥专利
首页

消息传输方法、装置、设备及存储介质

文献发布时间:2023-06-19 11:21:00


消息传输方法、装置、设备及存储介质

技术领域

本申请实施例涉及金融技术(Fintech)技术领域,尤其涉及一种消息传输方法、装置、设备及存储介质。

背景技术

目前,分布式系统中通常包括消息消费者群组、服务器和消息发布者群组。其中,消息消费者群组中包括至少一个消息消费者客户端(例如,C0、C1、C2),消息发布者群组中包括至少一个消息发布者客户端。在消息消费者群组订阅一个消息主题之后,消息发布者群组中的客户端向服务器发布该消息主题对应的消息。服务器中设置有该主题对应的至少一个消息队列(例如,Q0、Q1、Q2),一个消息队列对应一个消息消费者客户端、一个消息消费者客户端可以对应多个消息队列(例如,C0对应Q0,C1对应Q1,C2对应Q2),服务器将接收到的消息存储至多个消息队列中,并向消息消费者客户端发送该消息消费者客户端对应的消息队列中存储的消息(例如,向C0发送Q0和Q3中的消息)。

在相关技术中,服务器采用至少一次(at least once)发送策略向消息消费者客户端发送消息。服务器采用至少一次发送策略向消息消费者客户端发送消息的方法例如包括:服务器将Q1中的消息1发送给Q1对应的C1;C1对消息1处理完成之后,向服务器发送确认信息1;服务器再将Q1中的消息2发送给Q1对应的C1;若消息消费者群组中的C2突然退出,则服务器触发全局负载均衡,变更消息队列对消息消费者客户端的对应关系(例如,将消息队列Q1对应的C1变更为C3),此处若服务器未能及时地接收到C1发送的消息2对应的确认信息,服务器将消息2发送给C3。

在上述过程中,在服务器将消息2发送给C1之后,服务器还可以将消息2发送至C3,导致服务器重复向客户端发送相同的消息。

发明内容

本申请实施例提供一种消息传输方法、装置、设备及存储介质。用于避免服务器重复向客户端发送第一消息。

第一方面,本申请实施例提供一种消息传输方法,应用于服务器,方法包括:

接收第一客户端发送的消息请求;消息请求用于获取服务器的多个队列中目标队列的第一消息,消息请求中包括第一消息在目标队列中的第一偏移量;

根据第一偏移量和第二偏移量,确定是否发送过第一消息,第二偏移量为服务器最新接收到的确认信息对应的消息的偏移量,确认信息对应的消息为目标队列中的消息;

若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端。

在一种可能的设计中,消息请求还包括第一客户端的第一标识和目标队列的队列标识;

根据第一偏移量和第二偏移量,确定是否发送过第一消息,包括:

根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限;

若第一客户端具有从目标队列中获取消息的权限,则根据第一偏移量和第二偏移量,确定是否发送过第一消息。

在一种可能的设计中,根据第一偏移量和第二偏移量,确定是否发送过第一消息,包括:

若第一偏移量小于或等于第二偏移量,则确定发送过第一消息;

若第一偏移量大于第二偏移量,则确定未发送过第一消息。

在一种可能的设计中,根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限,包括:

从预先存储的消息记录表中获取与队列标识对应的客户端标识;消息记录表中包括队列标识与客户端标识的映射关系;

根据客户端标识和第一标识,判断第一客户端是否具有从目标队列中获取消息的权限。

在一种可能的设计中,根据客户端标识和第一标识,判断第一客户端是否具有从目标队列中获取消息的权限,包括:

若客户端标识和第一标识相同,则确定第一客户端具有从目标队列中获取消息的权限;或者,

若客户端标识和第一标识不同,则确定第一标识能否配置为队列标识对应的客户端标识,若第一标识能够配置为队列标识对应的客户端标识,则确定第一客户端具有从目标队列中获取消息的权限。

在一种可能的设计中,消息记录表中还包括第二客户端上一次从目标队列中获取消息的第一时刻、以及第二客户端对消息的平均处理时长;

确定第一标识能否配置为队列标识对应的客户端标识,包括:

获取当前时刻;

确定第一时刻和当前时刻之间的差值;

若差值大于平均处理时长与预设误差时长的和值,则确定第一标识能够配置为队列标识对应的客户端。

在一种可能的设计中,确定第一标识能否配置为队列标识对应的客户端标识,包括:

判断是否向第二客户端发送了新的消息,所述第二客户端为客户端标识对应的客户端;

若没有向所述第二客户端发送新的消息,则判断第四偏移量和第二偏移量是否相同;第四偏移量为目标队列中最后一次发送的消息的偏移量;

若第四偏移量和第二偏移量相同,则确定第一标识能够配置为队列标识对应的客户端标识。

在一种可能的设计中,方法还包括:

若第一客户端不具有从目标队列中获取消息的权限,则向第一客户端发送响应消息,响应消息用于表示第一客户端无法获取目标队列中的消息。

第二方面,本申请实施例提供一种消息传输装置,应用于服务器,装置包括:接收模块、确定模块、获取模块和发送模块,其中,

接收模块用于,接收第一客户端发送的消息请求;消息请求用于获取服务器的多个队列中目标队列的第一消息,消息请求中包括第一消息在目标队列中的第一偏移量;

确定模块用于,根据第一偏移量和第二偏移量,确定是否发送过第一消息,第二偏移量为服务器最新接收到的确认信息对应的消息的偏移量,确认信息对应的消息为目标队列中的消息;

获取模块用于,若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息;

发送模块用于,将第二消息发送给第一客户端。

在一种可能的设计中,消息请求还包括第一客户端的第一标识和目标队列的队列标识;

确定模块具体用于:

根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限;

若第一客户端具有从目标队列中获取消息的权限,则根据第一偏移量和第二偏移量,确定是否发送过第一消息。

在一种可能的设计中,确定模块具体用于:

若第一偏移量小于或等于第二偏移量,则确定发送过第一消息;

若第一偏移量大于第二偏移量,则确定未发送过第一消息。

在一种可能的设计中,确定模块具体用于:

从预先存储的消息记录表中获取与队列标识对应的客户端标识;消息记录表中包括队列标识与客户端标识的映射关系;

根据客户端标识和第一标识,判断第一客户端是否具有从目标队列中获取消息的权限。

在一种可能的设计中,确定模块具体用于:

若客户端标识和第一标识相同,则确定第一客户端具有从目标队列中获取消息的权限;或者,

若客户端标识和第一标识不同,则确定第一标识能否配置为队列标识对应的客户端标识,若第一标识能够配置为队列标识对应的客户端标识,则确定第一客户端具有从目标队列中获取消息的权限。

在一种可能的设计中,消息记录表中还包括第二客户端上一次从目标队列中获取消息的第一时刻、以及第二客户端对消息的平均处理时长;

确定模块具体用于:

获取当前时刻;

确定第一时刻和当前时刻之间的差值;

若差值大于平均处理时长与预设误差时长的和值,则确定第一标识能够配置为队列标识对应的客户端。

在一种可能的设计中,确定模块具体用于:

判断是否向第二客户端发送了新的消息,所述第二客户端为客户端标识对应的客户端;

若没有向所述第二客户端发送新的消息,则判断第四偏移量和第二偏移量是否相同;第四偏移量为目标队列中最后一次发送的消息的偏移量;

若第四偏移量和第二偏移量相同,则确定第一标识能够配置为队列标识对应的客户端标识。

在一种可能的设计中,发送模块还用于:

若第一客户端不具有从目标队列中获取消息的权限,则向第一客户端发送响应消息,响应消息用于表示第一客户端无法获取目标队列中的消息。

第三方面,本申请实施例提供一种服务器,包括:处理器和存储器;

存储器存储计算机执行指令;

处理器执行存储器存储的计算机执行指令,使得处理器执行如第一方面任一项的消息传输方法。

第四方面,本申请实施例提供一种计算机可读存储介质,计算机可读存储介质中存储有计算机执行指令,当处理器执行计算机执行指令时,实现如第一方面任一项的消息传输方法。

第五方面,本申请实施例提供一种计算机程序产品,包括计算机程序,计算机程序被处理器执行时实现如第一方面任一项的消息传输方法。

本申请实施例提供一种消息传输方法、装置、设备及存储介质,其中,消息传输方法包括:接收第一客户端发送的消息请求;消息请求用于获取服务器的多个队列中目标队列的第一消息,消息请求中包括第一消息在目标队列中的第一偏移量;根据第一偏移量和第二偏移量,确定是否发送过第一消息,第二偏移量为服务器最新接收到的确认信息对应的消息的偏移量,确认信息对应的消息为目标队列中的消息;若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端。在上述方法中根据第一偏移量和第二偏移量,确定是否发送过第一消息;若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端,可以避免服务器重复向客户端发送第一消息,进而避免第一消息被客户端重复消费。

附图说明

为了更清楚地说明本申请实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作一简单地介绍,显而易见地,下面描述中的附图是本申请实施例的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。

图1为本申请实施例提供的消息传输方法的应用场景示意图;

图2为本申请实施例提供的消息队列的示意图;

图3为本申请实施例提供的消息传输方法的流程示意图一;

图4为本申请实施例提供的消息传输方法的流程示意图二;

图5为本申请实施例提供的判断第一客户端是否具有从目标队列中获取消息的权限的流程示意图;

图6为本申请实施例提供的确定第一标识能否配置为队列标识对应的客户端标识的流程示意图一;

图7为本申请实施例提供的确定第一标识能否配置为队列标识对应的客户端标识的流程示意图二;

图8为本申请实施例提供的消息传输装置的结构示意图;

图9为本申请实施例提供的服务器的硬件结构示意图。

具体实施方式

为使本申请实施例的目的、技术方案和优点更加清楚,下面将结合本申请实施例中的附图,对本申请实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例是本申请一部分实施例,而不是全部的实施例。基于本申请中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本申请保护的范围。

本申请的说明书和权利要求书及上述附图中的术语“第一”、“第二”、“第三”、“第四”等(如果存在)是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。应该理解这样使用的数据在适当情况下可以互换,以便这里描述的本申请的实施例例如能够以除了在这里图示或描述的那些以外的顺序实施。此外,术语“包括”和“具有”以及他们的任何变形,意图在于覆盖不排他的包含,例如,包含了一系列步骤或单元的过程、方法、系统、产品或设备不必限于清楚地列出的那些步骤或单元,而是可包括没有清楚地列出的或对于这些过程、方法、产品或设备固有的其它步骤或单元。

在对本申请实施例提供的消息传输方法进行说明之前,首先对本申请实施例提供的消息传输方法的应用场景进行说明,具体的,请参见图1。

图1为本申请实施例提供的消息传输方法的应用场景示意图。如图1所示,分布式系统中通常包括:消息消费者群组、服务器和消息发布者群组。

消息消费者群组中包括至少一个消息消费者客户端,例如:C0、C1、C2。每个消息消费者客户端具有对应的标识,例如:C0对应的标识为0、C1对应的标识为1、C2对应的标识为2。

消息发布者群组中包括至少一个消息消费者客户端,例如:P0。在消息消费者群组订阅一个消息主题之后,P0可以向服务器发布该消息主题对应的多个消息。

服务器分别与消息消费者群组中的客户端和消息发布者群组中的客户端通信连接。服务器中包括至少一个主题各自对应的至少一个消息队列,至少一个主题中包括上述消息主题,上述消息主题具有对应的至少一个消息队列,例如:Q0、Q1、Q2、Q3、Q4、Q5。每个消息队列具有对应的标识,例如,Q0对应的标识为0、Q1对应的标识为1、Q2对应的标识为2、Q3对应的标识为3、Q4对应的标识为4、Q5对应的标识为5。服务器将接收到的一个消息存储至一个消息队列中,消息队列Q0、Q1、Q2、Q3、Q4、Q5中存储的消息各不相同。一个消息队列对应一个消息消费者群组中的一个消息消费者客户端、一个消息消费者客户端可以对应多个消息队列(例如,C0对应Q0和Q3,C1对应Q1和Q4,C2对应Q2和Q5)。

C0、C1、C2可以通过负载均衡算法确定其对应的消息队列。例如,负载均衡算法为取余算法时,消息消费者客户端可以根据至少一个消息消费者客户端的个数(3)、消息消费者客户端的标识和每个消息队列的标识,确定消息消费者客户端对应的消息队列。例如,C0通过取余算法获取3与每个消息队列的标识(0、1、2、3、4、5)的余数(0%3=0、1%3=1、2%3=2、3%3=0、4%3=1、5%3=2,其中,%取余算法),将上述余数中与C0的标识(0)相同的,确定为目标余数(0%3=0、3%3=0),将目标余数对应的消息队列(Q0和Q3),确定为C0对应的消息队列。

在消息消费者群组中存在一个消息消费者客户端异常或者退出时,消息消费者群组中的其他消息消费者客户端会重新通过负载均衡算法确定其对应的消息队列。例如,当C2异常或者退出时,C0通过负载均衡算法确定其对应的消息队列为Q0、Q2、Q4,C3通过负载均衡算法确定其对应的消息队列为Q1、Q3、Q5。

在实际应用中,服务器(broker)可以通过如下三种方式,将消息队列中的消息发送给消息队列对应的消息消费者客户端。

方式1、至少一次(At least once)发送策略,即确保每个消息至少被投递一次,保证消息绝对不丢失,但消息可能被重复投递。

方式2、最多一次(At most once)发送策略,即确保每个消息至多投递一次,保证消息绝对不被重复投递,但消息可能会丢。

方式3、仅此一次(Exactly once)发送策略,即确保每个消息被传输一次且仅传输一次,既保证消息不丢失,也保证消息不被重复投递。

在服务器将消息队列中的消息发送给消息消费者客户端的过程中,服务器通常维护消息队列的确认位点、分发位点、最大位点。

其中,确认位点(ackOffset),表示消息队列中已经成功被消息消费者客户端消费完成的消息在消息队列中的偏移量。其中,消费完成指消息消费者客户端接收到消息之后,对消息进行处理,并在处理完成之后向服务器发送消息对应的确认信息,且服务器接收到了该确认信息。其中,消费指消息消费者客户端接收到消息之后,对消息进行处理。需要说明的是,在消息队列中,确认位点以及确认位点之前的消息,是服务器接收到了该消息对应的确认信息对应的消息。

其中,分发位点(deliverOffset),表示已经分发给消息消费者客户端的消息的偏移量。需要说明的是,在消息队列中,该分发位点以及该分发位点之前的消息已经被发送给消息消费者客户端。

其中,最大位点(maxOffset),表示消息队列中最后一个消息的偏移量。

针对服务器中一个消息主题(Topic)的多个消息队列,每个消息队列均具有确认位点、分发位点、最大位点。服务器维护每个消息队列的确认位点、分发位点、最大位点。

下面以一个消息队列为例,结合图2实施例,说明服务器对消息队列的确认位点、分发位点、最大位点的维护过程。具体的,请参见图2。

图2为本申请实施例提供的消息队列的示意图。如图2所示,消息队列中包括至少一个消息,例如:消息1~消息72。其中,每个消息具有对应的索引,例如消息72的索引为72。

例如,在某一时刻,确认位点对应消息68,表示消息队列中的消息1~消息68已经被消息消费者客户端消费完成;分发位点对应消息71,表示消息队列中的消息1~消息71已经被发送给消费者客户端,但是服务器还没有收到消息69~消息71各自对应的确认信息;最大位点对应消息72,表示消息队列中只有消息1~消息72这72个消息。

进一步地,在另一时刻,在服务器接收到了消息69和消息70各自对应的确认信息之后,确认位点对应消息70。

进一步地,在又一时刻,在服务器接收到了消息发布者客户端发送的消息73~消息75之后,最大位点对应消息75。

进一步地,在再一时刻,在服务器向消息消费者客户端发送了消息71~消息73之后,分发位点对应消息73。

在至少一次发送策略中,在消息消费者客户端消费完成一个消息之后,向服务器发送确认位点,以使服务器根据接收到确认位点更新最近一次的接收到的确认位点。当消息消费者客户端重启、以重新对其对应的消息队里中的消息进行消费时,服务器根据确认位点向消息消费者客户端发送消息,以使消息消费者客户端对在确认位点之后的位置中存储的消息进行消费。

针对上述至少一次发送策略,当出现如下两种情况时,会出现同一个消息被重复消费:

情况1,当消息消费者群组中存在消息消费者客户端上线、下线或者突然退出时,服务器触发消息消费者群组中的消息消费者客户端进行负载均衡。例如,在负载均衡之前,C1正在消费Q1中的消息2;在负载均衡之后,Q1对应的C1变更为C3,由于C1消费消息2、且未能及时将消息2对应的确认信息发送给服务器,因此服务器向C3发送消息2,导致服务器重复发送消息2,进而导致消息2被重复消费。

情况2,负载均衡是由每个消息消费者客户端按照算法(例如取余算法)进行计算得到其对应的消息队列,消息消费者客户端之间不会同步各自对消息的消费情况,由于每个消息消费者客户端执行负载均衡的耗时有区别,所以不同的消息消费者客户端完成负载均衡、并且开始消费新的消息队列中的消息的时间通常不同,这会出现同一个消息队列中的消息在短时间之内被两个消息消费者客户端消费的情况。由于服务器对确认位点的更新总是会滞后于消息被送达至消息消费者客户端的时间,因此当消息的消费时长越大时,确认位点的更新延迟越明显,在上述情况2下越容易出现消息被重复消费。

在仅此一次发送策略中,需要在服务器中设置一个全局统一的存储器来记录全局的消息状态,从而根据该消息状态对待发送的消息进行避重判断(避免消息被重复发送的判断),在消息消费者客户端需要从服务器中获取消息时,服务器都需要查询消息状态、并更新消息状态。当消息状态被记录为消息消费者客户端已收到、但消息消费者客户端异常退出的时候,该消息状态对应的消息需要被及时确定为是未消费完成、而且是可以被其他消息消费者客户端再次接收和消费的。在上述仅此一次发送策略中,在服务器中引入全局统一的存储器来记录消费状态,使得消息消费者客户端从服务器中获取消息时,增加了服务器额外的查询和更新过程,使得服务器的性能损耗较大,增加了服务器的系统复杂度,进而增加了系统的风险点数量。进一步地,在上述仅此一次发送策略中,当消息消费者客户端异常退出时,面临如何及时、准确地确定一条已被发送过的消息需要被重新发送和消费的问题。

为了避免服务器重复发送消息,进而避免消息被重复消费,本申请实施例提供一种消息传输方法。下面对本申请实施例提供的消息传输方法的技术构思进行说明。

服务器向消息消费者客户端发送消息,在消息消费者客户端对消息消费完成之后,向服务器发送确认信息,服务器根据确认信息更新确定位点。由于在消息队列中,确定位点以及确定位点之前的消息是不能被重复发送的,因此发明人想到,可以在服务器接收到消息消费者客户端发送的消息请求(包括请求位点)之后,仅向消息消费者客户端发送确定位点之后的消息,从而避免服务器重复发送消息,进而避免消息被重复消费。为了达到仅向消息消费者客户端发送确定位点之后的消息的目的,发明人想到,可以根据消息请求中包括的请求位点和服务器中存储的确认位点,判断消息消费者客户端要获取的消息是否被发送过,从而达到仅向消息消费者客户端发送确定位点之后的消息的目的,进而实现避免服务器重复发送消息,避免消息被重复消费的有益效果。

下面结合图3实施例,对本申请实施例提供的消息传输方法进行说明,具体的,请参见图3实施例。

图3为本申请实施例提供的消息传输方法的流程示意图一。如图3所示,本实施例提供的消息传输方法包括:

S301、接收第一客户端发送的消息请求,消息请求用于获取服务器的多个队列中目标队列的第一消息,消息请求中包括第一消息在目标队列中的第一偏移量。

本申请实施例的执行主体为可以为服务器,也可以为服务器中的消息传输装置,其中,消息传输装置可以通过软件和/或硬件的结合来实现。

第一客户端为订阅了一个消息主题的消息消费者群组中的任意一个消息消费者客户端。

多个队列为服务器中上述消息主题对应的消息队列。

目标队列为当前时刻第一客户端对应的消息队列。当前时刻可以为服务器接收到消息请求的时刻,可以为第一客户端进行负载均衡之后的时刻。

第一偏移量(即requestOffset)为第一消息在目标队列中的位点。例如,第一偏移量为67,指示第一客户端请求的第一消息存储在目标队列中的位点为67的位置。

消息请求中还可以包括目标队列的队列标识、消息主题的标识、第一客户端的标识等。

S302、根据第一偏移量和第二偏移量,确定是否发送过第一消息,第二偏移量为服务器最新接收到的确认信息对应的消息的偏移量,确认信息对应的消息为目标队列中的消息。

第二偏移量为服务器实时维护的确认位点。

当消息请求还包括目标队列的队列标识、消息主题的标识、第一客户端的标识时,服务器可以根据消息请求确定第二偏移量,进而根据第一偏移量和第二偏移量,确定是否发送过第一消息。

在一种可能的设计中,服务器根据消息主题的标识,确定多个队列,多个队列各自对应的标识均与消息主题的标识对应;服务器根据目标队列的队列标识,获取第二偏移量,该第二偏移量对应于队列标识。

具体的,若第一偏移量小于或等于第二偏移量,则确定发送过第一消息。例如,当第一偏移量为67、第二偏移量为70时,确定发送过第一消息。

S303、若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端。

例如,若第一偏移量为67、第二偏移量为70,则确定发送过第一消息,进而将目标队列中位点为71处存储的消息确定为第二消息,从目标队列中获取第二消息,将第二消息发送给第一客户端。

其中,第二消息与第一消息不同。

在一种可能的设计中,消息请求中还可以包括消息个数。例如,在确定发送过第一消息之后,还可以根据消息个数和第二偏移量,从目标队列中获取第二消息。其中,消息个数可以为1、2、3等。

例如,当消息个数为2、第二偏移量为70时,可以将目标队列中位点为71和72处存储的消息确定为第二消息,即第二消息中包括2个消息(分别为位点为71处存储的消息和位点为72处存储的消息)。

在图3实施例提供的消息传输方法中,根据第一偏移量和第二偏移量,确定是否发送过第一消息;若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端,可以避免在负载均衡之后,由于服务器未收到第一消息对应确认信息,导致服务器重复向发送第一消息的问题,进而避免第一消息被重复消费。

在上述实施例的基础上,下面结合图4,对本申请实施例提供的消息传输方法进行做进一步地说明,具体的,请参见图4实施例。

图4为本申请实施例提供的消息传输方法的流程示意图二。如图4所示,本实施例提供的消息传输方法包括:

S401、接收第一客户端发送的消息请求,消息请求中包括第一消息在目标队列中的第一偏移量、第一客户端的第一标识和目标队列的队列标识。

具体的,S401的执行方法与S301的执行方法相似,此处不再赘述S401的执行过程。

S402、根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限。

若是,则执行S403,否则,执行S406。

在一种可能的设计中,根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限,包括:

从预先存储的消息记录表中获取与队列标识对应的客户端标识;消息记录表中包括队列标识与客户端标识的映射关系;

根据客户端标识和第一标识,判断第一客户端是否具有从目标队列中获取消息的权限。

消息记录表具有如下表1所示的形式。

表1

上述表1中,包括多个消息队列的标识、每个消息队列的标识对应的客户端标识。可以根据队列标识,在表1中确定队列标识对应的客户端标识。

下面结合具体举例,对DeliverOffsetNoChangeTimes(客户端每次获取消息时,分发位点连续不变的次数)的变化过程进行说明:

例如,客户端向服务器连续的发送5个消息请求(分别为r1、r2、r3、r4、r5),即在客户端向服务器发送r1,服务器向客户端发送r1对应消息,客户端接收到r1对应消息之后,对r1对应消息消费,在消费完成之后,向服务器发送r2,依次类推。当服务器执行r1(即向客户端发送r1对应消息之前,从队列中获取消息)时,获取deliverOffset,若此时deliverOffset=10,则DeliverOffsetNoChangeTimes=1;当服务器执行r2时,获取deliverOffset,若此时deliverOffset=10,则DeliverOffsetNoChangeTimes=2;当服务器执行r3时,获取deliverOffset,若此时deliverOffset=10,则DeliverOffsetNoChangeTimes=3;当服务器执行r4时,获取deliverOffset,若此时deliverOffset=12,则DeliverOffsetNoChangeTimes=0。

在表1中的,在消息消费者客户端向服务器发送消息请求时,可以将客户端(为表1中客户端标识对应的客户端)对消息的平均处理时长(avgCost)设置在消息请求。

表1中还可以包括消息主题的标识对应的消息消费者群组的标识。

具体的,若客户端标识和第一标识相同,则确定第一客户端具有从目标队列中获取消息的权限;若客户端标识和第一标识不相同,则确定第一客户端不具有从目标队列中获取消息的权限。

与现有技术不同,在现有的权限控制方式中,通常为不同的客户端配置不同的客户端标识,在服务器接收到一个客户端标识之后,根据客户端标识对应的消息消费者客户端的权限执行相应的操作,即现有的权限控制方式为静态固定的控制方式,无法随着实际应用场景的变化而变化,不够智能。而在本申请中,虽然一个消费者客户端只允许消费一个消息队列中消息,但是消费该消息队列中的消息的消费者客户端是可以变化的(不是固定),即本申请中的权限控制方式为动态可变的控制方法,可以随着实际应用场景的变化而变化,更加智能。

进一步地,在本申请中,通过动态可变的控制方法,实现一个消费者客户端只允许消费一个消息队列中的消息,可以防止出现不同的消费者客户端同时消费同一个消息队列中的消息的情况。

在另一种可能的设计中,可以根据如下图5实施例所示的方法,根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限。具体的,请参见图5实施例。

S403、根据第一偏移量和第二偏移量,确定是否发送过第一消息。

若否,则执行S404,否则,执行S405。

具体的,若第一客户端具有从目标队列中获取消息的权限,则执行S403。

S404、根据第二偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端。

具体的,S404的执行方法与S303的执行方法相似,此处不再赘述S404的执行过程。

在一种可能的设计中,在S404之前,还可以包括:根据第二偏移量和第一偏移量确定第三偏移量,向第一客户端发送包括第三偏移量的应答消息;

接收第一客户端发送的另一个消息请求,该另一个消息请求为第一客户端接收到应答消息之后发送的;

服务器根据第三偏移量,从目标队列中获取第二消息,并将第二消息发送给第一客户端。

在一种可能的设计中,根据第二偏移量和第一偏移量确定第三偏移量,包括:根据第一偏移量和第二偏移量,是否需要纠正偏移量(nextOffset);

若是,则将偏移量纠正为第二偏移量,得到第三偏移量。

具体的,当第一偏移量小于或等于第二偏移量时,确定需要纠正偏移量;当第一偏移量大于第二偏移量时,确定需要不纠正偏移量。

例如,当第一偏移量为65、第二偏移量为70时,确定需要纠正偏移量,将偏移量nextOffset纠正为70,得到第三偏移量70。

S405、根据第一偏移量,从目标队列中获取第一消息,并将第一消息发送给第一客户端。

具体的,若第一偏移量大于第二偏移量,则确定未发送过第一消息。例如,当第一偏移量为72、第二偏移量为70时,确定未发送过第一消息。

在一种可能的设计中,若第一偏移量大于第二偏移量,则服务器根据第一偏移量,查询目标队列得到第一消息,并将第一消息发送给第一客户端。

例如,当第一偏移量为72、第二偏移量为70时,服务器根据第一偏移量,查询目标队列,得到第一消息(即位点为72处存储的消息),并将第一消息发送给第一客户端。

S406、向第一客户端发送响应消息,响应消息用于表示第一客户端无法获取目标队列中的消息。

具体的,若第一客户端不具有从目标队列中获取消息的权限,则执行S406。

在图4实施例提供的消息传输方法中,根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限;若第一客户端不具有从目标队列中获取消息的权限,则向第一客户端发送响应消息,响应消息用于表示第一客户端无法获取目标队列中的消息,可以避免服务器触发全局负载均衡之后、导致第一客户端与其他客户端(其中,其他客户端为消息消费者群组中除第一客户端之外的客户端)同时消费目标队列中的消息的问题。进一步地,若第一客户端具有从目标队列中获取消息的权限,则根据第一偏移量和第二偏移量,确定是否发送过第一消息,可以避免服务器重复发送第一消息,进而避免第一消息被重复消费。

在上述实施例的基础上,下面结合图5对判断第一客户端是否具有从目标队列中获取消息的权限的方法进行说明,具体的请参见图5。

图5为本申请实施例提供的判断第一客户端是否具有从目标队列中获取消息的权限的流程示意图。如图5所示,本实施例提供的方法包括:

S501、从预先存储的消息记录表中获取与队列标识对应的客户端标识。

S502、判断客户端标识是否为预设空值。

若否,则执行S503,否则,执行S505。

例如,预设空值可以为NULL,还可以为其他。

S503、判断客户端标识与第一标识是否相同。

若否,则执行S504,否则,执行S505。

S504、确定第一标识能否配置为队列标识对应的客户端标识。

若是,则执行S505,否则,执行S506。

需要说明的是,对S504的详细说明,请参见图6实施例。

S505、确定第一客户端具有从目标队列中获取消息的权限。

在S502的基础上,客户端标识为预设空值,表示目标队列中的消息没有被客户端消费,因此可以确定第一客户端具有从目标队列中获取消息的权限。进一步地,确定第一客户端具有从目标队列中获取消息的权限之后,可以将第一客户端配置为队列标识对应的客户端标识。例如,当预设空值为NULL时,可以将消息记录表中的客户端标识替换为第一客户端的第一标识,从而完成将第一标识能够配置为队列标识对应的客户端标识。

在S503的基础上,客户端标识与第一标识相同,表示目标队列中的消息被第一客户端消费,因此可以确定第一客户端具有从目标队列中获取消息的权限,第一客户端继续保持对目标队列中消息的消费权限。

在上述S504的基础上,第一标识能配置为队列标识对应的客户端标识,表示服务器的等待时长达到最大允许等待时长、或者服务器没有向第二客户端(与客户端标识对应)发送新的消息各且服务器收到了已发送的所有消息对应的确认信息,因此可以确定第一客户端具有从目标队列中获取消息的权限。

S506、确定第一客户端不具有从目标队列中获取消息的权限。

在上述实施例的基础上,下面结合图6对确定第一标识能否配置为队列标识对应的客户端标识的方法进行说明,具体的请参见图6和图7实施例。

图6为本申请实施例提供的确定第一标识能否配置为队列标识对应的客户端标识的流程示意图一。如图6所示,本实施例提供的方法包括:

S601、获取当前时刻。

当前时刻(currentTime)可以为开始执行S504时对应的时刻、也可以为开始执行S601的时刻。

S602、确定第一时刻和当前时刻的之间的差值。

第一时刻为消息记录表中第二客户端上一次从目标队列中获取消息的第一时刻。具体的,第一时刻等于消息记录表中目标队列的队列标识对应的记录项lastAccessTimestamp。

此处,第二客户端为消息记录表中目标队列的队列标识对应的客户端。第二客户端为本申请中的第一客户端,还可以为消息消费者群组中除第一客户端之外的任意一个客户端。

差值t1为服务器的等待时长,t1等于currentTime-lastAccessTimestamp。

S603、判断差值是否大于平均处理时长与预设误差时长的和值。

若是,则执行S604,否则,执行S605。

平均处理时长可以包括在第一客户端发送的消息请求中。平均处理时长为第一客户端对消息的平均处理时长。平均处理时长等于消息记录表中目标队列的队列标识对应的记录项avgCost。

在一种可能的设计中,第一客户端确定平均处理时长的方法,包括:获取预设滑动时长;获取待统计时刻之前预设滑动时长内的M个消息处理时长;将M个消息处理时长的平均值确定为平均处理时长。M可以为10、20等。

预设滑动时长可以为1小时、1分钟、1天等。预设滑动时长的取值通常不能太小。当预设滑动时长的取值过小时,获取到的消息处理时长的数量M过小,导致确定出的平均处理时长不够准确。

待统计时刻可以为第一客户端每次向服务器发送消息请求之前的时刻。

针对一个消息,消息处理时长等于该消息的接收时刻与该消息的消费完成时刻的差值。

预设误差时长为预先存储在服务器中的误差时长。预设误差时长用于消除网络延时等额外耗时对服务器的等待时长影响。例如,预设误差时长可以为50毫秒、100毫秒等,具体的本申请不限定预设误差时长的具体取值。

平均处理时长与预设误差时长的和值为服务器的最大允许等待时长。

在一种可能的设计中,判断差值是否大于平均处理时长与预设误差时长的和值,得到第一判断结果(condition1)。

例如,当差值大于平均处理时长与预设误差时长的和值时,得到第一判断结果为1(或者true);当差值小于或等于平均处理时长与预设误差时长的和值时,得到第一判断结果为0(或者false)。

当第一判断结果为1或者true时,执行S604;当第一判断结果为0或者false时,执行S605。

S604、确定第一标识能配置为队列标识对应的客户端标识。

具体的,当差值大于平均处理时长与预设误差时长的和值时,表示服务器的等待时长达到最大允许等待时长,可以确定第二客户端不再消费目标队列中的消息。当第二客户端不再消费目标队列中的消息时,说明第二客户端异常退出、正常退出、或者负载均衡之后开始消费其他队列中的消息。

S605、确定第一标识不能配置为队列标识对应的客户端标识。

在图6实施例中,判断差值是否大于平均处理时长与预设误差时长的和值;若是,则确定第一标识能配置为队列标识对应的客户端标识,从而及时、准确地确定出第二客户端(与消息记录表中目标队列的队列标识对应的客户端标识对应)已经停止消费目标队列中的消息,第一客户端此时可以消费目标队列中的消息,进一步地,在图6的基础上,结合图4中的第一偏移量和第二偏移量,能够及时、准确地确定出第一客户端具体从哪个位点开始消费消息可以避免消息被重复消费。

在确定第一标识能否配置为队列标识对应的客户端标识,难以确定以下3种情况:

情况1、第二客户端是否仍然在线且能够消费消息;

情况2、第二客户端是否已经不再从目标队列中获取消息;

情况3、第二客户端发送的确认信息滞后;

针对情况1,第二客户端可能是正常停机、也可能是异常退出,但有无论第二客户端是正常停机、还是异常退出,第二客户端不会向服务器发送消息请求。因此服务器可以通过第二客户端上一次发送消息请求的时间,粗略判断第二客户端是否仍然在线且能够消费消息。

针对情况2,第二客户端已经不再从目标队列中获取消息,表现为从某个时间点开始不会再向服务器发送消息请求上。因此服务器可以通过消息记录表记录的lastAccessTimestamp,判断第二客户端多久没有获取目标队列中的消息,但服务器的最大允许等待时长具体设置为多少则是新的难题。消息消费者客户端通常采用轮询的机制从服务器中获取消息,向服务器发送消息请求的频次很高,间隔很短,因此最大允许等待时长只要大于正常轮询间隔时长,就可能第二客户端已经不再从目标队列中获取消息。

针对情况3,第二客户端发送的确认信息滞后,通常与消息的消费时长相关,消费时长越大,确认信息滞后越久。在实际应用中,由于不同消息消费者客户端对不同的消息队列中的消息的消费能力不同,因此消费时长也不同,无法使用统一的最大允许等待时长来做判断,需要自适应调整每个消息队列对应的最大允许等待时长。

基于上述3种情况,在本申请中,向服务器发送队列标识对应的平均处理时长,使得服务器将平均处理时长和预设误差时长的和值确定为队列标识对应的最大允许等待时长,从而解决3种情况存在的问题。

图7为本申请实施例提供的确定第一标识能否配置为队列标识对应的客户端标识的流程示意图二。如图7所示,本实施例提供的方法包括:

S701、获取第四偏移量、以及队列标识对应的客户端上一次获取消息的位点和次数。

第四偏移量为服务器存储的目标队列中最后一次发送的消息的偏移量。第四偏移量等于服务器中存储的队列标识对应的分发位点DeliverOffset。

队列标识对应的客户端上一次获取消息的位点等于lastDeliverOffset。

消息记录表中队列标识对应的次数为等于DeliverOffsetNoChangeTimes。

S702、根据第四偏移量、客户端上一次获取消息的位点、次数,判断是否向第二客户端发送了新的消息。

第二客户端为队列标识对应的客户端标识对应的客户端。

若否,则执行S703,否是,执行S705。

在一种可能的设计中,判断客户端上一次获取消息的位点是否等于第四偏移量;

若是,则更新次数,将次数加1;

若否,则更新次数,将次数置为0;

判断更新后的次数是否大于或等于预设次数;

若是,则确定没有向第二客户端发送新的消息;

若否,则确定向第二客户端发送了新的消息。

预设次数可以为5、8、10等。

在一种可能的设计中,判断更新后的次数是否大于或等于预设次数,得到第三判断结果(condition3)。例如,当更新后的次数大于或等于预设次数时,得到第三判断结果为1(或者true),确定没有向第二客户端发送新的消息;当更新后的次数小于预设次数时,得到第三判断结果为0(或者false),确定向第二客户端发送了新的消息,即第二客户端仍然在从目标队列中获取消息。

S703、判断第四偏移量和第二偏移量是否相同。

若是,则执行S704,否则,执行S705。

在一种可能的设计中,判断第四偏移量和第二偏移量是否相同,得到第二判断结果(condition2)。例如,当第四偏移量和第二偏移量相同时,得到第二判断结果为1(或者true),确定第四偏移量和第二偏移量相同;当第四偏移量和第二偏移量不相同时,得到第二判断结果为0(或者false),确定第四偏移量和第二偏移量不相同。

S704、确定第一标识能配置为队列标识对应的客户端标识。

S705、确定第一标识不能配置为队列标识对应的客户端标识。

在图7实施例中,当没有向第二客户端发送新的消息时,表示目标队列中没有需要被发送的消息;当第四偏移量和第二偏移量相同时,表示服务器已经接收到了目标队列中所有已被发送的消息对应的确认消息。因此可以确定第一标识能够配置为队列标识对应的客户端标识。进一步地,在本申请中引入第四偏移量,使得服务器可以准确的记录最后一次发送的消息的偏移量,从而避免服务器重复发送目标队列中消息。

在一种可能的设计中,可以判断(condition1)||(condition2&&condition3)是否为第一预设值,其中,||为逻辑运算“或”,&&逻辑运算“与”;

若是,则确定第一标识能配置为队列标识对应的客户端标识;

若否,则确定第一标识不能配置为队列标识对应的客户端标识。

其中,第一预设值可以为1,还可以为true。

例如,当condition1=1、condition2=1、condition3=1时,确定(condition1)||(condition2&&condition3)为第一预设值1;

或者,当condition1=0、condition2=1、condition3=1时,确定(condition1)||(condition2&&condition3)为第一预设值1;

或者,当condition1=1、condition2=0、condition3=1时,确定(condition1)||(condition2&&condition3)为第一预设值1;

或者,当condition1=1、condition2=1、condition3=0时,确定(condition1)||(condition2&&condition3)为第一预设值1。

与现有技术不同,在现有的仅此一次发送策略中,当根据消息状态对待发送的消息进行避重判断时,需要在服务器中引入全局统一的存储器来记录全局的消息状态,增加了服务器额外的查询和更新过程,导致服务器的性能损耗较大,增加了服务器的系统复杂度,进而增加了系统的风险点数量。而在本申请中,通过引入第四偏移量,详细记录最后一次下发的消息,避免了服务器额外的查询和更新过程,降低了服务器的性能损耗,降低了服务器的系统复杂度,进而降低了系统的风险点数量。

进一步地,与现有技术不同,在现有的仅此一次发送策略中,当根据消息状态对待发送的消息进行避重判断时,若消息消费者客户端异常退出,面临如何及时、准确地一条已被发送过的消息需要被重新发送和消费的问题。而在本申请中,通过第一时刻和当前时刻的之间的差值、以及平均处理时长与预设误差时长的和值,及时地、准确地确定消息消费者客户端异常退出,进而根据第四偏移量、次数和分发位点,能够解决及时、准确地确定一条已被发送过的消息需要被重新发送和消费的问题。

图8为本申请实施例提供的消息传输装置的结构示意图。如图8所示,消息传输装置10包括:接收模块101、确定模块102、获取模块103和发送模块104,其中,

接收模块101用于,接收第一客户端发送的消息请求;消息请求用于获取服务器的多个队列中目标队列的第一消息,消息请求中包括第一消息在目标队列中的第一偏移量;

确定模块102用于,根据第一偏移量和第二偏移量,确定是否发送过第一消息,第二偏移量为服务器最新接收到的确认信息对应的消息的偏移量,确认信息对应的消息为目标队列中的消息;

获取模块103用于,若确定发送过第一消息,则根据第二偏移量,从目标队列中获取第二消息.

发送模块104用于,将第二消息发送给第一客户端。

本申请实施例提供的消息传输装置可以执行上述方法实施例所示的技术方案,其实现原理以及有益效果类似,此处不再进行赘述。

在一种可能的设计中,消息请求还包括第一客户端的第一标识和目标队列的队列标识;

确定模块102具体用于:

根据第一标识和队列标识,判断第一客户端是否具有从目标队列中获取消息的权限;

若第一客户端具有从目标队列中获取消息的权限,则根据第一偏移量和第二偏移量,确定是否发送过第一消息。

在一种可能的设计中,确定模块102具体用于:

若第一偏移量小于或等于第二偏移量,则确定发送过第一消息;

若第一偏移量大于第二偏移量,则确定未发送过第一消息。

在一种可能的设计中,确定模块具体用于:

从预先存储的消息记录表中获取与队列标识对应的客户端标识;消息记录表中包括队列标识与客户端标识的映射关系;

根据客户端标识和第一标识,判断第一客户端是否具有从目标队列中获取消息的权限。

在一种可能的设计中,确定模块102具体用于:

若客户端标识和第一标识相同,则确定第一客户端具有从目标队列中获取消息的权限;或者,

若客户端标识和第一标识不同,则确定第一标识能否配置为队列标识对应的客户端标识,若第一标识能够配置为队列标识对应的客户端标识,则确定第一客户端具有从目标队列中获取消息的权限。

在一种可能的设计中,消息记录表中还包括第二客户端上一次从目标队列中获取消息的第一时刻、以及第二客户端对消息的平均处理时长;

确定模块102具体用于:

获取当前时刻;

确定第一时刻和当前时刻之间的差值;

若差值大于平均处理时长与预设误差时长的和值,则确定第一标识能够配置为队列标识对应的客户端。

在一种可能的设计中,确定模块102具体用于:

判断最后一次发送的消息是否为目标队列中的最后一个消息;

若为目标队列中的最后一个消息,则判断第四偏移量和第二偏移量是否相同;第四偏移量为目标队列中最后一次发送的消息的偏移量;

若第四偏移量和第二偏移量相同,则确定第一标识能够配置为队列标识对应的客户端标识。

在一种可能的设计中,发送模块104还用于:

若第一客户端不具有从目标队列中获取消息的权限,则向第一客户端发送响应消息,响应消息用于表示第一客户端无法获取目标队列中的消息。

本申请实施例提供的消息传输装置可以执行上述方法实施例所示的技术方案,其实现原理以及有益效果类似,此处不再进行赘述。

图9为本申请实施例提供的服务器的硬件结构示意图。如图9所示,该服务器20包括:处理器201和存储器202,

其中,处理器201、存储器202通过总线203连接。

在具体实现过程中,处理器201执行存储器202存储的计算机执行指令,使得处理器201执行如上的消息传输方法。

处理器201的具体实现过程可参见上述方法实施例,其实现原理和技术效果类似,本实施例此处不再赘述。

在上述图9所示的实施例中,应理解,处理器可以是中央处理单元(CentralProcessing Unit,CPU),还可以是其他通用处理器、数字信号处理器(Digital SignalProcessor,DSP)、专用集成电路(Application Specific Integrated Circuit,ASIC)等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等。结合申请所公开的方法的步骤可以直接体现为硬件处理器执行完成,或者用处理器中的硬件及软件模块组合执行完成。

存储器可能包含高速RAM存储器,也可能还包括非易失性存储NVM,例如磁盘存储器。

总线可以是工业标准体系结构(Industry Standard Architecture,ISA)总线、外部设备互连(Peripheral Component,PCI)总线或扩展工业标准体系结构(ExtendedIndustry Standard Architecture,EISA)总线等。总线可以分为地址总线、数据总线、控制总线等。为便于表示,本申请附图中的总线并不限定仅有一根总线或一种类型的总线。

本申请实施例还提供一种计算机可读存储介质,计算机可读存储介质中存储有计算机执行指令,当处理器执行计算机执行指令时,实现如上的消息传输方法。

本申请实施例提供一种计算机程序产品,包括计算机程序,计算机程序被处理器执行时实现如上的消息传输方法。

上述的计算机可读存储介质,上述可读存储介质可以是由任何类型的易失性或非易失性存储设备或者它们的组合实现,如静态随机存取存储器(SRAM),电可擦除可编程只读存储器(EEPROM),可擦除可编程只读存储器(EPROM),可编程只读存储器(PROM),只读存储器(ROM),磁存储器,快闪存储器,磁盘或光盘。可读存储介质可以是通用或专用计算机能够存取的任何可用介质。

一种示例性的可读存储介质耦合至处理器,从而使处理器能够从该可读存储介质读取信息,且可向该可读存储介质写入信息。当然,可读存储介质也可以是处理器的组成部分。处理器和可读存储介质可以位于专用集成电路(Application Specific IntegratedCircuits,简称:ASIC)中。当然,处理器和可读存储介质也可以作为分立组件存在于设备中。

单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。

作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。

另外,在本申请各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。

功能如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本申请的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本申请各个实施例方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(ROM,Read-Only Memory)、随机存取存储器(RAM,Random Access Memory)、磁碟或者光盘等各种可以存储程序代码的介质。

本领域普通技术人员可以理解:实现上述各方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成。前述的程序可以存储于一计算机可读取存储介质中。该程序在执行时,执行包括上述各方法实施例的步骤;而前述的存储介质包括:ROM、RAM、磁碟或者光盘等各种可以存储程序代码的介质。

最后应说明的是:以上各实施例仅用以说明本申请的技术方案,而非对其限制;尽管参照前述各实施例对本申请进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分或者全部技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本申请各实施例技术方案的范围。

相关技术
  • 消息中间件消息传输方法、装置、计算机设备和存储介质
  • 一种消息传输方法、消息转发设备及存储介质
技术分类

06120112895607