日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解proxy_pass、upstream与resolver

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解proxy_pass、upstream与resolver 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??詳解proxy_pass、upstream與resolver

應用場景

這里列舉幾個應用場景,下文會針對這幾個場景并結合代碼進行分析。

(1)proxy_pass + upstream

upstream foo.example.com {server 127.0.0.1:8001;}server {listen 80;server_name localhost;location /foo {proxy_pass http://foo.example.com;}}

訪問http://localhost/foo,proxy模塊會將請求轉發到127.0.0.1的8001端口上。

(2)只有proxy_pass,沒有upstream與resolver

server {listen 80;server_name localhost;location /foo {proxy_pass http://foo.example.com;}}

實際上是隱式創建了upstream,upstream名字就是foo.example.com。upstream模塊利用本機設置的DNS服務器(或/etc/hosts),將foo.example.com解析成IP,訪問http://localhost/foo,proxy模塊會將請求轉發到解析后的IP上。

如果本機未設置DNS服務器,或者DNS服務器無法解析域名,則nginx啟動時會報類似如下錯誤:

nginx: [emerg] host not found in upstream "foo.example.com" in /path/nginx/conf/nginx.conf:110

(3)proxy_pass + resolver(變量設置域名)

server {listen 80;server_name localhost;resolver 114.114.114.114;location /foo {set $foo foo.example.com;proxy_pass http://$foo;}}

訪問http://localhost/foo,nginx會動態利用resolver設置的DNS服務器(本機設置的DNS服務器或/etc/hosts無效),將域名解析成IP,proxy模塊會將請求轉發到解析后的IP上。

(4)proxy_pass + upstream(顯式) + resolver(變量設置域名)

upstream foo.example.com {server 127.0.0.1:8001;}server {listen 80;server_name localhost;resolver 114.114.114.114;location /foo {set $foo foo.example.com;proxy_pass http://$foo;}}

訪問http://localhost/foo時,upstream模塊會優先查找是否有定義upstream后端服務器,如果有定義則直接利用,不再走DNS解析。所以proxy模塊會將請求轉發到127.0.0.1的8001端口上。

(5)proxy_pass + upstream(隱式) + resolver(變量設置域名)

server {listen 80;server_name localhost;resolver 114.114.114.114;location /foo {set $foo foo.example.com;proxy_pass http://$foo;}location /foo2 {proxy_pass http://foo.example.com;}}

location /foo2實際上是隱式定義了upstream foo.example.com,并由本地DNS服務器進行了域名解析,訪問http://localhost/foo時,upstream模塊會優先查找upstream,即隱式定義的foo.example.com,proxy模塊會將請求轉發到解析后的IP上。

(6)proxy_pass + resolver(不用變量設置域名)

server {listen 80;server_name localhost;resolver 114.114.114.114;location /foo {proxy_pass http://foo.example.com;}}

不使用變量設置域名,則resolver的設置不起作用,此時相當于場景2,只有proxy_pass的場景。

(7)proxy_pass + upstream + resolver(不用變量設置域名)

upstream foo.example.com {server 127.0.0.1:8001;}server {listen 80;server_name localhost;resolver 114.114.114.114;location /foo {proxy_pass http://foo.example.com;}}

不使用變量設置域名,則resolver的設置不起作用,此時相當于場景1 proxy_pass + upstream。

(8)proxy_pass 直接指定IP加端口號

server {listen 80;server_name localhost;location /foo {proxy_pass http://127.0.0.1:8001/;}}

實際上是隱式創建了upstream,proxy_pass會將請求轉發到127.0.0.1的8001端口上。

主要代碼

解析proxy_pass指令的代碼:

static char * ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {ngx_http_proxy_loc_conf_t *plcf = conf;size_t add;u_short port;ngx_str_t *value, *url;ngx_url_t u;ngx_uint_t n;ngx_http_core_loc_conf_t *clcf;ngx_http_script_compile_t sc;if (plcf->upstream.upstream || plcf->proxy_lengths) {return "is duplicate";}clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);clcf->handler = ngx_http_proxy_handler;if (clcf->name.data[clcf->name.len - 1] == '/') {clcf->auto_redirect = 1;}value = cf->args->elts;url = &value[1];/* 查找指令中$符號的位置,判斷是否使用了變量 */n = ngx_http_script_variables_count(url);if (n) {/* 使用變量設置域名 */ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));sc.cf = cf;sc.source = url;sc.lengths = &plcf->proxy_lengths;sc.values = &plcf->proxy_values;sc.variables = n;sc.complete_lengths = 1;sc.complete_values = 1;if (ngx_http_script_compile(&sc) != NGX_OK) {return NGX_CONF_ERROR;}#if (NGX_HTTP_SSL)plcf->ssl = 1; #endifreturn NGX_CONF_OK;}if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {add = 7;port = 80;} else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {#if (NGX_HTTP_SSL)plcf->ssl = 1;add = 8;port = 443; #elsengx_conf_log_error(NGX_LOG_EMERG, cf, 0,"https protocol requires SSL support");return NGX_CONF_ERROR; #endif} else {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");return NGX_CONF_ERROR;}ngx_memzero(&u, sizeof(ngx_url_t));u.url.len = url->len - add;u.url.data = url->data + add;u.default_port = port;u.uri_part = 1;u.no_resolve = 1;plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);if (plcf->upstream.upstream == NULL) {return NGX_CONF_ERROR;}plcf->vars.schema.len = add;plcf->vars.schema.data = url->data;plcf->vars.key_start = plcf->vars.schema;ngx_http_proxy_set_vars(&u, &plcf->vars);plcf->location = clcf->name;if (clcf->named #if (NGX_PCRE)|| clcf->regex #endif|| clcf->noname){if (plcf->vars.uri.len) {ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,"\"proxy_pass\" cannot have URI part in ""location given by regular expression, ""or inside named location, ""or inside \"if\" statement, ""or inside \"limit_except\" block");return NGX_CONF_ERROR;}plcf->location.len = 0;}plcf->url = *url;return NGX_CONF_OK; }

upstream定義的后端服務器的處理邏輯,包括顯式定義的和隱式定義的。隱式定義,即proxy_pass指定的后端服務器的地址沒有顯式用upstream定義,nginx內部會定義一個。

ngx_int_t ngx_http_upstream_init_round_robin(ngx_conf_t *cf,ngx_http_upstream_srv_conf_t *us) {ngx_url_t u;ngx_uint_t i, j, n, w;ngx_http_upstream_server_t *server;ngx_http_upstream_rr_peer_t *peer, **peerp;ngx_http_upstream_rr_peers_t *peers, *backup;us->peer.init = ngx_http_upstream_init_round_robin_peer;/* * 使用upstream指令顯式定義upstream * 或者proxy_pass直接指定IP的場景*/if (us->servers) {server = us->servers->elts;n = 0;w = 0;for (i = 0; i < us->servers->nelts; i++) {if (server[i].backup) {continue;}n += server[i].naddrs;w += server[i].naddrs * server[i].weight;}if (n == 0) {ngx_log_error(NGX_LOG_EMERG, cf->log, 0,"no servers in upstream \"%V\" in %s:%ui",&us->host, us->file_name, us->line);return NGX_ERROR;}peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t));if (peers == NULL) {return NGX_ERROR;}peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n);if (peer == NULL) {return NGX_ERROR;}peers->single = (n == 1);peers->number = n;peers->weighted = (w != n);peers->total_weight = w;peers->name = &us->host;n = 0;peerp = &peers->peer;for (i = 0; i < us->servers->nelts; i++) {/* 設置sockaddr、weight、max_fails、fail_timeout等屬性 */}us->peer.data = peers;/* 處理backup servers相關邏輯 */return NGX_OK;}/* 未使用upstream指令,使用proxy_pass隱式定義upstream *//* an upstream implicitly defined by proxy_pass, etc. */if (us->port == 0) {ngx_log_error(NGX_LOG_EMERG, cf->log, 0,"no port in upstream \"%V\" in %s:%ui",&us->host, us->file_name, us->line);return NGX_ERROR;}ngx_memzero(&u, sizeof(ngx_url_t));u.host = us->host;u.port = us->port;if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {if (u.err) {ngx_log_error(NGX_LOG_EMERG, cf->log, 0,"%s in upstream \"%V\" in %s:%ui",u.err, &us->host, us->file_name, us->line);}return NGX_ERROR;}n = u.naddrs;peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t));if (peers == NULL) {return NGX_ERROR;}peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n);if (peer == NULL) {return NGX_ERROR;}peers->single = (n == 1);peers->number = n;peers->weighted = 0;peers->total_weight = n;peers->name = &us->host;peerp = &peers->peer;for (i = 0; i < u.naddrs; i++) {/* 設置sockaddr、weight、max_fails、fail_timeout等屬性 */}us->peer.data = peers;/* implicitly defined upstream has no backup servers */return NGX_OK; }

upstream模塊初始化請求時的邏輯:

static void ngx_http_upstream_init_request(ngx_http_request_t *r) {ngx_str_t *host;ngx_uint_t i;ngx_resolver_ctx_t *ctx, temp;ngx_http_cleanup_t *cln;ngx_http_upstream_t *u;ngx_http_core_loc_conf_t *clcf;ngx_http_upstream_srv_conf_t *uscf, **uscfp;ngx_http_upstream_main_conf_t *umcf;if (r->aio) {return;}u = r->upstream;/* NGX_HTTP_CACHE 等其他處理 */cln->handler = ngx_http_upstream_cleanup;cln->data = r;u->cleanup = &cln->handler;if (u->resolved == NULL) {/* 如果沒有使用resolver設置DNS,直接取upstream的設置 */uscf = u->conf->upstream;} else {#if (NGX_HTTP_SSL)u->ssl_name = u->resolved->host; #endifhost = &u->resolved->host;if (u->resolved->sockaddr) {if (u->resolved->port == 0&& u->resolved->sockaddr->sa_family != AF_UNIX){ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"no port in upstream \"%V\"", host);ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)!= NGX_OK){ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}ngx_http_upstream_connect(r, u);return;}umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);uscfp = umcf->upstreams.elts;/* 在顯式/隱式定義的upstream中查找 */for (i = 0; i < umcf->upstreams.nelts; i++) {uscf = uscfp[i];if (uscf->host.len == host->len&& ((uscf->port == 0 && u->resolved->no_port)|| uscf->port == u->resolved->port)&& ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0){goto found;}}if (u->resolved->port == 0) {ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"no port in upstream \"%V\"", host);ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}temp.name = *host;ctx = ngx_resolve_start(clcf->resolver, &temp);if (ctx == NULL) {ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}if (ctx == NGX_NO_RESOLVER) {ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,"no resolver defined to resolve %V", host);ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);return;}ctx->name = *host;ctx->handler = ngx_http_upstream_resolve_handler;ctx->data = r;ctx->timeout = clcf->resolver_timeout;u->resolved->ctx = ctx;if (ngx_resolve_name(ctx) != NGX_OK) {u->resolved->ctx = NULL;ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}return;}found:if (uscf == NULL) {ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,"no upstream configuration");ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}#if (NGX_HTTP_SSL)u->ssl_name = uscf->host; #endifif (uscf->peer.init(r, uscf) != NGX_OK) {ngx_http_upstream_finalize_request(r, u,NGX_HTTP_INTERNAL_SERVER_ERROR);return;}u->peer.start_time = ngx_current_msec;if (u->conf->next_upstream_tries&& u->peer.tries > u->conf->next_upstream_tries){u->peer.tries = u->conf->next_upstream_tries;}ngx_http_upstream_connect(r, u); }

詳細分析

場景1

解析proxy_pass的函數ngx_http_proxy_pass中,沒有找到$符號(即,變量設置域名),走ngx_http_proxy_pass后半部分的處理邏輯。ngx_http_upstream_init_round_robin初始化upstream時,走顯式定義upstream的邏輯。proxy_pass轉發請求初始化時,ngx_http_upstream_init_request中直接使用upstream中的后端server建立連接。

場景2

ngx_http_upstream_init_round_robin初始化upstream時,走隱式定義upstream的邏輯,會調用ngx_inet_resolve_host對proxy_pass中的域名進行解析,設置upstream。proxy_pass轉發請求初始化時,ngx_http_upstream_init_request中直接使用upstream中的設置,也就是利用本地設置的DNS服務器解析出的IP,建立連接。

場景3

解析proxy_pass指令時,找到了$符號,設置ngx_http_script_compile_t,并利用ngx_http_script_compile進行編譯,不走后半部分邏輯。配置文件沒有顯式/隱式定義upstream,所以不會調用ngx_http_upstream_init_round_robin方法。proxy_pass轉發請求初始化時,ngx_http_upstream_init_request中發現沒有顯式也沒有隱式定義的upstream,隨后調用ngx_resolve_start,對域名進行解析,之后將請求轉發過去。

場景4

解析proxy_pass指令時,找到了$符號,設置ngx_http_script_compile_t,并利用ngx_http_script_compile進行編譯,不走后半部分邏輯。顯式調用了upstream,所以調用ngx_http_upstream_init_round_robin方法中的顯式upstream的處理邏輯。proxy_pass轉發請求初始化時,ngx_http_upstream_init_request中優先查找upstream,如果找到了,直接將請求轉發到upstream中的后端server上。如果upstream中沒有找到,則對域名進行解析,然后將請求轉發到解析后的IP上。

場景5

基本與場景4相同,不同之處在于調用ngx_http_upstream_init_round_robin方法時,走隱式upstream部分的處理邏輯。

場景6

與場景2相同。

場景7

與場景1相同。

場景8

實際上是隱式創建了upstream,但是因為proxy_pass中指定了IP和端口號,所以ngx_http_upstream_init_round_robin初始化upstream時,us->servers不為空,所以走該函數的上半部分邏輯。與場景1有些類似。

?

總結

以上是生活随笔為你收集整理的详解proxy_pass、upstream与resolver的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线播放www | 青青草精品 | 青青操久久 | 91视频毛片 | 日本αv | 羞辱极度绿帽vk | 免费看黄色片视频 | 四虎一区二区三区 | 亚洲欧美综合在线观看 | 欧美一区二区三区在线免费观看 | 黄色性情网站 | 欧美xo影院 | 福利视频大全 | 日韩精品少妇 | 26uuu国产精品视频 | 国内精品久久久久久久影视简单 | 欧美亚洲综合在线 | 操碰视频在线 | 一级在线视频 | 欧美精品色哟哟 | 亚洲老女人av | 人人澡人人透人人爽 | 二级黄色录像 | 亚洲激情a| а中文在线天堂 | 久久亚洲AV成人无码一二三 | 大又大又粗又硬又爽少妇毛片 | 欧美一区二区三区色 | 成人毛片在线精品国产 | 成人免费片库 | 五月婷中文字幕 | 中文字幕1 | 中日韩毛片| 播播激情网 | 五月伊人网 | 亚洲高清免费 | 国产一页 | 成人羞羞免费 | 亚洲天堂网在线观看视频 | 国产资源第一页 | 亚洲网站在线 | 手机在线观看av网站 | 国产精品一区免费 | 精品国产三级a∨在线 | 国产美女一级片 | 欧美一级片在线播放 | 看黄网站在线观看 | 国产高清欧美 | 无码人妻一区二区三区在线视频 | 午夜av网 | 特级西西444www高清大胆 | 国产suv精品一区二区 | 欧美另类tv| 日韩福利视频 | 日本在线不卡一区二区 | 在线观看成年人网站 | 视色影院| 捆绑调教在线观看 | 波多野结衣 久久 | 一二区精品 | 男人在线天堂 | 最新中文字幕在线播放 | 国产女人和拘做受视频免费 | 久久7777| av观看一区 | 久久精品一二三 | 人人看人人模 | 对白超刺激精彩粗话av | 91美女在线视频 | 成年人三级视频 | 免费大黄网站 | 91爱爱视频| 欧美一区二区三区四区五区 | 精品国产丝袜一区二区三区乱码 | 日韩av中文字幕在线 | 日本久久久久久久久久久 | 国精品人妻无码一区二区三区喝尿 | 99r精品视频 | 黄色国产精品 | 17草在线| 午夜看黄神器 | 国产精品久久久久桃色tv | 国产xxxx | 亚洲性图一区二区三区 | 亚洲图片小说区 | 777米奇影视第四色 五月丁香久久婷婷 | 国产靠逼视频 | 污污视频在线免费看 | 国产福利视频一区二区三区 | 好色先生视频污 | 日韩欧美不卡视频 | 成人wwwww免费观看 | 国产视频欧美视频 | 天天色综合av | 成人性生交大全免 | 强制憋尿play黄文尿奴 | 麻豆精品国产 | 日韩在线视频免费看 | 五月天色站 |