消息分析:分析消息发送、接收、回复等消息相关的数据。

信途科技 新闻资讯 10 0
消息分析是指收集和分析有关消息发送、接收和回复的数据。这有助于企业了解其消息活动的表现,并识别改进领域。

消息分析指标

常用的消息分析指标包括:发送率:向用户发送的消息数量与创建的消息数量之比。 打开率:打开消息的收件人数量与收到消息的收件人数量之比。点击率:用户点击消息中链接或调用的次数与打开消息的次数之比。回复率:用户回复消息的次数与收到消息的次数之比。参与度:用户对消息采取任何行动(例如打开、点击或回复)的次数与收到消息的次数之比。

分析消息分析数据

分析消息分析数据时,应考虑以下因素:目标受众:消息发送给的目标受众。消息类型:所发送消息的类型(例如促销、更新或支持)。发送时间:消息发送的时间。通过分析这些因素,企业可以深入了解其受众的行为和偏好。

使用消息分析数据

消息分析数据可用于以下目的:优化消息活动:识别发送率、打开率、点击率和参与度较高的消息特征。改进目标受众定位:根据人口统计数据、兴趣和行为等因素细分受众,以提高消息相关性。个性化消息:根据每个收件人的兴趣和行为定制消息,以提高参与度。自动化消息:根据预定义的触发因素自动发送消息,例如欢迎消息或弃车恢复消息。衡量营销效果:跟踪消息活动对收入、客户保留和品牌认知度的影响。

消息分析工具

有多种消息分析工具可供使用,例如:邮件营销平台:通常提供内置消息分析功能。谷歌分析:允许跟踪消息活动并衡量其对网站流量和转化率的影响。 第三方分析工具:提供更高级的功能,例如消息归因和自动化报告。

结论

消息分析是了解消息活动绩效和改进领域的宝贵工具。通过分析消息发送、接收和回复的数据,企业可以优化其消息策略,提高客户参与度和实现业务目标。

WebSocket 分布式集群怎么搞?

问题起因

最近做项目时遇到了需要多用户之间通信的问题,涉及到了WebSocket握手请求,以及集群中WebSocket Session共享的问题。

期间我经过了几天的研究,总结出了几个实现分布式WebSocket集群的办法,从zuul到spring cloud gateway的不同尝试,总结出了这篇文章,希望能帮助到某些人,并且能一起分享这方面的想法与研究。

以下是我的场景描述

资源:4台服务器。其中只有一台服务器具备ssl认证域名,一台redis+mysql服务器,两台应用服务器(集群)

应用发布限制条件:由于场景需要,应用场所需要ssl认证的域名才能发布。 因此ssl认证的域名服务器用来当api网关,负责https请求与wss(安全认证的ws)连接。 俗称https卸载,用户请求https域名服务器,但真实访问到的是http+ip地址的形式。 只要网关配置高,能handle多个应用

需求:用户登录应用,需要与服务器建立wss连接,不同角色之间可以单发消息,也可以群发消息

集群中的应用服务类型:每个集群实例都负责http无状态请求服务与ws长连接服务

系统架构图

在我的实现里,每个应用服务器都负责http and ws请求,其实也可以将ws请求建立的聊天模型单独成立为一个模块。 从分布式的角度来看,这两种实现类型差不多,但从实现方便性来说,一个应用服务http+ws请求的方式更为方便。 下文会有解释

本文涉及的技术栈

Eureka 服务发现与注册

Redis Session共享

Redis 消息订阅

Spring Boot

Zuul 网关

Spring Cloud Gateway 网关

Spring WebSocket 处理长连接

Ribbon 负载均衡

Netty 多协议NIO网络通信框架

Consistent Hash 一致性哈希算法

相信能走到这一步的人都了解过我上面列举的技术栈了,如果还没有,可以先去网上找找入门教程了解一下。下面的内容都与上述技术相关,题主默认大家都了解过了...

