ThankNeko's Blog ThankNeko's Blog
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)

Hoshinozora

尽人事,听天命。
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)
  • 操作系统

  • 虚拟化服务

  • 数据库服务

  • 监控服务

  • Web服务

    • Nginx笔记

      • HTTP/HTTPS介绍
      • Nginx介绍与部署
      • Nginx配置与常用模块
      • Nginx负载均衡
      • Nginx优化
        • 服务性能优化介绍
          • 服务优化前提
          • 影响性能的指标
          • 根据OSI模型进行服务优化
          • ab压测工具
        • Nginx服务优化
          • 加大文件描述符
          • time_wait复用
          • Nginx代理长连接优化
          • Nginx代理优化
          • CPU亲和优化
          • 静态资源缓存
          • 静态资源读取
          • 静态资源压缩
          • 防止资源盗链
    • Tomcat笔记

  • 数据处理

  • Ops
  • Web服务
  • Nginx笔记
Hoshinozora
2023-03-30
目录

Nginx优化

# 服务性能优化介绍

# 服务优化前提

  • 了解当前系统最高能承担多少请求和并发
    • 一般在访问低峰期、或者下线时进行测试。
    • 了解当前系统的状态,通过top查看系统的CPU负载、内存使用率、和总的运行进程等,也可以通过stub_status模块查看站点情况。
    • 了解当前使用的服务,每个服务最大能支撑多大并发,QPS每秒查询率的访问请求最高瓶颈是多少。
  • 了解业务的场景模式
    • 了解流量的高峰期、低峰期等。
  • 了解系统层次化结构
    • 比如使用Nginx是用做代理、还是动静分离、还是后端服务等。
    • 同时对每一层服务进行梳理,服务之间的调用关系,调用时的短板和问题等。
  • 考虑性能和安全的平衡

# 影响性能的指标

  • 网络
    • 网络的流量。网络是否丢包,这些是否影响http的请求与调用。
  • 系统
    • 硬件有没有磁盘损坏、磁盘速率,系统负载、内存、系统稳定性。
  • 服务
    • 连接优化、请求优化,根据业务形态做对应的服务设置。
  • 程序
    • 接口性能、处理速度、程序执行效率,优化程序的效率一般是开发的职责。
  • 数据库
    • 数据库增删改查是否阻塞业务流程。
    • SQL语句是否使用到索引。

# 根据OSI模型进行服务优化

  • 硬件
    • 代理服务要考虑CPU、静态资源要考虑磁盘IO、动态资源要考虑CPU、内存。
  • 网络
    • 按业务需求,越快越好。
  • 系统
    • 优化文件描述符。
      • Linux中一切皆文件,读取打开文件、接收连接等都会占用描述符,系统默认是最大1024,一般是不够的所以需要优化。
      • 可通过进程PID在/proc/[进程PID]/fd/中查看打开的文件描述符。
  • 应用
    • 服务与服务之间保持长连接,比如开启http1.1。
  • 服务
    • 静态资源优化,比如增加缓存等。
    • 动静分离,不同的服务处理不同的请求。

# ab压测工具

  • 在系统业务量增长之前,我们就需要做好相应准备,以防压力徒增带来的接口压力,所以一般会提前进行压力测试,然后根据评估结果来拟定相应对策。

  • 一般会先测压静态资源,再测压动态资源,以此找到系统的短板。

  • 安装ab压测工具

    yum install -y httpd-tools
    
    1
  • ab命令

    • ab -n 200 -c5 http://127.0.0.1/
      • -n - 总的请求次数
      • -c - 并发请求数
      • -k - 是否开启长连接
  • 压测信息解释

    • Document Path - 测试页面路径
    • Document Length - 测试页面大小
    • Concurrency Level - 并发级别
    • Time take for tests - 完成请求总时间
    • Complete requests - 总请求次数
    • Failed requests - 请求失败次数
    • Write errors - 错误页面次数
    • Total transferred - 请求产生的总流量大小
    • HTML transferred - HTML页面传输的总大小
    • Requests per second - 每秒最多能处理的次数(重点需要关注的信息)
    • Time per request - 每一客户端的请求时间
    • Time per request - 每一请求的处理时间
    • Transfer rate - 传输的速率

# Nginx服务优化

# 加大文件描述符

  • 文件描述符会随着我们进程调用的增加而增加,而系统默认的最大文件句柄数一般是不够使用的。因为作为服务端,TCP连接过多时连接文件会占用文件描述符资源,此时如果文件描述符触发了限制,就可能无法建立新的连接,所以一般会对文件描述符限制进行合理的调整。

  • 文件描述符配置方法

    # 编辑文件描述符限制配置文件
    vim /etc/security/limits.conf
    
    # 在其中添加以下配置即可
    # 全部用户修改限制
    * soft nofile 65535
    * hard nofile 65535
    
    # 指定用户修改限制
    nginx soft nofile 65535
    nginx hard nofile 65535
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    • 第一列为nginx表示针对nginx用户进行限制,如果为*则表示所有用户。
    • 第二列为soft表示对单个服务软件最大文件描述符数进行限制。
    • 第二列为hard表示对整个服务器硬件最大文件描述符数进行限制。
    • nofile [num]表示定义限制的最大文件描述符数,文件描述符的数量限制应当根据内存大小来决定,文件描述符设的很大,但是内存不够也没有什么用,反而还可能内存溢出。
  • 相关命令

    • ulimit -a - 显示当前所有的资源限制。
    • lsof -p [PID] - 查看进程打开的文件描述符。

# time_wait复用

  • 作为TCP连接发起方时,如果 TIME_WAIT 状态过多,就可能会占满了所有端口资源,最终导致无法创建新连接。如果出现该问题,应当排查是异常原因引起还是正常原因导致的,如果只是单纯的正常连接很多,则我们可以通过调整内核参数来开启time_wait复用来进行优化。

  • 调整内核参数

    vim /etc/sysctl.conf
    
    # 在配置文件中添加
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_timestamps = 1
    
    1
    2
    3
    4
    5
    • time_wait复用配置只对TCP连接发起方(客户端)有意义。
    • 另外客户端和服务端都需要配置net.ipv4.tcp_timestamps = 1才有效。
    • 调整完后通过sysctl -p检查即可。

# Nginx代理长连接优化

  • Nginx代理作为转发用户请求的媒介,可以通过设置keepalive长连接来减少握手次数、提高效率、减少资源消耗。

  • 配置方式

    upstream test {
        server 10.0.0.7:80;
        keepalive 32;
        # keepalive_requests 100;
    }
    
    1
    2
    3
    4
    5
    • keepalive 32 - 表示集群后端的每个Worker接收的最大长连接数。
    • keepalive_requests 100 - 表示一次长连接的最大的请求次数,当请求数超过将会关闭连接。如果并发请求超过了该值,Nginx也会启动新的转发请求,新请求建立的也是长连接,但可能会造成大量的time_wait,需要使time_wait状态可复用。

# Nginx代理优化

  • 常用且通用的配置参数可以保存到另外的文件,如proxy_params.conf,然后使用include导入,使配置文件看上去更简洁、可读。

  • 配置方式

    # 继承客户端请求的Host信息进行转发,访问正确的server_name(一般必加)
    proxy_set_header Host $http_host;
    
    # 日志显示访问用户IP(一般必加)
    proxy_set_header X-Forward-For $remote_addr;
    
    # 清除"connection"头字段
    proxy_set_header Connection "";
    
    # 代理连接web超时时间
    proxy_connect_timeout 30s;
    
    # 代理等待web响应超时时间
    proxy_read_timeout 60s;
    
    # web回传数据至代理超时时间
    proxy_send_timeout 60s;
    
    # 开启代理缓冲区,web回传数据至缓冲区,代理边收边传返回给客户端
    proxy_buffering on;
    
    # 代理接收web响应的头信息的缓冲区大小
    proxy_buffer_size 32k;
    
    # 缓冲代理接收单个长连接内包含的web响应的数量和大小
    proxy_buffers 4 128k;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

# CPU亲和优化

  • CPU亲和可以减少进程之间的频繁切换,减少性能消耗。

  • 配置前worker在需要处理任务时,由于CPU核心已经被其他worker占用了,而占用的worker又没有处于工作状态,那么要处理任务的worker就会抢占使用这个CPU核心,这样就会造成来回的切换,就会造成系统性能的消耗。

  • 配置后CPU亲和会将CPU核心和worker进行进行绑定,将每个worker进程固定到对应的cpu上执行,这样就能提高CPU缓存命中率,获得更好的性能。

  • 配置方式

    # 主配置文件中添加配置
    
    # 或者等于核心数的1-1.5倍
    worker_processes auto;
    # CPU亲和,绑定CPU
    worker_cpu_affinity auto;
    
    1
    2
    3
    4
    5
    6
  • 查看CPU核心数

    • lscpu命令
      • 其中的CPU(s)就是总核心数。

# 静态资源缓存

  • 设置浏览器缓存可提高网站性能,使用户第一次访问后,数据在用户的浏览器中长时间缓存,这样下次用户访问相同资源时,就可以直接使用浏览器本地的缓存了。

  • 缓存原理

    • 浏览器缓存机制是基于HTTP协议缓存机制实现的,它依赖于特殊的头信息来与服务器进行特殊的验证,如:Expires (本地缓存过期具体时间)、Cache-control (本地缓存过期时长,为0表示不缓存)
    • 浏览器无缓存时
      • 浏览器请求 --> 无缓存 --> 请求WEB服务器 --> 请求响应、协商 --> 呈现。
    • 浏览器有缓存时
      • 浏览器请求 --> 有缓存 --> 校验是否过期 --> 呈现。
  • 浏览器过期校验检查机制

    • 浏览器请求服务器会先在本地检查缓存中数据是否过期,如果没有过期则直接从缓存文件中取。
    • 如果缓存过期,首先检查是否存在ETag,ETag类似于文件MD5加密的值。
    • 如果ETag存在,则客户端会向web服务器携带if-None-Match头信息进行请求,然后服务器会将if-None-Match值与etag值进行比对,如果一致则表示缓存只是过期,而数据并没有改变,然后由服务器决策返回200还是304。
    • 如果ETag不存在,则会进行last-Modified检查验证,last-Modified是缓存中文件最后修改时间。客户端会向web服务器携带if-Modified-Since头信息进行请求,然后服务器会将if-None-Match值与last-Modified值进行比对,如果一致则表示缓存只是过期,而数据并没有改变,然后由服务器决策返回200还是304。
  • 静态资源配置缓存

    # 如果请求的资源是静态资源则进行缓存
    location ~ \.*(jpg|png|jpeg|gif)$ {
        expires 1d;
    }
    
    1
    2
    3
    4
    • expires 1d; - 缓存过期时长,h时、d天、m月、y年。
  • 关闭缓存配置

    add_header Cache-Control no-store;
    add_header Pragma no-cache;
    
    1
    2

# 静态资源读取

  • sendfile

    • sendfile参数用于提高静态资源的读取效率,在主配置文件中默认是开启的。

    • 提高效率的原理

      # 传统处理文件方式
      # 应用读取磁盘的文件资源需要由内核调用,然后再到程序的用户空间中,然后再到内核空间,最后才由socket服务发送出去
      文件 -> 内核空间 -> 用户空间 -> 内核空间 -> Socket
      
      # sendfile处理文件方式
      # 只经过内核空间直接发出,大大提高读取效率
      文件 -> 内核空间 -> Socket
      
      1
      2
      3
      4
      5
      6
      7
  • tcp_nopush

    • tcp_nopush参数用于将多个包一次发送,提高大文件的网络传输效率,一般大文件或者静态资源传输建议打开,但建议不要在相同区域和tcp_nodelay一起开。

      # 需要启用sendfile才能使用
      Syntax: tcp_nopush on | off;
      Default: tcp_nopush off;
      Context: http,server,location
      
      1
      2
      3
      4
    • 配置方式

      # 在需要使用的location中配置即可
      location /doc {
          ... ...
          tcp_nopush on;
      }
      
      1
      2
      3
      4
      5
  • tcp_nodelay

    • tcp_nodelay参数用于提高网络数据传输的实时性,一般实时性要求比较高的文件或者动态资源建议打开,但建议不要在相同区域和tcp_nopush一起开。

      # 需要启用keepalive_timeout才能使用
      Syntax: tcp_nopush on | off;
      Default: tcp_nopush off;
      Context: http,server,location
      
      1
      2
      3
      4
    • 配置方式

      # 在需要使用的location中配置即可
      location /video {
          ... ...
          tcp_nodelay on;
      }
      
      1
      2
      3
      4
      5

# 静态资源压缩

  • 压缩静态资源可以有效节省带宽,并提高响应数据传输速度,配置后Nginx在响应报文发送至客户端之前进行压缩,然后再进行传输,浏览器收到之后再进行解压。

    # 开启压缩
    Syntax: gzip on | off;
    Default: gzip off;
    Context: http,server,location,if in location
    
    # 定义压缩类型,定义需要压缩的资源文件,资源类型可以在/etc/nginx/mime.types中查看或定义
    Syntax: gzip_types mime-type ... ;
    Default: gzip_types text/html;
    Context: http,server,location
    
    # 定义压缩的级别(比率),一般3即可
    # 压缩比率越高,传输效率越高,但是服务器压缩时、客户端解压时使用的CPU资源也会变高,所以适当即可
    Syntax: gzip_comp_level [level number];
    Default: gzip_comp_level 1;
    Context: http,server,location
    
    # 定义压缩协议版本,选择1.1版本即可,但因为默认就是1.1版本所以可不写
    Syntax:	gzip_http_version 1.0 | 1.1;
    Default:	gzip_http_version 1.1;
    Context:	http, server, location
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • 配置方式

    # 匹配需要压缩的资源进行压缩配置即可
    location ~* \.(html|txt)$ {
        gzip on;
        gzip_types text/html text/plain;
        gzip_comp_level 3;
    }
    
    1
    2
    3
    4
    5
    6

# 防止资源盗链

  • 防止其他网站恶意盗用自己网站的资源链接,从而减少不必要的带宽、系统等资源的浪费。

  • 防盗链的方法有很多种,Nginx自带的防盗链功能主要是针对客户端请求时的请求头来进行验证,客户端在请求的过程中会携带的referer信息,referer会告诉服务器请求是从哪一个页面来的,然后Nginx可以根据referer信息进行防盗链。这种方式的优点是规则简单、配置方便,缺点是referer信息可以被伪造,非100%可靠,但它能限制大部分的盗链情况。

    # 添加信任引用列表
    # 如果来源域名不在该列表中,则$invalid_referer会返回1,我们可以对此进行判断进行处理
    Syntax:	valid_referers none | blocked | server_names | string ...;
    Default: —
    Context: server, location
    
    # none - 表示来源头部为空的情况
    # blocked - 表示来源头部不为空的情况
    # server_names - 来源头部包含的域名情况 (可正则匹配)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 配置方式

    # 拒绝访问
    location *~ \.(jpg|jpeg|gif|png)$ {
        # 允许referer中域名为*.test.com的请求进行访问,其他的则拒绝
        valid_referers none blocked *.test.com;
        if ($invalid_referer) {
            return 403;
        }
    }
    
    # 替换图片,可以替换成一张有水印的图片
    location *~ \.(jpg|jpeg|gif|png)$ {
        # 允许referer中域名为*.test.com的域名进行访问,其他的则拒绝
        valid_referers none blocked *.test.com;
        if ($invalid_referer) {
            # break表示重写完后就停止匹配
            rewrite ^(.*)$ /public/ks.jpg break;
        }
    }
    
    # 允许搜索引擎盗用
    location *~ \.(jpg|jpeg|gif|png)$ {
        # 允许referer中的域名为*.test.com的请求和域名中包含.baidu的请求进行访问,其他的则拒绝
        valid_referers none blocked *.test.com server_names ~\.baidu\.;
        if ($invalid_referer) {
            return 403;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
#Web#Nginx
Nginx负载均衡
Tomcat介绍与部署使用

← Nginx负载均衡 Tomcat介绍与部署使用→

最近更新
01
二〇二五年四月十七日随笔
04-17
02
二〇二五年四月十六日随笔
04-16
03
二〇二五年四月九日随笔
04-09
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Hoshinozora | MIT License
湘ICP备2022022820号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式