static char * ngx_stream_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_proxy_srv_conf_t *pscf = conf; ngx_url_t u; ngx_str_t *value, *url; ngx_stream_core_srv_conf_t *cscf; if (pscf->upstream) { return "is duplicate"; } cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module); cscf->handler = ngx_stream_proxy_handler; value = cf->args->elts; url = &value[1]; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = *url; u.no_resolve = 1; pscf->upstream = ngx_stream_upstream_add(cf, &u, 0); if (pscf->upstream == NULL) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_stream_upm_parse(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { u_short port; ngx_int_t add = 0; ngx_url_t *u; ngx_str_t *value, *url; ngx_stream_upm_main_conf_t *ummcf = conf; if (ummcf->upstream) { return "is duplicate"; } if (cf->args->nelts != 2) { return "With Invalid command args"; } value = cf->args->elts; url = &value[1]; ummcf->um_url = ngx_pcalloc(cf->pool, sizeof(ngx_url_t)); if (ummcf->um_url == NULL) { return NGX_CONF_ERROR; } u = ummcf->um_url; if (ngx_strncasecmp(url->data, (u_char *)"http://", 7) == 0) { add = 7; port = 80; } else { return "Invalid args, only support http://"; } u->url.len = url->len - add; u->url.data = url->data + add; u->default_port = port; u->uri_part = 1; u->no_resolve = 1; ummcf->upstream = ngx_stream_upstream_add(cf, u, 0); if (ummcf->upstream == NULL) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static char * ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { char *rv; void *mconf; ngx_str_t *value; ngx_url_t u; ngx_uint_t m; ngx_conf_t pcf; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx, *stream_ctx; ngx_stream_upstream_srv_conf_t *uscf; ngx_memzero(&u, sizeof(ngx_url_t)); value = cf->args->elts; u.host = value[1]; u.no_resolve = 1; u.no_port = 1; uscf = ngx_stream_upstream_add(cf, &u, NGX_STREAM_UPSTREAM_CREATE |NGX_STREAM_UPSTREAM_WEIGHT |NGX_STREAM_UPSTREAM_MAX_FAILS |NGX_STREAM_UPSTREAM_FAIL_TIMEOUT |NGX_STREAM_UPSTREAM_DOWN |NGX_STREAM_UPSTREAM_BACKUP); if (uscf == NULL) { return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } stream_ctx = cf->ctx; ctx->main_conf = stream_ctx->main_conf; /* the upstream{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_stream_upstream_module.ctx_index] = uscf; uscf->srv_conf = ctx->srv_conf; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_STREAM_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; } } uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_stream_upstream_server_t)); if (uscf->servers == NULL) { return NGX_CONF_ERROR; } /* parse inside upstream{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_STREAM_UPS_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) { return rv; } if (uscf->servers->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no servers are inside upstream"); return NGX_CONF_ERROR; } return rv; }
// 解析upstream{}块,它相当于server{}块,级别相同 // 创建一个upstream{}块的配置信息 // 检查是否有同名的upstream{},如有则报错 // 加入main conf里的upstreams数组,之后就可以在这里找到所有的upstream{} // 创建数组,存储upstream{}里的服务器信息 // 要求至少有一个server指定上游服务器,否则出错 static char * ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { char *rv; void *mconf; ngx_str_t *value; ngx_url_t u; ngx_uint_t m; ngx_conf_t pcf; ngx_stream_module_t *module; ngx_stream_conf_ctx_t *ctx, *stream_ctx; ngx_stream_upstream_srv_conf_t *uscf; ngx_memzero(&u, sizeof(ngx_url_t)); value = cf->args->elts; // 指令的第一个参数是upstream块的名字 u.host = value[1]; u.no_resolve = 1; u.no_port = 1; // 创建或者获取一个upstream{}块的配置信息 // 获取时flags==0 // 检查是否有同名的upstream{},如果是创建时有则报错 // 加入main conf里的upstreams数组,之后就可以在这里找到所有的upstream{} uscf = ngx_stream_upstream_add(cf, &u, NGX_STREAM_UPSTREAM_CREATE |NGX_STREAM_UPSTREAM_WEIGHT |NGX_STREAM_UPSTREAM_MAX_FAILS |NGX_STREAM_UPSTREAM_FAIL_TIMEOUT |NGX_STREAM_UPSTREAM_DOWN |NGX_STREAM_UPSTREAM_BACKUP); if (uscf == NULL) { return NGX_CONF_ERROR; } // tcp流处理的配置结构体 // 与http不同的是没有location,只有两级 // 在cycle->conf_ctx里存储的是stream{}级别的配置 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_stream_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } // 保存stream{}的配置上下文 // 也就是stream{}里的ngx_stream_conf_ctx_t stream_ctx = cf->ctx; // main_conf直接指向stream{}的main_conf ctx->main_conf = stream_ctx->main_conf; /* the upstream{}'s srv_conf */ // 分配存储srv_conf的数组,数量是ngx_stream_max_module ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_stream_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } // 存储本配置块的配置 // ngx_stream_upstream_module相当于ngx_stream_core_module // 同时在main conf的servers数组里也有 ctx->srv_conf[ngx_stream_upstream_module.ctx_index] = uscf; // 保存本upstream{}的配置数组 uscf->srv_conf = ctx->srv_conf; // 遍历模块数组,调用每个stream模块create_srv_conf,创建配置结构体 // 但实际上除了负载均衡模块,其他模块不会在这里出现,没有意义 for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_STREAM_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf; } } // 创建数组,准备存储upstream{}里的服务器信息 uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_stream_upstream_server_t)); if (uscf->servers == NULL) { return NGX_CONF_ERROR; } /* parse inside upstream{} */ // 暂存当前的解析上下文 pcf = *cf; // 设置upstream模块的新解析上下文 // 使用刚才刚创建的配置结构体存储模块的配置信息 cf->ctx = ctx; cf->cmd_type = NGX_STREAM_UPS_CONF; // 递归解析事件相关模块 // 里面主要是server指令和负载均衡算法指令 rv = ngx_conf_parse(cf, NULL); // 恢复之前保存的解析上下文 *cf = pcf; if (rv != NGX_CONF_OK) { return rv; } // 要求至少有一个server指定上游服务器,否则出错 if (uscf->servers->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no servers are inside upstream"); return NGX_CONF_ERROR; } return rv; }