深入connector

2024-05-09 07:18
文章标签 深入 connector

本文主要是介绍深入connector,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在与客户端通信的时候,pomelo目前提供了hybridconnector和sioconnector,其中hybridconnector支持tcp,websocket;sioconnector支持socket.io。但是实际编程中,只有这些connector可能还无法满足我们的需求,我们可能需要自己定制自己的connector,pomelo提供了定制connector的接口,在这部分就是要说明这个问题。

内建的connector分析

pomelo内建的connector包括sioconnector和hybridconnector,这里以sioconnector为例来分析,说明如何实现一个connector。
首先sioconnector的构造函数里需要三个参数host、port、opts,(host,port)是要监听socket绑定的,在sioconnector的start调用中,会开启对应的监听,并使得当有连接事件发生时,能够将连接事件抛出。抛出连接事件的时候,对应的通信socket是SioSocket。SioSocket的事件中,当客户端主动断开连接时,需要触发disconnect事件,当通信出现错误时,触发error事件,当有消息获得的时候触发message事件。当收到客户端的请求message或者需要给客户端发送回应或者推送消息的时候,pomelo会使用connector的decode函数对数据进行解码。对于客户端请求的消息,其上报到应用层的格式应为:


{ id : <requestId>,route: <handlerRoute>,body:  <requestBody>
}
  • 这里id是客户端请求的requestId,这个数值由客户端产生的,因此不同session的请求id是互相不干涉的。如果不是请求,只是一个notify的话,id值为空。route是对应应用服务器的请求位置,格式为".."。body为具体请求时携带的参数信息,当我们发起filter-handler链对请求进行处理的时候,参数msg就是这里的body值,是在这里产生的。

  • 对于服务器端给客户端的响应或者服务器端的推送消息,会使用connector的encode进行编码,编码函数的签名为:

    encode(reqId, route, msg);

其中,如果是响应的话,reqId是对应的请求id,route为请求携带的route,实际上可以省略,msg会具体的相应内容;

  • 如果是推送消息的话,reqId为空值,route为客户端的route,也就是"on"这种格式。其返回值应该是能被socket发送的缓冲区。

  • decode/encode函数还可以通过配置选项opts来进行配置,如果在opts里指定了encode/decode,那么将会优先使用opts中指定的encode/decode。

  • connector还应实现stop方法,对于sioconnector来说,其stop方法里面关闭了监听socket连接。

经过对sioconnector的分析,我们完成了pomelo中connector的抽象。

connector抽象

在涉及到客户端与服务器端进行通信的时候,往往都会使用类似与tcp服务器客户端通信的模式,我们的connector抽象也不例外。在这里,我们假定要实现一个FooConnector,看看需要实现些什么。

  • 首先需要一个FooConnector,FooConnector的构造函数需要一些自己的参数,这些参数要包括创建一个连接监听所需要的所有信息,当然比较经典的参数信息是(host,port)对,但是对于一些比较特殊的connector来说,其连接监听所需要的信息可能就不是(host,port)对了,比如用于本地通信的share memory以及命名管道等。

  • FooConnector需要实现一个start函数,在这个start函数中,会启动对连接的监听,最经典的操作应该是listen调用。当然在具体实现一些比较特殊的connector的时候,可能不会是listen调用。start中还应该对实现当有连接到来的时候,触发connector的connection事件,对应经典实现的accept返回,当然是异步的触发。在触发connection事件的时候,应该传出参数FooSocket。

  • FooSocket是FooConnector触发connection事件时传出的参数,可以类比经典tcp通信中,accept返回的用于通信的socket。当FooSocket出现通信错误时,触发error事件;当遇到客户端主动断开连接时,应该触发事件disconnect;当收到客户端传来的消息时,应该能够触发message事件,message事件携带的参数为FooBuffer类型。

  • FooBuffer类型可以类比经典tcp通信中的byte数组,在javascript中,FooBuffer一般为string或者Buffer类型,当然用户也可以定制自己的类型。需要注意的每一次message事件的触发,携带的都应该是一个完整的包,不能出现半包以及粘包,用户的connector实现要保证这一点。当然,只有类似与tcp这样的流协议的时候才可能出现半包粘包的问题,一些基于数据报的协议是不会出现这种问题的。

  • Connector还需要提供一个decode函数,这个decode函数的参数为上面FooSocket的message事件携带的FooBuffer,这个decode函数应该能够把这个FooBuffer解码成具体的应用层能够直接使用的请求对象,也就是说decode函数的返回值应该为如下格式的对象:

{id: <requestId>,route: <handlerRoute>,body: <requestBody>
}
  • 当服务端向用户发起消息推送或者响应的时候,Connector应该提供encode函数,完成具体的打包操作,Connector提供的encode函数签名应该为:

    encode(reqId, route, body);

