Nginx 学习笔记

分析流程: 用户输入域名 -> 服务器接收 -> 浏览器显示整个网页
 

一、Nginx基础

   是什么?
    是高性能的 web服务器, 是 反向代理服务器, 是email服务器
 
   Apache和Nginx哪个好(结论相对)?
    相同机器配置, Nginx的并发数多
    **Apache适于处理动态页面, Nginx适于处理静态页面
  
   背景?
    Nginx[Engine x] 俄罗斯程序员 2004年发布的开源的高性能的web服务器
 
   搭建开发环境(CentOS)
    Linux操作系统上(LAMP, LNMP)下载安装Nginx
    官方:  nginx.org
              实操版本: 稳定版中pre-built包(因为Nginx是c语言实现的, 使用源代码需要编译等等复杂的步骤)
    

 

   Linux系统安装软件包的方式:
  1. 源代码方式
  2. rpm包安装
  3. yum原生安装
  4. yum本地源安装(Nginx官方推荐安装)

 

   使用yum下载/安装/启动Nginx步骤:
  1. 创建文件
    $ sudo  vi  /etc/yum.repos.d/nginx.repo
  1. 输入字母i进入插入模式, 添加下面内容
    
    [nginx]
    name=nginx repo
    gpgcheck=0
    enabled=1
    说明:
     OS需要替换成centos
     OSRELEASE需要替换成6或者7 (取决于CentOS的主版本号)
  1. 输入Esc键, 然后输入:wq, 保存退出
  2. 输入下面命令进行下载安装
    $ sudo  yum  install  nginx
  1. 启动nginx服务
    $ sudo  nginx
  1. 验证:
    浏览器输入 localhost, 返回”Welcome to nginx”页面即可
    或者使用下面命令查看nginx进程
    $ ps  aux  |  grep  nginx
            返回下面结果, 也表示成功启动nginx服务
    

 

   Nginx其他常用命令:
    linux命令添加-h, 或者--h或者-help参数查找其他命令
      $ nginx  -h
    查看nginx安装版本(version)
      $ nginx  -v
    判断/测试(test)nginx配置文件的语法是否正确
      $ nginx  -t
    给主进程发送各种信息:
      强制停止nginx服务(断电)
        $ sudo  nginx  -s  stop
 
      退出停止nginx服务(优雅地gracefully)
        $ sudo  nginx  -s  quit
    
      如果配置文件内容发生修改, 使之生效
                      $ sudo  nginx  -s  reload
 

 
二、nginx 的编译安装
 
安装准备: nginx依赖于pcre库,要先安装pcre (缺少 xx.h头文件则安装 xx-devel)
 
*.devel软件一般都是C语言编写的一些头文件或cpp文件,往往是其他模块或这我们自己写的模块在编译时,需要依赖这些*-devel软件包
 
yum  install  pcre  pcre-devel
cd /usr/local/src/
tar zxvf nginx-1.14.2.tar.gz
cd nginx-1.14.2
./configure --prefix=/usr/local/nginx
make && make install
 
启动:
cd /ulsr/local/nginx, 看到如下4个目录
./
 ....conf   配置文件 
 ... html   网页文件
 ...logs    日志文件
 ...sbin    主要二进制程序
 

 

[root@localhost nginx]# ./sbin/nginx
若出现以下报错:
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
....
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
原因:不能绑定80端口,80端口已经被占用
(有时是自己装了apache,nginx等,还有更多情况是操作系统自带了apache并作为服务启动)
解决:把占用80端口的软件或服务关闭即可.

 

三、Nginx的信号控制
 
TERM, INT
Quick shutdown
QUIT
Graceful shutdown  优雅的关闭进程,即等请求结束后再关闭
HUP
Configuration reload ,Start the new worker processes with
 a new configuration Gracefully shutdown the old worker processes
改变配置文件,平滑的重读配置文件
USR1
Reopen the log files 重读日志,在日志按月/日分割时有用
USR2
Upgrade Executable on the fly 平滑的升级
WINCH
Gracefully shutdown the worker processes 优雅关闭旧的进程(配合USR2来进行升级)
 
                                                                                                                         
    具体语法:
      Kill  -信号 选项 nginx的主进程号
      Kill  -HUP 4873
      Kill  -信号控制 `cat /xxx/path/log/nginx.pid`
      Kil; -USR1 `cat /xxx/path/log/nginx.pid`
 

 
四、Nginx配置段
 
主配置文件语法构成
  1. 简单指令:  指令名  指令值1  指令值2;
  2. 块指令
       块指令名 {
            简单指令;
            简单指令;
      }
 
