网路编程中常用的线程(进程)模型以及封闭原则

【ZMQ polling机制】ZMQ异步接收机制以及与epoll/select的对比分析 ZeroMQ,通常简称为ZMQ,是一个高性能的消息传递库,它提供了多种消息模式,其中最受欢迎的是发布-订阅(PUB-SUB)模式。在这种模式下,发布者(PUB)发送消息,而订阅者(SUB)可以选择接收它们。这种模式的一个关键特点是,订阅者可以选择订阅特定的消息主题,从而只接收与该主题相关的消息。 阅读详情

突发奇想,想写一篇综合性的,就算算是对到现在为止读过的框架这方面的一个总结吧,

先来点客套话吧,嗯,为啥会有线程或者进程模型这种东西,因为计算机CPU主频已经很难再提高了,现在更倾向于设计多核系统,那么要发挥现在计算机的处理能力,就需要将系统设计成支持多处理器的,最简单的那肯定就是多线程(进程)程序了。。。尤其是在网络编程中,特别是对于每个事物都是独立的情况下,例如没有会话的HTTP请求啥的,这种方式可以极大的提高程序的吞吐量和伸缩性。。。。

当然,多线程,多进程的方式必然会增加程序设计的复杂性,尤其是在一些同步,加锁的地方会使编码难度变大,不过其实遵循良好的模式来设计程序的话,可以避免陷入太多的坑。。。。


好了,下面先来看看Nginx的设计吧:

嗯,Nginx属于比较单纯的HTTP服务器,对于它来说,每一个http请求都是独立的,所以不用考虑session啥的这种共享的东西,所以在需要进行同步的地方很少。。。。

Nginx采用的是Master/Worker模型,一个master进程,多个Worker进程。。。

所有的Worker进程之间只有很少的共享变量,首先是一段共享内存,这里面我现在还能想起来的大概有:

(1)其中的一段用于锁的实现,Nginx所有worker进程之间的同步都是通过这把锁来完成的

(2)好像还有一个计数器,用于保存所有的http请求数量吧。。。好像是。。记不太清了。。。

另外所有的由于监听Socket是在Master进程中创建的,所以它的文件描述符被所有的Worker进程共享。、。。。

好啦,用一张图来描述一下整个上面这些东西的大致结构吧:


其实画了这张图之后,觉得好像读过的所有源码的实现其实都差不太多。。主体基本上都是这样子的。。。。

由于监听器Socket如果同时被注册到多个epoll里面之后,会引起惊群现象,所以Nginx中所有的worker进程需要获取共享内存中的一个锁之后才能将这个监听Socket放入到自己的Epoll里面,这样就将外部的TCP连接分布到了每一个Worker进程,每个Woker进程处理自己的连接的请求就ok了。。。够简单吧。。。其实这也体现了在并发编程中特别重要的一个原则:封闭原则,将可变的状态信息封闭在线程或者进程的内部,这样就没有了并发环境下的不一致的情况了。。。

其实这里还有另外一种实现,不再将监听器Socket交给Worker进程来共享,而是将其放到另外一个地方,然后将接收到的连接的socket的文件描述符传递给Worker进程。。然后Worker进程中再具体的处理这些socket的IO请求就好了。。这样就省去了对监听Socket进行同步的过程。。。


好了,接下来来看看Netty吧:

首先Netty中也严格遵循了封闭性,不过这里就是线程封闭性了,每一个执行线程都有自己的selector,然后所有外部的TCP连接都分属于这些Selector,也就分属于这些执行线程,对于这些TCP连接的所有IO操作,都将会封闭在所属的线程内部。。。

其实对于Netty最重要的就是要知道它是如何实现线程封闭的,因为在java多线程程序中会存在许多的线程,有用户线程,Netty自己的IO线程。其余的线程池啥的,而这些对象会在线程之间传递。。如何确保属于某个Netty的IO线程的连接上面的IO操作只由这个线程来执行就需要一些额外的机制了来实现了。。。。

其实要搞清楚整个Netty的运行情况,将它的EventLoopGroup以及EventLoop搞清楚就差不多了:

(1)EventLoopGroup继承自EventExecutorGroup,而EventExecutorGroup可以将它看成是一个线程池,而EventLoopGroup只不过是扩展了了线程池的功能,加入了一些事件的处理。例如channel的注册啥的。。

(2)EventLoop继承自EventExecutor,而一个EventExecutor可以将其看成是一个线程池中的执行线程,而EventLoop扩展了EventExecutor的主循环,一般情况下线程池中的线程要做的就是不断的从任务队列里面后去Task,然后执行他们,而EventLoop中加入了select以及IO的处理过程。。。

