阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

高性能Web服务器Nginx使用指南

436次阅读
没有评论

共计 22802 个字符,预计需要花费 58 分钟才能阅读完成。

Nginx 是一个高性能的 http 服务器和反向代理服务器,是一个高度模块化的 web 服务器,和 Apache 的模块化不同,Nginx 的模块不支持动态编译,Nginx 要加入新的第三方模块的时候,必须先下载模块,然后重新编译 Nginx,而 Apache 只需要将新加入的模块编译成 so 文件,然后配置文件指定是否加载即可,无需重新编译 Apache。并且 Nginx 的 rewrite 模块会使用正则表示式进行匹配,因此需要 pcre 软件库的支持,另外 ssl 加密需要 openssl-devel 软件库的支持,gzip 压缩传输需要 zlib-devel 软件库的支持。编译安装 Nginx 之前确定这三个软件库已经安装。

目录

  • Nginx 的配置文件结构

  • Nginx 的配置文件参数

  • 虚拟主机

  • LNMP 架构

  • 状态监控页面

  • URL 重写

  • Nginx 的负载均衡功能

  • Nginx 的缓存服务器应用

  • Nginx 的性能优化

  • Nginx 的 I / O 模型

1.Nginx 的配置文件结构

通过 epel 源安装的 Nginx 的配置文件在 /etc/nginx/ 目录下,对于编译安装的 Nginx,其配置文件在安装目录下的 conf 目录下,Nginx 配置文件以 block 块的形式组织,每个 block 以 {…} 为界限,block 块中包含各种指令。整体结构分为 main 层、events 块、http 块,main 是最高层,从上到下继承,位于 main 层的指令会向下继承至 events 和 http,events 块指令会继承至 http。http 往下分为多个 server 块,server 块再往下分为 location 块,继承关系是从外到内。

高性能 Web 服务器 Nginx 使用指南高性能 Web 服务器 Nginx 使用指南

一个完整的 Nginx 的配置结构如下,

…              #全局块,包含 main 层指令,同时包含 events 块和 http 块
 
