前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >单机高并发模型设计

单机高并发模型设计

作者头像
方丈的寺院
发布于 2022-11-08 05:21:59
发布于 2022-11-08 05:21:59
66400
代码可运行
举报
文章被收录于专栏:方丈的寺院方丈的寺院
运行总次数:0
代码可运行

背景

微服务架构下,我们习惯使用多机器、分布式存储、缓存去支持一个高并发的请求模型,而忽略了单机高并发模型是如何工作的。这篇文章通过解构客户端与服务端的建立连接和数据传输过程,阐述下如何进行单机高并发模型设计。

经典C10K问题

如何在一台物理机上同时服务10K用户,及10000个用户,对于java程序员来说,这不是什么难事,使用netty就能构建出支持并发超过10000的服务端程序。那么netty是如何实现的?首先我们忘掉netty,从头开始分析。每个用户一个连接,对于服务端就是两件事

  1. 管理这10000个连接
  2. 处理10000个连接的数据传输

TCP连接与数据传输

连接建立

我们以常见TCP连接为例。

一张很熟悉的图。这篇重点在服务端分析,所以先忽略客户端细节。服务器端通过创建socket,bind端口,listen准备好了。最后通过accept和客户端建立连接。得到一个connectFd,即连接套接字(在Linux都是文件描述符),用来唯一标识一个连接。之后数据传输都基于这个。

数据传输

为了进行数据传输,服务端开辟一个线程处理数据。具体过程如下

  1. select应用程序向系统内核空间,询问数据是否准备好(因为有窗口大小限制,不是有数据,就可以读),数据未准备好,应用程序一直阻塞,等待应答。
  2. read内核判断数据准备好了,将数据从内核拷贝到应用程序,完成后,成功返回。
  3. 应用程序进行decode,业务逻辑处理,最后encode,再发送出去,返回给客户端

因为是一个线程处理一个连接数据,对应的线程模型是这样

多路复用

阻塞vs非阻塞

因为一个连接传输,一个线程,需要的线程数太多,占用的资源比较多。同时连接结束,资源销毁。又得重新创建连接。所以一个自然而然的想法是复用线程。即多个连接使用同一个线程。这样就引发一个问题, 原本我们进行数据传输的入口处,,假设线程正在处理某个连接的数据,但是数据又一直没有好时,因为 select是阻塞的,这样即使其他连接有数据可读,也读不到。所以不能是阻塞的,否则多个连接没法共用一个线程。所以必须是非阻塞的。

轮询 VS 事件通知

改成非阻塞后,应用程序就需要不断轮询内核空间,判断某个连接是否ready.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (connectfd fd:  connectFds) {
    if (fd.ready) {
        process()}
}

轮询这种方式效率比较低,非常耗CPU,所以一种常见的做法就是被调用方发事件通知告知调用方,而不是调用方一直轮询。这就是IO多路复用,一路指的就是标准输入和连接套接字。通过提前注册一批套接字到某个分组中,当这个分组中有任意一个IO事件时,就去通知阻塞对象准备好了。

select/poll/epoll

IO多路复用技术实现常见有select,poll。select与poll区别不大,主要就是poll没有最大文件描述符的限制。

