参考链接

一个虚拟服务是在 http 模块(context)中被 server 指令定义的。

It is possible to add multiple server directives into the http context to define multiple virtual servers.

在 http 模块中可以定义多个 server 模块。

listen 指令

例子:

  1. server {
  2. listen 127.0.0.1:8080;
  3. # The rest of server configuration
  4. }

listen 指令可以指定 ip 和 端口。

If a port is omitted, the standard port is used. Likewise, if an address is omitted, the server listens on all addresses. If the listen directive is not included at all, the “standard” port is 80/tcp and the “default” port is 8000/tcp, depending on superuser privileges.

如果省略了端口,默认监听 80 端口。如果省了地址,则默认监听所有的地址。

server_name 指令

server name 为虚拟服务器的识别路径。因此不同的域名会通过请求头中的HOST字段,匹配到特定的server块,转发到对应的应用服务器中去。

The parameter to server_name can be a full (exact) name, a wildcard, or a regular expression

  • server_name 的参数可以是完整的路径名,通配符(wildcard), 或者正则表达式(regular expression)。
  • server_name 可以写多个,用空格分隔。
  • 匹配 Host header 时,按照如下顺序 nginx 选择一个 server 模块:
    1. Exact name
    2. Longest wildcard starting with an asterisk, such as *.example.org
    3. Longest wildcard ending with an asterisk, such as mail.*
    4. First matching regular expression (in order of appearance in the configuration file)

例子,多个 server_name:

  1. server {
  2. listen 80;
  3. server_name example.org www.example.org;
  4. #...
  5. }

return 指令

  1. server {
  2. listen 80;
  3. server_name 112.10.116.104;
  4. client_max_body_size 1m;
  5. location /api {
  6. return 666;
  7. }
  8. }

这个 666 是 response Header 中的 http code。

注意点

listen 与 server 有先后顺序

If there are several servers that match the IP address and port of the request, NGINX Plus tests the request’s Host header field against the server_name directives in the server blocks.

先匹配端口,如果匹配到了多个 server, 才去匹配 server_name.

server_name 不匹配时

If the Host header field does not match a server name, NGINX Plus routes the request to the default server for the port on which the request arrived. The default server is the first one listed in the nginx.conf file, unless you include the default_server parameter to the listen directive to explicitly designate a server as the default.

如果nginx 中所有的 server_name 都不匹配 request 中的 host 字段,Nginx 路由会把请求分发到监听端口的第一个匹配, 比如:

  1. ls /etc/nginx/conf.d
  2. a.conf b.conf c.conf

那会走 a.conf , 因为它的文件名字母顺序排列在前面,会先被加载。

指定 default_server

上面的处理逻辑可能有问题,可以通过 default_server 指令去指定在匹配 nginx 中所有的 server_name 都不匹配 request 中的 host 字段时默认的 server 块:

  1. server {
  2. listen 80 default_server;
  3. #...
  4. }

多个配置文件有相同的 listen 和 server_name

比如 a.conf 和 b.conf 的 listen 指令和 server_name 指令的参数都相同,那么用 nginx 检测时会抛出 warn 警告:
因为当 listen 和 server_name 相同时,这表示的是同一个虚拟服务器。在这种情况下,应该把所有的 location 写到同一个配置文件。否则会出现如下的情况:
配置文件a.conf:

  1. server {
  2. listen 80;
  3. server_name 112.10.116.555;
  4. client_max_body_size 1m;
  5. location /api {
  6. return 666;
  7. }
  8. }

b.conf:

  1. server {
  2. listen 80;
  3. server_name 112.10.116.555;
  4. client_max_body_size 1m;
  5. location /test {
  6. return 888;
  7. }
  8. }

当请求 /test 时,nginx 会把请求分发到 a.conf server 上进行处理,a.conf 上面没有配置 /test , 上面的请求会抛出 404.