美文网首页Nginx
Nginx 虚拟主机配置

Nginx 虚拟主机配置

作者: JunChow520 | 来源:发表于2019-05-15 11:27 被阅读177次

    Nginx有什么作用呢?

    Ngnix作为一款高性能的HTTP服务器、反向代理服务器、电子邮件代理服务器,主要有三方面的应用:

    • HTTP服务器

    Nginx作为HTTP服务器可独立提供HTTP服务,也可做为静态资源服务器。

    • 虚拟主机

    Nginx可以实现一台服务器虚拟出多个站点

    • 反向代理负载均衡

    当访问量达到一定量级后单台服务器无法支撑用户的请求时,可使用多台服务器做集群。此时可使用Nginx做反向代理,并可以为多台服务器做负载均衡以分担负载,因而不会因为某个节点负载过高宕机或某个节点闲置的情况。

    什么是虚拟主机呢?

    虚拟主机使用的是特殊的软硬件技术,将单台物理机(服务器)切分为多台虚拟的主机,每台虚拟主机都可以具有独立的域名,并具有完整的Internet服务器功能,如WWW、FTP、Email等。同时,同一台物理服务器上的虚拟主机之间是完全独立的。从站点访问者的角度来看,每台虚拟主机和一个独立主机完全是一样的。

    虚拟主机

    利用虚拟主机不必为每个要运行的站点提供一台单独的Nginx服务器,或是单独运行一组Nginx进程。虚拟主机提供了在同一台物理机、同一组Nginx进程上运行多个站点的功能。

    Nginx的配置文件的组成结构是什么样的呢?

    Nginx配置文件结构

    Nginx配置文件文件可以分为六部分

    • main 全局配置
    • events Nginx工作模式
    • http HTTP配置
    • server Server模块作为HTTP的模块主要用来配置虚拟主机
    • upstream 上游服务器设置,主要为反向代理、负载均衡等相关设置。
    • location URL匹配特定位置后的设置,每部分包含若干指令。

    Nginx将配置文件拆分为若干部分,主要分为

    • nginx.conf 主配置文件
    • vhost.conf 虚拟主机配置文件
    • fastcgi_params 与PHP相关的配置
    • uwsgi_params 与Python相关的配置
      ...

    Nginx可以配置哪几种类型的虚拟主机呢?

    • 基于域名的虚拟主机

    使用不同的域名对应相同的IP以区分站点

    • 基于IP的虚拟主机

    使用不同的域名不同的IP区分站点

    • 基于端口的虚拟主机

    不使用域名、IP来区分不同站点,而是使用不同的TCP端口区分

    Nginx虚拟主机的配置文件是什么样的呢?

    server {
            listen       80;
            server_name  yxkwx.cn yxkwx.cn;
            root   "D:/phpStudy/PHPTutorial/WWW/myproj/public";
            location / {
                index  index.html index.htm index.php;
                #autoindex  on;
                if (!-e $request_filename) {
                    rewrite  ^/(.*)$  /index.php/$1  last;
                    break;
                }
            }
            location ~ \.php(.*)$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_param  PATH_INFO  $fastcgi_path_info;
                fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
                include        fastcgi_params;
            }
    }
    

    配置解读

    用户对PHP动态网页访问过程

    当Nginx只是作为一个Web服务器时,本身是并没有Apache那么强大的功能的,不过通过支持各种模块让Nginx实现对多种功能的支持。另外,Nginx本身只能处理静态页面的解析,如果要解析动态页面的话,就需要使用到反向代理。也就是说,Nginx会将PHP等动态页面请求转发给后端其它Web服务器进行处理,如Tomat、IIS、Apache等。如果访问量过大的话就是要使用到Nginx的负载均衡架构。

    对于PHP页面而言,通过Nginx转发给后端会有两种情况:反向代理、FastCGI,需要注意的是这里反向代理的后端指的是Web服务器,而FastCGI是实现PHP的解析程序。当Nginx将PHP页面请求转发给FastCGI程序时,也就时通过FastCGI方式对PHP进行了支持,PHP页面会交由FastCGI代理处理,这也是反向代理的一个应用。

    Nginx+FastCGI+Wrapper+PHP

    当用户浏览器发起对yxkwx.cn/index.php地址的访问时,用户和Nginx服务器会进行三次握手建立TCP链接,这里我们忽略掉Nginx访问控制策略和防火墙访问控制策略等,结合vhost.conf虚拟主机配置文件来分析下Nginx与PHP、FastCGI、PHP-FPM的运行过程。

    第1步

    用户将HTTP请求发送给Nginx服务器

    第2步

    Nginx根据用户访问的URI和后缀对请求进行判断

    用户访问yxkwx.cn/index.php地址时,Nginx会根据配置文件中的location进行匹配。由于访问的是index.php所以会被匹配到location ~ \.php(.*)$,正则所表示的含义是对用户通过URI访问的资源进行区分大小写的匹配且访问的资源中包含.php

    Nginx根据用户请求的资源匹配到具体的location后,会执行location对应的动作,location中动作是

    fastcgi_pass   127.0.0.1:9000;
    
    fastcgi_index  index.php;
    
    fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
    
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    
    fastcgi_param  PATH_INFO  $fastcgi_path_info;
    
    fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
    
    include        fastcgi_params;
    

    根据Nginx服务器的配置,可看出用户访问的是动态的PHP资源,Nginx会调用PHP脚本解析器对用户访问的资源进行解析。

    具体每行指令的含义分析如下:

    • include fastcgi_params;

    表示Nginx会调用FastCGI这个接口

    • fastcgi_intercept_errors on;

    表示开启FastCGI的中断和错误信息记录

    • fastcgi_pass 127.0.0.1:9000;

    表示Nginx通过fastcgi_pass将用户请求的资源发送给127.0.0.1:9000进行解析,这里的Nginx和PHP脚本解析服务器是在同一台机器上的,所以127.0.0.1:9000表示的是本地的PHP脚本解析服务器。

    Nginx通过location指令将所有包含.php的文件都交给127.0.0.1:9000来处理,这里的IP地址和端口就是FastCGI进程监听的IP地址和端口,其整个工作流程如下:

    1. FastCGI进程管理器PHP-FPM自身初始化,启动主进程PHP-FPM并启动start_servers这个CGI子进程。主进程PHP-FPM主要是管理FastCGI子进程并监听9000端口,FastCGI子进程等待来自Nginx的连接。

    2. 当客户端请求到达Nginx时,Nginx通过location指令将所有包含.php的文件交由127.0.0.1:9000来处理。

    3. FastCGI进程管理器PHP-FPM选择并连接到一个子进程CGI解释器,Nginx将CGI环境变量和标准输入发送到FastCGI子进程。

    4. FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回给Nginx,当FastCGI子进程关闭连接时请求便告处理完成。

    5. FastCGI子进程接着等待并处理来自FastCGI进程管理器的下一个连接

    第3步

    通过第2步可以看出用户请求的是动态内容,Nginx会将请求交给FastCGI客户端,通过fastcgi_pass将用户的请求发送给PHP-FPM。如果用户访问的是静态资源,Nginx会直接将用户请求的静态资源返回给用户。

    FastCGI

    这里出现的FastCGI是什么呢?

    了解FastCGI之前首先要明白CGI是什么,CGI全程Common Gateway Interface,意为通用网关接口,是用于HTTP服务上的程序服务通信交流的一种工具,是一个可伸缩地、高速地在HTTP服务器和动态脚本语言之间进行通信的接口,这个接口在Linux下也就是Socket,只是这个Socket可以是文件Socket也可以是IP Socket。

    对比传统的CGI接口方式,由于传统的CGI接口方式性能与安全性较差,由于每次HTTP服务器遇到动态程序需要重启解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发时几乎是不可能的,因此诞生了FastCGI。

    FastCGI PHP-FPM

    PHP-FPM又是什么呢?

    PHP-FPM是管理FastCGI的一个管理器,它作为PHP的插件存在。PHP-FPM提供了更好的PHP进程管理方式,可以有效地控制内存和进程,可以平滑重载PHP配置。

    第4步

    fastcgi_pass将动态资源交给PHP-FPM后,PHP-FPM会将资源转给PHP脚本解析服务器的wrapper

    Nginx+FastCGI

    Nginx不支持对外部程序的直接调用或解析,所有的外部程序如PHP必须通过FastCGI接口来调用。为了调用CGI程序,还需要一个FastCGI的wrapperwrapper可以理解为用于启动另一个程序的程序,这个wrapper绑定在某个固定socket上,如端口或文件socket。当Nginx将CGI请求发送给这个socket时,通过FastCGI接口wrapper接收到请求,然后Fork派生出一个新的线程,这个线程调用解释器或外部程序处理脚本并读取返回数据。接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx。最后,Nginx将返回的数据(如HTML页面或图片等)发送给客户端。

    简单来说,首先需要一个wrapper完成以下工作:

    • 调用FastCGI库函数使用socket与Nginx通信
      其读写socket是FastCGI内部实现的功能,对wrapper是非透明的。
    • 调度线程进行Fork和Kill
    • 和应用(PHP)进行通信

    第5步

    wrapper收到PHP-FPM转交过来的请求后,wrapper会生成一个新的线程调用PHP动态程序解析服务器。

    如果用户请求的是需要读取,如MySQL数据库等将会触发读库操作。

    如果用户请求的是图片或附件等资源,PHP会触发依次查询后端存储服务器,例如通过NFS进行存储的存储集群。

    第6步

    PHP会将查询到的结果返回给Nginx

    第7步

    Nginx构造一个响应报文将结果返回给用户

    综上所述

    这只是Nginx中其中一种实现,用户请求的和返回给用户的结果都是异步进行的,也就是说用户请求的资源在Nginx中做了一次中转。Nginx也支持同步,即解析出来资源后服务器直接返回给用户,不用再中转。

    是不是每次用户对动态资源的请求都需要触发一次完整的动态资源解析过程呢?

    不是的,其实有两种方法可以解决这个问题:

    第1种:启用Nginx本身所具有的缓存功能,将动态资源解析结果缓存起来,下次用户进行对应资源访问时,Nginx进行本次缓存查询,如果查询命中则直接将动态资源解析后的静态资源返回给用户。

    第2种:在Nginx后端部署缓存机器,例如部署Varnish缓存集群,对资源进行缓存,用户请求的资源可以先在缓存集群上进行查找。

    使用Nginx做缓存是否可行呢?

    这个要看实际情况,如果在整个Web架构中Nginx不是瓶颈的前提下,Nginx是可以用来做缓存的,但并不建议这样来做,因为Nginx是用户请求和应答的必经之路。如果Nginx出现了瓶颈则后端的其它如存储集群等性能再好也没用。所以,在实际部署中并不建议启用Nginx的缓存功能(在将Nginx作为HTTP服务器的情况下)。因为启用了Nginx缓存功能后会降低Nginx的性能,另外会消耗部署Nginx对应服务器的硬件资源。

    配置语法

    正则表达式匹配

    • = 表示请求字符串与URI严格匹配,一旦匹配成功则停止,用于标准URI前。
    • ~ 表示匹配时区分大小写,用于正则URI前。
    • ~* 表示匹配时不区分大小写,用于正则URI前。
    • !~ 表示区分大小写则不匹配
    • !~* 表示不区分大小写则不匹配
    • ^~ 表示匹配以什么开头的
      用于标准URI前,要求Nginx找到标识URI和请求字符串匹配度最高的location后立即使用此location处理请求,而不再使用location块中的正则URI和请求字符串做匹配。
    • $ 表示匹配以什么结尾的
    • \ 转义字符,用于字符的转义。
    • * 表示任意字符

    文件与目录的匹配

    • -f 表示存在某文件
    • !-f 表示不存在某文件
    • -d 表示存在某目录
    • !-d 表示不存在某目录
    • -e 表示存在文件或目录
    • !-e 表示不存在文件或目录
    • -x 表示文件可执行
    • !-x 表示文件无法执行

    例如:

    • location / {} 表示匹配任何查询,因为所有请求都是以/开头,但正则规则和长的块规则将被优先和查询匹配。
    • location ^~ /images/ {} 表示匹配任意以/images/开头的查询请求并停止搜索
    • location ~* \.(gif|jpg|jpeg)$ {} 表示匹配任何以.gif.jpg.jpeg结尾的请求

    配置指令

    server

    server {}
    
    ### listen
    
    

    Nginx的虚拟主机通过server节点指定,若要设置多个虚拟主机则可配置多个server节点即可。

    listen       80;
    

    listen用于指定虚拟主机监听的TCP端口号,也就是虚拟主机的服务端口,默认80为WWW服务对应的端口号。

    server_name

    server_name  yxkwx.cn yxkwx.cn;
    

    server_name用于指定虚拟主机名,当用户使用链接访问虚拟主机名时就会由所对应的虚拟主机进行处理。
    虚拟主机名可以有四种格式

    • 准确的名字,例如yxkwx.cn
    • *开头的名字,例如*.yxkwx.cn
    • *结尾的名字,例如yxkwx.*
    • 正则表达式形式,例如~^www\d+\.yxkwx\.com$,注意必须以~开头。

    虚拟主机名可以同时设置多个,设置多个时以空格隔开。

    例如: server_name yxkwx.cn www.yxkwx.cn *.yxkwx.cn

    当设置多个虚拟主机名时,其优先级先后顺序为

    • 准确的名字
    • 最长的以*开头的通配符的名字
    • 最长的以*结尾的同配置的名字
    • 第一个匹配的正则表达式名字

    root

    root   "D:/phpStudy/PHPTutorial/WWW/myproj/public";
    

    root指定当前虚拟主机实际物理根目录的绝对路径

    location

    location模块是Nginx中最常使用也是最重要的模块,用来定位并解析URL
    location提供了强大的正则匹配功能,也支持条件判断匹配。
    用户可使用location指令实现Nginx对动态与静态网页进行过滤处理。

    location指令的格式为location [modifier] uri {...},当一个请求进入时URI会被检测并匹配一个最佳的location,首先会进行精确匹配若匹配失败则会进行字符串的前缀匹配,依次进行正则匹配、匹配常规字符串模糊匹配,若以上匹配都不成功,将会执行默认匹配。

    location = /

    表示精确匹配

    location /documents/

    表示匹配常规字符串,模糊匹配。如果有正则检查则正则优先。

    location /

    由于所有的请求都是以/开头,所以location /表示匹配所有请求,另外也表示匹配访问站点根目录。当所有location都不能匹配后的默认匹配原则。

    location ~

    location指令可以使用正则匹配,开启正则匹配是使用location ~

    location ^~ /images/

    表示先进行字符串的前缀匹配,如果匹配到了就不做正则匹配检查。

    location ~* .(gif|jpg|jpeg|png)$

    表示正则匹配,*表示不区分大小写。

    例如:

    location ~ \.php(.*)$ {
      fastcgi_pass   127.0.0.1:9000;
      fastcgi_index  index.php;
      fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
      fastcgi_param  PATH_INFO  $fastcgi_path_info;
      fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
      include        fastcgi_params;
    }
    

    \.php(.*)$是使用正则匹配以.php结尾的URL,进而用来解析PHP文件。

    例如:Nginx设置禁止访问某类文件

    location ~* \.(txt|doc)$
    {
      if (-f $request_filename)
      {
        root /usr/local/nginx/html/test;
        break;
      }
    }
    
    location ~* \.(txt|doc)$
    {
      root /usr/local/nginx/html/test;
      deny all;
    }
    

    例如:Nginx设置静态文件处理

    location ~* \.(css|js|jpg|jpeg|gif|png|swf)$
    {
      if (-f $request_filename)
      {
        root /usr/local/nginx/html;
        expires 1d;
      }
      break;
    }
    

    index

    index  index.html index.htm index.php;
    

    index指定当前虚拟主机默认访问首页的文件名,index中是有先后顺序的,如果没有开启目录浏览权限同时又找不找这些默认首页的话,就会出现403错误。

    autoindex

    autoindex on; 
    

    autoindex表示是否开启网站根目录文件列表功能,开启后访问目录时会列出根目录中的文件列表,默认关闭off

    autoindex_exact_size on;
    

    autoindex_exact_size表示是否显示文件列表中每个文件的确切大小,注意单位是字节bytes,默认为开启状态on

    autoindex_localtime off;
    

    autoindex_localtime表示是否显示文件列表中每个文件的服务器本地时间,时间格式为GMT格林威治时间,默认为关闭状态off

    
    ### allow
    allow all;
    

    允许所有访问

    charset

    charset
    

    charset 用于配置网页的默认编码格式

    access_log

    access_log
    

    access_log用来指定当前虚拟主机的访问日志存放路径,最后的main用于指定访问日志的输出格式。

    rewrite

    rewrite指令主要用于实现URL地址重写,Nginx的重写规则需要PCRE的支持,即通过Perl兼容正则表达式语法进行规则匹配。默认参数编译时Nginx就会安装支持rewrite的模块,但也必须要有PCRE软件的支持。

    rewrite指令语法:rewrite regex replacement [flag]

    例如:URL重写跳转为rewrite ^/(.*) http://www.baidu.com/$1 permanent;

    rewrite为重写参数,正则部分为^/(.*) http://www.baidu.com/$1,其中$1表示获取正则()括号部分的值。

    flag标记符号的取值范围

    • last 表示本条规则匹配完成后,继续向下匹配新的location URI规则。
    • break 表示本条规则匹配完成即终止,不再匹配后面的任何规则。
    • redirect 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址。
    • permanent 返回302永久重定向,浏览器地址栏会显示跳转后的URL地址。

    错误处理

    错误1:浏览器访问http://192.168.50.25:81/admin/login出现404错误

    Nginx多域名配置中支持PATHINFO路由模式

    server {
            listen       81;
            server_name  yxkwx.cn yxkwx.cn;
            root   "D:/phpStudy/PHPTutorial/WWW/myproj/public";
            location / {
                index  index.html index.htm index.php;
                #autoindex  on;
                if (!-e $request_filename) {
                    rewrite  ^/(.*)$  /index.php/$1  last;
                    break;
                }
            }
            location ~ \.php(.*)$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_param  PATH_INFO  $fastcgi_path_info;
                fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
                include        fastcgi_params;
            }
    }
    

    错误2:浏览器访问http://192.168.50.25:82,页面出现错误No input file specified.

    查看Nginx错误日志文件error.log文件发现错误信息

    2019/05/15 11:03:18 [crit] 13928#9540: 
    *5 GetFileAttributesEx() "D:\phpStudy\PHPTutorial\WWW
    myproj\public/api.html" failed 
    (123: The filename, directory name, or volume label syntax is incorrect), 
    client: 192.168.50.25, 
    server: nbb.cn, 
    request: "GET /api.html HTTP/1.1",
     host: "192.168.50.25:82"
    

    以上错误信息重点关注The filename, directory name, or volume label syntax is incorrect说明文件路径有问题

    查看多域名配置文件vhost.confroot配置项目root "D:\phpStudy\PHPTutorial\WWW\myproj\public";,将正斜杠\修改为反斜杠/重启Nginx服务器即可。

    server {
            listen       82;
            server_name  nbb.cn nbb.cn;
            root   "D:/phpStudy/PHPTutorial/WWW/myproj/public";
            
            location / {
                index  index.html index.htm index.php;
                #autoindex  on;
                if (!-e $request_filename) {
                    rewrite  ^/(.*)$  /index.php/$1  last;
                    break;
                }
            }
            
            location ~ \.php(.*)$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_param  PATH_INFO  $fastcgi_path_info;
                fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
                include        fastcgi_params;
            }
    }
    

    未完待续...

    相关文章

      网友评论

        本文标题:Nginx 虚拟主机配置

        本文链接:https://www.haomeiwen.com/subject/ngjuaqtx.html