(3)每一个channel都注册到了其中一个EventLoop的selector上面,在这个channel上面产生的所有IO事件的处理都将会是在这个EventLoop中进行处理。。。

下面用一张图来说明一下上面提到的之间的关系吧:



上面图形算是刻画了几个东西之间的对应关系吧,其实这里更重要的还是分析Netty中如何保证Channel上面的IO操作都保证在其所属的EventLoop中执行。。。来看一段代码吧:

    private void write(Object msg, boolean flush, ChannelPromise promise) {

        DefaultChannelHandlerContext next = findContextOutbound();   //像前找,找到第一个outboundhandler
        EventExecutor executor = next.executor();  //获取其所属的executor对象
        if (executor.inEventLoop()) {   //如果当前的执行线程就是当前channel所属的executor的线程,那么直接执行就好了,否则的话需要创建task提交到相应的evetnLoop
            next.invokeWrite(msg, promise);
            if (flush) {
                next.invokeFlush();
            }
        } else {  //这里表示当前的线程并不是当前channel所属的eventloop的执行线程,那么这里要做的是创建一个task,并将其提交给所属的EventLoop对象就好了
            int size = channel.estimatorHandle().size(msg);
            if (size > 0) {
                ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();
                // Check for null as it may be set to null if the channel is closed already
                if (buffer != null) {
                    buffer.incrementPendingOutboundBytes(size, false);
                }
            }
            executor.execute(WriteTask.newInstance(next, msg, size, flush, promise));
        }
    }

其实这里的实现挺简单的,一般情况下针对Channel的IO操作都会在Channel对象的pipeline上面调用相应的方法,这里举出了write方法,其余的IO操作的方法其实都一样,可以看到这里其实会判断当前的执行线程是否是当前channel所属的EventLoop的执行线程,如果是的话,那么可以直接在当前线程中具体的执行IO操作了,如果不是的话,那么就需要创建一个Task,将IO操作封装在这个task里面,然后提交给所属的EventLoop,这样,也就保证了Channel的所有IO操作都封闭在其所属的EventLoop中了。。

够简单的吧。。。

这里需要注意的是,每一个EventLoop都有自己的task队列,而不是所有的EventLoop共享同一个task队列,这与一般的线程池的实现有不太一样的地方。。。。


下面先来看看ZeroMQ(java)的设计实现吧:

个人感觉ZeroMQ(java)中的实现算是比较奇葩的一种了。。。。


在ZeroMQ中有专门封装出了IO线程,也就是IOThread类型,可以就将其理解为工作线程,而且一般情况下所有的对象都要依附于相应的IOThread对象才能运行。。。

这里要做的就是如何将这些对象的方法的执行都封闭在各自所属的IOThread对象的工作线程中运行。。。。嗯,这个个人觉的实现的比较的婉转。。。

来看一张图形吧:



嗯,看起来挺复杂的,来具体的说明一下这张图上的东西是怎么运行的吧:

(1)CTX是整个ZeroMQ的执行上下文,它会维护当前所有的socket对象以及IOThread对象,每一个IOThread对象都有自己的Poller对象,用于维护channel的注册,以及事件的回调,当然这些都是在当前的工作线程中执行的

(2)每一个具体的连接将会注册到其中一个IO线程的poller上面去,这里还有一个比较奇特的东西,那就是MailBox,每一个IO线程都有一个自己的mailbox,这里与其说对象方法的执行依赖于IO线程,还不如说依赖于某一个mailbox,

(3)ZObject可以理解为用于响应命令以及发送命令的对象,它可以给其他的ZObject对象发送命令,让其执行某个方法,也要接受别的ZObject发送过来的命令,执行相应的操作,那么其实所有的命令都是其实都是直接放到ZObject对象所属的MailBox的命令队列里面去的。。。然后命令里将会含有目的对象的引用。。那么接下来的事情就是如何让目的对象的相应的方法执行。。。

(4)这个就比较囧了,每一个mailbox都有一个channel注册到poller上面,当别的地方给这个mailbox发送命令的时候,会同时给这个channel写一个标志数据,这样就会被poller上面的selector感应到,这个时候的IO回调是执行mailbox里面的所有命令,这样也就保证了对象执行命令的时候是在其所依赖的IO线程中执行的。。。


够婉转的了。。。


好啦,这里介绍了几种比较代表性的实现。。。。

呵呵,献丑了。。。

