Linux高性能服务器技术总结(linux高性能服务器编程怎么样)
ahcoder 2025-06-13 10:56 5 浏览
1 服务器简介
服务器是提供计算服务的设备, 由于服务器需要响应用户请求,因此在处理能力、稳定性、安全性、可扩展性、可管理性等方面提出了较高要求。随着虚拟化技术的进步, 云服务器(ECS) 已经快速的在国内普及开来, 其管理方式比物理服务器更简单高效。用户可迅速创建或释放任意多台云服务器, 帮助企业降低开发运维的难度和整体 IT 成本, 使整个研发周期更专注于核心业务的创新。在网络环境下,根据服务器提供的服务类型不同,分为文件服务器、 数据库服务器、应用程序服务器、 WEB 服务器等。
此次学习总结的主要内容:
- 如何处理多个客户端连接。
- 探讨面对百万千万级客户端连接时的性能优化。
- 服务器如何高效处理并发的数据。
- 深度分析大数据通信时, Linux 内核瓶颈。
- 如何攻克瓶颈
2 I/O复用技术
2.1 循环方式
当服务器有多个网络连接需要看管,那么循环遍历打开的网络连接的列表,来判断是否有要读取的数据。
缺点:
- 速度缓慢(必须遍历所有的网络连接)
- 效率低(处理一个连接时可能发生阻塞,妨碍其他网络连接的检查和处理)
示例:
typedef struct ClientInfo{
int client_fd;
string client_ip;
}ClientInfo;//客户端结构体
std::deque<ClientInfo> m_client1;//客户端队列 1
std::deque<ClientInfo> m_client2;//客户端队列 2
void MServer::ClientHandel(std::deque<ClientInfo> *client){
char data[1024] = {0};
int len = 0;
for(int i = 0; i < client->size(); ++i){
//当没有数据可读时, 发生阻塞
len = read(client->at(i).client_fd, data, sizeof data);
//处理数据
bzero(data,sizeof data);//清空缓存
}
}
2.2 select 方式
select 首先将第二三四个参数指向的 fd_set 拷贝到内核,对每个被 SET 的描述符进行poll,记录在临时结果中(fdset),如果有事件发生, select 会将临时结果写到用户空间并返回。
缺点:
select 返回后,需要逐一检查描述符是否被 SET(事件是否发生)。(select 支持的
文件描述符数量太小了,默认是 1024)。
示例:
void MServer::ClientHandel(std::deque<ClientInfo> *client){
char data[1024] = {0};
fd_set input;// fdset 记录 poll 结果
int len = 0;
int retval = 0;
FD_ZERO(&input);//清空记录
for(int i = 0; i < client->size(); ++i){
FD_SET(client->at(i).client_fd, &input);
retval = select(client->at(i).client_fd + 1, &input, NULL, NULL, NULL);
//检测事件是否发生
if(retval > 0 && FD_ISSET(client->at(i).client_fd, &input)){
//读取数据
len = read(client->at(i).client_fd, data, sizeof data);
//处理数据
bzero(data,sizeof data);
}
//处理其他事情
}
}
2.3 poll方式
poll 与 select 不同,通过一个 pollfd 数组向内核传递需要关注的事件,故没有描述符个数的限制, pollfd 中的 events 字段和 revents 分别用于标示关注的事件和发生的事件,故 pollfd 数组只需要被初始化一次。 poll 的实现机制与 select 类似,其对应内核中的 sys_poll,只不过poll 向内核传递 pollfd 数组,然后对 pollfd 中的每个描述符进行 poll,相比处理 fdset 来说, poll 效率更高。
缺点:
poll 需要对 pollfd 中的每个元素检查其 revents 值,来得知事件是否发生。
示例:
std::vector<struct pollfd> pollfds;
void MServer::ClientHandel(std::deque<ClientInfo> *client){
int nready = 0;
int len = 0;
char data[1024] = {0};
//初始化 pollfds 容器
for(int i = 0; i < client->size(); ++i){
struct pollfd pfd;
pfd.fd = client->at(i).client_fd;//设置 pollfd
pfd.events = POLLIN;//设置 pollin 事件
pfd.revents = 0;//设置没有任何事件返回,置为零pollfds.push_back(pfd);
}
while(1){
nready = poll(&*pollfds.begin(), pollfds.size(), -1);//负数表示无限等待,直到发生事
件才返回
for(PollFdList::iterator it = pollfds.begin(); it != pollfds.end() && nready > 0; ++it){ //遍历查看 fd 产生的事件
if (it->revents & POLLIN){
len = read(it->fd, buf, sizeof data);
//处理数据
bzero(data,sizeof data);
}
}
//处理其他事情
}
}
相关视频推荐
90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc原理
学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂
需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
2.4 epoll 方式
epoll 与 select、 poll 不同,其不用每次调用都向内核拷贝事件描述信息,在第一次调用后,事件信息就会与对应的 epoll 描述符关联起来。其次, epoll 不是通过轮询,而是通过在等待的描述符上注册回调函数,当事件发生时,回调函数负责把发生的事件存储在就绪事件链表中,最后写到用户空间。
epoll 返回后,该参数指向的缓冲区中即为发生的事件,对缓冲区中每个元素进行处理即可,而不需要像 poll、 select 那样进行轮询检查。
示例:
void MServer::ClientHandel(std::deque<ClientInfo> *client){
int wait_fds;//事件产生的数量
int i = 0;
int len = 0;
char data[1024] = {0};
int epoll_fd = epoll_create(1024);//创建 epoll
for(i = 0; i < client->size(); ++i){
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET;//设置触发事件的类型
ev.data.fd = client->at(i).client_fd;
//向 epoll 中增加 client_fd
if( epoll_ctl( epoll_fd, EPOLL_CTL_ADD, client->at(i).client_fd, &ev ) < 0 ){
printf("Epoll Error : %d\n", errno);
exit( EXIT_FAILURE );
}
}struct epoll_event evs[1024];//epoll 事件缓存区
while(1){
if( ( wait_fds = epoll_wait( epoll_fd, evs, 0, -1 ) ) == -1 ){
break;
}
for( i = 0; i < wait_fds; ++i){
len = read( evs[i].data.fd, data, sizeof data);
//处理数据
bzero(data,sizeof data);
}
}
}
3 多线程方式
多线程技术也可以处理高并发的客户端连接,因为在服务器中可以创建大量的线程来监视连接。
缺点:
多线程技术则不太适合处理长连接,因为建立一个线程 linux 中会消耗栈空间, 当产生大量的连接后, 会导致系统内存消耗殆尽。
示例:
typedef struct ClientInfo{
int client_fd;
pthread_t pid;
bool pthread_enlable;
}ClientInfo;
std::deque<ClientInfo> client;//客户端队列
void MServer::ClientHandel(){
int i = 0;
//创建多线程处理连接
for(i = 0; i < client.size(); ++i){
if(pthread_create(&client[i].pid, NULL, ClientPthread, &client[i]) != 0){
client[i].pthread_enlable = true;
}
}
//等待线程结束
for(i = 0; i < client.size(); ++i){
if(client[i].pthread_enlable)
pthread_join(client[i].pid, NULL);
}
}//end func ClientHandel
void *MServer::ClientPthread(void *arg){
char data[1024] = {0};
int len = 0;
while(1){
len = read(((MServer*)arg)->client_fd, data, sizeof data);
//处理数据
bzero(data,sizeof data);//清空缓存
}
pthread_exit(NULL);
}
多线程 + I/O 复用技术,使用一个线程负责监听一个端口和描述符是否有读写事件产生,
再将事件分发给其他的工作线程处理数据。
模型架构:
这种架构主要是基于单线程 I/O 多路复用(select/poll/epoll),达到高并发效果,同时避免了多线程 I/O 来回切换的各种开销,而基于线程池的多工作者线程,进一步提高业务处理能力和避免产生过多线程。
4 CPU多核并行计算
程序的线程是指能同时并发执行的逻辑单元的个数,是通过时间片分配算法实现的;
CPU 的线程是指将 CPU 的指令执行过程(取指、译指、执行、 访存、写数)做出流水线从而提高并发度的方法。
并行计算和多线程的区别:
- 并行计算比多线程具有更高的 CPU 利用率,因此效率相对更高。
- 并行计算是利用 CPU 的多核进行计算,而多线程是利用 CPU 一个核在不同时间段内进行计算。
- 并行计算是多个线程运行在多核 CPU 上,多线程是多线程运行在单核 CPU 上。
综合上述得出多线程并不能真正提高数据处理能力, 其局限于单核 CPU 的性能, 当服务器需要进行大量的数据运算(如图形处理、 复杂的算法) 时考虑多核并行计算。
5 深度分析内核性能
5.1 中断处理
当网络中大量数据包到来时,会产生频繁的硬件中断请求,这些硬件中断可以打断之前较低优先级的软中断或者系统调用的执行过程,如果这种打断频繁的话,将会产生较高的性能开销。
5.2 内存拷贝
正常情况下,一个网络数据包从网卡到应用程序需要经过如下的过程:数据从网卡通过 DMA (直接存储器访问) 等方式传到内核开辟的缓冲区,然后从内核空间拷贝到用户态空间,在 Linux 内核协议栈中,这个耗时操作甚至占到了数据包整个处理流程的 57.1%。
5.3 上下文切换
频繁到达的硬件中断和软中断都可能随时抢占系统调用的运行,这会产生大量的上下文切换开销。另外,在基于多线程的服务器设计框架中,线程间的调度也会产生频繁的上下文切换开销,同样,锁竞争的耗能也是一个非常严重的问题。
5.4 局部性失效
如今主流的处理器都是多个核心的,这意味着一个数据包的处理可能跨多个 CPU 核心,比如一个数据包可能中断在 cpu0,内核态处理在 cpu1,用户态处理在 cpu2,这样跨多个核心,容易造成 CPU 缓存失效,造成局部性失效。
5.5 内存管理
传统服务器内存页为 4K,为了提高内存的访问速度,避免 cache miss,可以增加 cache 中映射表的条目,但这又会影响 CPU 的检索效率。综合以上问题,可以看出内核本身就是一个非常大的瓶颈所在, 解决方案就是想办法绕过内核。
6 高性能网络框架DPDK
DPDK 为 Intel 处理器架构下用户空间高效的数据包处理提供了库函数和驱动的支持,它不同于 Linux 系统以通用性设计为目的,而是专注于网络应用中数据包的高性能处理。
DPDK 官网: https://www.dpdk.org/
DPDK 架构图:
Linux 内核网络数据流程:
- 硬件中断--->取包分发至内核线程--->软件中断--->内核线程在协议栈中处理包--->处理
- 完毕通知用户层
- 用户层收包-->网络层--->逻辑层--->业务层
DPDK 网络数据流程:
- 硬件中断--->放弃中断流程
- 用户层通过设备映射取包--->进入用户层协议栈--->逻辑层--->业务层
下面就具体看看 dpdk 做了哪些突破?
UIO (用户空间的 I/O 技术)的加持, dpdk 能够绕过内核协议栈,本质上是得益于 UIO技术,通过 UIO 能够拦截中断,并重设中断回调行为,从而绕过内核协议栈后续的处理流程。
相关推荐
- linux服务器--PVE(一)简介及安装(pve安装ifupdown2)
-
1.PVE(ProxmoxVirtualEnvironment)简介ProxmoxVirtualEnvironment基于debian,是一个完整的、开源的企业虚拟化服务器管理平台。它在一个平...
- 手把手教你!如何在 Linux 服务器中搭建 Sentinel 环境?
-
你在Linux服务器上搭建Sentinel环境时,是不是也遇到过各种报错,要么是启动失败,要么是配置后无法正常访问控制台?看着同事顺利搭建好,自己却一头雾水,别提多着急了!其实,很多互联网大厂...
- Linux高性能服务器技术总结(linux高性能服务器编程怎么样)
-
1服务器简介服务器是提供计算服务的设备,由于服务器需要响应用户请求,因此在处理能力、稳定性、安全性、可扩展性、可管理性等方面提出了较高要求。随着虚拟化技术的进步,云服务器(ECS)已经快速的在...
- 从 0 到 1:使用 Ansible 自动化运维 Linux 服务器全流程
-
Ansible是一款强大的IT自动化工具,广泛用于服务器配置管理、软件部署和任务自动化。本文将带你从零开始,学习如何使用Ansible对Linux服务器进行自动化运维,涵盖Ansibl...
- 诡异!Win11 “此电脑” 莫名现 Linux 图标,啥情况?
-
我这电脑出了个怪事儿,“此电脑”下面莫名其妙多了个Linux的图标,可我压根儿就没装过Linux系统啊!琢磨了一下,估计是系统可选功能里那个“适用于Linux的Windows子系统”插件搞的鬼。实例系...
- Linux基础运维篇:Linux 终端与 Shell 基础(第006课)
-
一、啥是终端?先搞懂「人和电脑对话的窗口」你可以把终端(Terminal)理解成一个「文字版的电脑操作台」。在Windows里,类似「命令提示符」或PowerShell;在Linux里,...
- 2025罗技大师系列智「简」大赛-罗技大师系列-MX KEYS S键盘评测
-
在2025罗技大师系列智「简」大赛中,MXKEYSS键盘凭借其卓越的设计与智能化体验,成为众多创作者的理想之选。本篇文章将深入评测这款键盘的核心功能、使用体验及创新亮点,帮助你了解它如何提升...
- Linux编辑命令vim(linux使用vim编辑文件)
-
1、vi编辑器简介vim是一个全屏幕纯文本编辑器,是vi编辑器的增强版,我们主要讲解的是vim编辑器。可以利用别名让输入vi命令的时候,实际上执行vim编辑器,例如:#定义别名...
- 全选是ctrl加什么?全选的快捷键是什么介绍
-
如何高效使用「全选」快捷键(Ctrl+A/A)提升工作效率在日常电脑操作中,"全选"是最基础却至关重要的功能之一。无论您是文字工作者、程序员还是普通用户,掌握全选快捷键都能极大提升操作...
- Linux命令大全(linux命令大全书)
-
个人博客:https://chunyu.work/文章较长,可以收藏备用常用快捷键(1)ctrl+c:停止进程(2)ctrl+l:清屏(3)善于用tab键(4)上下键:查找执行过的命令文件目录类(...
- Xshell是做什么用的?Xshell使用教程分享
-
Xshell是一款功能强大的终端模拟器,支持SSH1,SSH2,SFTP,TELNET,RLOGIN和SERIAL。通过提供业界先进的性能,Xshell包含了其他SSH客户端无法发现的功能和优势,作为...
- Java 开发者线上问题排查常用的 15 个 Linux 命令
-
作为Java开发者,线上环境的问题排查是日常工作的重要组成部分。熟练掌握Linux命令能大幅提升排查效率,快速定位进程异常、日志错误、性能瓶颈等核心问题。本文结合Java应用特点,整理1...
- Linux的常用命令就是记不住,怎么办?
-
1.帮助命令1.1help命令#语法格式:命令--help#作用:查看某个命令的帮助信息#示例:#ls--help查看ls命令的帮助信息#netst...
- 别再乱学 Linux 了!这 5 个核心技巧,让你效率飙升 10 倍!
-
在Linux学习的漫漫长路上,不少人犹如在黑暗中摸索的行者,四处碰壁,学习效果却不尽如人意。你是不是也曾在海量的Linux知识面前迷失方向,感觉自己投入了大量时间,却收效甚微?其实,掌握Li...
- Linux终端神器Terminator时隔1年回归,2.1.5新版发布
-
IT之家5月23日消息,科技媒体linuxiac今天(5月23日)发布博文,报道称Terminator在沉寂一年后,最新发布了2.1.5版本,在分割终端窗格时支持克隆SSH...
- 一周热门
- 最近发表
-
- linux服务器--PVE(一)简介及安装(pve安装ifupdown2)
- 手把手教你!如何在 Linux 服务器中搭建 Sentinel 环境?
- Linux高性能服务器技术总结(linux高性能服务器编程怎么样)
- 从 0 到 1:使用 Ansible 自动化运维 Linux 服务器全流程
- 诡异!Win11 “此电脑” 莫名现 Linux 图标,啥情况?
- Linux基础运维篇:Linux 终端与 Shell 基础(第006课)
- 2025罗技大师系列智「简」大赛-罗技大师系列-MX KEYS S键盘评测
- Linux编辑命令vim(linux使用vim编辑文件)
- 全选是ctrl加什么?全选的快捷键是什么介绍
- Linux命令大全(linux命令大全书)
- 标签列表
-
- linux 远程 (37)
- u盘 linux (32)
- linux 登录 (34)
- linux 路径 (33)
- linux 文件命令 (35)
- linux 是什么 (35)
- linux 界面 (34)
- 查看文件 linux (35)
- linux 语言 (33)
- linux代码 (32)
- linux 查看命令 (33)
- 关闭linux (34)
- root linux (33)
- 删除文件 linux (35)
- linux 主机 (34)
- linux与 (33)
- linux 函数 (35)
- linux .ssh (35)
- cpu linux (35)
- 查看linux 系统 (32)
- linux 防火墙 (33)
- linux 手机 (32)
- linux 镜像 (34)
- linux ip地址 (34)
- linux 用户查看 (33)