Nginx 虚拟主机配置

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;
        }
}

未完待续...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343