PCIe Gen4眼图测试实战:如何用示波器快速定位信号完整性问题(附避坑指南) 本文详细解析了PCIe Gen4眼图测试中的信号完整性诊断方法,通过示波器操作技巧和实战案例,帮助工程师快速定位抖动、反射等信号问题。特别针对眼图闭合、阻抗失配等常见问题提供了避坑指南和解决方案,提升高速信号调试效率。 阅读详情

相关推荐

Jetbrains IDE 配置上Gemini Code 插件,让你的的编程高效起飞~

Gemini Code Assist是 Google 家产品,基座模型为最新的Gemini 2.5 Pro。本篇实践了在 WebStrom 中Gemini Code Assist插件的高效编程。

2301_76993408的博客 4594

[译]nanomsg和ZeroMQ的区别

原文地址: Differences between nanomsg and ZeroMQ 自这篇文档完成以后,Nanomsg和ZeroMQ都已经发生了很大的变化。尽管如此,本文档从ZeroMQ和Nanomsg原创作者的角度来阐述,仍有助于理解nanomsg的历史变更。 授权 Nanomsg库基于MIT授权,这就意味着Nanomsg不同于ZeroMQ,你可以修改源代码,可以作为专利产品以不同的授权重新发布等。更多关于授权许可的信息可以在这里找到。 PO

木牛的博客 1539

Mixly米思齐——超声波测距控制LED灯

为了更加地贴近中小学信息技术的课程,我们用米思齐做了一个实验——根据距离的远近开启警报灯(利用超声波测出距离)。 实验硬件准备 arduino uno R3 、USB 数据线、YFROBOT UNO I/O扩展板、YFROBOT超声波传感器模块、模块3P连接线x1、LED灯x1 硬件连接图如下: 在arduino uno R3 上再接一个LED灯,实物图如下: 在本次实验中,LE...

Janise_的博客 9977

zeroMQ和nanoMSG的对比

zeromq是作者用cpp早期创作,作者承认存在一些明显问题;nanomsg则是用C写的,更为成熟。

haozizang的博客 1493

海康工业相机使用教程

海康工业相机连接电脑教程

qq_43251445的博客 2万+

anaconda安装-超详细版

文章目录一、anaconda安装1.1 anaconda安装地址1.2 安装详细步骤检验安装是否成功更改conda源(后续安装第三方库可以加快速度) 一、anaconda安装 Anaconda 是一个用于科学计算的 Python 发行版,支持 Linux, Mac, Windows, 包含了众多流行的科学计算、数据分析的 Python 包。装anaconda,就不需要单独装python了。 anaconda优点: 1、anaconda里面集成了很多关于python科学计算的第三方库,主要是安装方便,而p

in546的博客 25万+

消息队列-ZeroMQ

可用于并发处理,一个消息只能被一个worker拉到。类似生产者/消费者关系。中间转发,用于分发,负载均衡。

justlpf的专栏 648

死磕GMSSL通信-java/Netty系列(二)

Netty-tcnative再linux编译比较好编译,但是再window编译,我尝试了各种办法,总是编译失败,所以我采用半自动的方式进行编译,Netty-tcnative会生成临时文件,直接用vs打开,设置openssl的头文件和静态库路径,然后生成静态库,静态库改个名字放到jar包里边,其实自动编译也是这个原理哈哈O(∩_∩)O。直接传输五个证书的路径吗,之前有的是说要转成x509之类的,转来转去的有点麻烦,这个是直接传输证书路径,由底层gmssl去解析,格式必须是pem格式。然而,若项目已依赖于。

qq_36577699的博客 3025

Storm通信机制,Worker进程间通信,Worker进程间通信分析,Worker进程间技术(Netty、ZeroMQ),Worker 内部通信技术(Disruptor)(来自学习资料)

Storm通信机制Worker间的通信经常需要通过网络跨节点进行,Storm使用ZeroMQ或Netty(0.9以后默认使用)作为进程间通信的消息框架。 Worker进程内部通信:不同worker的thread通信使用LMAX Disruptor来完成。 不同topologey之间的通信,Storm不负责,需要自己想办法实现,例如使用kafka等;2.1、Worker进程间通信worke

涂作权的博客 4062

​银行IT运维人必看!IT运维监控指标大全,一篇讲透

