(转)openfire源码学习之十:连接管理(上)

wangle100 wangle100     2022-09-09     524

关键词:

转:http://blog.csdn.net/huwenfeng_2011/article/details/43415827

关于连接管理分为上下两部分

 

连接管理

 

在大并发环境下,连接资源 需要随着用户并发访问量的增加而增加,所以可伸缩的连接资源就是支持大访问量的关键技术。openfire系统通过增加独立部署的连接管理器程序提高并发的能力,连接管理的前端是一台负载均衡设备,它负责把用户访问分配到指定连接管理器,多台连接管理器在访问服务器。使用连接管理器后,服务器的连接池是提供给连接管理器连 接,而一台连接管理器也提供指定数量的连接给客户端访问,这样通过添加连接管理器,以适应用户访问量。

 

技术分享

 

l 它是啥?

你部署的每个openfire连接管理单元,依靠处理一部分客户端连接,来提高openfire服  务器的容量。它适用于大规模的openfire安装(几千的在线用户)。

 

l 每个连接管理能够处理多少用户呢?

每个连接管理应该只是能够处理5000的在线用户。对于无绑定的实验性支持正在被提  高,用以更多的提高每个连接管理单元所能处理的连接数量。

 

l 连接管理可以被用在其他服务器上吗?

当然(理论上)。连接管理协议正在通过开放的XEP处理来提高。我们希望和其他服务 器供应商一起协作,以便全部的XMPPP/Jabber协会支持这个协 议。我们同样期望会       有其他的兼容openfire的连接管理实现。例如,一个用本地代码编写的连接管理可以在       一个特殊的平台上达到一个非常高的容量。

 

l openfire连接管理用的许可和openfire本身一样吗?

当然,这个模块是是在开源GPL下的dual-licensed,或者是Jive Software同意授权的一 个商业软件许可。

连接配置

Of配置Connection Manager——So easy!

第一步:服务器设置

        在服务器设置/连接管理中,将连接管理设置为启动。并设置端口号和密码。如图

技术分享

 

第二步:配置manager.xml文件

    配置<domain>xxxx</domain>节点,这里面的内容为of服务器域名

    配置<password></password>节点,这里密码填写在控制台的密码。

 

第三步:启动连接管理器

       找到connection_managerin目录下的cmanager.bat(windows环境)文件点击启动。          如图:

        启动完后,在of控制台将出现如图信息:

技术分享

 

第四步:测试连接

       使用Spark登陆连接管理器,如果配置成功,控制台“客户端回会话”值将变为“1”

技术分享

 

Connection

 

Connection是一个接口代表在服务器上的一个连接。该接口的主要方法:

方法名

说明

validate

验证连接,通常这样做是通过发送一个数据包之间的空格字符。

init

初始化会话连接,允许连接类与会话相关信息配置

deliver

发送数据包

deliverRawText

发送文本字节

类图:

技术分享

 

 

Connection接口下面有三个实现类:NIOConnection、SocketConnection、VirtualConnection。其中VirtualConnection是个抽象接口,而它又派生两个子类:

ClientSessionConnection、HttpVirtualConnection。

NIOConnection

该类中最为常用的方法是deliver()。

代码清代:

[java] view plain copy
 
  1. public void deliver(Packet packet) throws UnauthorizedException {  
  2.         if (isClosed()) {  
  3.             backupDeliverer.deliver(packet);  
  4.         }  
  5.         else {  
  6.             ByteBuffer buffer = ByteBuffer.allocate(4096);  
  7.             buffer.setAutoExpand(true);  
  8.   
  9.             boolean errorDelivering = false;  
  10.             try {  
  11.                 XMLWriter xmlSerializer =  
  12.                         new XMLWriter(new ByteBufferWriter(buffer, encoder.get()), new    
  13.                                                     OutputFormat());  
  14.                 xmlSerializer.write(packet.getElement());  
  15.                 xmlSerializer.flush();  
  16.                 if (flashClient) {  
  17.                     buffer.put((byte) ‘‘);  
  18.                 }  
  19.                 buffer.flip();  
  20.                 ioSession.write(buffer);  
  21.             }  
  22.             catch (Exception e) {  
  23.                 Log.debug("NIOConnection: Error delivering packet" + " " + this.toString(), e);  
  24.                 errorDelivering = true;  
  25.             }  
  26.            。。。。。。。  
  27.         }  
  28.     }  

