关于guacamole项目中的一点感悟与理解

news2024/9/21 1:31:57

关于guacamole项目中的一点想法

  • 前言
  • 一、guacd模块启动相关
  • 二、一些感悟与理解
  • 参考

前言

Guacamole 是基于 Web 的 VNC 客户端,使用它可以通过web浏览器访问远程服务器终端并进行操作。它的基本架构如下图所示。

在这里插入图片描述

巧合之下,前段时间了解了项目中guacd模块有关的一些内容,重点关注的是这个模块启动过程中涉及网络IO、线程、进程的建立(网络并发模型)等,学习记录在此,希望可以便人便己。


一、guacd模块启动相关

整个guacd模块的启动比较复杂,下面画了一个简要的代码流程图(流程图中主要关注的是网络IO、进程、线程的建立),如下所示。
在这里插入图片描述

流程比较复杂,下面根据上图简要介绍下:

  1. guacd所在的main(假设所在进程为P0,线程也是T0)运行之后,会在打开一个监听端口,等待accep()连接到来;

  2. 当有连接到来之时,新建一个线程T1(对应的进程是P1)处理请求;然后T0接着accept;

  3. T1执行guacd_connection_thread(),在这个函数中判断连接请求是不是想加入原有的连接,还是建立新的连接。

    //蓝色右边部分:作为第一个进程,加载插件,然后建立工作进程

  4. 如果是新建连接,则会新建一个子进程P2;在P2中先通过动态链接的方式加载协议,之后阻塞在guacd_recv_fd()上,等待父进程P1(建立子进程后父进程P1返回继续执行原来的任务,执行guac_add_user())发送父子间通信的套接字端口proc_fd (这个proc_fd是用于IO线程和工作线程之间沟通用的);

  5. 若P2接收到了发送的P1proc_fd,会新建一个线程T3;在T3中执行guacd_user_thread. 在guacd_user_thread中是主要建立连接关系的一些操作,然后执行 guac_user_handle_connection()

  6. 在guac_user_handle_connection()中又新建了一个子线程T4(这算是工作线程);在T4中正式通过proc_fd和IO线程联系,循环处理客户端的请求。

    //红色左边部分:用于为每个请求建立IO线程(一个读线程、一个写线程)

  7. 在上述步骤3中,若请求是想加入一个已有的连接,则会跳过建立新进程的步骤;直接执行guacd_add_user();

  8. 在guacd_add_user()中会建立一个unix套接字用于父子进程通信,通过guacd_send_fd()发送给子进程(步骤3中的)

  9. 之后会新建io子线程T5,在io子线程中执行guacd_connection_io_thread();在guacd_connection_io_thread()中又会新建一个写线程T6, 用来从网络中读,然后写到客户端(即工作线程);T5线程当做读线程,从客户端(即工作线程)读数据,写入到网络中。

其基本的逻辑有两点需要说明:
 1、一个连接可以被多个用户共享(类似于分享屏幕),第一个建立这个连接的用户叫做这个连接的owner,逻辑会走一遍右边建立新进程的过程(需要加载动态库插件)。 后续想加入同一个连接的用户则不需要建立新的进程,只需要由owner所对应的进程建立工作线程即可。

 2、每个用户都会为其建立一组IO线程(读线程和写线程)和工作线程。其中前者主要是当做工作线程和网络之间的通信中介,其目的大概是提高整体的IO效率;后者的工作则主要是进行实际的业务处理。其基本关系如下图所示。

在这里插入图片描述

