nginx当没有匹配到server块时会选择default server处理请求。default server的定义分为两种:
1. 显式定义
listen 指令后加default_server参数,则该server块被定义为default server。对于相同的监听端口,只能有一个server被显示定义为default server。如下图,server xxxx.com是default server。
http{
server {
listen 80;
server_name xxx.com;
}
server {
listen 80 default_server;
server_name xxxx.com;
}
}
2. 隐式定义
当一个监听地址没有显式的default_server定义时,加载配置时该地址第一个被载入的server即是default_server。
代码说明
加载配置时,listen配置会存入ngx_http_listen_opt_t中。
typedef struct {
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t addr_text;
unsigned set:1;
unsigned default_server:1; //如果listen后配置了default_server,该字段被设置成1
unsigned bind:1;
unsigned wildcard:1;
unsigned ssl:1;
#if (NGX_SSL_ASYNC)
unsigned asynch:1;
#endif
unsigned http2:1;
#if (NGX_HAVE_INET6)
unsigned ipv6only:1;
#endif
unsigned deferred_accept:1;
unsigned reuseport:1;
unsigned so_keepalive:2;
unsigned proxy_protocol:1;
int backlog;
int rcvbuf;
int sndbuf;
#if (NGX_HAVE_TCP_FASTOPEN)
int fastopen;
#endif
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
int tcp_keepidle;
int tcp_keepintvl;
int tcp_keepcnt;
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
char *accept_filter;
#endif
}
之后调用ngx_http_add_listen将监听添加到ngx_http_conf_port_t中。对于已有的监听端口,调用ngx_http_add_addresses;对于第一次出现的监听端口,调用ngx_http_add_address。ngx_http_add_address会新增一个监听地址,同时将该监听地址的default_server设置成该server配置。
static ngx_int_t
ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
{
ngx_http_conf_addr_t *addr;
...
addr->opt = *lsopt;
addr->hash.buckets = NULL;
addr->hash.size = 0;
addr->wc_head = NULL;
addr->wc_tail = NULL;
#if (NGX_PCRE)
addr->nregex = 0;
addr->regex = NULL;
#endif
addr->default_server = cscf;
addr->servers.elts = NULL;
return ngx_http_add_server(cf, cscf, addr);
}
对于已存在的监听地址,ngx_http_add_addresses在ngx_http_listen_opt_t.default_server为1时会将ngx_http_conf_addr_t中的default_server替换为新的server配置。
static ngx_int_t
ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
{
ngx_http_conf_addr_t *addr;
...
if (lsopt->default_server) {
if (default_server) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"a duplicate default server for %V",
&addr[i].opt.addr_text);
return NGX_ERROR;
}
default_server = 1;
addr[i].default_server = cscf;
}
addr[i].opt.default_server = default_server;
...
}