文章摘要:本文从七个维度系统阐述了IT运维指标体系,涵盖机房环境、基础设施、网络设施、数据存储、虚拟化平台、数据库中间件和应用层。作者结合20年金融行业经验,详细分析了各层级关键监控指标、正常范围及异常后果,并给出典型故障场景。重点强调现代运维需从被动响应转向主动预防,通过精细化指标管理实现系统稳定性保障。文章特别指出,在国产化与DevOps背景下,运维工作需兼顾传统架构与新兴技术,构建全方位监控体系,将运维从"故障报警"升级为"业务守护"。

最近开始研究AIGC领域技术,欢迎交流 1106

SAP采购订单行项目增强实战:用BADI ME_GUI_PO_CUST添加自定义字段(避坑指南)

本文详细解析了如何通过BADI ME_GUI_PO_CUST在SAP采购订单行项目中添加自定义字段,包括技术架构理解、字段扩展步骤、自定义函数组创建及BADI实现。文章特别强调了避开官方文档未提及的陷阱,如字段映射限制和屏幕显示问题,并提供了高级优化技巧和性能建议。

weixin_30402343的博客 594

NNG简介和使用总结

ZeroMQ(简称ZMQ)是一个基于消息队列的多线程网络库,其对套接字类型、连接处理、帧、甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字。ZMQ不是单独的服务,而是一个嵌入式库,(按照TCP/IP划分),它封装了网络通信、消息队列、线程调度等功能,向上层提供简洁的API,应用程序通过加载库文件,调用API函数来实现高性能网络通信。

qq_28576837的博客 7020

【即插即用模块】注意力篇 | ECCV 2024 | DPB:高低频动态分离+双提示融合,PSNR直冲40+!

本文提出了一种基于频率提示的图像恢复方法FPro,通过动态滤波器分离输入特征的高低频分量,并采用双提示块(DPB)进行频域专属提示生成与调制。DPB包含低频提示调制器(LPM)和高频提示调制器(HPM),分别处理不同频段信号,通过生成提示组件并融合解码器特征来优化恢复效果。实验表明,该方法在U型结构中表现优异,尤其适用于分割、底层视觉和多模态任务。模块通过动态无监督频率分离、频域专属提示生成和适配性融合机制,有效解决了传统方法对频域信息关注不足的问题,显著提升了图像恢复质量。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 147

Nginx+netty实现tcp负载均衡,获取客户端真实ip

在nginx.conf文件中,events,http同级添加配置启动nginx服务。

qq_27955093的博客 2239

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

记一次被问netty与nginx比较

Q: 做socket通信,一般无脑用netty,为什么不用nginx,做呢? A:ZHI呜呜 后续了解 也就是为了做对比,ng能做流量转发,转发过后也是需要有工具维护连接; ng做不了维护工作,我觉得是这样,不知道对不对噢 netty 用作网络数据处理,nginx用作网络数据转发。他个人觉得不算一类东西;我也附议 有新的理解再更新~ ...

飞奔的小土豆@1024 3015

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

nginx代理 netty tcp服务端获取客户端真实IP