从轮询变成事件通知,使用多路复用IO优化后,虽然应用程序不用一直轮询内核空间了。但是收到内核空间的事件通知后,应用程序并不知道是哪个对应的连接的事件,还得遍历一下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
onEvent({
// 监听到事件
    for (connectfd fd:  registerConnectFds) {
        if (fd.ready) {
            process()}
    }
}

可预见的,随着连接数增加,耗时在正比增加。相比较poll返回的是事件个数,epoll返回是有事件发生的connectFd数组,这样就避免了应用程序的轮询。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
onEvent({
// 监听到事件
    for (connectfd fd: readyConnectFds) {
       process()}
}

当然epoll的高性能不止是这个,还有边缘触发(edge-triggered),就不在本篇阐述了。

非阻塞IO+多路复用整理流程如下:

  1. select应用程序向系统内核空间,询问数据是否准备好(因为有窗口大小限制,不是有数据,就可以读),直接返回,非阻塞调用。
  2. 内核空间中有数据准备好了,发送ready read给应用程序
  3. 应用程序读取数据,进行decode,业务逻辑处理,最后encode,再发送出去,返回给客户端

线程池分工

上面我们主要是通过非阻塞+多路复用IO来解决局部的 selectread问题。我们再重新梳理下整体流程,看下整个数据处理过程可以如何进行分组。这个每个阶段使用不同的线程池来处理,提高效率。首先事件分两种

  1. 连接事件 accept动作来处理
  2. 传输事件 selectread, send 动作来处理。 连接事件处理流程比较固定,无额外逻辑,不需要进一步拆分。传输事件 readsend是相对比较固定的,每个连接的处理逻辑相似,可以放在一个线程池处理。而具体逻辑 decode, logic, encode 各个连接处理逻辑不同。整体可以放在一个线程池处理。

服务端拆分成3部分

  1. reactor部分,统一处理事件,然后根据类型分发
  2. 连接事件分发给acceptor,数据传输事件分发给handler
  3. 如果是数据传输类型,handler read完再交给processorc处理

因为1,2处理都比较快,放在线程池处理,业务逻辑放在另外一个线程池处理。

以上就是大名鼎鼎的reactor高并发模型。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 方丈的寺院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
AdGuard搭建去广告公共DNS
AdGuard 是摆脱恼人广告、在线跟踪,保护您远离恶意软件的最佳选择。AdGuard 使您网络冲浪更快速,更安全,更便捷!
星哥玩云
2022/05/27
4.5K0
AdGuard搭建去广告公共DNS
善用开源, 用AdGuard Home搭建私有DNS服务
首先需要再次明确的是, 搭建一个私有的DNS服务是有适应场景的, 建议在以下几个场景中你完全可以考虑搭建一个私有的DNS服务
御剑
2024/01/29
7.1K1
善用开源, 用AdGuard Home搭建私有DNS服务
Centos防火墙设置与端口开放的方法
Centos升级到7之后,内置的防火墙已经从iptables变成了firewalld。所以,端口的开启还是要从两种情况来说明的,即iptables和firewalld。更多关于CentOs防火墙的最新内容,请参考Redhat官网。
全栈程序员站长
2022/07/02
2K0
CentOS 7 开放防火墙端口命令
CentOS 7 开放防火墙端口 命令         最近公司新的server要求用CentOS7, 发现以前CentOS 6 系列中的 iptables 相关命令不能用了,查了下,发现Centos 7使用firewalld代替了原来的iptables。 使用方法如下: >>> 关闭防火墙 systemctl stop firewalld.service             #停止firewall systemctl disable firewalld.service        #禁止firewa
庞小明
2018/03/08
3.8K0
搭建AdGuard Home无广告及跟踪的DNS解析服务器
安装完成后可以在浏览器中输入以下内容,在端口3000(防火墙需要开通对应的端口)上访问AdGuard Home Web界面 http://xxxx:3000/,将xxxx替换为服务器的公网IP地址。
zeruns
2020/03/23
7.6K0
服务器安全设置Centos7 防火墙firewall与iptables
一.>>>>>>启用centos7 iptables防火墙Centos7 防火墙firewall设置方法
网站安全专家
2019/07/24
3.1K0
服务器安全设置Centos7 防火墙firewall与iptables
用腾讯云服务器搭建属于你的AdGuard Home与AdGuard Home的设置
用SSH工具连接服务器,在终端按顺序输入如下命令即可手动编译安装AdGuard Home
MoraEX
2022/04/08
18K3
用腾讯云服务器搭建属于你的AdGuard Home与AdGuard Home的设置
CentOS 7安装和配置Pure-ftpd
PureFTPd是一款专注于程序健壮和软件安全的免费FTP服务器软件(基于BSD License),目前常见的一键安装包,如Oneinstack、lnmp.org、宝塔等服务都已集成PureFTPd服务,可见PureFTPd是一款非常流行的FTP服务软件。
星哥玩云
2022/08/13
2.3K0
CentOS 7安装和配置Pure-ftpd
使用jiacrontab搭建一个可视化的定时任务
如果您使用过Windows计划任务或Linux的crontab,那么对“定时任务”这个名词可能并不陌生。简言之就是在设定好的时间去执行一个任务或者根据条件循环的执行一个或多个任务。Linux下的crontab需要通过命令行操作,有了jiacrontab就可以通过WEB界面来创建计划任务,比直接使用crontab简单很多。
星哥玩云
2022/08/13
1K0
使用jiacrontab搭建一个可视化的定时任务
宝塔面板利用Adguardhome搭建私人dns
Adguard Home是一款开源的广告拦截器和网络过滤器,可以在路由器上运行,用于保护所有连接到该路由器的设备免受广告和跟踪的侵害。它使用先进的过滤技术和大量的过滤规则来阻止广告和恶意网站的加载,并提供许多定制选项,以帮助用户获得最佳的网络体验。 Adguard Home还可以用于管理和监控网络流量,并具有防止DNS污染和加密DNS流量的功能。
曈曈too
2023/02/27
4.8K0
宝塔面板利用Adguardhome搭建私人dns
OpenWrt配置双AdGuard实现DNS国内外分流
从去年改造了家里的网络到现在都很稳定,但是最近自建的出墙偶尔抽风,我一直使用的Hysteria协议,发现有版本升级,于是升级了服务端,最后发现还是不丝滑,发现是我现在用的openwrt中的passwall插件不支持端口跳跃功能, 所以在恩山论坛找了个最新的OpenWrt固件进行安装,前段时间刷到了一个利用双AdguardHome分流国内外DNS解析,说这样可以防DNS污染,反正这次要升级OpenWrt,所以就折腾了一下,为了保持以前服务正常使用,我直接重新启动了一个OpenWrt,等觉得没问题再销毁全部切换过来,本篇记录自己踩的坑,当水篇文章了~。
Lcry
2023/06/14
18K0
OpenWrt配置双AdGuard实现DNS国内外分流
细说firewalld和iptables
在RHEL7里有几种防火墙共存:firewalld、iptables、ebtables,默认是使用firewalld来管理netfilter子系统,不过底层调用的命令仍然是iptables等。
孙杰
2019/10/29
3.8K0
Centos7设置防火墙相关命令
命令含义: --zone #作用域 --add-port=80/tcp #添加端口,格式为:端口/通讯协议 --permanent #永久生效,没有此参数重启后失效
用户7162790
2022/03/23
2.7K0
AdGuard Home:搭建去广告DNS | 树莓派
AdGuard Home 项目是著名广告拦截器 AdGuard 里 DNS Server 的一个开源版本。该项目的原理是,在 DNS 的域名解析的过程里拦截网页上的广告。
uniartisan
2022/03/03
6.5K0
AdGuard Home:搭建去广告DNS | 树莓派
live-torrent:一个支持磁力链和种子的在线搜索云播Web客户端
说明:live-torrent是一个功能强大的BT Web客户端工具,支持BT搜索和云播,我们可以直接使用程序内置的引擎搜索查找资源,也可以自行上传种子文件或磁力链接添加任务,程序支持自动识别种子内视频文件,点击播放按钮可以直接在线播放,该程序支持对接OpenSubtitles,自动给视频添加字幕。同时也提供一个热门电影排行榜,并提供对应资源给你播放和下载。不过唯一有点小遗憾的就是,不支持在线搜索中文资源,所以中文资源只能自己上传种子文件进行识别播放下载。
用户8851537
2021/08/16
6.6K0
多种功能强大的BT离线下载程序Docker镜像及安装
说明:最近看到很多小伙伴对离线下载啥的,兴趣蛮大,博主以前也水了不少了BT下载相关的脚本和安装,不过都没Docker简单,这里就找了一些用的人比较多,也经常在维护的BT离线程序的Docker镜像,包括Aria2、utorrent、Deluge、Transmission、Rutorrent、Qbittorrent,算是比较全了,这里就分享下。
子润先生
2021/05/28
1.3K0
CentOS 7防火墙快速开放端口配置方法
  CentOS升级到7之后,发现无法使用iptables控制Linuxs的端口,baidu之后发现Centos 7使用firewalld代替了原来的iptables。下面记录如何使用firewalld开放Linux端口:
会长君
2023/04/26
16.1K0
Centos 7防火墙开放端口方法
看到不少的网友还是有使用的是CentOS7版本的,比如我们较多的还是用到可视化面板宝塔面板建站。如果我们用的可视化面板建站环境的,防火墙的设置还是相对简单,我们直接在可视化面板上面添加放行或者限制的端口。当然老左提醒大家也不要忘记在服务器端安全组的设置,有些服务商是必须强制使用安全组的。
用户9996328
2022/08/25
4.6K0
在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问
🎉在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问
IT_陈寒
2023/12/14
5780
在CentOS 7.9上搭建高性能的FastDFS+Nginx文件服务器集群并实现外部远程访问
使用 Envoy 和 AdGuard Home 阻挡烦人的广告
通常我们使用网络时,宽带运营商会为我们分配一个 DNS 服务器。这个 DNS 通常是最快的,距离最近的服务器,但会有很多问题,比如:
米开朗基杨
2019/09/24
6.3K0
使用 Envoy 和 AdGuard Home 阻挡烦人的广告
推荐阅读
相关推荐
AdGuard搭建去广告公共DNS
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验