该方法中用了Mina框架的字节缓冲类ByteBuffer。ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer。

 

1.创建ByteBuffer

  ByteBufferbuffer = ByteBuffer.allocate(4096);

  以上方法将创建一个容量为4096字节的ByteBuffer,如果发现创建的缓冲区容量太小,

  唯一的选择就是重新创建一个大小合适的缓冲区。

 

2.设置自动扩张,of在这里设置了true

  buffer.setAutoExpand(true);

 

3.回绕缓冲区
   buffer.flip();
   这个方法用来将缓冲区准备为数据传出状态,执行以上方法后,输出通道会从数据的开头  

   而不是末尾开始。回绕保持缓冲区中的数据不变,只是准备写入而不是读取。

ConnectionManager

Openfire Connection Manager是Openfire服务器的扩展,它可以透明的处理大规模并发XMPP客户端对Openfire服务器的联接。根据Connection Manager主页介绍,每个Connection Manager可以处理至少五千个并发用户。Openfire服务器可以连接一个或多个Connection Manager。每个Connection Manager可以处理一个或多个支持XMPP的客户端。为Openfire配置Connection Manager后,支持XMPP的客户端仅需要连接Connection Manager,由Connection Manager负责管理对来自XMPP客户端对Openfire服务器的连接。

连接管理的端口说明:

5222

默认端口为客户XMPP。这个端口可以用于担保和无担保的连接。客户将首先使用一个未加密的连接,连接可能安全使用StartTLS。

5223

Jabbe默认SSL通行遗留的端口。这个老方法,很快被弃用,使用加密的连接就被创建。

5275

默认的XMPP端口外部组件。

5269

默认端口为服务端对服务端的 XMPP通信。

5262

默认XMPP连接多路传输端口

管理流程

1. 打开 Openfire Admin Console

2. 点击 Server 选项卡下面的 Server Settings 页面

3. 点击左侧的 Connection Managers 页面

4. 选择 Enable 单选按钮以打开 Connection Manager 监听服务

5. 设置 password 。例如, 123 。

技术分享

 

通过以上配置,完成了开启 Openfire 监听Connection Manager 服务。下面是对连接管理的源码分析。

通过控制台页面connection-managers-settings.jsp,会调用如下两个方法来启动连接管理:

步骤一:connectionManager.enableConnectionManagerListener(true); 

         这是一个启动服务端对服务端通信的端口侦听器:

         1.设置xmpp socket有效值true.

           JiveGlobals.setProperty("xmpp.multiplex.socket.active",                                          "true");

         2.创建连接管理的监听程序createConnectionManagerListener()

[java] view plain copy
 
  1. private void createConnectionManagerListener() {  
  2.         // Start多路复用器soket  
  3.         if (isConnectionManagerListenerEnabled()) {  
  4.             // Create SocketAcceptor with correct number of processors  
  5.             multiplexerSocketAcceptor = buildSocketAcceptor();  
  6.             // Customize Executor that will be used by processors to process incoming stanzas  
  7.             ExecutorThreadModel threadModel = ExecutorThreadModel.getInstance("connectionManager");  
  8.             int eventThreads = JiveGlobals.getIntProperty("xmpp.multiplex.processing.threads", 16);  
  9.             ThreadPoolExecutor eventExecutor = (ThreadPoolExecutor) threadModel.getExecutor();//固定大小线程池  
  10.             eventExecutor.setCorePoolSize(eventThreads + 1);  
  11.             eventExecutor.setMaximumPoolSize(eventThreads + 1);  
  12.             eventExecutor.setKeepAliveTime(60, TimeUnit.SECONDS);  
  13.             multiplexerSocketAcceptor.getDefaultConfig().setThreadModel(threadModel);  
  14.             // Add the XMPP codec filter  
  15.             multiplexerSocketAcceptor.getFilterChain().addFirst("xmpp", new ProtocolCodecFilter(new XMPPCodecFactory()));  
  16.   
  17.         }  

    3.启动连接管理的监听程序    

步骤二:connectionManager.setConnectionManagerListenerPort(port);

        设置启动监听端口

 

ConnectionManagerImpl

ConnectionManager声明了五种连接:client、clientssl、external component、other server、connectionmanager,它们有各自的端口并且可禁用。ConnectionManagerImpl创建多个SocketAcceptor监听各个端口,并绑定不 同的ConnectionHandlerOpenfire连接管理配置服务端配置步骤。

创建监听的方法:

[java] view plain copy
 
  1. private synchronized void createListeners() {  
  2.         if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null)  
  3.         {  
  4.             return;  
  5.         }  
  6.         //创建s2s通信端口监听  
  7.         createServerListener(localIPAddress);  
  8.         // 创建连接管理监听  
  9.         createConnectionManagerListener();  
  10.         // 创建外部组件监听  
  11.         createComponentListener();  
  12.         // 创建客户端监听  
  13.         createClientListeners();  
  14.         // 创建SSL监听  
  15.         createClientSSLListeners();  
  16.     }  

