Nginx常用HTTP模块配置解析

3,217 阅读4分钟

  nginx作为常用的Web服务器和反向代理,使用已经非常普遍。关于HTTP协议的所有的HTTP配置项都是属于http块、server块、location块、upstream块。本次就从使用场景入手,来讲解nginx的HTTP模块的常用配置。

一、http模块配置

1.日志:
  日志对于nginx的运维环境调试是非常重要的,在搭建运维环境,我们需要判断请求是否有被相应的服务接收到或者定位问题出现在接收请求前还是接收请求后时,最简单的方式就是看请求有没有打出access日志。如果nginx接收的请求处理出错可以根据error日志来定位问题。
  1)在配置access日志选项之前,我们一般先在http块中通过log_format选项配置日志的格式,例如配置一个日志格式为"main":

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

  其中默认配置文件除了有客户端的ip地址、请求时间、请求方法与url、响应状态和响应body字节数、请求代理信息等还可以通过nginx定义唯一的request id打到日志中进而在上游服务中跟踪请求处理情况。   定义完了日志的格式以后,就可以在http、server或者location块中通过:

#access_log access日志位置 access日志格式
access_log  logs/host.access.log  main;

来配置access日志了,access日志格式就可以使用我们之前定义的"main"。

  2)error.log 主要是处理http请求错误和nginx本身服务错误状态作为nginx本身的一个日志类型并不需要定义日志格式,可以在nginx.conf文件起始部分直接通过error_log配置项来配置:

#error_log  error日志位置 error日志级别
error_log  logs/error.log  notice;

2.include 导入配置:

  在启动一个nginx服务时,可能nginx会同时处理多个server的服务,为了使多个server的配置更加便于管理,一般会在http配置块中通过include配置项来引入其他的server配置文件,相当于把其他配置文件的内容写入到了nginx总的配置文件中,语法如下:

include     server/*.conf;

在单独的conf文件中,直接单独配置server:

server{
        listen 80;
        server_name test.com;
        location / {
                proxy_pass http://127.0.0.1:8888;
                proxy_set_header Host $host;
        }
}

  在server配置块中,需要通过listen配置项指定当前server监听的是哪个端口。并且通过server_name来指定当前该server所代表的域名。只有端口和域名匹配了,请求才能进入这个server被处理。
  server中location的处理是为同一域名下的不同url来给不同的服务分发请求:
  1)在location中可以通过文件路径的配置项root、alias、index和try_files对请求直接返回html文件进行处理。
  2)nginx作为反向代理还可以把进来的请求通过代理模块二次分发给上游服务,正如上面的例子中,我们通过proxy_pass配置项,直接把请求分发给了8888端口的进程进行处理。
  3)在作为反向代理时,除了通过proxy_pass直接发送给进程,还可以通过upstream模式将请求透传给指定的上流集群。这里涉及到负载均衡的知识点,稍后详细来讲。

二、.对不同的域名进行代理的nginx配置

  上文中的例子是对于80端口只起了一个域名的服务器。那如果我们想让nginx在一个端口上通过请求的不同域名来进行分发,该怎么配置server呢?很简单,只要对server配置不同的server_name就可以了:

server{
        listen 80;
        server_name test.com;
        location / {
                proxy_pass http://127.0.0.1:8888;
                proxy_set_header Host $host;
        }
}

server{
        listen 80;
        server_name a.test.com;
        location / {
                proxy_pass http://127.0.0.1:8888;
                proxy_set_header Host $host;
        }
}

  server_name当然也可以指定多个域名。当我们如上设置的时候,相当于写了两个完全匹配的server_name配置,nginx会在监听80端口的server中,优先选择绝对匹配的一个server来处理请求。访问a.test.com请求到服务器的时候,与第二个server完全匹配进而会分配给第二个server来进行处理。
  如果没有严格匹配的server,nginx就会再来匹配通配符在前面的域名,类似于:

*.test.com

再逐个匹配通配符在后面、正则表达式的server_name。

三、相同域名下不同请求路径

  在使用一个域名的项目中,我们想要根据请求路径的不同,转发到不同的服务,在nginx中是通过location块来配置的。两个upstream块可以看作是两个上游服务的集群,下面会详细讲解。两个location分别匹配请求路径以/prod/和/user/开头的uri且大小写敏感。

upstream prod {
  server localhost:8081 weight=5;
}
upstream user {
  server localhost:8082 weight=5;
}

server {
    listen              80;
    server_name         test.com;
    access_log  /data/log/nginx/access.log main;

    location ^~/prod/ {
        proxy_set_header Host $host;
        proxy_set_header  X-Real-IP        $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://prod/;
    }

    location ^~/user/ {
        proxy_set_header Host $host;
        proxy_set_header  X-Real-IP        $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://user/;
    }

}

  在代理转发的过程中,通过proxy_set_header配置项为转发请求加上代理所需的Header来标识代理过程。

四、负载均衡

  上文中多次提到了upstream块,nginx主要用它来实现负载均衡,尽量把请求平均地分步到每一台上游服务器上。需要在http块中使用,内部通过server配置项来定义集群中的服务器。格式为:

#server name [parameters]
server localhost:8082 weight=5;

其中name可以是域名、IP地址端口、UNIX句柄等。 其后可跟的参数如下,有两种分发策略:
1)weight=number:设置向这台上游服务器转发的权重,默认为1。
2)upstream块中标记ip_hash:在有些场景下,我们可能希望来自某一个用户的请求始终落到固定的一台上游服务器中。ip_hash就可以根据客户端的IP地址计算出一个key,将key按照upstream集群里的上游服务器数量进行取模,然后以取模后的结果把请求转发到相应的上游服务器中。这样就确保了同一个客户端的请求只会转发到指定的上游服务器中。如果集群中有一台上游服务器暂时不可用,不能直接删除该配置,而是要用down参数标识,确保转发策略的一贯性。例如:

upstream backend {
  ip_hash;
  server backend1.example.com;
  server backend2.example.com;
  server backend3.example.com down;
  server backend4.example.com;
}

参考:
1.《深入理解nginx》 陶辉
2.blog.csdn.net/linlin_0904… csdn博客
3.《HTTP协议原理》 慕课网

更多精彩文章敬请关注: