目录
1.ngx_http_rewrite_module 模块指令
2.2.域名永久(permanent)与临时重定向(redirect)
引言
在数字化时代,企业网站的性能直接关联到用户体验和业务成果。高性能的Web服务器不仅能够应对日益增长的用户访问量,还能保证数据的快速处理和传输。本文将深入探讨如何通过优化Web服务器配置,实现企业级服务的高性能目标。
一、 Web服务器基础与发展历程
1.互联网与Web服务发展简史
自1993年中国接入Internet以来,互联网服务经历了飞速的发展。从最初的中国黄页、阿里巴巴的创建,到淘宝、支付宝的诞生,再到天猫的更名和阿里巴巴集团的上市,每一个里程碑都标志着互联网服务的一次重大进步。
Web服务器作为互联网信息服务的核心,也经历了不断的技术革新。从Apache的经典Web服务端到Nginx的高性能服务端,技术的演进使得Web服务器能够更好地应对高并发、高可用性的需求。
2. Apache与Nginx的性能对比
2.1 Apache服务器
Apache服务器以其稳定性和广泛的社区支持而闻名。它通过不同的模型(如prefork、worker、event)来处理Web请求,适应不同的应用场景。
Apache prefork 模型
- 预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
- 每个子进程有一个独立的线程响应用户请求
- 相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
- 是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
Apache worker 模型
- 一种多进程和多线程混合的模型
- 有一个控制进程,启动多个子进程
- 每个子进程里面包含固定的线程
- 使用线程程来处理请求
- 当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求
- 由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
Apache event模型
- Apache 中最新的模式, 2012 年发布的 apache 2.4.X 系列正式支持 event 模型 , 属于事件驱动模型 (epoll) 每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
- 它和 worker 模式很像,最大的区别在于,它解决了 keepalive 场景下长期被占用的线程的资源浪费问题(某些线程因为被keepalive ,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
- event MPM 中,会有一个专门的线程来管理这些 keepalive 类型的线程
- 当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理
keepalive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许
它释放
缺点:没有线程安全控制
2.2 Nginx服务器
Nginx以其轻量级、高并发处理能力而受到青睐。它的事件驱动模型和高效的内存管理机制,使其在处理静态内容和代理服务时表现卓越。
3. 用户访问体验的重要性
3.1 用户速度体验原则
用户对网页加载速度的容忍度非常有限。根据1-3-10原则:
- 1秒内完成加载的网页提供最佳用户体验。
- 1-3秒内加载完成的网页用户体验较好。
- 3-10秒内加载完成的网页用户体验较差。
- 超过10秒未能加载完成的网页,用户将难以接受,可能导致大量用户流失。
3.2 影响用户体验的因素
客户端因素
- 硬件配置:客户端设备的处理能力影响页面渲染速度。
- 网络速率:用户的网络连接速度直接关系到数据加载时间。
- 地理距离:客户端与服务端的物理距离影响数据传输延迟。
服务器因素
- 网络速率:服务端的网络带宽和稳定性对响应速度至关重要。
- 硬件配置:服务器的CPU、内存和存储性能直接影响处理能力。
- 架构设计:服务端的软件架构和代码优化对性能有显著影响。
- 应用程序工作模式:如Apache和Nginx的不同工作模式对并发处理能力有差别。
- 并发数量:服务端能够同时处理的请求数量。
- I/O性能:磁盘和网络I/O性能影响数据处理和传输效率。
4. 服务端I/O流程与性能
服务端的I/O(输入/输出)性能是决定Web服务器响应速度的关键因素之一。了解服务端I/O流程对于优化Web服务器性能至关重要。
4.1 I/O基本概念
I/O是计算机中处理数据输入和输出的过程。在Web服务器中,I/O通常涉及磁盘I/O和网络I/O,它们共同决定了数据处理和传输的效率。
4.2 磁盘I/O
磁盘I/O涉及从磁盘读取或写入数据的过程。它包括以下几个关键步骤:
- 寻道时间:磁头移动到正确的磁道上所需的时间。
- 旋转延迟:磁盘旋转到数据所在扇区所需的时间。
- 数据传输时间:从磁盘读取数据到内存或相反过程所需的时间。
4.2.1 磁盘性能指标
- IOPS(每秒输入/输出操作数):衡量磁盘性能的主要指标,表示单位时间内系统能处理的I/O请求数量。
4.2.2 磁盘I/O计算方法
对于不同转速的磁盘,可以通过以下公式计算其最大IOPS:
- 7200转磁盘:IOPS=1000寻道时间+平均旋转延迟时间IOPS=寻道时间+平均旋转延迟时间1000
- 10000转磁盘:调整上述公式中的转速参数即可。
4.3 网络I/O
网络I/O涉及通过网络传输数据的过程。它包括以下步骤:
- 获取请求数据:客户端与服务器建立连接并发出请求。
- 构建响应:服务器接收请求,并在用户空间处理客户端的请求。
- 返回数据:服务器将构建好的响应通过内核空间的网络I/O发送回客户端。
4.3.1 网络I/O性能影响因素
- 带宽:网络连接的最大数据传输速率。
- 延迟:数据从客户端发送到服务器,再从服务器返回客户端所需的时间。
- 丢包率:网络中数据包丢失的比例,影响数据传输的可靠性。
5. I/O模型详解
在现代Web服务器和应用程序的设计中,I/O模型对于性能和可伸缩性起着至关重要的作用。理解不同的I/O模型可以帮助我们更好地编写高效、可扩展的代码。
5.1 I/O模型相关概念
5.1.1 同步与异步
- 同步(Synchronous):调用者在等待操作完成期间,不会接收到任何完成状态的通知,需要主动查询操作是否完成。
- 异步(Asynchronous):被调用者在操作完成时,通过状态、通知或回调机制主动通知调用者。
5.1.2 阻塞与非阻塞
- 阻塞(Blocking):在I/O操作完成之前,调用者无法执行其他任务。
- 非阻塞(Non-blocking):调用者在发起I/O请求后可以立即返回,无需等待操作完成。
5.2 网络I/O模型
5.2.1 阻塞型I/O模型
- 用户线程发起I/O请求后,必须等待操作完成才能继续执行其他任务。
- 优点:实现简单,CPU资源占用低。
- 缺点:在高并发场景下效率低,因为每个连接都需要独立的线程或进程。
5.2.2 非阻塞型I/O模型
- 用户线程发起I/O请求后立即返回,通过轮询机制不断检查I/O操作是否完成。
- 优点:可以在单个线程内处理多个I/O请求。
- 缺点:频繁的轮询可能导致CPU资源浪费。
5.2.3 多路复用I/O模型
- 通过系统调用(如select、poll、epoll)同时监控多个I/O请求。
- 优点:可以在单个线程内高效地处理大量并发连接。
- 缺点:在连接数较少时,效率可能不如多线程模型。
5.2.4 信号驱动式I/O模型
- 通过信号通知机制,在数据就绪时通知应用程序进行I/O操作。
- 优点:减少了无数据时的轮询,提高了效率。
- 缺点:在大量I/O操作时,信号队列可能溢出。
5.2.5 异步I/O模型
- 内核在I/O操作完成时主动通知应用程序。
- 优点:应用程序可以在等待I/O时执行其他任务,充分利用了系统资源。
- 缺点:实现复杂,需要操作系统的底层支持。
5.3 I/O模型的比较
5.3.1 性能对比
- 阻塞型I/O模型在低并发场景下简单易用,但在高并发场景下效率较低。
- 非阻塞型和多路复用I/O模型在高并发场景下表现更好,但实现复杂度较高。
- 异步I/O模型提供了最高的效率和可伸缩性,但需要更多的系统资源和复杂的编程模型。
5.3.2 实际应用选择
- 对于低并发需求,可以选择阻塞型I/O模型。
- 对于需要处理大量并发连接的服务器,多路复用或异步I/O模型更为合适。
6. 零拷贝
6.1零拷贝的概念
在传统的Linux系统中,标准I/O操作(如read和write)通常涉及数据在用户空间和内核空间之间的多次拷贝。这种数据拷贝过程不仅消耗CPU资源,而且随着数据量的增加,性能瓶颈也变得更加明显。
零拷贝是一种减少或消除数据在用户空间和内核空间之间拷贝的技术。它并不是完全没有拷贝,而是尽可能减少不必要的数据复制操作,从而提高效率。
6.2零拷贝相关技术
6.2.1 MMAP (Memory Mapping)
内存映射(MMAP)是一种允许进程通过内存地址空间直接访问文件内容的技术。使用mmap系统调用,文件内容被映射到进程的地址空间,避免了read和write调用中的额外数据拷贝。
6.2.2 SENDFILE
SENDFILE是一种高效的数据传输系统调用,它允许内核直接将文件数据发送到网络套接字,无需将数据先复制到用户空间的缓冲区。这种方式显著减少了数据拷贝的开销。
6.2.3 DMA辅助的SENDFILE
某些系统支持使用直接内存访问(DMA)来辅助SENDFILE操作,进一步提高数据传输的效率。
二、 Nginx架构与安装
1.Nginx 架构概述
1.1 Nginx 简介
Nginx(发音为“engine X”)最初由俄罗斯程序员Igor Sysoev开发,并于2004年首次公开发布。它以高稳定性、丰富的功能集和低资源消耗而闻名。
1.2 核心特性
- 模块化设计:易于扩展和定制。
- 高可靠性:支持平滑重载配置文件和升级程序,无需中断服务。
- 低内存消耗:优化的内存管理机制。
- 事件驱动:高效的事件处理机制,支持大量并发连接。
1.3 进程模型
Nginx采用多进程模型,主要由Master进程和Worker进程组成:
- Master进程:负责管理Worker进程,读取和验证配置文件,处理信号等。
- Worker进程:实际处理网络请求,执行具体业务逻辑。
2.Nginx 安装
2.1 安装前的准备
#下载并解压所需的安装包
[root@nginx ~]# ls
公共 下载 echo-nginx-module-0.63 nginx-1.26.1
模板 音乐 echo-nginx-module-0.63.tar.gz nginx-1.26.1.tar.gz
视频 桌面 eth160.nmconnection test.sh
图片 anaconda-ks.cfg nginx-1.24.0
文档 clear_mnt nginx-1.24.0.tar.gz
#解决依赖
[root@nginx ~]#dnf install gcc pcre-devel zlib-devel openssl-devel -y
[root@nginx ~]# cd nginx-1.24.0/
2.2 编译安装Nginx
#对nginx编译
[root@nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --add-module=/root/echo-nginx-module-0.63 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module
#找到makefile文件进行安装
[root@nginx nginx-1.24.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@nginx nginx-1.24.0]# make && make install
2.3.nginx启动文件编写
[root@nginx nginx-1.24.0]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss.lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
3平滑升级和回滚
有时候我们需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时 Nginx又在跑着业务无法停掉,这时我们就可能选择平滑升级
3.1平滑升级流程
- 将旧Nginx二进制文件换成新Nginx程序文件(注意先备份)
- 向master进程发送USR2信号
- master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin
- master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进程的PID存放至新生成的pid文件nginx.pid
- 向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止
- 向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件
- 如果发现升级有问题,可以回滚∶向老master发送HUP,向新master发送QUIT
3.2.平滑升级
3.2.1 解压新版本NGINX编译
[root@nginx ~]# tar -xzf nginx-1.26.1.tar.gz
[root@nginx ~]# cd nginx-1.26.1/
[root@nginx nginx-1.26.1]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@nginx nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --add-module=/root/echo-nginx-module-0.63 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module
[root@nginx nginx-1.26.1]# make