技术可行性分析

下面我将描述session特性,以及根据这些特性列举出n个解决分布式架构中处理ws请求的集群方案

WebSocketSession与HttpSession

在Spring所集成的WebSocket里面,每个ws连接都有一个对应的session:WebSocketSession,在Spring WebSocket中,我们建立ws连接之后可以通过类似这样的方式进行与客户端的通信:

protectedvoidhandleTextMessage(WebSocketSessionsession,TextMessagemessage){(服务器接收到的消息:+message);//(newTextMessage(message));}

那么问题来了:ws的session无法序列化到redis,因此在集群中,我们无法将所有WebSocketSession都缓存到redis进行session共享。 每台服务器都有各自的session。 于此相反的是HttpSession,redis可以支持httpsession共享,但是目前没有websocket session共享的方案,因此走redis websocket session共享这条路是行不通的。

有的人可能会想:我可不可以将sessin关键信息缓存到redis,集群中的服务器从redis拿取session关键信息然后重新构建websocket session...我只想说这种方法如果有人能试出来,请告诉我一声...

以上便是websocket session与http session共享的区别,总的来说就是http session共享已经有解决方案了,而且很简单,只要引入相关依赖:spring-session-data-redis和spring-boot-starter-redis,大家可以从网上找个demo玩一下就知道怎么做了。 而websocket session共享的方案由于websocket底层实现的方式,我们无法做到真正的websocket session共享。

解决方案的演变

Netty与Spring WebSocket

刚开始的时候,我尝试着用netty实现了websocket服务端的搭建。 在netty里面,并没有websocket session这样的概念,与其类似的是channel,每一个客户端连接都代表一个channel。 前端的ws请求通过netty监听的端口,走websocket协议进行ws握手连接之后,通过一些列的handler(责链模式)进行消息处理。 与websocket session类似地,服务端在连接建立后有一个channel,我们可以通过channel进行与客户端的通信

/***TODO根据服务器传进来的id,分配到不同的group*/privatestaticfinalChannelGroupGROUP=newDefaultChannelGroup();@OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,TextWebSocketFramemsg)throwsException{//retain增加引用计数,防止接下来的调用引用失效(服务器接收到来自+()()+的消息:+());//将消息发送给group里面的所有channel,也就是发送消息给客户端(());}

那么,服务端用netty还是用spring websocket?以下我将从几个方面列举这两种实现方式的优缺点

使用netty实现websocket

玩过netty的人都知道netty是的线程模型是nio模型,并发量非常高,spring5之前的网络线程模型是servlet实现的,而servlet不是nio模型,所以在spring5之后,spring的底层网络实现采用了netty。如果我们单独使用netty来开发websocket服务端,速度快是绝对的,但是可能会遇到下列问题:

与系统的其他应用集成不方便,在rpc调用的时候,无法享受springcloud里feign服务调用的便利性

业务逻辑可能要重复实现

使用netty可能需要重复造轮子

怎么连接上服务注册中心,也是一件麻烦的事情

restful服务与ws服务需要分开实现,如果在netty上实现restful服务,有多麻烦可想而知,用spring一站式restful开发相信很多人都习惯了。

使用spring websocket实现ws服务

spring websocket已经被springboot很好地集成了,所以在springboot上开发ws服务非常方便,做法非常简单。

Spring Boot 基础就不介绍了,推荐下这个实战教程:第一步:添加依赖

<dependency><groupId></groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>

第二步:添加配置类

@ConfigurationpublicclassWebSocketConfigimplementsWebSocketConfigurer{@OverridepublicvoidregisterWebSocketHandlers(WebSocketHandlerRegistryregistry){(myHandler(),/)(*);}@BeanpublicWebSocketHandlermyHandler(){returnnewMessageHandler();}}

第三步:实现消息监听类

@Component@SuppressWarnings(unchecked)publicclassMessageHandlerextendsTextWebSocketHandler{privateList<WebSocketSession>clients=newArrayList<>();@OverridepublicvoidafterConnectionEstablished(WebSocketSessionsession){(session);(uri:+());(连接建立:+());(currentseesion:+());}@OverridepublicvoidafterConnectionClosed(WebSocketSessionsession,CloseStatusstatus){(session);(断开连接:+());}@OverrideprotectedvoidhandleTextMessage(WebSocketSessionsession,TextMessagemessage){Stringpayload=();Map<String,String>map=(payload,);(接受到的数据+map);(s->{try{(发送消息给:+());(newTextMessage(服务器返回收到的信息,+payload));}catch(Exceptione){();}});}}

从这个demo中,使用spring websocket实现ws服务的便利性大家可想而知了。 为了能更好地向spring cloud大家族看齐,我最终采用了spring websocket实现ws服务。

因此我的应用服务架构是这样子的:一个应用既负责restful服务,也负责ws服务。 没有将ws服务模块拆分是因为拆分出去要使用feign来进行服务调用。 第一本人比较懒惰,第二拆分与不拆分相差在多了一层服务间的io调用,所以就没有这么做了。

从zuul技术转型到spring cloud gateway

要实现websocket集群,我们必不可免地得从zuul转型到spring cloud gateway。原因如下:

zuul1.0版本不支持websocket转发,zuul 2.0开始支持websocket,zuul2.0几个月前开源了,但是2.0版本没有被spring boot集成,而且文档不健全。 因此转型是必须的,同时转型也很容易实现。

在gateway中,为了实现ssl认证和动态路由负载均衡,yml文件中以下的某些配置是必须的,在这里提前避免大家采坑。

Spring Boot 基础就不介绍了,推荐下这个实战教程:如果要愉快地玩https卸载,我们还需要配置一个filter,否则请求网关时会出现错误not an SSL/TLS record

@ComponentpublicclassHttpsToHttpFilterimplementsGlobalFilter,Ordered{privatestaticfinalintHTTPS_TO_HTTP_FILTER_ORDER=;@OverridepublicMono<Void>filter(ServerWebExchangeexchange,GatewayFilterChainchain){URIoriginalUri=()();ServerHttpRequestrequest=();=();StringforwardedUri=()();if(forwardedUri!=null&&(https)){try{URImutatedUri=newURI(http,(),(),(),(),(),());(mutatedUri);}catch(Exceptione){thrownewIllegalStateException((),e);}}ServerHttpRequestbuild=();ServerWebExchangewebExchange=()(build)();(webExchange);}@OverridepublicintgetOrder(){returnHTTPS_TO_HTTP_FILTER_ORDER;}}

这样子我们就可以使用gateway来卸载https请求了,到目前为止,我们的基本框架已经搭建完毕,网关既可以转发https请求,也可以转发wss请求。 接下来就是用户多对多之间session互通的通讯解决方案了。 接下来,我将根据方案的优雅性,从最不优雅的方案开始讲起。

session广播

这是最简单的websocket集群通讯解决方案。场景如下:

教师A想要群发消息给他的学生们

教师的消息请求发给网关,内容包含{我是教师A,我想把xxx消息发送我的学生们}

网关接收到消息,获取集群所有ip地址,逐个调用教师的请求

集群中的每台服务器获取请求,根据教师A的信息查找本地有没有与学生关联的session,有则调用sendMessage方法,没有则忽略请求

session广播实现很简单,但是有一个致命缺陷:计算力浪费现象,当服务器没有消息接收者session的时候,相当于浪费了一次循环遍历的计算力,该方案在并发需求不高的情况下可以优先考虑,实现很容易。

spring cloud中获取服务集群中每台服务器信息的方法如下

@ResourceprivateEurekaClienteurekaClient;Applicationapp=(service-name);//instanceInfo包括了一台服务器ip,port等消息InstanceInfoinstanceInfo=()(0);(ipaddress:+());

服务器需要维护关系映射表,将用户的id与session做映射,session建立时在映射表中添加映射关系,session断开后要删除映射表内关联关系

一致性哈希算法实现(本文的要点)

这种方法是本人认为最优雅的实现方案,理解这种方案需要一定的时间,如果你耐心看下去,相信你一定会有所收获。 再强调一次,不了解一致性哈希算法的同学请先看这里,现先假设哈希环是顺时针查找的。

首先,想要将一致性哈希算法的思想应用到我们的websocket集群,我们需要解决以下新问题:

集群节点DOWN,会影响到哈希环映射到状态是DOWN的节点。

集群节点UP,会影响到旧key映射不到对应的节点。

哈希环读写共享。

在集群中,总会出现服务UP/DOWN的问题。

针对节点DOWN的问题分析如下:

一个服务器DOWN的时候,其拥有的websocket session会自动关闭连接,并且前端会收到通知。 此时会影响到哈希环的映射错误。 我们只需要当监听到服务器DOWN的时候,删除哈希环上面对应的实际结点和虚结点,避免让网关转发到状态是DOWN的服务器上。

实现方法:在eureka治理中心监听集群服务DOWN事件,并及时更新哈希环。

针对节点UP的问题分析如下:

现假设集群中有服务 CacheB上线了,该服务器的ip地址刚好被映射到key1和 cacheA之间。 那么key1对应的用户每次要发消息时都跑去 CacheB发送消息,结果明显是发送不了消息,因为 CacheB没有key1对应的session。

此时我们有两种解决方案。

方案A简单,动作大:

eureka监听到节点UP事件之后,根据现有集群信息,更新哈希环。 并且断开所有session连接,让客户端重新连接,此时客户端会连接到更新后的哈希环节点,以此避免消息无法送达的情况。

方案B复杂,动作小:

我们先看看没有虚拟节点的情况,假设 CacheC和 CacheA之间上线了服务器 CacheB。 所有映射在 CacheC到 CacheB的用户发消息时都会去 CacheB里面找session发消息。 也就是说 CacheB一但上线,便会影响到 CacheC到 CacheB之间的用户发送消息。 所以我们只需要将 CacheA断开 CacheC到 CacheB的用户所对应的session,让客户端重连。

接下来是有虚拟节点的情况,假设浅色的节点是虚拟节点。 我们用长括号来代表某段区域映射的结果属于某个 Cache。 首先是C节点未上线的情况。 图大家应该都懂吧,所有B的虚拟节点都会指向真实的B节点,所以所有B节点逆时针那一部分都会映射到B(因为我们规定哈希环顺时针查找)。

接下来是C节点上线的情况,可以看到某些区域被C占领了。

由以上情况我们可以知道:节点上线,会有许多对应虚拟节点也同时上线,因此我们需要将多段范围key对应的session断开连接(上图红色的部分)。 具体算法有点复杂,实现的方式因人而异,大家可以尝试一下自己实现算法。

哈希环应该放在哪里?

gateway本地创建并维护哈希环。 当ws请求进来的时候,本地获取哈希环并获取映射服务器信息,转发ws请求。 这种方法看上去不错,但实际上是不太可取的,回想一下上面服务器DOWN的时候只能通过eureka监听,那么eureka监听到DOWN事件之后,需要通过io来通知gateway删除对应节点吗?显然太麻烦了,将eureka的职责分散到gateway,不建议这么做。

eureka创建,并放到redis共享读写。 这个方案可行,当eureka监听到服务DOWN的时候,修改哈希环并推送到redis上。 为了请求响应时间尽量地短,我们不可以让gateway每次转发ws请求的时候都去redis取一次哈希环。 哈希环修改的概率的确很低,gateway只需要应用redis的消息订阅模式,订阅哈希环修改事件便可以解决此问题。

至此我们的spring websocket集群已经搭建的差不多了,最重要的地方还是一致性哈希算法。现在有最后一个技术瓶颈,网关如何根据ws请求转发到指定的集群服务器上?

答案在负载均衡。 spring cloud gateway或zuul都默认集成了ribbon作为负载均衡,我们只需要根据建立ws请求时客户端发来的user id,重写ribbon负载均衡算法,根据user id进行hash,并在哈希环上寻找ip,并将ws请求转发到该ip便完事了。 流程如下图所示:

接下来用户沟通的时候,只需要根据i

“TMF”指代“跟踪消息格式”时的英文全称是什么?

英语缩写词TMF,全称为Trace Message Format,在中文中被翻译为跟踪消息格式。 这个术语主要用于描述在计算机和网络领域中,用于追踪和记录消息传输过程的标准化格式。 根据数据,TMF的拼音为gēn zōng xiāo xi gé shì,其在英文中的流行度达到了4910次,表明在相关领域中得到了广泛的应用。 TMF属于Computing(计算机)领域的缩写词,主要应用于驱动程序或其他需要监控和追踪消息传递情况的软件或系统中。 例如,网络监控工具、故障排查或数据包分析中,经常会使用到TMF格式来记录和分析消息的发送和接收过程。 请注意,虽然TMF的信息源自网络,主要用于学习和交流,但版权仍归原作者所有。 在使用时,应确保遵守相关使用规定,以避免潜在风险。 以上是对TMF的详细解释和应用背景。

BPM是什么?联科软件的BPM流程管理平台怎么样?

联科BPM是一个开放的、稳建的、可扩展的、易维护的、可支撑大用户量的核心架构平台,此平台将可以承担企业未来十年或更长时间因为业务发展需要而进行的业务功能及需求调整而导致的IT系统变化,在业务变化的过程中Linkey BPM能及时灵活的响应需求而不必进行大量的系统改造。 Linkey BPM业务流程管理平台首先是一个易于维护的平台,维护可以分为两种权限及类型进行划分,一种是最高系统权限的用户,其具有完全业务系统维护功能如业务规则编写、数据维护、系统插件及补丁部署、系统运行状况检查及统计、高级权限调整等工具,此类维护需要具有一定的业务技能且对Lotus Domino和基础平台都比较了解的IT人员。 另一种是各部门的普通系统管理员,他们可以进行流程及表单的设计、监控、分析、自定义报表、用户注册、权限分配、业务模块维护等日常级别的维护工作。 Linkey BPM业务流程管理平台可以严格控制这两类用户权限的分配并做到数据和系统的绝对安全,在设计上能够提供两套不同类别的系统维护入口且简单易用,从而大大降低系统的维护成本和维护工作量及参与维护的工程师数量。 Linkey BPM业务流程管理平台能够无缝集成其他业务系统(HR、BI、SAP、FC)及数据库(SQL、Oracle、DB2),当有新的业务系统需要集成时企业的IT人员应能够通过编写简单的业务规则(业务规则可以使用LotusScript或者是Java进行编写)即可以进行业务系统的集成,且这些业务规则可以进行复用也可以导出到其他同样使用此基础平台的其他关联单位使用,这样业务规则只需要编写一次即可以运行在多个单位的BPM系统中。 Linkey BPM业务流程管理平台集成其他业务系统的同时要能被其他业务系统所集成,Linkey BPM业务流程管理平台提供了完善的WebService、HTTP的API接口,以便其他系统能够很方便的驱动和读取Linkey BPM业务流程管理平台的数据及系统运行状况,特别是对于业务流程的集成方面其他业务系统要能够很方便的启动、状态查询、暂停、恢复等基础平台中的业务流程的相关信息。 当企业的业务需求发生变化需要新的API接口时,企业自有的IT人员要能很方便的在BPM平台上增加新的API接口而不需要修改底层的系统架构。

标签: 接收 回复等消息相关的数据 消息分析 分析消息发送

抱歉,评论功能暂时关闭!