encode函数的返回值类型为FooBuffer,也就是FooSocket可以处理的类型,encode完成用户的请求数据的打包。如果是服务端推送数据的话,reqId的值应该为空。

  • 由于我们自己定义了encode/decode函数,因此我们可以设计实现我们自己的线上协议,只要在应用层抛数据的时候保持一致即可。

  • 当具体发送打包后的数据时,需要FooSocket提供一个发送方法send,send的参数就是encode打包后的FooBuffer,其签名为:

    send(FooBuffer);

  • 在具体实现数据往客户端发送的时候,有时候并不是一旦数据产生就往外发出,而是会先缓存,定时发送数据,这样对于大量小包产生的场景,将会带来很大的性能提升。因为产生的很多小包,可以批量发出,因此FooSocket还要支持批量发消息,对应的函数签名为:

    sendBatch(FooBufferArray);

一般来说,对于底层协议是二进制协议的话,在打包的时候由于已经定义了包边界,因此当有多个包的FooBuffer要发出的时候,只需要将所有的Buffer打包成一个大的Buffer就可以了,hybridconnector中就是这样实现的。而在sioconnector中,因为其底层协议使用的json,因此其将这些消息组成了一个json数组,具体可以参考它们对应的实现。我们在实现FooSocket的sendBatch方法时,可以根据具体的实际情况进行实现,其语义就是一次批量发送多个包。

  • FooSocket还应该有主动断开连接的方法disconnect,用于当服务器想把某个用户kick掉的时候调用。

  • 当最后应用程序关闭的时候,FooConnector需要提供stop方法,用来关闭相应的连接监听,可以类比tcp服务器中最后关闭用来监听的socket。

  • 综上所述,我们得出与定制Connector相关的类图,如下:

在这里插入图片描述

  • 在app.js中,如果我们的FooConnector的构造函数使用的绑定地址信息是(host,port)对的话,我们通过如下的调用,启用我们自己定制的connector:

app.set('connectorConfig', {connector: FooConnector,encode : <encode func>, //optionaldecode : <decode func>, //optionalothers: <others>});

这里需要指出,通过opts配置的encode/decode会优先使用,如果没有通过opts配置encode/decode的话,将会使用connector配置的encode/decode,如果既没有配置encode/decode,又没有对connector实现decode/encode,将会出现错误。这里的connector配置项使用的是FooConnector的构造函数,当pomelo构造connector时,如果发现配置的是一个构造函数的话,会按如下的方式进行构造:

new FooConnector(host, clientPort, opts);

如果定制的FooConnector的构造的时候使用的地址信息不是(host,port),那么你就不能使用这种方式进行配置,你可以使用如下方式进行配置:


var conn = new FooConnector(<addr_args>, opts);app.set('connectorConfig', {connector: conn,// ....
});

小结

在本部分,阐述了如何实现自定义connector,给出了connector的抽象,介绍了当实现一个全新的connector的时候应该需要实现的内容。pomelo对于connector的实现是完全开放的,用户可以根据自己的需求定制connector,定制自己的通信协议,只要自己的客户端与服务端线上协议保持一致就行了。

这篇关于深入connector的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理 秒杀系统是应对高并发、高压力下的典型业务场景,涉及到并发控制、库存管理、事务管理等多个关键技术点。本文将深入剖析秒杀商品业务中常见的几个核心问题,包括 AOP 事务管理、同步锁机制、乐观锁、CAS 操作,以及用户限购策略。通过这些技术的结合,确保秒杀系统在高并发场景下的稳定性和一致性。 1. AOP 代理对象与事务管理 在秒杀商品

深入探索嵌入式 Linux

摘要:本文深入探究嵌入式 Linux。首先回顾其发展历程,从早期尝试到克服诸多困难逐渐成熟。接着阐述其体系结构,涵盖硬件、内核、文件系统和应用层。开发环境方面包括交叉编译工具链、调试工具和集成开发环境。在应用领域,广泛应用于消费电子、工业控制、汽车电子和智能家居等领域。关键技术有内核裁剪与优化、设备驱动程序开发、实时性增强和电源管理等。最后展望其未来发展趋势,如与物联网融合、人工智能应用、安全性与

PostgreSQL中的多版本并发控制(MVCC)深入解析

引言 PostgreSQL作为一款强大的开源关系数据库管理系统,以其高性能、高可靠性和丰富的功能特性而广受欢迎。在并发控制方面,PostgreSQL采用了多版本并发控制(MVCC)机制,该机制为数据库提供了高效的数据访问和更新能力,同时保证了数据的一致性和隔离性。本文将深入解析PostgreSQL中的MVCC功能,探讨其工作原理、使用场景,并通过具体SQL示例来展示其在实际应用中的表现。 一、

PHP: 深入了解一致性哈希

前言 随着memcache、redis以及其它一些内存K/V数据库的流行,一致性哈希也越来越被开发者所了解。因为这些内存K/V数据库大多不提供分布式支持(本文以redis为例),所以如果要提供多台redis server来提供服务的话,就需要解决如何将数据分散到redis server,并且在增减redis server时如何最大化的不令数据重新分布,这将是本文讨论的范畴。 取模算法 取模运