events {#events 块,包含 events 指令
  …
}
http                    #http 块,包含 http 指令和多个 server 块
{
    …                #http 全局指令块
    server        #server 块
    {
        …      #server 全局指令块
        location [PATTERN]  #location 块
        {
            …
        }
        location [PATTERN]
        {
            …
        }
    }
    server
    {
      …
    }
    …                #http 全局块

2.Nginx 的配置文件参数

通过 yum 安装的 Nginx,其配置文件类型如下图所示,当然了,Nginx 都会默认为 每种类型的配置文件提供一个.default 结尾的文件用以参考。

高性能 Web 服务器 Nginx 使用指南

主配置文件 nginx.conf

对于 rpm 安装的 Nginx 而言,它的主配置文件是由 /etc/sysconfig/nginx 文件决定的,其中的 NGINX_CONF_FILE 参数定义主配置文件。

高性能 Web 服务器 Nginx 使用指南

主配置文件的主要参数如下,关于 main 全局配置

user nginx nginx;       定义 Nginx 的 worker 进程的用户和用户组,默认是 nobody 

worker_processes auto;      定义开启 worker 进程的数量

error_log(日志错误级别 debug|info|notice|warn|error|crit)定义全局错误日志文件

pid     定义 nginx 的 master 进程 ID 的存储文件,防止程序启动多个实例

        进程运行后会给 pid 文件加一个文件锁,只有获得该锁的进程才具有写权限,将自身的 pid 写入 pid 文件中,其他试图获得该锁的进程会退出。

关于 events 事件驱动配置

use epoll;   定义 Nginx 工作时的 I / O 模型,支持的 I / O 模型有 select、poll、epoll 等,其中 select 和 poll 是标准的方式,epoll 是高效的工作方式,也是 Nginx 优先考虑的 I / O 模型。

work_connections   定义每个 worker 进程允许的最大的同时连接数,总之,Nginx 能够同时打开的最大文件数 =worker_processes*work_connections。

注意:Linux 系统默认规定进程打开的最大文件数为 1024,因此,如果work_connections 的值大于 1024 的话,则无法生效。例如,设置 worker_connnects 65535,Nginx 在启动之前需要运行命令 ulimit -n 65535 将进程支持的最大文件数改为 65535。

 

关于 http 块的配置

log_format     定义 Nginx 的日志输出格式,main 为该日志的输出格式名称,下面的指令如果想要调用该日志格式的话,直接引用 main 关键词即可。

高性能 Web 服务器 Nginx 使用指南

access_log  /var/log/nginx/access.log  main;    定义 Nginx 被访问的日志,同时引用 log_format 定义的以 main 为命名的日志格式。

日志格式中各变量的含义如下,

    $remote_addr                 客户端 IP 地址

    $remote_user                客户端用户名称

    $time_local                     访问的时间与时区

    $request                         请求的 URL

    $status                           请求状态(http 的请求状态码)

    $body_bytes_sent          发送给客户端的文件主体大小

    $http_referer                  记录从哪个页面链接过来的

    $http_user_agent           客户端浏览器的信息

    $http_x_forwarded_for   客户端的 IP 地址

注意:$remote_addr 和 $http_x_forwarded_for 同样都是访问服务器的客户端 IP,但是这两者还是有区别的,对于前端设置了反向代理的服务器,$remote_addr 是指反向代理服务器的 IP 地址,$http_x_forwarded_for 是指真实的客户端 IP 地址

charset utf-8                       设置网页的编码格式,默认编码为 utf-8,还有 gb2312 等

server_names_hash_bucket_size

                                           服务器名字的 hash 表大小,nginx 的多个 server_name 是存放在哈希表中的。这样可以提高 nginx 速度

client_max_body_size         客户端请求单个文件的最大字节数

    当请求的文件数大于该值的时候,服务器会报出 413(Request Entity Too Large)的错误

client_header_buffer_size   指定客户端请求头的 buffer 大小, 一般情况下 1K 大小足以

large_client_header_buffers <number> <size>

                                           请求头大小超过 client_header_buffer_size 的值时,会将请求头的大小重新设置为 large_client_header_buffers 的值。例如large_client_header_buffers 4 128K,最大缓存量为 4 个 128K。

    上诉两个请求头的 buffer 的关系,受到 http 请求时,先根据 client_header_buffer_size 分配一个 buffer,如果 buffer 无法容纳请求头,那么会根据 large_client_header_buffers 重新分配 buffer。

keepalived_timeout            客户端保持连接的超时时间

client_header_timeout        客户端请求头读取超时时间

client_body_timeout           客户端请求主体读取超时时间

    上述请求头和请求主体的超时时间,如果超过时间客户端还没有发送数据,则 Nginx 返回 408(Request time out)的错误。

send_timeout                     服务端响应的超时时间,对于已经建立的连接,如果客户端在超时时间内没有任何动作,Nginx 断开连接。

conf.d/ 和 default.d/ 扩展配置文件目录
Nginx 中引入扩展配置文件的目录是为了降低主配置文件 nginx.conf 的复杂度,Nginx 的 http 块是由多个 server 块组成,每个 server 也是有多个 location 块组成的,这么多的 server 和 location 当然都可以放在一个主配置文件中,但还是 server 过多的情况下,会使得主配置文件变得十分庞大,而且也不便于管理与修改。因此引入了扩展配置文件目录。

conf.d/ 目录下存放 server 块的配置文件,default.d/ 目录下存放 location 块的配置文件,引用的时候使用 include 指令将相对应的 server 块配置文件和 location 配置文件加入各自的 block 块中即可。

http {
    …<http 全局指令 >…
    include /etc/nginx/conf.d/*.conf;
}
或者
server {
    …<server 全局指令 >…
    include /etc/nginx/default.d/*.conf;
}

fastcgi_params/fastcgi.conf

Nginx 在 fastcgi 解析的时候,需要调用这两个文件中的服务器变量,内置的服务器变量如下,

高性能 Web 服务器 Nginx 使用指南

这个文件的区别就是.conf 比 params 多了一行 fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

高性能 Web 服务器 Nginx 使用指南

uwsgi_params

和 fastcgi_params 一样,这里是调用关于 uwsgi 协议的一些服务器变量。

scgi_params

这里是调用关于 scgi 协议的一些服务器变量。

mime.types

web 资源类型配置文件,定义 web 资源的类型,即文件扩展名和资源类型的映射表,nginx 就是根据这个映射表设置 http 请求响应头的 Content-Type 值。

高性能 Web 服务器 Nginx 使用指南

mime.types 在 http 块的全局配置中被引用,下面的指令的意思是根据 mime.types 定义 web 资源类型,如果在映射表中找不到对应关系,则使用 default_type 定义的默认资源类型。

高性能 Web 服务器 Nginx 使用指南 

koi-win/koi-utf/win-utf

这三个文件都是与编码转换映射相关的文件,用于在输出内容到客户端时,将一种编码转换到另一种编码。

koi-win:charset_map  koi8-r < — > windows-1251

koi-utf:charset_map  koi8-r < — > utf-8

win-utf:charset_map  windows-1251 < — > utf-8

3. 虚拟主机

对 Nginx 而言,一个 server 块就是一个虚拟主机,我这里将每个 server 块的配置单独作为一个文件放入 conf.d/ 目录下。然后在主配置文件中 include 命令包含进来即可。

关于虚拟主机的指令如下,

 

server {…}        虚拟主机开始的关键字

listen address[:port] [default_server]

                        虚拟主机监听的 IP 和端口

        default_server 定义该 server 为默认,如果所有 server 段都没有使用该参数,则第一个 server 为默认

        该参数通常在地址列没有输入 server_name,而是输入 IP 地址的时候,Nginx 会定位在 default_server 的虚拟主机。

        例: listen 192.168.124.100:80 default_server

server_name    指定虚拟主机的域名,可以定义多个域名,之间用空格隔开,可以使用通配符和正则表达式

        server_name 的作用:Nginx 收到一个 http 请求的时候,会取出首部的 server 字段,然后和所有 server_name 字段进行比较,匹配则定位到对应的 server 块;

        server 可以是多个,相对应的 server_name 也会有多个,多个 server_name 之间的优先顺序是:

            精确匹配               www.linux.com

            左侧通配符匹配    *.linux.com

                这个左侧通配符匹配实际应用场景很广,www.linux.com、bbs.linux.com、blog.linux.com 等都可以通过一个左侧通配符来完成

            右侧通配符匹配    www.*

            正则表达式匹配    ^.*\.linux\.com$

root                   定义虚拟主机的网页根目录,可以是绝对路径,也可是相对路径

index                 定义虚拟主机默认的首页文件

charset              定义网页的默认编码格式,既可以用于 http 全局,也可以用于 server 全局

access_log        同样既可以用于 http 全局,也可以用于 server 全局

location {…}       地址匹配开始的关键字,location 块对 URL 地址匹配进行设置,支持正则表达式匹配

 

        location 和 URL 进行匹配,匹配成功则进行其中的处理。控制服务端的访问路径

            =    精确匹配

            ~    正则表达式匹配,区分大小写

            ~*   正则表达式匹配,不区分大小写

            ^~  URL 前半部分匹配,忽略大小写

            /      通用匹配,因为所有的匹配都是以 / 为开始的

    他们的优先级:

            = -> ^~ -> ~ 或者~* -> /

例如:

location ^~ /bbs.txt {| location ^~ /bbs{
    alias /var/www/html/1.txt;  |  alias /var/www/html/1.txt;
}                    | }
location = /bbs.txt {| location = /bbs{ 
    alias /var/www/html/2.txt;  |  alias /var/www/html/2.txt;
}                    | }
结果会优先返回优先级高的匹配 URL    | 结果会优先返回优先级高的匹配 URL 
即 2.txt 的页面内容            | 即 2.txt 的页面内容

alias                    定义 Nginx 中别名功能,只能用在 location 中

tips:

root 既可以写在 server 中,也可以写在 location,当同时存在时,内层会替换外层。例如

root path1;
location / {
  root path2;
}
location ~ \.php$ {
 
}

第一个 location 生效的是 path2,第二个 location 生效的是 path1.

root 和 alias 的区别:

root 指定的是根目录,alias 指定的是当前目录,

location /html {
    root /data/web/;
}
# 如果 URL 请求的是 /html/index.html,则 nginx 会在 /data/web/html/ 目录查找 index.html 文件
location /html {
    alias /data/web/;       
}
# 如果 URL 请求的是 /html/index.html,则 nginx 会在 /data/web/ 目录下查找 index.html 文件
location ~ ^/download/(.*)$ {
    alias /data/web/$1;
}
# 如果 URL 请求的是 /download/nginx.tar.gz,则 nginx 会在 /data/web/ 目录下查找 nginx.tar.gz 文件

nginx 中配置文件中的正则表达式依赖于 pcre 库,这也是安装 nginx 之前为什么必须先安装 pcre 的原因。

http_geoip_module 模块可以处理来自不同地区的访问

        include /usr/share/nginx/modules/mod-http-geoip.conf

Nginx -V        # 查看 Nginx 编译过程中的参数

–sbin-path    定义开启 Nginx 的主进程的命令路径

–modules-path    定义 Nginx 的模块的存储路径

–conf-path    定义 Nginx 配置文件的路径

–error-log-path    定义错误日志的路径

–http-client-body-temp-path    客户端主体请求的临时文件的路径

–http-proxy-temp-pathNginx    代理(负载均衡)的临时文件的路径

–http-fastcgi-temp-path            fastcgi 的临时文件的路径

–with-file-aio        文件的异步 IO

4.LNMP 架构

现在大多数的电子商务网站都是基于 LNMP(Linux+Nginx+MySQL+PHP)架构设计的。LNMP 的架构的简单的工作原理如下,

其中,Nginx 作为 web 服务器,响应客户端发来的 http 请求,和 Apache 一样,本身只能处理静态请求,而对于动态请求,则需要 Nginx 与专门的语言解释器进行交互,例如 PHP 解释器,然后 PHP 解释器执行 php 脚本,其中会涉及到一些数据的操作,因此就需要到后端的数据库服务器中存取数据。最后 php 的执行结果交给 nginx,nginx 继而将结果返回给客户端。

fastcgi:

nginx 收到的请求不能直接转发给 php,因为 php 不认识,反过来,php 处理后的结果也不能直接返回给 nginx,因此需要在他们两者中间加入公共接口,即 fastcgi,使得 nginx 和 php 都能够支持 fastcgi,当 nginx 和 php 交互的时候,都需要通过 fastcgi 协议的处理。

PHP 和 php-fpm 的关系:

php-fpm 是 php 和 fastcgi 的管理器,它其实 php 的一个补丁,是为了将 fastcgi 的管理器整合到 php 中,这样一来,仅可以通过 php-fpm 服务,既可以管理 fastcgi 进程,也可以 reload 重新加载 php(在修改 php 的配置文件 php.ini 后无需重新启动 php)。

因此 LNMP 详细的工作流程是,Nginx 收到浏览器的 web 请求后,Nginx 自身处理其中的静态请求,例如图片、视频等,对于动态请求,Nginx 将其通过 fastcgi 处理后转发给 php-fpm 进程,php-fpm 调用 php 解析器执行 fastcgi 处理后的 php 脚本,期间 php 再连接数据库进行数据的操作,php 解析器处理完毕后,将结果转发给 php-fpm 进程,php-fpm 将结果通过 fastcgi 交付给 Nginx,最后 Nginx 将最终的结果返回给浏览器。

LNMP 搭建过程:

① 安装 Nginx,为了方便我这里使用 yum 安装,当然也可以使用源码编译安装,我使用的阿里云的 epel 源,直接在 Linux 中输入如下命令,就可以成功配置 yum 仓库。

[root@CentOS6 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
[root@CentOS6 ~]# yum makecache
[root@CentOS6 ~]# yum -y install nginx

我这里安装的 nginx 版本是 1.10.2

高性能 Web 服务器 Nginx 使用指南

② 安装数据库 mysql,直接使用本地 base 源即可。

[root@CentOS6 ~]# yum -y install mysql-server

安装成功之后会发现也会为我们安装 mysql 客户端工具,用于连接 mysql 服务端。

然后创建用于存放数据的数据库 wordpress,赋予用户 wordpress 使用该数据库的所有权限,并设置连接数据库的秘密 centos,

[root@CentOS6 ~]# mysql
mysql> create database wordpress;
mysql> grant all on wordpress.* to wordpress@’%’ identified by ‘centos’;
mysql> flush privileges;

③ 接下来就是 php 和及其扩展包的安装,同样使用 base 源即可

[root@CentOS6 ~]# yum -y install php php-mysql

④ 安装 统一管理php 解释器和 fastcgi 进程的工具 php-fpm。

[root@CentOS6 ~]# yum -y install php-fpm

修改 php-fpm 的工作进程的用户和用户组为 nobody.nobody(需要同 Nginx 工作进程的用户 / 用户组一致,我这里设置的是 nobody.nobody),这样做的目的是限制 php-fpm 和 Nginx 的权限。php-fpm 的配置文件是/etc/nginx/php-fpm.d/www.conf

修改后的内容如下,其他的指令保持默认。

高性能 Web 服务器 Nginx 使用指南

⑤ 修改 Nginx 的配置,使其能将动态请求转发给 php-fpm。

Nginx 主配置文件的内容如下:

[root@CentOS6 nginx]# cat /etc/nginx/nginx.conf
user nobody nobody;   
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
 
events {
    use epoll;
    worker_connections  1024;
}
http {
    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  /var/log/nginx/access.log  main;
    keepalive_timeout  65;
    charset            utf-8;
    include          /etc/nginx/mime.types;
    default_type        application/octet-stream;
 
    include /etc/nginx/conf.d/*.conf;    # 引用 server 块的扩展配置文件
}

Nginx 的 server 块的扩展配置文件内容如下,

[root@CentOS6 conf.d]# cat /etc/nginx/conf.d/default.conf
#
# The default server
#
server {
    listen    80;
    server_name  wordpress.linux.com;
    root /data/web;
 
    location / {
      index index.php;
    }
    location ~ \.php$ {
      fastcgi_pass  127.0.0.1:9000;    # 运行 php-fpm 进程的 ip 和端口
      fastcgi_index  index.php;        # 定义网页的入口文件
      fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include /etc/nginx/fastcgi_params;
    }
}

⑥ 测试 LNMP 架构是否成功

在 nginx 服务器的 /data/web/(由 root 指令决定)目录下,创建 index.php 文件,写入连接数据库和 php 的测试代码

[root@CentOS6 ~]# cd /data/web
[root@CentOS6 web]# cat index.php
<?php
 $link=mysql_connect(“192.168.239.129″,”wordpress”,”centos”);
 # 三个参数分别为运行数据库服务的 IP 地址,用户,密码
 if ($link) 
    echo “success”;
 else
    echo “failed”;
 
  phpinfo();
?>

在 windows 的 hosts 文件中添加记录,

192.168.239.129  wordpress.linux.com

然后在浏览器中出现如下如所示的界面,表示 LNMP 架构已经搭建完成。

高性能 Web 服务器 Nginx 使用指南
利用 LNMP 架构搭建博客,下载 wordpress,将解压后的所有文件放在 /data/web/ 目录下,需要保持这些文件的用户和用户组和 nginx 进程的保持一致,因此设置这些文件的用户和组为 nobody。

[root@CentOS6 web]# chown -R nobody.nobody /data/web/*

高性能 Web 服务器 Nginx 使用指南

然后修改其中的 wp-config.php 文件,该文件主要用于连接数据库配置,主要修改的内容如下,

/** The name of the database for WordPress */
define(‘DB_NAME’, ‘wordpress’);
 
/** MySQL database username */
define(‘DB_USER’, ‘wordpress’);
 
/** MySQL database password */
define(‘DB_PASSWORD’, ‘centos’);
 
/** MySQL hostname */
define(‘DB_HOST’, ‘192.168.239.129’);

最后在浏览器中输入 wordpress.linux.com,首次访问需要完成安装的步骤,按照指示一步步完成即可。最后再次访问该域名,出现如下界面表示博客搭建成功。这样 LNMP 的一个实际应用就已经实现了。

高性能 Web 服务器 Nginx 使用指南tips:

LNMP 搭建网站的时候,首次都需要连接数据库的步骤,该步骤的完成通常都是修改源码中的 config.php 文件来完成的(例如该例中的 wp-config.php),该文件中一般定义了要连接的数据库的名称,用户和用户口令等信息。

LNMP 和 LAMP 的区别:

LAMP 中的 php 是作为 Apache 的一个模块存在的,所以 php 和 Apache 共存亡;LNMP 中的 php 是作为一个单独的服务存在的,通过 php-fpm 进行管理。

5. 状态监控页面

Nginx 内置了 StubStatus 的工作模块,该模块可以监控 Nginx 的工作状态。监控页面完成通过一个 location 就可以完成,location 的配置如下,

location /status {
    stub_status on;        # 开启状态监控的功能
    access_log  /var/log/nginx/status.log; # 定义状态页面的访问日志
    # 采用 auth_basic 认证机制
    auth_basic  “NginxStatus”; # 定义状态页面的名称
    auth_basic_user_file /etc/nignx/conf.d/htpasswd; # 指定密码文件
}

其实只需要 stub_status on 就可以开启 Nginx 的状态监控功能,和上边的区别就是没有日志记录文件,没有密码认证的功能。

另外 auth_basic 认证机制的密码文件需要 Apache 的 htpasswd 命令生成。

[root@CentOS6 default.d]# htpasswd -c /etc/nignx/conf.d/htpasswd admin
# 允许登录的用户为 admin,然后根据指示设置密码
# 因为 nginx 的工作进程为 nobody,因此需要将密码文件对 nobody 用户有 r – 权限
[root@CentOS6 default.d]# chown nobody.nobody /etc/nignx/conf.d/htpasswd
[root@CentOS6 conf.d]# chmod 400 htpasswd
[root@CentOS6 conf.d]# ll htpasswd
-r——–. 1 nobody nobody 20 Jul 19 03:03 htpasswd

然后在浏览器中输入 wordpress.linux.com/status,输入正确的用户名和密码后,就可以看到状态页面。

高性能 Web 服务器 Nginx 使用指南

高性能 Web 服务器 Nginx 使用指南

Nginx 的状态页面的参数含义:

Active connections     当前活动的客户端连接数

accepts                       已经累计收到的客户端连接数量

handled                     已经处理的客户端连接数量

requests                     客户端的总的请求数量

    accepts/handled/requests 这三个参数的区别是:

        客户端发起的总的请求数是 requests,服务端可以不接受请求,也即实际接受的请求数是 accepts,而服务器在接受的请求数中实际处理的请求数是 handled

reading                       正在读取的客户端请求数量

writing                        正在发送响应报文的连接数量

waiting                       等待发送请求的空闲连接数量 

        对于长连接,还需要等待用户发送数据等等的情况,因此会出现空闲连接。

6.URL 重写

Nginx 的配置文件支持类似 shell 编程的逻辑判断,对于不同的请求定义不同的规则。

URI/URN/URL 的区别

    URI       统一资源标识符,URI 由 URN 和 URL 组成,mailto:John.Doe@example.com

    URN    统一资源名称,代表资源的名称,John.Doe

    URL      统一资源定位符,代表资源的路径,mailto:example.com

 

if 判断指令

    if (condition) {…}, 仅仅在 server 和 location 块中使用

        condition 是一个变量的时候,为空或者以 0 开头的字符串都将被判定为 false

        逻辑判断表达式:

                = 或!=    等于或不等于

        正则表达式匹配:

                ~       区分大小写的匹配

                ~*      不区分大小写的匹配

                !~        区分大小写的不匹配

                !~*     不区分大小写的不匹配

        文件 / 目录匹配:

                -f/!-f      文件是否存在

                -d/!-d     目录是否存在

                -e/!-e     文件或者目录是否存在

                -x/!-x     文件是否可以执行

        Nginx 内置的全局变量

            $host     请求主机头字段,即 server_name

            $http_user_agent     客户端 agent 信息,即客户端使用的何种浏览器, 这个值一定要根据日志 access.log 中显示的浏览器信息为依据,尤其是 IE 浏览器,之前我就以 MSIE 为 IE 的 http_user_agent,结果实验老是失败。

            $http_cookie     会话标识

            $limit_rate         限制连接速率,例如网盘的限速

            $request_meathod    客户端请求的动作

            $remote_addr     客户端的 IP 地址

            $request_filename     当前请求的文件路径

            $scheme          http 方法(http 或者 https)

            $server_protocol        http 协议版本

            $server_addr     服务器 IP 地址

            $server_name     服务器名称

            $server_port     服务器的端口号

            $request_uri     包含参数的 URI,例如 www.xxx.com/xxx.php?xxx

rewrite 指令

    只能用在 server、location、if 中,并且只能对 URL 中的非传递参数的字符串起作用。

    rewrite 和 location 都能实现地址跳转,但是两者还是有区别的,rewrite 是在同一域名内改变资源路径,而 location 是对一类路径做访问控制,他们的执行顺序是server 中 rewrite->location-> location 中 rewrite

    rewrite 重复执行超过 10 次还找不到资源就会返回 500 错误代码。

    rewrite 指令的格式:rewrite <regex> < 替换后的 URL> [flag]

    重定向的标志位 flag

        last             表示完成 rewrite,一般用在 server 和 if 中,浏览器地址栏的 URL 不变

        break         通常使用在 locating 中,表示后续的 rewrite 不再执行,浏览器地址栏的 URL 不变

        redirect       返回 302 临时重定向,浏览器地址栏显示跳转后的地址

        permanent 返回 301 永久重定向,浏览器 地址栏显示跳转后的地址

例子:

以上边 LNMP 搭建的博客为例,在浏览器中的域名后边随便输入一个字符串表示一个不存在的目录或者文件,然后浏览器默认会返回 404 的错误页面。

高性能 Web 服务器 Nginx 使用指南

现在使用 yum 安装 nginx 时其默认提供的 404 错误页面,而不是使用浏览器提供的 404 错误页面。

cp /usr/share/nginx/html/404.html /data/web/

server {
    listen      80;
    server_name  wordpress.linux.com;

 
    if (!-e $request_filename) {
        rewrite ^(.*)$ /404.html break;
    }

 
}
 
如果访问的文件或者目录不存在,则重定向到 404.html 页面

高性能 Web 服务器 Nginx 使用指南

server {
    listen      80;
    server_name  wordpress.linux.com;

    if ($http_user_agent ~ “Firefox”) {
    rewrite ^(.*)$ http://www.baidu.com/ redirect;

}
域名跳转

现在使用火狐浏览器访问,结果成功的跳转到百度的首页。

高性能 Web 服务器 Nginx 使用指南

高性能 Web 服务器 Nginx 使用指南

然后使用 360 浏览器,结果域名没有跳转。

高性能 Web 服务器 Nginx 使用指南

7.Nginx 的负载均衡功能

Nginx 拥有基于 7 层交换的负载均衡功能,对于后端 10 台左右的 web 服务器的情况,Nginx 的负载均衡性能最佳。因此 Nginx 适用于小型网站的负载均衡。Nginx 通过 upstream 命令实现负载均衡功能。Nginx 的负载均衡模块支持的常用负载均衡算法如下,

轮询            Nginx 默认调度算法,按请求时间将请求逐一分配到后端服务器

加权轮询     指定后端服务器的权值,权值越大,请求被分配的概率越大,轮询是权值都为 1 的加权轮询 

ip_hash       根据客户端 IP 的哈希结果分配请求,这样同一客户端的请求就可以分配到固定的后端服务器,可以解决 session 共享的问题

fair              根据后端服务器的响应时间分配请求,响应时间短的优先分配。

url_hash      根据访问的 URL 的哈希结果分配请求,这样同一 URL 的请求就可以分配到固定的后端服务器。

Nginx 的负载均衡调度算法中,轮询、加权轮询、ip_hash 是 Nginx 自身提供的,而 fair、url_hash 分别由第三方模块 upstream_fair 模块和 hash 软件包提供。

Nginx 负载均衡功能的配置格式:

upstream xxx {
    server ip1:port1 status;
    server ip2:port2 status;
    …
}
server {
    …
    location …{
        proxy_set_header Host $host;
            proxy_set_header X-Forward-For $remote_addr;
      proxy_pass http://xxx;
        …
    }
}
# xxx 为定义的后端服务器群的名称
# ip:port 为后端提供 web 服务的 ip 和端口号
# status 是后端服务器群各个节点的状态

proxy_set_header 的作用:

该指令的意义在于修改 http 请求头的信息。这里修改的主要是请求头中的 host 字段和 remote_addr 字段。在设置了负载均衡之后,客户端的请求先到达负载均衡层,再到真实的 web 服务器,由此请求经过了一个中间层。Host 的含义是表明请求的主机名,因为 nginx 作为反向代理使用,而如果后端真实的服务器设置根据 http 请求头中的 host 字段来进行路由或判断功能的话(即根据 host 字段判断请求发往哪个虚拟主机),如果反向代理层的 nginx 不重写请求头中的 host 字段,将会导致请求失败(默认反向代理服务器会向后端真实服务器发送请求,并且请求头中的 host 字段应为 proxy_pass 指令设置的服务器,也就是上边的 xxx)。x-forward-for 表示 http 请求由谁发起的,如果负载均衡层不重写该字段的 ip,则后端真实服务器收到的 http 请求头中都是负载均衡服务器的 ip 地址,如果后端有防×××策略的话,那么负载均衡服务器就被真实服务器封掉了。

status 的常用状态有

down                表示该 web 节点不参与负载均衡的调度

weight              定义该 web 节点的权值

backup              表示预留 web 节点,只有当所有的非 backup 的 web 节点出现故障的时候,backup 节点才会接受请求

max_fails           表示请求该 web 节点的最大的失败次数

fail_timeout       表示该节点在经历 max_fails 次的失败请求之后,暂停服务的时间

实验环境:

192.168.239.130:80    前端负载均衡节点

192.168.239.129:80    后端提供 web 服务的节点 1

192.168.239.132:80    后端提供 web 服务的节点 2

负载均衡节点的 nginx.conf 内容如下:

user  nobody nobody;
worker_processes  2;
 
error_log  /usr/local/nginx/logs/error.log  notice;
 
pid        /usr/local/nginx/logs/nginx.pid;
 
events {
    use epoll;
    worker_connections  1024;
}
 
http {
    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  /usr/local/nginx/logs/access.log  main;
    sendfile        on;
    tcp_nopush    on;
    tcp_nodelay    on;
    keepalive_timeout  60;
    gzip  on;
   
    upstream webserver {
          # web1
        server 192.168.239.129:80 weight=4 max_fails=3 fail_timeout=20s;
          # web2
        server 192.168.239.132:80 weight=3 max_fails=3 fail_timeout=20s;
    }
    server {
        listen      80;
        server_name  blog.linux.com;
        root    /data/html;
        index  index.php index.html index.htm;
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Forward-For $remote_addr;
            proxy_pass http://webserver;
    }

节点 1 就是 4.LNMP 架构搭建的 web 服务,这里不再重写其 nginx.conf 文件的内容

节点 2 的 nginx.conf 的配置内容如下:

user nobody nobody;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
 
events {
    use epoll;
    worker_connections 1024;
}
 
http {
    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  /var/log/nginx/access.log  main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay        on;
    keepalive_timeout  65;
    types_hash_max_size 2048;
    include            /etc/nginx/mime.types;
    default_type        application/octet-stream;
   
    server {
        listen      80;
        server_name  web2.linux.com;
        root        /data/web;
 
        location / {
            index index.html;
        }
    }

然后在节点 2 的 web 根目录下创建 index.html 文件。

[root@CentOS7 ~]# echo “this is web2” > index.html

这样负载均衡服务器和后端服务器已经搭建完成,现在在浏览器中输入负载均衡服务器的 ip,不停地刷新,结果会交替返回节点 1 和节点 2 的 web 页面。

高性能 Web 服务器 Nginx 使用指南

高性能 Web 服务器 Nginx 使用指南

8.Nginx 的缓存服务器应用

这里使用的是 Nginx 自带的缓存模块,通过 proxy_cache 指令来实现。用于反向代理时对后端 web 服务器进行缓存。这里的实验以前一小节搭建负载均衡服务器为前提。在负载均衡服务器上设置缓存。nginx.conf 文件中增加的内容如下:

http {
    …
    proxy_cache_path    /data/cache levels=1:2 keys_zone=cache_one:1m inactive=1h max_size=1g;
    proxy_temp_path    /data/temp_cache;
    server {
        …
        location / {
        proxy_cache cache_one;
        proxy_cache_valid  200 304 302 12h;
        proxy_cache_key $host$uri$is_args$args;
        proxy_set_header Host $host;
        proxy_set_header X-Forward-For $remote_addr;
        proxy_pass http://webserver;
        expires 1d;
      }
    }
}

proxy_cache_path   

    /data/cache        定义缓存文件的目录

    levels=1:2           定义目录深度,并且第一层目录为 1 个字符,第二层目录为 2 个字符。

        缓存文件是以 proxy_cache_key 指令定义的 key 值进行 hash 得到的结果,例如生成的缓存文件为 f9e228c5ead32aa97fe65df97a5b8196,从文件名的最右边开始,第一层目录的目录名为 6,第二层目录的目录名为 19。

    keys_zone           cache_one 为自定义的缓存区的名称,1m 表示内存缓存空间大小为 1M

    inactive               定义自动清除没有第二次访问的缓存文件的时间

    max_size              当内存缓冲空间不足时,需要将缓存文件放到硬盘中,这里的 max_size 为存放缓存文件的硬盘空间最大值

proxy_temp_path    定义临时缓存文件路径

proxy_cache            反向代理设置缓存的指令,格式为 proxy_cache zone|off,关闭为 off,开启直接写keys_zone 指令定义缓存区名称

proxy_cache_valid   对不同 http 状态码的页面设置不同的缓存时间

proxy_cache_key    定义以什么样的 key 值得到文件名 

这样反向代理缓存已经配置完成,重启 nginx,然后在查看进程状态,当出现 cache manager process 进程时表明缓存已经建立成功。

高性能 Web 服务器 Nginx 使用指南

并且生成了缓存文件目录。

高性能 Web 服务器 Nginx 使用指南

最后在浏览器中输入负载均衡服务器的 ip 地址,当返回页面内容的时候,查看 /data/cache/ 目录,结果生成了缓存文件。

高性能 Web 服务器 Nginx 使用指南

查看该缓存文件正是刚才返回的页面的请求头信息和页面内容信息。

高性能 Web 服务器 Nginx 使用指南

9.Nginx 的性能优化

提高 Nginx 进程和 CPU 的亲缘性,减少进程上下文的切换

worker_process         开启 worker 进程数

worker_cpu_affinity   开启利用多核 cpu,将 worker 进程绑定至 CPU,提高 CPU 的性能 

    例如: 两核 CPU,两个进程

        worker_process 2;

        worker_cpu_affinity 01 10;

    目的:

        提高 CPU 的缓存命中率,设置 worker 进程数和 CPU 核心数一致,并且将一个 worker 进程绑定至一个 CPU 核心,这样就可以避免 CPU 缓存从一个核心切换到另一个核心,减少进程上下文的切换的时间。当然上诉情况仅用于 CPU 密集型,对于网络密集型和 I / O 密集型的情况,可以设置 CPU 核心数是 worker 进程数的 1.5- 2 倍。

    taskset 命令

        查看某个进程运行在哪个 CPU 核心上。可以将某个进程运行在指定的 CPU 核心上

        taskset -pc PID                     查看 PID 的进程运行在哪个 CPU 核心

        taskset -c <CPU 核心 > < 指定命令 > 定义指定命令开启的进程运行在指定 CPU 核心

[root@CentOS6 ~]# ps -ef |grep ping
root      13707  8104  0 11:14 pts/0    00:00:00 /bin/ping www.baidu.com
root      13709  9069  0 11:14 pts/1    00:00:00 grep ping
[root@CentOS6 ~]# taskset -pc  13707
pid 13707’s current affinity list: 0,1
[root@CentOS6 ~]# ps -ef |grep ping
root      13729  8104  0 11:18 pts/0    00:00:00 /bin/ping www.baidu.com
root      13731  9069  0 11:18 pts/1    00:00:00 grep ping
[root@CentOS6 ~]# taskset -pc  13729
pid 13729’s current affinity list: 0

提高处理性能

开启 epoll 事件处理模型,提高处理效率 –use epoll

multi_accept     开启多请求处理机制,worker 按串行方式处理连接,一个连接只有一个 worker,其他的 worker 处于休眠状态 –multi_accept on

sendfile on        避免内核缓冲区数据和用户缓冲区数据之间的拷贝

提高并发

worker_connections    决定允许客户端每个进程的最大连接数,一般 65535 足够了 –worker_connection 65535

worker_rlimit_nofile    能够打开的最大文件数 –worker_rlimit_nofile 65535

提高连接复用率

keepalive_timeout 60     连接超时时间

tcp_nodelay on           提高高频发送小数据报文的实时性

tcp_nopush  on           允许将 http 首部和内容在同一个报文中发送

开启 Nginx 压缩功能,节省带宽

gzip on

gzip_comp_level 3        压缩比,1-9,默认是 1

gzip_min_length           设置页面开始压缩的最小字节数,默认为 0,建议设置为 1K,小于 1K 的页面压缩效果不好。

        页面的字节数就是 http 头的 Content_Length

gzip_buffers                  设置内存大小作为压缩缓存

        例如 gzip_buffers    4 16K    设置 4 个 16KB 的内存作为压缩缓存

gzip_http_version        设置 http 协议版本,默认 1.1 即可

gzip_types                    指定被压缩文件的类型

gzip_vary    on            让前端的缓存服务器缓存经过压缩的页面

fastcgi 性能优化

fastcgi_cache_path    /usr/local/nginx/fastcgi_cache    levels=1:2    keys_zone=TEST:10m    inactive=5m

        fastcgi 缓存文件路径,目录等级结构、关键字区域存储时间和非活动删除时间

fastcgi_connect_timeout    指定连接到后端 fastcgi 的超时时间

fastcgi_send_timeout        指定向 fastcgi 传送请求的超时时间

fastcgi_read_timeout        指定接受 fastcgi 应答的超时时间

fastcgi_buffer_size            指定读取 fastcgi 应答第一部分需要大多的缓冲区

fastcgi_buffers                 指定本地需要多少和多大的缓冲区来缓冲 fastcgi 的应答请求

php-fpm 参数优化(php-fpm 的配置文件)

request_terminate_timeout    脚本运行超时时间

pm = dynamic | static        调整 php-fpm 进程的工作模式

pm.max_children                静态模式下的 php-fpm 进程数量

pm.start_servers                 动态模式下的 php-fpm 的起始进程数量

pm.min_spare_servers        动态模式下的 php-fpm 的最小进程数量

pm.max_spare_servers        动态模式下的 php-fpm 的最大进程数量

pm.max_requests                php-fpm 进程处理多少个请求后销毁

request_slowlog_timeout   慢查询日志时间

slowlog                               慢查询日志路径

rlimit_files                           打开的最大文件数

针对 Nginx 的 Linux 内核参数优化

 

net.ipv4.tcp_syncookies = 1       开启 SYN cookies

net.ipv4.tcp_max_tw_buckets = 6000    设置 timewait 的数量

net.ipv4.ip_local_port_range = 1024 65000    设置允许系统打开的端口范围

net.ipv4.tcp_tw_recycle = 1        启用 timewait 的快速回收

net.ipv4.tcp_tw_reuse = 1           启用 timewait 的重用,就是将 TIME-WAIT sockets 重新用于新的 tcp 连接

net.core.somaxconn = 262144    设置系统同时发起的 tcp 连接数

net.core.netdev_max_backlog = 262144    当网络接口接受数据包的速率大于内核处理速率的时候,设置发送到队列的数据包的最大数量

net.ipv4.tcp_max_orphans = 262144          设置系统最多多少个 TCP 套接字不被关联到用户文件句柄

net.ipv4.tcp_max_syn_backlog = 262144    设置尚未收到客户端确认信息的最大连接请求最大值

net.ipv4.tcp_synack_retries = 1     设置内核放弃连接之前发送 syn + ack 数据包的数量   

net.ipv4.tcp_syn_retries = 1           设置内核放弃建立连接之前发送 syn 数据包的数量

net.ipv4.tcp_fin_timeout = 1         设置套接字保持在 FIN-WAIT- 2 状态的时间

net.ipv4.tcp_keepalive_time = 30  TCP 发送 keepalive 消息的频度,单位是小时

 


10.Nginx 的 I / O 模型

Web 服务器的网络 I / O 流程:

(1)客户发起请求到服务器网卡;

(2)服务器网卡接受到请求后转交给内核处理;

(3)内核根据请求对应的套接字,将请求交给工作在用户空间的 Web 服务器进程

(4)Web 服务器进程根据用户请求,向内核进行系统调用,申请获取相应资源(如 index.html)

(5)内核发现 web 服务器进程请求的是一个存放在硬盘上的资源,因此通过驱动程序连接磁盘

(6)内核调度磁盘,获取需要的资源

(7)内核将资源存放在自己的缓冲区中,并通知 Web 服务器进程

(8)Web 服务器进程通过系统调用取得资源,并将其复制到进程自己的缓冲区中

(9)Web 服务器进程形成响应,通过系统调用再次发给内核以响应用户请求

(10)内核将响应发送至网卡

(11)网卡发送响应给用户

     用户请求 –> 送达到用户空间 –> 系统调用 –> 内核空间 –> 内核到磁盘上读取网页资源 -> 返回到用户空间 -> 响应给用户。

客户端向 Web 服务器请求的过程中,有两个 I / O 过程,一个就是客户端请求的 I /O,另一个就是 Web 服务器请求页面的磁盘 I /O

I/ O 模型

    同步 / 异步(以被调用者是否有消息通知机制为依据)

        同步 – 调用者主动等待被调用者返回结果

        异步 – 调用者只需被调用者的消息通知,期间无需特地等待结果

    阻塞 / 非阻塞(以调用者等待结果之前的状态为依据)

        阻塞 – 结果返回之前,调用者被挂起

        非阻塞 – 结果返回之前,调用者不会被挂起

通常就是同步阻塞和异步非阻塞,Nginx 采用的就是异步非堵塞 I / O 模型。

    例子:

    ①老王以传统的水壶烧水,老王相当于调用者,水壶相当于被调用者,老王必须一直盯着水壶,等待水烧开,这就是 同步,后来老王换了一个响水壶,可以在水烧开的时候发出响声(加入消息通知机制),老王再也不用死盯着水壶(无需等待),水烧开的时候,发出响声通知老王即可,这就是异步。

    ②水壶在烧水的期间,老王不干别的事情,这就是 堵塞,水壶在烧水的期间,老王去看个电视啥的,这就是非堵塞。

I/ O 复用

    进程可以监听多个文件描述符

    select–I/ O 复用模型,监听端口数量受限于 /proc/sys/fs/file-max,采用轮询方式扫描端口

    poll–I/ O 复用模型,本质和 select 没有区别,poll 将数据放置在内核空间,select 将数据放置在用户空间,放置在内核空间之后,效率提高,并且最大连接数没有限制

    epoll–I/ O 复用模型,select 和 poll 的增强版

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计22802字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7991566
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
国产开源公众号AI知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率

国产开源公众号AI知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率

国产开源公众号 AI 知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率 大家好,我是星哥,...
Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集

Prometheus:监控系统的部署与指标收集 在云原生体系中,Prometheus 已成为最主流的监控与报警...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
飞牛NAS玩转Frpc并且配置,随时随地直连你的私有云

飞牛NAS玩转Frpc并且配置,随时随地直连你的私有云

飞牛 NAS 玩转 Frpc 并且配置,随时随地直连你的私有云 大家好,我是星哥,最近在玩飞牛 NAS。 在数...
240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

  240 元左右!五盘位 NAS 主机,7 代 U 硬解 4K 稳如狗,拓展性碾压同价位 在 NA...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Android 的最优解?

  三大开源投屏神器横评:QtScrcpy、scrcpy、escrcpy 谁才是跨平台控制 Andr...
240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

  240 元左右!五盘位 NAS 主机,7 代 U 硬解 4K 稳如狗,拓展性碾压同价位 在 NA...
多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞定

多服务器管理神器 Nexterm 横空出世!NAS/Win/Linux 通吃,SSH/VNC/RDP 一站式搞...
每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

每天一个好玩的网站-手机博物馆-CHAZ 3D Experience

每天一个好玩的网站 - 手机博物馆 -CHAZ 3D Experience 一句话介绍:一个用 3D 方式重温...
星哥带你玩飞牛 NAS-10:备份微信聊天记录、数据到你的NAS中!

星哥带你玩飞牛 NAS-10:备份微信聊天记录、数据到你的NAS中!

星哥带你玩飞牛 NAS-10:备份微信聊天记录、数据到你的 NAS 中! 大家对「数据安全感」的需求越来越高 ...