二、一些感悟与理解

  • 关于IO线程和工作线程

    在这里插入图片描述
    在guacamole中会为每个用户建立一组IO线程和工作线程。按照我目前所了解的,很多项目,尤其是涉及到网络IO的项目,其IO并发模型中大都会把用户的整个逻辑拆分为IO和实际的业务处理,对应由不同的线程进行处理。有必要吗?

    大部分情况下还是有必要的,尤其是对于并发量较大的web业务来说。按照我的理解分离IO线程和业务处理线程好处以下几点:
    (1)、一是可以在某种程度情况下,IO线程和业务线程并发处理(甚至可以利用多核的优点达到并行),使得业务线程在处理业务之时不影响IO(客户端的请求和回复),当然这也只是在一定程度上的,如果业务线程一直跟不上,IO线程再快,整体的服务质量也会下降。
    (2)、可以使用IO复用的机制,让IO线程同时处理多个连接的IO,或者使用以IO复用为基础的Reactor模式,大大提高系统的并发量。
    (3)、IO线程和业务线程解耦,在某些情况下可以方便的进行勘误或者性能调优,这一点我目前还没遇到过。

    当然把IO线程和业务线程分离也有一点不好的地方,由于把整个的业务逻辑(IO+具体对数据的处理)进行了拆分,因此在数据传递时会出现线程切换,造成一些性能损耗;在guacd中IO线程和工作线程分属于两个进程,切换的损耗还要更大些。

  • 关于IO复用
    在这里插入图片描述
    在很多现在的项目中都使用了IO复用的机制(epoll、select等),由多个连接共享一个IO线程。但是guacd这里用的就不是IO复用;它是给每个用户建立连接对应的一个IO读写线程和一个工作线程(应该是一个?),这种方式的话并发量可能不是很高,guacd为什么要这么设计呢?

    我想了想,大概是由于guacamole面向的大都是视频传输,传输的数据量都比较大,如果使用同一个线程来进行IO,会造成IO线程忙不过来的状况,倒不如使用每个连接一组IO线程的情形。这样说的话,选择什么样的IO并发模型也不是定数,还要根据具体的业务要求来进行判断。

  • 关于建立线程还是建立进程
    在这里插入图片描述
    线程和进程最主要的区别在我来看有两点,这两点分别是二者的优缺点:进程独立而切换慢,线程共享而切换快。在guacd中大部分逻辑都是建立的线程,但是在第一个owner建立连接的时候创建的是进程。

    按照我的理解是因为每个owner主管的连接所对应协议不尽相同,所需要加载的插件也不同,如果都是用线程的话,那么只能把所有用到的插件都加载到同一份进程空间中,大家一起共享了。虽然这么说理论说好像也可以,但这样的话占用的进程空间可能也比较了。 同时,所有的线程都放在一个进程中,逻辑上也有点混乱。

  • 关于同步
    我们以前学操作系统的时候知道线程、进程同步的一些机制,比如说条件变量、信号量等等。其实从某种程度上来说,使用IO的阻塞操作也可以达到同样的效果,如上图中的owner所在进程在等着父进程发送fd,也算是一种同步操作;再比如说,pthread_join,wait_pid这些等待子线程、子进程退出的操作,也能算作是一种同步手段。
    我的理解是,从本质上来说,这些手段底层都需要有共享的一个“东西”( 可以是阻塞中的fd,可以是信号量中的信号,也可以是条件变量中的变量等等),用来起到一个通知的作用。

  • 关于进程和线程
    什么是进程,什么是线程?在linux上线程也是一种进程。那么它们的本质是什么?

    是一种执行流。 新建了一个进程或者线程,就相当于开辟了一个新的执行流,让其他的执行流因为暂时阻塞的缘故,cpu可以选择另一个执行流,以此来增加cpu的利用率和系统整体的吞吐量。

  • 一点的不理解
    在这里插入图片描述

    最后,在来谈点不理解的内容吧。
    一般来说,根据运行时间长短,线程或者进程可分为两种,一种是长期任务,一种是短期任务;长期任务的生命周期一般由用户的进入与退出(连接的建立与断开、或者整个程序的开始与结束)来决定,一般主逻辑里都会有一个while{} 循环(如上图中的IO线程和工作线程);而短期的任务一般是临时的任务,执行完就结束了,一般不会有一直运行的循环操作(如上述guacd中的accpet之后建立的T1);

    我不懂的是,为什么在上述流程图中的owner所在进程主管的部分(右半黄色部分),在有用户想要加入已有的连接之后,需要创建两个线程T3、T4;代码中T3新建了T4之后,就一直在那join了(阻塞住了),反正也没用,为什么不直接用T3来当做工作线程处理整个逻辑呢?目前还不是很懂,有了解的小伙伴,可以教教我。


参考

【1】guacamole项目地址
【2】《真象还原》
【3】为什么建议 Netty 的 I/O 线程与业务线程分离
【4】框架篇:见识一下linux高性能网络IO+Reactor模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/659960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

构建大数据环境:Hadoop、MySQL、Hive、Scala和Spark的安装与配置

前言 在当今的数据驱动时代,构建一个强大的大数据环境对于企业和组织来说至关重要。本文将介绍如何安装和配置Hadoop、MySQL、Hive、Scala和Spark,以搭建一个完整的大数据环境。 简介 安装Hadoop 首先,从Apache Hadoop的官方网站下载所需的…

测试(一)

1.用户需求 可以简单理解为甲方提出的需求,如果没有甲方,那么就是终端用户使用产品时必须要完成的任务。该需求一般比较简略。 2.软件需求 或者叫功能需求,该需求会详细描述开发人员必须实现的软件功能(所谓的测试文档)。 大多数公司在进行…

05- c语言函数 (C语言)

一 函数的概念 1、在程序设计过程中,为了实现某个功能需要编写多行代码,例如求一个二维数组中的最大值,如果 该功能需要被多次使用,我们可以在每次使用时将原来的代码重复编写,但是这样未免有“凑代码”的嫌疑&#x…

大数据治理.数据储存技术

hive是基于Hadoop的一个数据仓库工具,用来进行数据提取、转化、加载,这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表,并提供SQL查询功能,能将SQL语句转…

Spark大数据处理学习笔记(3.8.3) Spark RDD典型案例-利用RDD实现分组排行榜

该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/Twpwe】 文章目录 一、任务目标二、准备工作2.1 在本地创建成绩文件2.2 将成绩文件上传到HDFS上指定目录 三、完成任务3.1 在Spark Shell里完成任务3.1.1 读取成绩文件得到RDD3.1.2 利用映射算子生…