启动监听的方法:

[java] view plain copy
 
    1. private synchronized void startListeners() {  
    2.         if (isSocketStarted || sessionManager == null || deliverer == null || router == null || serverName == null) {  
    3.             return;  
    4.         }  
    5.   
    6.         // 检查插件是否被加载  
    7.         PluginManager pluginManager = XMPPServer.getInstance().getPluginManager();  
    8.         if (!pluginManager.isExecuted()) {  
    9.             pluginManager.addPluginManagerListener(new PluginManagerListener() {  
    10.                 public void pluginsMonitored() {  
    11.                     // 停止插件监听事件  
    12.                     XMPPServer.getInstance().getPluginManager().removePluginManagerListener(this);  
    13.                     // 启动监听  
    14.                     startListeners();  
    15.                 }  
    16.             });  
    17.             return;  
    18.         }  
    19.   
    20.         isSocketStarted = true;  
    21.   
    22.         // Setup port info  
    23.         try {  
    24.             localIPAddress = InetAddress.getLocalHost().getHostAddress();  
    25.         }  
    26.         catch (UnknownHostException e) {  
    27.             if (localIPAddress == null) {  
    28.                 localIPAddress = "Unknown";  
    29.             }  
    30.         }  
    31.         // 启动s2s端口监听  
    32.         startServerListener();  
    33.         // 启动连接管理端口监听  
    34.         startConnectionManagerListener(localIPAddress);  
    35.         // 启动外部组件监听  
    36.         startComponentListener();  
    37.         // 启动客户端监听  
    38.         startClientListeners(localIPAddress);  
    39.         // 启动SSL监听  
    40.         startClientSSLListeners(localIPAddress);  
    41.         // 启动http监听  
    42.         startHTTPBindListeners();  
    43. }  

(转)openfire源码学习之十五:插件开发

...csdn.net/huwenfeng_2011/article/details/43418493Plugin接口规范插件是openfire功能的增强表现,它的主要任务:l  在XMPP协议中作为附加功能实现l  动态修改控制管理台l  使用openfireapi作为新功能添加到服务器Openfire里面... 查看详情

(转)openfire源码学习之六:用户注册

转:http://blog.csdn.net/huwenfeng_2011/article/details/43413509用户注册注册流程:1、客户端进行握手给服务端发送连接消息: [html] viewplain copy <stream:stream to="192.168.2.104" xmlns="jabber:clien 查看详情

(转)openfire源码学习之四:openfire的启动流程

转:http://blog.csdn.net/huwenfeng_2011/article/details/43413233openfire启动ServerStarter启动流程图: 启动的总入口在ServerStarter的main方法中。通过上图首先它会先加载它所需要的jar文件。最后通过Java反射机制将XMPPServer加入当前线程。 [j... 查看详情

flink学习之十一-window&eventtime实例(代码片段)

上面试了ProcessingTime,在这里准备看下EventTime,以及必须需要关注的,在ET场景下的Watermarks。EventTime&WatermarkEventtimeprogramsmustspecifyhowtogenerateEventTimeWatermarks,whichisthemechanismthatsignalsprogressineventtime.以e 查看详情

源码学习之spring容器创建原理

1前言众所周知,Spring可以帮我们管理我们需要的bean。在我们需要用到这些bean的时候,可以很方便的获取到它,然后进行一系列的操作。比如,我们定义一个beanMyTestBeanpublicclassMyTestBeanprivateStringtestStr="testStr";publicStringgetTestStr()ret... 查看详情

laravel源码学习之container

