框架分析--server、connector等组件与客户端通信

2024-05-09 07:18

本文主要是介绍框架分析--server、connector等组件与客户端通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这部分,主要介绍pomelo是如何与客户端通信以及前端服务器是如何处理用户请求的。处理客户端的请求和响应是pomelo的核心之一,它涉及到了很多组件,包括session组件,server组件,connection组件,connector组件,proxy组件,remote组件等。在本部分,我们仅仅介绍与前端服务器相关的组件,以及他们的作用,对于rpc以及后端服务器以来的backendSession以及channel,这里不做深入介绍,将在其他部分进行介绍。

对于前端服务器来说,session组件是sessionService的包装组件,用来维护用户的session信息;connection组件是connectionService的包装组件,是用来做连接统计的;connector组件会开启监听接口,承受客户端的连接,这里对connector组件底层使用的具体的connector不做太多关注,只关心其抽象行为。

对于server组件来说,会维护服务器的Handler和HandlerFilter,当用户的请求到达前端服务器时,如果前端服务器定义了相应的Handler,那么前端服务器会使用filter-handler链对其进行处理,然后将处理后的结果返回;如果对请求路由检查发现请求是发向到后端服务器的,那么前端服务器会根据用户配置的router(也可能是默认的),计算出要发往的后端服务器id,然后发起rpc调用,后端服务器在接收到rpc调用时,从其中取出请求路由以及请求参数,发起filter-handler链对请求进行处理,完成调用,并将响应发给前端服务器,前端服务器再将响应发送到客户端,整个处理流程如下如所示:

request-flow

下面的类图粗略地展示了这些类之间的关系:

在这里插入图片描述

下面通过类时序图的方式,选取典型的用例行为,来介绍框架的控制流程:

在这里插入图片描述

初始化
  • 在CoConnector的afterStart回调中,会开启socket的监听,端口使用服务器配置中的clientPort,然后就可以接受用户的连接了,并绑定了connctor的connection事件。

  • 在CoServer的start回调里,会扫描当前服务器应该加载的Handler和HandlerFilter,并完成Handler和Filter的加载。此时已经做好了接收客户端连接的准备。

客户端连接

当客户端连接到前端服务器时,会触发connector的监听事件,在事件的处理中,会通过CoConnection增加连接信息,用来做统计。会对连接返回的用来数据通信的socket绑定message,close,error,disconnect等事件,然后创建session,session由CoSession包装的SessionService维护。每一个session都会维护与其相关的socket。此时,客户端已经完成了与服务器端的连接。

客户端请求
  • 当客户端连接完成后,客户端就会发起请求,请求会触发socket的message事件,在此事件处理中,首先会对message事件所携带的包进行解包,然后将请求交给CoServer处理。如果请求的是前端服务器的Handler,那么CoServer的doHandle中将会发起其filter-handler链,完成请求的处理,最常见的这种请求就是用户登录请求。如果请求的路由不是前端服务器的,那么CoServer的doFoward将会发起sys rpc给相应的后端rpc。当发起sys rpc调用时,由于同类型的后端服务器一般都有很多,故需要做一个路由选择。这个路由选择策略用户可以配置,通过app.route调用,如果用户不配置的话,pomelo会使用一个默认的路由配置。后端服务器接受到请求后,会执行其CoServer的doHandle,跟前端服务器一样,会使用filter-handler链,对用户的请求进行处理,然后将响应返回给前端服务器,并由前端服务器将响应发送到客户端。

  • 前端服务器会调用connector的send函数将响应或者推送的消息发送给客户端,send调用不会直接将要发送的消息通过socket直接发送给客户端,而是将发送任务调度给CoPushScheduler,CoPushScheduler可以实现具体的发送策略。pomelo中提供了两种方式的pushScheduler,direct会立即将用户的响应发送给用户,buffer则会缓冲发送任务,并按时冲刷,pomelo默认使用的是direct的方式,如果想使用buffer的方式,可以通过如下的调用启用:

    app.set('pushSchedulerConfig', {scheduler: pomelo.pushSchedulers.buffer, flushInterval: 20});

这里,flushInterval是定时冲刷的周期,我们也可以自己定制实现相应的scheduler,并配置到应用程序中。

  • 当服务器的请求处理逻辑需要给客户端推送消息时,会通过用户的uid或者session id从SessionService里获得到对应的Session,session中会维护与客户端用来数据通信的socket,然后将要推送的数据通过session维护的socket连接发送到客户端。
绑定/解绑用户
  • 一般来说,当session连接完成后,都会有用户登录的请求,从而完成session与具体用户的绑定。一般在CoServer的处理中,当会将相应的用户绑定到session上,此时会调用CoSession包装的SessionService的操作bind完成对应的用户绑定操作。此外,还会调用CoConnection的addLoginedUser来增加用户,维护统计信息。

  • 对于用户注销的请求,一般在CoServer的处理中,会完成session与uid的解绑,此时会调用CoSession包装的SessionService的操作unbind完成对应用户的解绑操作。此外,还会调用CoConnection的removeLoginedUser来减少登录用户,维护统计信息。

客户端断开