Openfire身份认证绕过漏洞复现+利用(CVE-2023-32315)

0x01 产品简介 Openfire是免费的、开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器甚至可支持上万并发用户。 0x02 漏洞概述 Openfire的管理控制台是一个基于 Web 的…

自然语言处理从入门到应用——动态词向量预训练:ELMo词向量

分类目录:《自然语言处理从入门到应用》总目录 在双向语言模型预训练完成后,模型的编码部分(包括输入表示层以及多层堆叠LSTM)便可以用来计算任意文本的动态词向量表示。最自然的做法是使用两个LSTM的最后一层隐含层输出作为词的动…

Qt项目网络聊天室设计

效果演示 网络聊天室 Qt网络聊天室服务端 网络聊天室程序 基于TCP的可靠连接(QTcpServer、QTcpSocket) 一个服务器,多个客户端 3. 服务器接收到某个客户端的请求以及发送信息,经服务器发给其它客户端 最终实现一个共享聊天内容的聊天室! …

大数据治理.数据采集/归集技术

第一部分 阿里巴巴DATAx DataX 是阿里开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 DataX设计理念 DataX本身作为数据同步框架,将不同…

分布式系统消息通信技术:MOM与RPC

一、中间件 什么是中间件 中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台…

springboot配置 spring.profiles.active spring.profiles.include @profile

springboot配置 spring.profiles.active spring.profiles.include profile spring.profiles.active spring.profiles.include profile的命名方式 以 application-开头, --横杠(减号)不能少 application-{这部分自定义}.propertiesapplication-{这部分自定义}.ymlapplicatio…

c++多态详解

前言: 对于面向对象语言来说,多态是面向对象的三大特性之一,简单一点来说多态就是多种形态,是不同对象接收到同一种消息产生的不同动作或者反应,听起来有点抽象,实际上就是完成一个任务让不同的对象来做产生…

合宙Air724UG Cat.1模块硬件设计指南--模拟语音通道

模拟语音通道 简介 模拟音频技术是由传感器采集得到的连续变化的值,根据其电压的幅度用来展示声音强弱。CAT.1内置3种音频输出模式,分别为扬声器(SPK)输出,耳机(HP)输出和听筒(RECEIVER)输出。 特性 SPK接口 SPK-、SPK。Speaker差分信号接口…

记压测环境数据表死锁导致接口长时间pending问题

背景 压测过程中测试小伙伴反映某个页面长时间loading无法打开,接下来我们排查一下,既然是压测环境,那么就需要排除服务器资源层面的因素,现在考验的就是在系统资源不足时系统的情况,那么我们就直接从代码层面开始排查…

PADS-LAYOUT菜单及工具说明

目录 1 材料清单输出 2 元件属性检查 3 材料清单制作 4 原理图生成PDF 4.1PDF文件生成 4.2PDF文件查阅 4.3PDF文件打印 5 PADS转Altium Designer 5 Altium Designer转PADS 5.1 直接导入法 5.2 软件生成法 6 PADS层定义 7 设计规则输出 7.1 PADS对象管理 7.2 PAD…

pandas---分箱(离散化处理)、绘图、交叉表和透视表

1. 分箱 分箱操作就是将连续型数据离散化。分箱操作分为等距分箱和等频分箱. 1.1 等宽分箱 pandas.cut(x, bins, rightTrue, labelsNone, retbinsFalse, precision3, include_lowestFalse, duplicatesraise, orderedTrue) x:要分箱的一维数组或者 Series。 bi…

分布式系统概念和设计——分布式共享内存

分布式系统概念和设计 分布式共享内存 分布式共享内存是在不共享物理内存的计算机之间实现数据的共享的一个抽象。 有一个底层运行的系统保证其透明性,但是进程还是根据内存的分布处理物理内存的分布式能力 DMS最关键点: 不需要关心数据的通信&#xff…

百家号热议排名代发

百家号热议排名代发,百度排名怎么做,有什么技巧或者方式方法吗#百度首页关键词排名#百度推广#百度竞价推广#百度关键词排名#百度首页关键词排名方法# 其实百度推广并不赚钱,也没有你想象中的那么好做。 我说三点, 99% 的用户都遇…

C语言之动态内存分配讲解(2)

动态内存函数的介绍 在开始本章节之前,我们来复习一下动态内存分配(1)中所讲到的知识,看下面目录一和目录二 为什么存在动态内存分配 我们已经掌握的内存开辟方式有 int val 20;//在栈空间上开辟四个字节 char arr[10] {0};/…

Go语言并发之扇入和扇出

1、Go语言并发之扇入和扇出 编程中经常遇到扇入和扇出两个概念,所谓的扇入是指将多路通道聚合到一条通道中处理,Go 语言最简单的扇入 就是使用 select 聚合多条通道服务;所谓的扇出是指将一条通道发散到多条通道中处理,在Go语言…