Ioc模式Ioc(InversionofControl)模式又称依赖注入(DependencyInjection)模式。控制反转就是将组件之间的依赖关系从程序的内部转移到程序外部,而依赖注入是指组件的依赖关系通过外部参数或其他形式注入,两种说法从本质上是一样的。... 查看详情

tensorflow深度学习之十二:基础图像处理之二

Tensorflow深度学习之十二:基础图像处理之二from:https://blog.csdn.net/davincil/article/details/76598474 首先放出原始图像:1、图像的翻转importtensorflowastfimportcv2#这里定义一个tensorflow读取的图片格式转换为opencv读取的图片格式的函数#请... 查看详情

hadoop-2.4.1学习之map任务源码分析(上)(代码片段)

    众所周知,Mapper是MapReduce编程模式中最重要的环节之一(另一个当然是Reducer了)。在Hadoop-2.x版本中虽然不再有JobTracker和TaskTracker,但Mapper任务的功能却没有变化,本篇文章将结合源代码深入分析Mapper任务时如... 查看详情

谈谈源码管理那点事儿——源码管理十诫(转)

...言: 若是还有能够毫无偏见地涉及各个编程语言。比源码管理软件更必要的工具。我倒是非常想见识一下。源码管理软件是我们工作的必备工具,是很多开发团队的血液。那为什么我们都会对它有所误解呢?为什么都非常难... 查看详情

gui学习之十九——qfontcombobox学习总结(代码片段)

我们上一章学习了QComboBox的用法,这一章我们来看一下它的一个比较常用的子类:QFontComboBox()。一.描述:  QFontComboBox()是QComboBox()的一个子类,但是它的内容是不能被编辑的,主要是用来选择字体。二.功能作用  1.设置和获... 查看详情

gui学习之十四——qabstractspinbox学习总结(代码片段)

QAbstractSpinBox是一个抽象类,是将所有步长调节器的通用的功能抽象出了一个父类。虽然QAbstractSpinBox是一个抽象类,但是可以直接实例化使用。QAbstractSpinBox包含了一个QLineEdit和两个QPushbutton。数据的更改可以通过点击按钮或使用... 查看详情

hadoop-2.4.1学习之map任务源码分析(下)(代码片段)

    在Map任务源码分析(上)中,对MAP阶段的代码进行了学习,这篇文章文章将学习Map任务的SORT阶段。如果Reducer的数量不为0,则还需要进行SORT阶段,但从上面的学习中并未发现与MAP阶段执行完毕调用mapPhase.complete... 查看详情

html学习之十三(导航栏的制作)(代码片段)

<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>导航效果</title><styletype="text/css">.tab-itemlist-style:none;font-family:"宋体";font-size:18px;text-decorat 查看详情

ffmpeg4.1源码学习之-转封装(代码片段)

前言ffmpeg的源码量非常的多,而且非常繁杂,非常多的函数,如果一个函数一个函数看的话要花费比较多的时间。所以本文通过跟踪ffmpeg转封装的过程来学习ffmpeg的源码具体转封装的命令:ffmpeg-i1_cut.flv-ccopy-fmp41.m... 查看详情

(转)机器学习之svd分解

一、SVD奇异值分解的定义  假设是一个的矩阵,如果存在一个分解:其中为的酉矩阵,为的半正定对角矩阵,为的共轭转置矩阵,且为的酉矩阵。这样的分解称为的奇异值分解,对角线上的元素称为奇异值,称为左奇异矩... 查看详情

牛耕田学习之管理磁盘分区

首先呢,在耕田学习机上添加一块虚拟的硬盘然后就达到这个效果出现新硬盘 硬盘2 好了我们去Xshell连接耕田学习机在root用户下用fdisk-l看看什么情况好 我们看到了sda已经分好了sda1是引导区我们添加的sdb就是硬盘2&nbs... 查看详情

数据库学习之十四:读写分离atlas架构(代码片段)

十四、读写分离Atlas架构1、安装软件rpm-ivhAtlas-2.2.1.el6.x86_64.rpm2、修改配置cd/usr/local/mysql-proxy/vim/usr/local/mysql-proxy/conf/test.cnf[mysql-proxy]admin-username=useradmin-password=pwdproxy-backend-addresses=10. 查看详情

html学习之十六(表格与表单学习--课程表制作)(代码片段)

<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>课程表</title><style>table/*设置外部相关属性,不要设置内部属性*/width:500px;height:300px;border:3pxblacksolid;margin:100pxa 查看详情