场景描述: netty tcp 服务端与客户端进行交互,之前采用服务器直连的方式,即: 客户端 -----------> 服务端(tcp) 此时服务端可以通过: ctx.channel().remoteAddress() 获取客户端IP进行相关的业务使用。 但是后续随着客户端增加,服务端就上来了,此时使用nginx代理的方式增加netty服务端数量一次来处理更多的连接数。 客户端 -----------> nginx --------------->服务端(tcp,多台部署.

K1215400017的博客 7236

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Nginx搭建Netty负载均衡

Nginx搭建Netty负载均衡笔记记录一下用Nginx实现netty的负载均衡学习过程。

机器学习菜鸟 3850

Netty案例 手动实现Nginx和聊天室支持单聊和群聊,心跳检测,强制下线

手动实现一个Nginx加聊天室的案例 闲来无事?🔥快来拿个小案例练手 简单易懂快速上手 案例不长快快 上车! 上车 🚗GO! GO! GO! 🚗 相信通过这个案例能让你学到更多东西 关注收藏是我最大动力 文章目录服务器开发环境准备代码编写服务器后端代码聊天室前端代码聊天室后端代码效果测试 代码全部粘贴下面了,如果想要一个完整的包可以私信我,我也会把打包的链接留在后面 来介绍一下这个小案例: 1.服务器 实现一个资源通过http映射类似Nginx 我们的案例都在我们自己实现的服务器上面运行,没有使用Tomc

qq_52314655的博客 3096

Storm实战 (2) storm中ZMQ和netty作用

storm中ZMQ和netty作用     在storm集群安装中,我选择的是版本storm1.0.0,官网关于storm1.0.0需要的依赖库说的是要jdk1.6+和Python2.6.6,但在浏览博客时无意间发现有个博客上选择的版本是storm0.8.1说的是需要ZMQ,当时比较迷惑,到底需不需要呢?????????      参考资料: storm学习之Netty代替ZMQ   ...

猿类崛起 654

ZeroMQ:云计算时代最好的通讯库

还在学socket编程吗?还在研究为什么epoll比select更好吗? 噢,不必了! 在复杂的云计算环境中,我们面临的难题远比这个复杂得多。 庞大的服务器集群作为计算云,对来来看或许只是一个简单的搜索框;而在云的内部,复杂的互联和海量的通讯,加之不稳定的网络环境,廉价服务器的低可用性——构建一个高可用性且具备伸缩能力的云计算的环境,不是那么容易的! 为什么说ZeroMQ是云计算时代最...

weixin_33709590的博客 240

zmq库、pyzmq的编译及安装

转载请注明来源: http://blog.youkuaiyun.com/lx1848/article/details/50393128 Centos下安装zmq库及pyzmq 1. ZeroMQ简介 ZMQ(ØMQ、ZeroMQ, 0MQ)看起来像是一个网络库,但它工作起来更像是一个并发框架。它可以提供线程间、进程间、TCP、广播等类型的Socket通信。你可。ZMQ的以构建多种通信模式,如Fanout、发布-订阅、任务分发、请求-应答等,它优异的性能足以应对集群应用的性能需求。它使用异步I/O机制,这让你能够轻松构建

lx1848的专栏 4854

使用LVS+NGinx+Netty实现数据接入

AIO:异步非阻塞,AIO引入了异步通道的概念,采用了Proactor模式,简化了程序编写,有效的请求才启动线程,他的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且链接时间较长的应用。BIO:同步阻塞IO,也就是传统阻塞型的IO,服务器实现模式是一个连接对应一个线程。NIO:同步非阻塞IO,服务器实现模式是一个线程处理多个请求,客户端发送的链接请求都会注册到多路复用器上,多路复用器轮询到链接有IO请求就进行处理。:虚拟路由的ID,用于在VRRP组中标识不同的虚拟路由器。

qq_42496461的博客 1378

nginx配置netty

1、首先,先下载nginx的rpm包,下载地址:http://nginx.org/packages/centos/7/x86_64/RPMS/二、配置nginx 配置文件 7001 是netty服务器的端口。systemctl start nginx 启动nginx。systemctl restart nginx 重启命令。systemctl stop nginx 停止命令。nginx安装目录:/etc/nginx。nginx -V 查看版本及安装路径等。三、指定配置文件启动nginx。

QWERTY55555的专栏 699

美团T9分享官方进阶文档:Nginx+Netty跟着案例学这两份开源手册

最早接触Nginx大概是在2011年,面对着一个全新的Web服务器,和大多数人一样最初我也是一片茫然,能找到的参考资料十分有限,安装、配置、运行几乎都是“摸着石头过河”,犯过许多低级错误。随着对Nginx逐渐熟悉,它的高并发处理能力给我留下了深刻的印象,作为一个开源软件的爱好者,很自然地想要探究一下它的内部工作原理。我由此开始了对Nginx源码的钻研之路,中间经过了很多的艰辛曲折,走过不少的弯路。Nginx的横空出世为Web服务器开辟了一个崭新的天地,它搭建了一个高性能的服务器。

the shy 332

Netty-zmtp:高性能ZeroMQ协议实现

Netty-zmtp:高性能ZeroMQ协议实现 项目介绍 Netty-zmtp 是一个基于Netty框架实现的ZeroMQ消息传输协议(ZMTP)编解码器。该项目旨在支持ZMTP 1.0和2.0版本,并提供了一种在JVM上实现高性能ZeroMQ通信的方式。尽管该项目已经停止维护,但其代码和实现仍然具有很高的参考价值,尤其是在需要高性能、低延迟的分布式系统中。 项目技术分析 技术栈 Netty:...

gitblog_00058的博客 498

消息队列mq总结

转自:http://blog.youkuaiyun.com/konglongaa/article/details/52208273 http://blog.youkuaiyun.com/oMaverick1/article/details/51331004 https://yq.aliyun.com/articles/25385 https://www.zhihu.com/question/22480085

jasonhui512的博客 2万+
上一篇: ZeroMQ(JAVA)中的数据流,SessionBase与SocketBase
下一篇: ZeroMQ(java)Socket之Dealer
fjs_cloud
博客等级 码龄15年 248粉丝 192原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值