简单指令包含四个:
  

 

    1、 user指令(理解):
    设置nginx 工作进程所属用户和群组, group群组如果省略, 值等于user的值;
      1.1  默认配置:  nginx工作进程所属用户和群组均为nginx(用户群组名)
    
           1.2  软件启动 -> 进程 -> 进程之间关系
           1.3  $ ps  aux  |  grep  nginx命令, 第一列root, 表示该进程的所属用户是root(只有root用户以及拥有超级用户权限的用户才可以操作该进程); 第二列为进程ID号
      • master process nginx: nginx的主进程; 分配客户端请求给工作进程处理
      • worker process: 工作进程(子进程), 所属用户就是第一列nginx; 处理客户端请求的进程
               
      1. kill某个子进程, 对web服务几乎没有影响
      2. kill主进程, worker子进程几乎做不了什么
    2、worker_process指令(***): 设置nginx工作进程的个数; 影响nginx的性能(处理请求的并发数)
      2.1  默认:
    
      2.2  设置工作进程的个数依据原则: 推荐设置为可用CPU核的个数
      2.3  修改这个指令: 从1改成3(主配置文件指令发生变化), 使之生效, 需要执行下面的命令
      $ sudo  vi  /etc/nginx/nginx.conf
                 保存退出(esc键;  :wq)
      $ sudo  nginx  -s  reload
     2.4  如果kill nginx的工作进程(子进程), 系统自动按照worker_processes指令设置的值, 重新创建新的工作进程; 如果kill掉主进程, web服务器无法处理客户端的请求
    • kill 某个进程:
      $ sudo  kill  -9  进程ID
    • 查看nginx的进程情况:
      $ ps  aux  |  grep  nginx
     2.5  如果kill命令没有-9参数, 表示不仅仅kill掉该进程4242(Nginx主进程id), 还包含所有子进程
       
 
  3、 error_log指令: 设置nginx错误日志的路径, 文件名以及日志级别; 记录nginx进程相关的日志信息(启动, 信号, bind端口号等等)
        3.1   日志级别: 级别从低到高, 级别越低, 信息量越大
      debug: 开发阶段, 查看更多信息
      debug, info, notice, warn, error, crit, alert, 或者 emerg
 
 4、 pid指令: 设置nginx主进程的id
        4.1  思路: 自动化(shell/perl/python)的读取该文件内容(id), 直接调用kill命令, 直接kill掉所有进程
          
 
块指令包含两个: 
  

  

  1、Events块指令

      1.1  默认:
          

  

        1.2  worker_connections指令(***): 设置一个 工作进程可以开启的最大连接数(理论上)是1024个
         理论上nginx一共开启的连接数 = 1024 * worker_processes值(3)
          思考:  HTTP中请求数和上面的连接数是一回事吗?
      答: 不是一回事; 连接数connection: TCP连接; 请求数request; 建立一次TCP连接, 发送多次请求
                   HTTP协议中Connection: keep-alive保持一段时间的连接
                   Nginx默认设置的超时timeout时间为65s(秒); 具体流程图可以查看附录中的第3部分.
            

        

 

              

  2、http块指令

        2.1    access_log指令: 设置访问log路径以及格式对应名字
        2.2     lof_format指令: 设置accee.log文件内日志消息格式
    
    
        access.log日志信息内容如下:
       

 

     2.3    如何修改access_log格式?
         2.3.1  找所有以$开头变量
    
 
     

 

  

 

    2.4    include指令: 引入外部指令目录下的某个文件; 引入mime.types文件(面试点)
            mime.types映射关系: mime类型和该类型对应的文件扩展名; Apache相关配置查看下面附录部分
            Accept: text/*, text/html; 指定客户端请求资源的mime类型;
            Content-Type: text/html; 服务器返回的mime类型text/html, 文件名xxxx.html / xxxx.htm
       2.5    default_type指令: 如果客户端请求的资源mime类型无法mime.types内找到映射, 指定一个默认的资源类型
              2.5.1 application/octet-stream: 二进制字节流类型; 无法找到的类型, 认为是程序(可执行文件), 浏览器无法显示/解析, 直接下载
 
         mime对应流程图:
  
     mime类型流程描述:
    描述: web服务器会为所有的HTTP对象数据附加一个MIME类型, 当web浏览器从web服务器获取一个资源/对象时, 会查看服务器mime.types中存储的相关类型, 浏览器依据服务器返回的Content-Type字段的值(mime类型), 决定如何处理
 
  证明上面理论:
    a、 客户端请求一个不存在的类型:  test.aaa
        a. Nginx web服务器包含test.aaa
        b. localhost/test.aaa 放在Nginx配置的根目录下
          1) 子配置文件:  /etc/nginx/conf.d/default.conf
          2) 根目录:      /usr/share /nginx /html/
    b 、正确性: 客户端看到下载test.aaa资源(弹出对话框)
     
 

五、全局区
 
worker_processes 1;  // 有1个工作的子进程,可以自行修改,但太大无益,因为要争夺CPU,一般设置为 CPU数*核数
Event {
    // 一般是配置nginx连接的特性
    // 如1个word能同时允许多少连接
     worker_connections  1024; // 这是指 一个子进程最大允许连1024个连接
}
http {  //这是配置http服务器的主要段
     Server1 { // 这是虚拟主机段
      
            Location {  //定位,把特殊的路径或文件再次定位 ,如image目录单独处理
            }             /// 如.php单独处理
     }
     Server2 {
     }
}
 
例子1: 基于域名的虚拟主机
    server {
        listen 80;  # 监听端口
        server_name  a.com; # 监听域名
        location  /  {
                root  /var/www/a.com;    # 根目录定位,也可以是相对目录(相对于nginx程序目录)
                index   index.html;  # 设置默认请求主页面文件名
        }
    }
 
例子2: 基于端口的虚拟主机配置
    server {
        listen 8080;
        server_name 192.168.1.204;
        location  /  {
                root   /var/www/html8080;
                index   index.html;
        }
    }
 

六、日志管理
 
我们观察nginx的server段,可以看到如下类似信息
  #access_log  logs/host.access.log  main;
这说明 该server, 它的访问日志的文件是  logs/host.access.log ,使用的格式”main”格式。
除了main格式,你可以 自定义其他格式:
 
main格式是什么?
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
main格式是我们定义好一种日志的格式,并起个名字,便于引用.
以上面的例子, main类型的日志,记录的 remote_addr.... http_x_forwarded_for等选项.
 
1: 日志格式 是指记录哪些选项
默认的日志格式: main
     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                            '$status $body_bytes_sent "$http_referer" '
                            '"$http_user_agent" "$http_x_forwarded_for"';
如默认的main日志格式,记录这么几项
远程IP- 远程用户/用户时间 请求方法(如GET/POST) 请求体body长度 referer来源信息
http-user-agent 用户代理/蜘蛛 ,被转发的请求的原始IP
http_x_forwarded_for:在经过代理时,代理把你的本来IP加在此头信息中,传输你的原始IP
 
2: 声明一个独特的log_format并命名
    log_format  mylog  '$remote_addr- "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
在下面的server/location,我们就可以引用 mylog
在server段中,这样来声明:
Nginx允许针对不同的server做不同的Log ,(有的web服务器不支持,如lighttp)
access_log  logs/access_8080.log  mylog;  
声明log   log位置          log格式;
 
实际应用: shell+定时任务+nginx信号管理,完成日志按日期存储
分析思路:
凌晨00:00:01,把昨天的日志重命名,放在相应的目录下
再USR1信息号控制nginx重新生成新的日志文件
具体脚本:
#!/bin/bash
base_path='/usr/local/nginx/logs'
log_path=$(date -d yesterday +"%Y%m")
day=$(date -d yesterday +"%d")
mkdir -p $base_path/$log_path
mv $base_path/access.log $base_path/$log_path/access_$day.log
#echo $base_path/$log_path/access_$day.log
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
 
定时任务
Crontab 编辑定时任务
01 00 * * * /xxx/path/b.sh  每天0时1分(建议在02-04点之间,系统负载小)
 

七、location 语法
 
location 有” 定位”的意思, 根据Uri来进行不同的定位.
在虚拟主机的配置中,是必不可少的,location可以把网站的不同部分,定位到不同的处理方式上.
比如, 碰到.php, 如何调用PHP解释器?  --这时就需要location
 
location 的语法:
    location  [ =|~|~*|^~]  patt {
            root
            index
            error_page
    }
中括号可以不写任何参数,此时称为 一般匹配
也可以写参数
因此, 大类型可以分为3种
    location = patt {} [ 精准匹配]
    location patt {}  [ 一般匹配]
    location ~ patt {} [ 正则匹配]
 
如何发挥作用?:
   首先看有没有精准匹配,如果有,则停止匹配过程.
  比如,
  location = patt {
               config A
       }
  如果 $uri == patt,匹配成功,使用configA。
 
     location =  / {
              root   /var/www/html/;
             index   index.htm index.html;
        }
        
     location / {
             root   /usr/local/nginx/html;
            index   index.html index.htm;
       }
 
  如果访问   http://xxx.com/
 
定位流程是: 
1: 精准匹配中 ”/”  ,得到index页为  index.htm
2: 再次访问  /index.htm , 此次内部转跳uri已经是”/index.htm” ,
  根目录为/usr/local/nginx/html
3: 最终结果,访问了 /usr/local/nginx/html/index.htm
 
再来看, 正则也来参与:
location  /  {
            root   /usr/local/nginx/html;
            index  index.html index.htm;
        }
 
location ~ image {
           root  /var/www/image;
           index  index.html;
}
如果我们访问    http://xx.com/image/logo.png
此时,  “/”  与 ”/image/logo.png”  匹配,
同时,”image”正则 与”image/logo.png”也能匹配,
谁发挥作用?
正则表达式的成果将会使用。 覆盖 “/” 的匹配
图片真正会访问 /var/www/image/logo.png
 
location  / {
             root   /usr/local/nginx/html;
             index  index.html index.htm;
         }
 
location  /foo {
            root  /var/www/html;
            index  index.html;
}
我们访问  http://xxx.com/foo
 对于uri “/foo”,   两个location的patt,都能匹配他们
即 ‘/’ 能从左前缀匹配 ‘/foo’, ‘/foo’也能左前缀匹配’/foo’,
此时, 真正访问 /var/www/html/index.html
原因:’/foo’ 匹配的更长,因此使用之.;
 

 

 

八、rewrite 重写
 
 
 
重写中用到的指令
if  (条件) {}  设定条件,再进行重写
set     # 设置变量
return     # 返回状态码
break     # 跳出rewrite
rewrite     # 重写
 
If  语法格式:
If 空格 (条件) {
    重写模式
}
 
条件又怎么写?
答:3种写法
1: “ =” 来判断相等, 用于字符串比较
2: “ ~”  用正则来匹配(此处的正则 区分大小写)
      ~*  不区分大小写的正则
3: -f  -d  -e 来判断是否为 文件,为 目录是否存在.
例子:
            if  ($remote_addr = 192.168.1.100) {
                 return 403;
            }
             if ($http_user_agent ~ MSIE) {
                 rewrite  ^.*$ /ie.htm;
                 break;     #(不break会循环重定向)
            }
             if (!-e $document_root$fastcgi_script_name) {
                 rewrite  ^.*$ /404.html break;
            }
            注, 此处还要加break。
 
以  xx.com/dsafsd.html 这个不存在页面为
我们观察访问日志,日志中显示的访问路径,依然是GET /dsafsd.html HTTP/1.1
提示: 服务器内部的rewrite和302跳转不一样.
跳转的话URL都变了,变成重新http请求404.html,而 内部rewrite,上下文没变,就是说 fastcgi_script_name 仍然是 dsafsd.html,因此 会循环重定向,需要用break
 
set 是设置变量用的, 可以用来达到多条件判断时作标志用。
达到apache下的 rewrite_condition的效果
如下:判断IE并重写,且不用break; 我们用set变量来达到目的
if ($http_user_agent ~* msie) {
                set  $isie  1;
 }
if ($fastcgi_script_name = ie.html) {
                set  $isie  0;
}
 if ($isie 1) {
                rewrite ^.*$ ie.html;
}
 
 
Rewrite语法:
Rewrite 正则表达式  定向后的位置 模式
Goods-3.html ----> Goods.php?goods_id=3
goods-([\d]+)\.html ---> goods.php?goods_id =$1 
location /ecshop {
    index index.php;
    rewrite goods-([\d]+)\.html$  /ecshop/goods.php?id=$1;
    rewrite article-([\d]+)\.html$  /ecshop/article.php?id=$1;
    rewrite category-(\d+)-b(\d+)\.html  /ecshop/category.php?id=$1&brand=$2;
    rewrite category-(\d+)-b(\d+)-min(\d+)-max(\d+)-attr([\d\.]+)\.html  /ecshop/category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5;
    rewrite category-(\d+)-b(\d+)-min(\d+)-max(\d+)-attr([\d+\.])-(\d+)-([^-]+)-([^-]+)\.html  /ecshop/category.php?id=$1&brand=$2&price_min=$3&price_max=$4&filter_attr=$5&page=$6&sort=$7&order=$8;
}
注意:用url重写时,正则里如果有”{}”,正则要用双引号包起来
 
 

九、nginx+php的编译
 
apache一般是把php当做自己的一个模块来启动的。
而nginx则是把http请求变量(如get,user_agent等)转发给 php进程(两者平级),即 php独立进程与nginx进行通信,称为 fastcgi 运行方式。
因此,为apache所编译的php,是不能用于nginx的.
注意:我们编译的PHP 要有如下功能:
连接mysql,,gd, ttf,以 fpm(fascgi) 方式运行
./configure  --prefix=/usr/local/fastphp \
--with-mysql=mysqlnd \
--enable-mysqlnd \
--with-gd \
--enable-gd-native-ttf \
--enable-gd-jis-conv
--enable-fpm
 
安装MariaDb 在 centos7下

 

编译完毕php后:
nginx+php 的配置比较简单,核心就一句话---- 把请求的信息转发给9000端口的PHP进程,
让PHP进程处理 指定目录下的PHP文件.
如下例子:
location ~ \.php$ {
            root html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;  # conf目录下的文件,定义了一些fastcgi参数
        }
1:碰到php文件,
2: 把根目录定位到 html,
3: 把请求上下文转交给9000端口PHP进程,
4: 并告诉PHP进程,当前的脚本是 $document_root$fastcgi_scriptname
(注:PHP会去找这个脚本并处理,所以脚本的位置要指对)网页内容的压缩编码与传输速度优化
 

十、Nginx支持gzip压缩(**)

  1. HTTP请求: Accept-Encoding域
    
  1. HTTP响应: Content-Encoding域
    
  1. Nginx如何支持压缩gzip(是nginx模块) : nginx的主配置文件: 什么类型资源需要压缩; 多大才需要压缩, 缓存大小等等, 步骤如下:
      3.1  配置文件修改如下:
  • gzip on: 打开gzip压缩模块
  • gzip_buffers: 设置gzip压缩使用系统缓存个数和每页缓存大小
  • gzip_comp_level: 设置 压缩级别, 取值范围为1 ~ 9, 值越小, 压缩速度越快, 压缩程度越低
  • gzip_min_length: 设置压缩 最小大小(单位: bytes字节)
  • gzip_types: 设置 压缩的mime类型
  
     3.2 reload nginx配置文件
    $ sudo  nginx  -s  reload
     3.3 验证:
  1. 创建test.css文件, 任意添加内容
    $ sudo  vi  /usr/share/nginx/html/test.css
  1. 命令行输入下面命令:
    $ curl  -I  -H  "Accept-Encoding:gzip" "http://127.0.0.1/test.css"
  1. 返回结果(红色框内容)表明设置成功
==================================================
 
我们观察  news.163.com 的头信息
请求:
    Accept-Encoding:gzip,deflate,sdch
响应:
    Content-Encoding:gzip
    Content-Length:36093
再把页面另存下来,观察,约10W字节,实际传输的36093字节
原因-------就在于gzip压缩上.
 
原理:
浏览器---请求----> 声明可以接受 gzip压缩 或 deflate压缩 或compress 或 sdch压缩
从http协议的角度看--请求头 声明 acceopt-encoding: gzip deflate sdch  (是指压缩算法,其中sdch是google倡导的一种压缩方式,目前支持的服务器尚不多)
服务器-->回应---把内容用gzip方式压缩---->发给浏览器
浏览<-----解码gzip-----接收gzip压缩内容----
 
推算一下节省的带宽:
假设 news.163.com  PV  2亿
2*10^8  *  9*10^4 字节 ==
2*10^8 * 9 * 10^4  * 10^-9 = 12*K*G = 18T
节省的带宽是非常惊人的
 
gzip配置的常用参数(可以写在http,server,location,if):
gzip on|off;      #是否开启gzip
gzip_buffers 32 4K | 16 8K     #缓冲(压缩在内存中缓冲几块? 每块多大?)
gzip_comp_level [1-9]     #推荐6 压缩级别(级别越高,压的越小,越浪费CPU计算资源)
gzip_disable     #正则匹配UA 什么样的Uri不进行gzip
gzip_min_length  200     # 开始压缩的最小长度(再小就不要压缩了,意义不在)(单位: bytes字节)
gzip_http_version 1.0 | 1.1     # 开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议)
gzip_proxied          # 设置请求者代理服务器,该如何缓存内容
gzip_types  text/plain  application/xml     # 对哪些类型的文件用压缩 如txt,xml,html ,css
gzip_vary on|off      # 是否传输gzip压缩标志
注意:
图片/mp3这样的 二进制文件,不必压缩
因为压缩率比较小,比如100->80字节,而且压缩也是耗费CPU资源的。
 

 
比较小的文件不必压缩, nginx的 缓存设置  提高网站性能
对于网站的图片,尤其是新闻站, 图片一旦发布, 改动的可能是非常小的.我们希望 能否在用户访问一次后, 图片缓存在用户的浏览器端,且时间比较长的缓存。可以, 用到 nginx的expires设置 .
nginx中设置过期时间,非常简单,
location或if段里,来写.
格式  expires 30s;
      expires 30m;
      expires 2h;
      expires 30d;
(注意:服务器的日期要准确,如果服务器的日期落后于实际日期,可能导致缓存失效)
 

另: 304 也是一种很好的缓存手段
原理是: 服务器响应文件内容时,同时响应  etag 标签(内容的签名,内容一变,他也变)和 last_modified_since 2个标签值。
浏览器下次去请求时,头信息发送这两个标签, 服务器检测文件有没有发生变化,如无,直接头信息返回 etag,last_modified_since
浏览器知道内容无改变,于是直接调用本地缓存。
这个过程,也请求了服务器,但是传着的内容极少.
对于变化周期较短的,如静态html,js,css,比较适于用这个方式

 

 

十一、Nginx负载均衡Load Balance

  1. 术语:
      代理Proxy:  也称为网络代理, 是一种特殊的网络服务, 允许一个网络终端通过该服务与另一个网络终端进行连接
 
      正向代理服务器:
  1. 描述: 通常就是正向代理,隐藏真实请求客户端,服务器不清楚真正的客户端是谁.
  2. 截图:
    

 

       反向代理服务器(负载均衡):
  1. 描述: 反向代理服务器隐藏了真实的服务器端, 客户端直接发送请求给反向代理服务器, 由proxy反向代理服务器通过设置的负载均衡算法, 交由其他web服务器处理
  2. 截图:
  
 
        Nginx负载均衡截图:
      

 

  1. Nginx中负载均衡一般配置, 涉及默认四个负载均衡算法
      nginx子配置文件中, http块指令
     http {
       upstream  cluster {
          server  server_name或者IP地址;
          server  server_name或者IP地址;
          server  server_name或者IP地址;
      }
 
      location / {
          proxy_pass:  http://域名;
      }
    }
 
      默认包含四个负载均衡算法:
  1. Round Robin(默认): 轮训调度算法; 依次给服务器发送请求
    upstream  cluster {
         server  server_name或者IP地址;
         server  server_name或者IP地址;
         server  server_name或者IP地址;
      }
  1. 最少连接数算法: 找哪台机器的连接数最少给谁
    upstream  cluster {
         least_conn;
         server  server_name或者IP地址;
         server  server_name或者IP地址;
         server  server_name或者IP地址;
      }
  1. 权重算法: 每台服务器指定一个权重数; 给性能好的服务器指定较大的权重(处理请求多)
    upstream  cluster {
         server  server_name或者IP地址 weight=100;
         server  server_name或者IP地址 weight=50;
         server  server_name或者IP地址 weight=10;
      }
  1. IP-Hash散列算法: 某些客户端直接发送请求给某台/某组服务器
    upstream  cluster {
         ip_hash;
         server  server_name或者IP地址;
         server  server_name或者IP地址;
         server  server_name或者IP地址;
      }
  1. 实际: 上述多个算法结合使用, 依据测试结果
  2. 实际方案: 结合算法+内部实现算法(自定义需求)
  1. Nginx反向代理服务器(负载均衡) à N个Apache提供web服务; LAMP, LNMP, LNAMP
 
 
nginx反向代理服务器+负载均衡实例:
用nginx做反向代理和负载均衡非常简单,
支持两个用法 1个proxy, 1个upstream,分别用来做反向代理,负载均衡
以反向代理为例, nginx不自己处理php的相关请求,而是把php的相关请求转发给apache来处理。

 

----这不就是传说的”动静分离”,动静分离不是一个严谨的说法,叫反向代理比较规范.
 
反向代理后端如果有多台服务器,自然可形成 负载均衡,
但proxy_pass如何指向多台服务器?
把多台服务器用 upstream指定绑定在一起并起个组名,
然后proxy_pass指向该组

 

默认的均衡的算法很简单,就是针对后端服务器的顺序,逐个请求.
也有其他负载均衡算法,如一致性哈希,需要安装第3方模块.
反向代理导致了后端服务器的IP,为前端服务器的IP。而不是客户真正的IP,怎么办?

 

 

十二、Nginx具体的压缩配置
 
常用以下配置
gzip on|off
gzip_buffers 4K|8K 缓冲(和硬盘块相当)
gzip_comp_level [1-9] 推荐6
gzip_disable 正则匹配如User-Agent,针对古老浏览器不压缩
gzip_min_length 200
gzip_http_version 1.0|1.1
gzip_types text/plain , application/xml (各mime之间,一定要加空格,不是逗号)
gzip_vary on|off
Vary的作用:

 

Vary是用来标志缓存的依据.
如上图: 看出,这个新闻页面由
思考:
1: 如果2个人,一个浏览器支持gzip,一个浏览器不支持gzip
  2个同时请求同个页面, chinaCache缓存压缩后,还是未压缩的?
2: 如果1人,再次请求页面,chinaCache返回压缩后的缓存内容,还是压缩前的缓存内容?
这个时候 Vary的作用体现出来.
即------缓存的内容受 Accept-Encoding头信息的影响.
所以如果--
请求时,不支持gzip, 缓存服务器将会生成一份未gzip的内容.
请求时,支持gzip, 缓存服务器将会生成一份gzip的内容.
下次再请求时, 缓存服务器会考虑客户端的Accept-Encoding因素,并合理的返回信息
Nginx对于图片,js等静态文件的缓存设置
注:这个缓存是指针对浏览器所做的缓存,不是指服务器端的数据缓存.
主要知识点: location expires指令
        location ~ \.(jpg|jpeg|png|gif)$ {
            expires 1d;
        }
        location ~ \.js$ {
           expires 1h;
        }
设置并载入新配置文件,用firebug观察,
会发现 图片内容,没有再次产生新的请求,原因--利用了本地缓存的效果.
注: 在大型的新闻站,或文章站中,图片变动的可能性很小,建议做1周左右的缓存
Js,css等小时级的缓存.
如果信息流动比较快,也可以不用expires指令,
用last_modified, etag功能(主流的web服务器都支持这2个头信息)
 
原理是:
响应: 计算响应内容的签名, etag 和 上次修改时间
请求: 发送 etatg, If-Modified-Since 头信息.
服务器收到后,判断etag是否一致, 最后修改时间是否大于if-Modifiled-Since
如果监测到服务器的内容有变化,则返回304,
浏览器就知道,内容没变,直接用缓存.
304 比起上面的expires 指令
多了1次请求,
但是比200状态,少了传输内容.
Nginx反向代理与负载均衡
正向代理

 

反向代理
             
 

 

具体的负载均衡的方式
注意:负载均衡是一种方案,实现办法有DNS轮询,
如下图,DNS服务器允许一个域名有多个A记录,
那么在用户访问时,一般按地域返回一个较近的解析记录.
这样,全国不同的地区的用户,看到的163的主页,来自不同的服务器.

 

第二步: 当 解析出结果,比如浏览器连接60.217时,
这台主机后面还有N台,也要做负载均衡.
1: 硬件上做负载均衡, F5 BIG-IP ,硬件负载均衡(很贵).
直接从TCP/IP的底层协议上,直接做数据包的中转.
2: 软件负载均衡, LVS
3: 反向代理+负载均衡
反向代理与keep-alive连接
            
 

 

Nginx反向代理设置
例: 把图片重写到 8080端口(既然能写到8080端口,就意味着可以写到其他独立服务器上)
        location ~ \.(jpg|jpeg|png|gif)$ {
                proxy_pass http://192.168.1.204:8080;
                expires 1d;
        }
集群与均衡-----如果后端的服务器非常多,该如何写? 又如何均匀的分发任务
nginx 与memcached的组合
用法: nginx响应请求时,直接请求memcached,
如果没有相应的内容,再 回调PHP页面,去查询database,并写入memcached.
分析: memcached是k/v存储, key-->value,
nginx请求memecached时,用什么做key?
一般用 uri arg 做key,  如 /abc.php?id=3
 

十三、Nginx 第三方模块的安装
 
以ngx_http_php_memcache_standard_balancer-master为例
1:解压 到 path/ngx_module
配置:
./configure --prefix=/xxx/xxx --add_module=/path/ngx_module
编译 安装
Make && make install
配置memcache集群
    upstream memserver {  把用到的memcached节点,声明在一个组里
        hash_key $request_uri;  // hash计算时的依据,以uri做依据来hash
        server localhost:11211;
        server localhost:11212;
    }
Location里
        location / {
           # root   html;
           set $memcached_key $uri;
           memcached_pass memserver;  // memserver为上面的memcache节点的名称
           error_page 404 /writemem.php;
           index  index.php index.html index.htm;
        }
 
在nginx中做集群与负载均衡,步骤都是一样的
Upstream {}模块 把多台服务器加入到一个组
然后 memcached_pass, fastcgi_pass, proxy_pass ==> upstream组
 
默认的负载均衡的算法:
是设置计数器,轮流请求N台服务器.
可以安装第3方模式,来利用uri做hash等等.
这个模块就是用一致性hash来请求后端结节,并且其算法,与PHP中的memcache模块的一致性hash算法,兼容.
 
安装该模块后:
Nginx.conf中
    upstream memserver {
        consistent_hash $request_uri;
        server localhost:11211;
        server localhost:11212;
    }
 
在PHP.ini中,如下配置
memcache.hash_strategy = consistent
这样: nginx与PHP即可完成对memcached的集群与负载均衡算法.
 

十四、Nginx支持PHP(***)

  1. 两个术语(理解)
     CGI: Common Gateway Interface 通用网关接口: 定义一系列标准, 定义web服务器和外部程序之间的标准, 包括传什么格式数据, 返回什么格式数据…..
    
    CGI程序实现: 独立于语言, 使用任意脚本语言或者完全独立的编译语言; C/C++ CGI程序; PHP CGI程序; Python CGI程序;……
    优势: 解放web服务器, 交给CGI程序处理客户端请求
     FastCGI:快速通用网关接口, 是CGI的进阶版本
  1. Nginx支持动态页面内部结构图:
    

 

  1. Nginx如何支持PHP(动态页面和静态页面)?
     3.1 实现静态页面加载和动态页面执行的分离
      

 

  1. 实现Nginx支持动态页面加载
    下载并安装php-fpm
        $ php-fpm  -v
    上述命令没有返回值, 使用下面命令安装三个包
      $ sudo  yum  install  php  php-mysql  php-fpm
  
    如果只需要安装php-fpm, 执行下面命令
      $ sudo  yum  install  php-fpm
  1. 修改nginx子配置文件(default.conf), 关于FastCGI部分(PHP部分)
            
  • root: 设置php文件的根目录
  • fastcgi_pass: 设置FastCGI server的ip地址和端口号
  • fastcgi_index: 默认php文件名
  • fastcgi_param: nginx服务器获取php文件的路径; 其中$document_root即为/usr/share/nginx/html
  • include: 加载fastcgi_params文件路径
  1. pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000: nginx主进程将php文件传给FastCGI服务器, 该服务器监听9000端口
  2. 实操版本:  nginx和php-fpm安装在同一个虚拟机
  1. 启动php-fpm进程
    $ sudo  service  php-fpm  start
    验证: 下面两个命令均可
    $ ps  aux  |  grep  php-fpm
    $ sudo  lsof  -P  |  grep  LISTEN
  1. 重新reload nginx配置文件
    $ sudo  nginx  -s  reload
 
  1. 验证:
    1、在nginx根目录下创建test.php
      $ sudo  vi  /usr/share/nginx/html/test.php
      添加内容 phpinfo();
    2、浏览器输入URL:  localhost/test.php
    其中php-fpm需要时active状态
    
 
 

  1. 面试题一:  Apache和Nginx处理静态和动态页面的区别?
    PHP默认是Apache的一个module模块, 无论加载静态还是动态页面, httpd进程都会执行/解析
    Nginx默认只支持静态页面的加载; 经过下面一系列步骤: 安装/启动php-fpm程序, 修改nginx.conf配置, reload, 才可以支持动态页面加载;
 

 

  1. 面试题二: php-cgi,php-fpm和CGI, FastCGI什么关系?
     php-fpm 是使用PHP语言, 实现的 FastCGI标准; 目前启动php-fpm程序
     php-cgi 是使用PHP语言, 实现的 CGI标准
    cgi(common gateway interface,通用网关接口)指web服务器在接收到客户端发送过来的请求后转发给程序的一组机制。
 
  1. Apache和Nginx处理客户端请求的机制区别?  Apache和Nginx有什么不同?
        3.1 从module角度
      Apache和Nginx全都是模块化设计
      Apache默认添加模块, “热添加”其他模块
      Nginx默认添加模块,  “冷添加”其他模块
              3.2 处理客户端请求机制角度:
      a、Apache多进程架构:  同步阻塞机制
        描述: Apache服务启动, 主进程预先创建多个子进程(配置文件中设置), 每当接收到client客户端请求, 主进程就直接交由子进程处理, 直到该请求处理完毕, 才可以接收其他请求
        一个进程对应一个请求
        缺点: 操作系统创建进程, 占用大量资源
          

 

    b、Apache 多进程多线程架构(改进架构): 同步阻塞机制
      优势: 系统开销小, 更多的线程执行客户端请求
      一个线程对应一个请求
                    

 

         3.3 Nginx如何客户端请求: 异步非阻塞机制
      工作进程接收某个请求(动态页面),直接交个php-fpm主进程, 此时该工作进程就可以继续接收其他请求
      一个进程对应多个请求
      简单流程图如下:
                        

 

 
   4. Apache如何支持PHP?
      windows: 安装Apache -> PHP, 在httpd.conf 添加PHP有关配置
   
       LAMP手动: 安装Apache -> PHP, 自动支持静态和动态页面
       结论:
  1. Apache只要稍微配置PHP,支持动态页面
  2. 每个httpd进程都包含phpx_module模块,无论加载静态页面,还是加载动态页面,都会耗费”一些”内存(多余)

 

 

 

 

 

转载于:https://www.cnblogs.com/cshaptx4869/p/10510541.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值