当客户端断开连接时,connector监听的socket上会激发disconnect事件,在具体的事件处理中,会从SessionService中删除掉对应的Session,释放掉session维护的连接,还会调用ConnectionService上decreaseConnectionCount,维护统计信息。

上面选取了客户端与服务器交互的几个典型行为,说明了整个客户端请求中的控制流程。这里仅仅涉及到了前端服务器,对于后端服务器的具体处理,这里仅仅提到了会发起rpc调用,而没有具体地深入介绍。

Pomelo中的请求处理链

在pomelo中,HandlerFilter分为beforeFilter和afterFilter,对于beforeFilter来说,其方法签名为

before(msg, session, next);

其中msg是请求,session表示当前请求的session,在前端服务器的话是FrontendSession,在后端服务器的话是BackendSession,next是用来组成请求链的,是用来指定下一步调用的。如果在具体的filter上没有错误的话,那么就直接调用next(), 否则,则调用next(err, resp),向后面传递具体的处理错误以及响应。在filter的具体实现中,在逻辑处理完后,必须调用next,否则将打断整个处理链。如果有任意一个beforeFilter的next调用中传递了err的话,此处理链将会立即被中断,直接会转入错误处理。在next传递err的时候,可以携带一个resp参数,作为对客户端错误的响应,即next(err, resp)。

具体Handler的签名一般为:

<handler_Name>(msg, session, next);

msg是经过beforeFilter链处理过的msg,session是经过beforeFilter链处理后的session,next是下一步处理。如果需要给客户端响应的话,没有错误的话,使用next(null, resp),否则可以使用next(err, resp),向后面传递错误信息。这里,resp是给客户端的响应,一般来说客户端的响应都是在Handler的具体逻辑中生成。在具体Handler的实现中,也必须调用next。其next语义与前面的beforeFilter中的next语义一致。

对于afterFilter来说,其方法签名为:

after(err, msg, session, resp, next);

afterFilter是做一些清理操作的,在执行afterFilter链的时候,具体的响应已经发送给了客户端,也就是说在afterFilter如果对resp做更改的话,将对客户端响应没有任何影响。同样,这里的next参数,也是指定了下一步的处理,其签名是next(err),不过与上面beforeFilter和Handler不同的是,由于在afterFilter中常做的是一些清理操作,而且此时具体的响应resp已经发送到了客户端,所以afterFilter中,处理链对err将不再敏感,无论是否有err,整个afterFilter链都会执行完毕。

ErrorHandler,是当在处理请求时产生异常时进行的处理,具体的签名为:

<errorHandler_Name>(err, msg, resp, session, cb);

在beforeFilter或者Handler中,如果处理产生错误,那么将会转向错误处理,ErrorHandler就是用来进行错误处理的,具体的参数意义跟上面的一样,其中resp是由前面产生错误的next(err, resp)调用传递来的,cb的签名为cb(err, resp),cb会将resp发送给客户端。因此在ErrorHandler里面,是需要调用cb(err, resp), 否则,客户端将得不到服务器端的响应。在errorHandler中可以根据传入的resp以及err信息,重新生成要发送给客户端的resp。通过如下方式设置全局的ErrorHandler,

var errorHandler = require('<path');
app.set('errorHandler', errorHandler);

如果用户没有配置全局的errorHandler的话,默认的errorHandler会向客户端返回由beforeFilters或者Handler产生的resp。整个请求处理链的大致流程如下:

在这里插入图片描述

pomelo内建filter

pomelo内建了常见的一些filter,用户可以通过如下的方式启用:

app.filter(pomelo.filters.<filterName>(<args>));

下面介绍一下这几个fitler:

serial

这个filter是用来对用户请求做串行化的,可以使得用户的请求只有在第一个请求被处理完后,才会处理第二个请求。serial中使用了一个taskManager,当用户请求到来时,在beforeFilter中,将用户的请求放到taskManager中,taskManager中维护着一个task队列。在对应的afterFilter中,如果taskManager还有未处理的请求,将会处理其请求,即在一个请求的afterFilter里启动在taskManager中还没处理的下一个请求,这样就实现了请求的序列化。

timeout

这个filter是用来对服务端处理超时进行警告的,在beforeFilter中会启动一个定时器,在afterFilter中清除。如果在其定时器时间内,afterFilter被调用,定时器将会被清除,因此不会出现超时警告。如果定时器超时时,afterFilter还没有执行到,则会引发超时警告,并记录日志。默认的处理超时是3秒,可以在加载timeout的时候作为参数传入。

time

这个filter使用来记录服务器处理时间的,在beforeFilter中会记录一下当前的时间戳,在afterFilter中再次获取当前的时间戳,然后两个时间戳相减,得到整个处理时间,然后记录日志。

toobusy

这个filter中,一旦检测到node.js中事件循环的请求等待队列过长,超过一个阀值时,就会触发toobusy。一旦触发了toobusy,那么toobusy的filter中将终止此请求处理链,并在next调用中,传递错误参数。

总结

在本部分,介绍了前端服务器与客户端的通信的相关内容,讲述了相关的类关系,以及典型用例行为的控制流程。对于请求响应链中的before filter,handler,after fitler,error handler等做了较为详细的分析,最后简单分析了一下pomelo内建提供的一些filter。

这篇关于框架分析--server、connector等组件与客户端通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/972742

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud