Nginx学习课题

2019-07-11

Nginx概述

Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

Nginx基础架构

  • 源码目录结构
.
├── auto            自动检测系统环境以及编译相关的脚本
│   ├── cc          关于编译器相关的编译选项的检测脚本
│   ├── lib         Nginx编译所需要的一些库的检测脚本
│   ├── os          与平台相关的一些系统参数与系统调用相关的检测
│   └── types       与数据类型相关的一些辅助脚本
├── conf            存放默认配置文件,在make install后,会拷贝到安装目录中去
├── contrib         存放一些实用工具,如geo配置生成工具(geo2nginx.pl)
├── html            存放默认的网页文件,在make install后,会拷贝到安装目录中去
├── man             Nginx的man手册
└── src             存放Nginx的源代码
    ├── core        Nginx核心源代码,包括常用数据结构的定义,及Nginx初始化运行的核心代码如main函数
    ├── event       对系统事件处理机制的封装,以及定时器的实现相关代码
    │   └── modules 不同事件处理方式的模块化,如select、poll、epoll、kqueue等
    ├── http        Nginx作为http服务器相关的代码
    │   └── modules 包含http的各种功能模块
    ├── mail        Nginx作为邮件代理服务器相关的代码
    ├── misc        一些辅助代码,测试c++头的兼容性,以及对google_perftools的支持
    └── os          主要是对各种不同体系统结构所提供的系统函数的封装,对外提供统一的系统调用接口
  • Nginx工作代码包括核心和功能模块。 Nginx的核心是负责维护严格的运行循环,并在请求处理的每个阶段执行模块代码的适当部分。模块构成了大部分的演示和应用层功能。模块读取和写入网络和存储,转换内容,执行出站过滤,应用服务器端包含操作,并在启用代理时将请求传递给上游服务器。
  • Nginx的模块化架构通常允许开发人员扩展一组Web服务器功能,而无需修改Nginx内核。 Nginx模块略有不同,即核心模块,事件模块,阶段处理程序,协议,可变处理程序,过滤器,上游和负载均衡器。此时,Nginx不支持动态加载的模块;即在构建阶段将模块与核心一起编译。然而,对于未来的主要版本,计划对可加载模块和ABI的支持。
  • 在处理与接受,处理和管理网络连接和内容检索相关的各种操作时,Nginx在基于Linux,Solaris和BSD的操作系统中使用事件通知机制和一些磁盘I / O性能增强,如kqueue,epoll,和事件端口。目标是为操作系统提供尽可能多的提示,以便及时获取入站和出站流量,磁盘操作,读取或写入套接字,超时等异步反馈。对于每个基于Unix的Nginx操作系统,大量优化了对多路复用和高级I / O操作的不同方法的使用。

Nginx的架构设计

  • 优秀的模块化设计
  • 事件驱动架构
  • 请求多阶段异步处理
  • 管理进程多工作的设计

Nginx架构图:

image

Nginx多层次结构图:

image

Nginx处理事件模型图:

image

Nginx主要优点

  • 热部署

得益于master管理进程与worker工作进程的分离设计,使的Nginx具有热部署的功能,那么在7×24小时不间断服务的前提下,升级Nginx的可执行文件。也可以在不停止服务的情况下修改配置文件,更换日志文件等功能。

  • 高并发

Nginx在网络应用中表现超群,在于其独特的设计。许多网络或应用服务器大都是基于线程或者进程的简单框架,最突出的地方就在于其成熟的事件驱动框架,它能应对现代硬件上成千上万的并发连接,10万远未封顶。

  • 低内存消耗

在一般的情况下,10000个非活跃的HTTP Keep-Alive 连接在Nginx中仅消耗2.5M的内存,这也是Nginx支持高并发连接的基础。

  • 处理响应请求快

在正常的情况下,单次请求会得到更快的响应。在高峰期,Nginx可以比其他的Web服务器更快的响应请求。

  • 高可用性

对于访问量巨大的网站,面对高负载Nginx + keepalived 可对前端Nginx实现HA高可用。

Nginx反向代理与负载均衡原理

  • 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。Nginx在做反向代理时,提供性能稳定,并且能够提供配置灵活的转发功能。Nginx可以根据不同的正则匹配,采取不同的转发策略,比如图片文件结尾的走文件服务器,动态页面走web服务器,只要你正则写的没问题,又有相对应的服务器解决方案,你就可以随心所欲的玩。并且Nginx对返回结果进行错误页跳转,异常判断等。如果被分发的服务器存在异常,他可以将请求重新转发给另外一台服务器,然后自动去除异常服务器。

    Nginx反向代理工作流程如下:

    image

  • 负载均衡(Load Balance)是指将请求分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

    Nginx支持的负载均衡调度算法方式如下:

    1.weight轮询(默认):接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,nginx会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。 这种方式下,可以给不同的后端服务器设置一个权重值(weight),用于调整不同的服务器上请求的分配率;权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。

    2.ip_hash:每个请求按照发起客户端的ip的hash结果进行匹配,这样的算法下一个固定ip地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下session共享的问题。

    3.(fair)(第三方):智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配,响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少;结合了前两者的优点的一种调度算法。但是需要注意的是Nginx默认不支持fair算法,如果要使用这种调度算法,请安装upstream_fair模块

    4.url_hash(第三方):按照访问的url的hash结果分配请求,每个请求的url会指向后端固定的某个服务器,可以在nginx作为静态服务器的情况下提高缓存效率。同样要注意nginx默认不支持这种调度算法,要使用的话需要安装nginx的hash软件包

    轮询算法流程图:

    image

    Ip hash算法流程图:

    image

Nginx web运维实验

一、实验环境

准备3台虚拟机,其中一台搭建Nginx代理服务器,另外两台搭建测试服务器,实现使用Nginx的反向代理与负载均衡模块配置基于域名主机的访问。在整个实验环境中,我们假定webserver-1和webserver-1提供pzy.nginx.com的网站内容服务,Nginx在webserver-1和webserver-2前面作为反向代理服务器与负载均衡服务器,当用户访问pzy.nginx.com时,Nginx负载均衡器会把请求分发到两个节点服务器上,由节点服务器返回实际的内容数据。

主机类型 操作系统 IP地址 作用
宿主机 MacOS 10.14 192.168100.1/24 远程3台虚拟机,进行配置,同时也作为测试使用的客户端。
虚拟机1:lb-1 CentOS 7.4 192.168.100.105/24 用作负载均衡服务器和代理服务器,将请求分担到Web节点服务器中
虚拟机2:webserver-1 CentOS 7.4 192.168.100.106/24 Web节点服务器webserver-1
虚拟机3:webserver-2 CentOS 7.4 192.168.100.107/24 Web节点服务器webserver-2

实验拓扑:

image

二、环境搭建

  • 在webserver-1服务器上安装apache
# 在webserver-1上安装httpd服务
[root@webserver-1 ~]# yum -y install httpd
# 修改默认主页内容为"webserver-1 is ok"
[root@webserver-1 ~]# echo "webserver-1 is ok" > /var/www/html/index.html
# 启动htppd并设为开机自启动
[root@webserver-1 ~]# systemctl start httpd
[root@webserver-1 ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
# 关闭并禁用防火墙
[root@webserver-1 ~]# systemctl stop firewalld
[root@webserver-1 ~]# systemctl disable firewalld
# 修改默认监听端口为8080
[root@webserver-1 ~]# vim /etc/httpd/conf/httpd.conf
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses.
#
#Listen 12.34.56.78:80
Listen 8080
# 重启httpd
[root@webserver-1 ~]# systemctl restart httpd
# 查看httpd监听端口
[root@webserver-1 ~]# netstat -anlpt | grep httpd
tcp6       0      0 :::8080                 :::*                    LISTEN      6955/httpd
# 访问测试
[root@webserver-1 ~]# curl 192.168.100.106:8080
webserver-1 is ok

webserver-2按照webserver-1的步骤执行即可,不同的地方是将监听端口改为9090。在本地浏览器上输入http://192.168.100.106:8080和http://192.168.100.107:9090可以分别打开如下网页:

image

image

  • 在服务器lb-1上编译安装Nginx

1.到官网上查看最新稳定版为nginx-1.16.0

# 安装nginx依赖包
[root@lb-1 ~]# yum -y install pcre-devel zlib-devel gcc-c++ 
# 下载Nginx-1.16.0
[root@lb-1 ~]# wget http://nginx.org/download/nginx-1.16.0.tar.gz
# 解压安装包
[root@lb-1 ~]# tar zxvf nginx-1.16.0.tar.gz
# 配置并检查依赖,添加用户和组nginx
[root@lb-1 nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
# 添加系统用户nginx
[root@lb-1 nginx-1.16.0]# useradd -s /sbin/nologin nginx -M
[root@lb-1 nginx-1.16.0]# tail -l /etc/passwd
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
nginx:x:1000:1000::/home/nginx:/sbin/nologin
# 加速编译
[root@lb-1 nginx-1.16.0]# make -j 33
# 编译安装
[root@lb-1 nginx-1.16.0]# make install
# 添加软链接
[root@lb-1 nginx-1.16.0]# ln -s /usr/local/nginx/sbin/nginx  /usr/sbin/
# 测试nginx语法
[root@lb-1 nginx-1.16.0]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

2.配置nginx

[root@lb-1 nginx-1.16.0]# vim /usr/local/nginx/conf/nginx.conf
user  nginx;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
    #接受尽可能多的链接
    multi_accept on;
    #设置轮询方法
    use epoll;
}


http {
    #关闭错误页面中版本号
    server_tokens off;
    #发送所有头文件,不要缓存数据
    tcp_nopush on;
    tcp_nodelay on;
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;
    #缓冲数据
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    upstream webserver {
			server 192.168.100.106:8080 weight=10;
			server 192.168.100.107:9090 weight=10;

        }
    server {
        listen       80;
        server_name  pzy.nginx.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
	          proxy_pass http://webserver;
        }
	      #添加日志
	      access_log /var/logs/nginx/access_log;

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

3.配置完成后重启nginx并检查语法

[root@lb-1 nginx-1.16.0]# nginx -s reload
[root@lb-1 nginx-1.16.0]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

4.查看nginx监听状态

root@lb-1 nginx-1.16.0]# netstat -anlpt | grep nginx
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      10315/nginx: master

5.创建日志目录

[root@lb-1 nginx-1.16.0]# mkdir -p /var/logs/nginx/

6.修改本地主机hosts文件

pzy# vim /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1	localhost
255.255.255.255	broadcasthost
::1             localhost

192.168.100.105 pzy.nginx.com

三、负载均衡测试

在新的窗口中动态查看日志信息

[root@lb-1 ~]# curl pzy.nginx.com
webserver-1 is ok
[root@webserver-1 ~]# curl pzy.nginx.com
webserver-2 is ok
[root@webserver-1 ~]# curl pzy.nginx.com
webserver-1 is ok
[root@lb-1 ~]# tail -f /var/logs/nginx/access_log

查看日志,可以看到各个节点的访问请求

image

浏览器访问pzy.nginx.com刷新,我们可以看到两种页面,说明nginx已经把我们的请求分发到不同的地方去了,已实现轮询

image

image

四、Nginx参数优化

  • 配置整理
# 运行用户
user www-data;    
# 启动进程,通常设置成和cpu的数量相等
worker_processes  1;

# 全局错误日志及PID文件
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

# 工作模式及连接数上限
events {
    use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
    worker_connections 1024; #单个后台worker process进程的最大并发链接数
    # multi_accept on; 
}

#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
    #设定mime类型,类型由mime.type文件定义
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    #设定日志格式
    access_log    /var/log/nginx/access.log;

    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    #必须设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.
    sendfile        on;
    #将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞
    tcp_nopush      on;
    tcp_nodelay     on;
    #连接超时时间
    keepalive_timeout  65;

    #开启gzip压缩
    gzip  on;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    #设定请求缓冲
    client_header_buffer_size    1k;
    large_client_header_buffers  4 4k;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    #设定负载均衡的服务器列表
    upstream mysvr {
        #weigth参数表示权值,权值越高被分配到的几率越大
        #本机上的Squid开启3128端口
        server 192.168.8.1:3128 weight=5;
        server 192.168.8.2:80  weight=1;
        server 192.168.8.3:80  weight=6;
    }


    server {
        #侦听80端口
        listen       80;
        #定义使用www.xx.com访问
        server_name  www.xx.com;

        #设定本虚拟主机的访问日志
        access_log  logs/www.xx.com.access.log  main;

        #默认请求
        location / {
            root   /root;      #定义服务器的默认网站根目录位置
            index index.php index.html index.htm;   #定义首页索引文件的名称

            fastcgi_pass  www.xx.com;
            fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name; 
            include /etc/nginx/fastcgi_params;
        }

        # 定义错误提示页面
        error_page   500 502 503 504 /50x.html;  
            location = /50x.html {
            root   /root;
        }

        #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            root /var/www/virtual/htdocs;
            #过期30天,静态文件不怎么更新,过期可以设大一点,如果频繁更新,则可以设置得小一点。
            expires 30d;
        }
        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ \.php$ {
            root /root;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /home/www/www$fastcgi_script_name;
            include fastcgi_params;
        }
        #设定查看Nginx状态的地址
        location /NginxStatus {
            stub_status            on;
            access_log              on;
            auth_basic              "NginxStatus";
            auth_basic_user_file  conf/htpasswd;
        }
        #禁止访问 .htxxx 文件
        location ~ /\.ht {
            deny all;
        }

    }

    #第一个虚拟服务器
    server {
        #侦听192.168.8.x的80端口
        listen       80;
        server_name  192.168.8.x;

        #对aspx后缀的进行负载均衡请求
        location ~ .*\.aspx$ {
            root   /root;#定义服务器的默认网站根目录位置
            index index.php index.html index.htm;#定义首页索引文件的名称

            proxy_pass  http://mysvr;#请求转向mysvr 定义的服务器列表

            #以下是一些反向代理的配置可删除.
            proxy_redirect off;

            #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            client_max_body_size 10m;    #允许客户端请求的最大单文件字节数
            client_body_buffer_size 128k;  #缓冲区代理缓冲用户端请求的最大字节数,
            proxy_connect_timeout 90;  #nginx跟后端服务器连接超时时间(代理连接超时)
            proxy_send_timeout 90;        #后端服务器数据回传时间(代理发送超时)
            proxy_read_timeout 90;         #连接成功后,后端服务器响应时间(代理接收超时)
            proxy_buffer_size 4k;             #设置代理服务器(nginx)保存用户头信息的缓冲区大小
            proxy_buffers 4 32k;               #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
            proxy_busy_buffers_size 64k;    #高负荷下缓冲大小(proxy_buffers*2)
            proxy_temp_file_write_size 64k;  #设定缓存文件夹大小,大于这个值,将从upstream服务器传
        }
    }
}
  • 优化nginx进程个数的策略

    在高并发、高访问量的web服务场景,需要事先启动好更多的nginx进程,以保证快速响应并处理大量并发用户的请求。

    worker_processes 1;一般调整到与CPU的核数相同(如,2个四核的cpu计为8)

    # 查看LInux可查看CPU个数及总核数
    grep processor /proc/cpuinfo|wc -l
    # 查看CPU总颗数
    grep 'physical id' /proc/cpuinfo|sort|uniq|wc -l
    # 通过执行top命令,然后按数字1,即可显示所有的CPU核数
    top  按1键就会显示第一个的信息
    Cpu0  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0
    
  • 优化绑定不同的nginx进程到不同的CPU上

    默认情况下,nginx的进程跑在某一个CPU或CPU的某一个核上,导致nginx进程使用硬件的资源不均,本节的优化是不同的nginx进程给不同的CPU处理,充分有效的利用有效的硬件资源

    # 四核cpu配置
    worker_processes    4;
    worker_cpu_affinity 0001 0010 0100 1000;
    # 双核配置
    worker_processes    2;
    worker_cpu_affinity 0101 1010;
    

    还有一个命令taskset -c用来分配服务给CPU     

  • 开启高效传输模式

    sendfile   on;
    tcp_nopush on;
    tcp_nodelay on;
    server_tokens off;
    server_names_hash_bucket_size 128;
    server_names_hash_max_size 512;
    keepalive_timeout  65;
    client_header_timeout 15s;
    client_body_timeout 15s;
    send_timeout 60s;

五、Nginx监控

  • 通过安装http_stub_status_module模块实现页面监控展示
# 查看模块安装情况
[root@lb-1 nginx-1.16.0]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.16.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
# 修改配置文件nginx.conf,在server块中增加
location /nginx_status {
	# 开启nginx状态监控
	stub_status    on;
	# 关闭日志
	access_log    off;
	# Security: Only allow access from 192.168.100.1 IP #
	allow 192.168.100.1;
	# Send rest of the world to /dev/null #
	#deny all;
}
# 重启nginx
[root@lb-1 nginx-1.16.0]# nginx -s reload

本地浏览器输入192.168.100.105/nginx_status查看监控状态

Active connections: 1 
server accepts handled requests
 9 9 79 
Reading: 0 Writing: 1 Waiting: 0 

ctive connections:与后端建立的服务连接数

server accepts handled requests:Nginx总共处理了9个连接,成功创建了9次握手,总共处理了79个请求

Reading:nginx读取到客户端的Header信息数

Writing:nginx返回到客户端的Header信息数

Waiting:开启Keep-alive的情况下,这个值等于 Active -(Reading + Writing)。表示nginx已经处理完成,正在等候下次一次请求的连接数。

说明:如果Reading + Writing数量比较高,表示当前并发很大;如果Waiting较大,表示处理的很快,已经在等待之后的请求了。

  • 通过命令查看监控详情

1.查看哪些ip正在连接

[root@lb-1 ~]# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN
tcp        0      0 192.168.100.105:22      192.168.100.1:51630     ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN
tcp6       0      0 ::1:25                  :::*                    LISTEN
udp        0      0 127.0.0.1:323           0.0.0.0:*
udp6       0      0 ::1:323                 :::*
raw6       0      0 :::58                   :::*                    7

2.查看当前Nginx运行状态

[root@lb-1 ~]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 1

CLOSE_WAIT:表示被动关闭

ESTABLISHED:当前并发连接数

TIME_WAIT:主动关闭,处理完毕,等待超时结束的连接数

3.查看Web服务和Nginx进程数

[root@lb-1 ~]# ps -ef | grep httpd | wc -l
1
[root@lb-1 ~]# ps -ef | grep nginx | wc -l
3

4.查看http占用内存的平均数

[root@lb-1 ~]# ps aux|grep -v grep|awk '/httpd/{sum+=$6;n++};END{print sum/n}'
976

5.查看Nginx中访问前10的ip

# 格式:awk '{print $1}' 日志文件路径 | sort | uniq -c | sort -nr -k1 | head -n 10
[root@lb-1 ~]# awk '{print $1}' /var/logs/nginx/access_log | sort
192.168.100.1
192.168.100.1
192.168.100.1
192.168.100.1
192.168.100.1
192.168.100.1

...