Linux: Nginx proxy_pass域名解析引發的故障

背景

業務架構:

clipboard.png

部署細節:
  兩容器均部署在同一機器上,通過 docker-compose 編排,并且通過link方式鏈接。

故障描述

在有次更新代碼時,發現前端能夠打開,但是所有接口請求全是502(Bad GateWay)

clipboard.png

故障排查

查看前端容器compose_ui_1的日志,刷了一大波502(Bad GateWay)

clipboard.png

UI沒問題的話,第一反映就是 compose_api_1 跪了,所以直接去容器看看日志
clipboard.png

容器日志看起來很正常,沒有崩潰,而且這個日志就好像從來沒收到請求那樣,但是很明顯我前端肯定有訪問的,感覺很奇怪。將接口取出來單獨訪問試試看:
clipboard.png

接口單獨訪問結果還是很殘暴的502(Bad GateWay),感覺還是不太可信,是不是端口或者主機什么訪問錯誤了?
本機開啟 wireshark 抓包確認下請求的主機和端口:
clipboard.png

這樣就很確保前端compose_ui_1訪問的主機和端口是正確的,而且確切結果是502(Bad GateWay),這樣只能從compose_api_1下手排查了。

之前也是遇到相似的問題,因為compose_api_1是通過uwsgi部署的python flask,那會總是用法覺得有點問題,改過uwsgi配置之后消停了一會。現在又卷土重來了。

先判斷下compose_api_1是不是真的跪了。。。雖然對這個沒抱什么希望。。。

直接訪問 后端api 接口
clipboard.png

額。。。尷尬。。。仿佛冤枉錯好人了。這不對吧,抓包看看再次確認下先:
clipboard.png

仿佛真的是。。。再 see see 容器日志:
clipboard.png

額。。。好吧。。。我錯了,compose_api_1沒跪。

于是問題來了。。。后端接口沒問題,前端訪問出錯了,見鬼了?

有種預感是容器的特性導致的問題。但愿不要。。

先進去compose_ui_1容器抓包分析下,看看整個請求鏈有沒有問題:
clipboard.png

似乎發現了點貓膩,Flags[R.]是代表 tcp鏈接 被 reset 重置 了,但是為什么平白無故重置呢?

看到 172.17.0.5.8080 返回的, 先 telnet 問問先:
clipboard.png

What???這就很迷了,首先這個 172.17.0.5.8080 哪來的呢?其次就是為毛端口不通?

突然想到一個很重要的問題:

容器之間是怎么知道它要把請求發給誰呢 ?

在前面已經交代過,這兩個容器是通過 link 的方式鏈接的,像下面這樣:

clipboard.png

谷歌搜了下 link 工作原理:

link機制通過環境變量的方式提供了這些信息,除此之外像db的密碼這些信息也會通過環境變量提供,docker將source container中定義的環境變量全部導入到received container中,在received container中可以通過環境變量來獲取連接信息。使用了link機制后,可以通過指定的名字來和目標容器通信,這其實是通過給/etc/hosts中加入名稱和IP的解析關系來實現的

所以就是說在 compose_ui_1 的 根據指定的名字并在 /etc/hosts 翻譯出具體的ip然后進行通信咯?
看看容器的名字是啥?

clipboard.png

compose_ui_1/etc/hosts

root@e23430ed1ed7:/# cat /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.4    detectapi fc1537d83fdf compose_api_1
172.17.0.3    authapi ff83f8e3adf2 compose_authapi_1
172.17.0.3    authapi_1 ff83f8e3adf2 compose_authapi_1
172.17.0.3    compose_authapi_1 ff83f8e3adf2
172.17.0.4    api_1 fc1537d83fdf compose_api_1
172.17.0.4    compose_api_1 fc1537d83fdf
172.17.0.6    e23430ed1ed7

如果真是按照資料所說,那 172.17.0.4:8080 才是 compose_api_1 的地址隱射才對吧?,試下先
clipboard.png
雖然返回了 auth product is None,但其實這是有效的請求。

再看看 compose_api_1 容器的日志:
clipboard.png

所以基本沒跑了, 為什么前端訪問直接就是 502, 原因就是 ui容器向錯誤的地址發送請求了

那么為什么會這樣呢?平白無故抽風了?

剛才根據 host 的記錄實驗了,按照它的映地址發起接口請求,是沒有問題的:

查看下 compose_ui_1nginx 日志
clipboard.png

尷尬。。。 nginx 日志居然直接連接到標準輸出和標準錯誤。。。
那為了簡單點,還是直接用 docker logs 查看吧
clipboard.png

看來 nginx 的轉發已經是錯誤的,為什么會轉發到 172.17.0.5, 看看 nginx 關于轉發的配置:
clipboard.png

這個 detectapi 和 上面貼出的 hosts 表能找到正確的地址 172.17.0.4 呀?搞不明白為什么會轉發到 172.17.0.5

難道是系統的域名解析錯誤了?
clipboard.png

尼瑪這真是太神奇了。

男人的直覺告訴我 nginx 有貓膩!

重啟下容器的 nginx,然而容器也被重啟了。。。
clipboard.png

再訪問頁面,居然可以了。。。
clipboard.png

再看看容器的nginx日志,已經轉發成功了
clipboard.png

這樣子的話,其實應該能定位到,問題是出在了 nginx 上面?

故障定位

只是為什么 nginx 會有這樣的錯誤呢?不太應該呀。。 感覺應該是 nginx 內部域名解析緩存問題。

然后查了下資料,呵呵,還真有。https://www.zhihu.com/questio...

clipboard.png

這就非常尷尬了。對這個問題抱有點懷疑,咨詢了資深大佬,然后大佬的回復就是:

如果 proxy_pass 后面跟的域名的話,在 nginx 啟動的時候就會初始化好,以后就只會復用這個值;參考:ngx_http_upstream_init_round_robin 函數
如果 proxy_pass 后面跟的是upstream,配置才會走解析和緩存的邏輯;

改善措施

  1. 不直接 proxy_pass 真實域名,而是轉發到 upstream 配置;
  2. 也可參考剛才的知乎鏈接處理方案:https://www.zhihu.com/questio...;

延展問題

  1. 為什么 compose_ui_1 指定的 compose_api_1 會出錯?
  2. proxy_pass 如果后面跟真實域名,是真的直接復用還是有時間緩存?

本來想用 gdb 調試下這個問題,然而花了一天時間,毛都沒有。不過也有點小收獲,那就是如何配置nginx來支持gdb

1.修改編譯配置文件:auto/cc/conf

ngx_compile_opt="-c"  改成 ngx_compile_opt="-c -g"

2../configure 時,增加編譯參數:--with-cc-opt='-O0', 避免編譯器優化;
例如:./configure --prefix=/usr/local/nginx --with-cc-opt='-O0' ....
如果不這樣的話,編譯器會優化代碼,導致調試過程中,循環中的一些變量值無法打印,會報下面的錯誤:

value optimized out

下面可以看下調試的效果:
nginx worker process 處理入口:ngx_http_static_handler

clipboard.png
歡迎各位大神指點交流, QQ討論群: 258498217
轉載請注明來源: https://segmentfault.com/a/11...

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/277980.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/277980.shtml
英文地址,請注明出處:http://en.pswp.cn/news/277980.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle建立全文索引詳解

Oracle建立全文索引詳解1.全文檢索和普通檢索的區別 不使用Oracle text功能,當然也有很多方法可以在Oracle數據庫中搜索文本,比如INSTR函數和LIKE操作: SELECT *FROM mytext WHERE INSTR (thetext, Oracle) > 0; SELECT * FROM mytext WHE…

面向全球用戶的Teams app之夏令時篇

我在前兩篇文章里分享了Global Ready的teams app時會遇到的不同挑戰。這篇我繼續分享在夏令時方面的挑戰。 夏令時,主要是為了節約能源,英文里通常縮寫成DST(Daylight Saving Time)。一般在天亮早的夏季人為將時間調快一小時,可以使人早起早…

爬取全部的校園新聞

1.從新聞url獲取新聞詳情: 字典,anews 2.從列表頁的url獲取新聞url:列表append(字典) alist 3.生成所頁列表頁的url并獲取全部新聞 :列表extend(列表) allnews *每個同學爬學號尾數開始的10個列表頁 4.設置合理的爬取間隔 import time import…

面向全球用戶的Teams app之合規性篇

我在前兩篇文章里分享了Global Ready的app時會遇到的不同挑戰。這篇我繼續分享在合規性方面的挑戰。 說到合規性compliance,不得不說GDPR標準,當我們發布了一個teams app后,微軟會要求開發人員做一個security self assessment,這…

C進階 - 內存四驅模型

一.內存四驅模型 不知我們是否有讀過 《深入理解 java 虛擬機》這本書,強烈推薦讀一下。在 java 中我們將運行時數據,分為五個區域分別是:程序計數器,java 虛擬機棧,本地方法棧,java 堆,方法區。…

行內元素中去掉文字的上下間距,使得文字所在元素的高度同字體高度一致的方法...

之前在p這類塊元素中的文字,給line-hight1;就可以去掉文字自帶的上下間距, 像這樣: 最近突然發現這個方法在行內塊和塊元素上好使,可當用在span或者a這類內聯元素上都不好使,除了轉為塊元素的方法來去掉上下間距&#…

VSCode的Teams插件

隨著今年在線的Build大會的結束,又是一大波的 Teams 新功能,新工具,新SDK。我接下來幾篇博客就會詳細和大家一一介紹。我今天先從VSCode的插件開始。 打開VS Code,搜索Teams,就可以找到Microsoft Teams Toolkit插件&a…

ADB原理,Wi-Fi連接,常用命令及拓展

Android 開發筆記 onGithub 文章多處鏈接需要科學上網 本文按順序主要講解了ADB的原理,使用Wi-Fi連接設備,ADB常用命令,在Java代碼中執行shell命令,使用ddmlib進行擴展。 ADB的原理 參考 官方文檔 ADB(Android Debug B…

使用Flow快速開發Teams小應用

繼續我的上一篇博客,這篇繼續介紹BUILD大會里的內容:Flow。 Flow是微軟power平臺的一個服務,通過簡單的拖拽就可以完成一個業務邏輯的處理,現在Flow和Teams的結合十分緊密。我們來試一下。 先點擊Teams左邊的Flow菜單。 如果你的…

python正則中如何匹配漢字以及encode(‘utf-8’)和decode(‘utf-8’)的互轉

正則表達式&#xff1a;  [\u2E80-\u9FFF]$ 匹配所有東亞區的語言   [\u4E00-\u9FFF]$ 匹配簡體和繁體   [\u4E00-\u9FA5]$ 匹配簡體   <input type"text" name"username" οnkeyup"valuevalue.replace([\u4E00-\u9FA5]$)"> 正則表…

【區塊鏈】認識區塊鏈的基本概念

2018年區塊鏈技術風卷全球&#xff0c;似乎大家都在談論區塊鏈&#xff0c;那到底什么區塊鏈&#xff0c;區塊鏈到底能干什么&#xff0c;對普通人會有什么影響&#xff0c;很多人還是稀里糊涂&#xff0c;那么就談談我的一些理解吧&#xff0c;拋磚引玉歡迎探討。 我是如何接觸…

Java 分割、合并byte數組

場景&#xff1a;上傳文件較大&#xff0c;把存放文件內容byte數組拆分成小的。下載的時候按照順序合并。 起初覺得挺麻煩的&#xff0c;寫完覺得挺簡單。 切割&#xff1a; /*** 拆分byte數組* * param bytes* 要拆分的數組* param size* 要按幾個組成一…

Java版本的Bot Framework SDK

微軟為了鼓勵Java開發人員開發bot&#xff0c;在上個月推出了Java的Bot SDK v4.6版本&#xff0c;目前還在Preview版本&#xff0c;相信不用多久就可以趕上其他版本了。 我的java還停留在 n 年前的水平&#xff0c;但是處于好奇&#xff0c;決定玩一下這套sdk。 這套sdk目前建…

jquery方法.serializeArray()獲取name和value并轉為json數組

jquery的.serializeArray()方法可以獲取形如以下 [ {name: firstname, value: Hello}, {name: lastname, value: World}, ] name value組成的對象數組&#xff0c;如果我們想得到key為name,value為value的json對象&#xff0c;則如下轉換&#xff1a; var m {}; $.each($(&quo…

Teams Bot 如何使用新的 System.Text.Json 庫

我最近把 LuckyDraw的代碼升級到了 .net core 3.1&#xff0c;當然我也很想使用最新的微軟json庫&#xff0c;System.Text.Json這個庫的性能比之前Newtonsoft.Json速度更快&#xff0c;而且就我本人愛好來說&#xff0c;更加喜歡System.Text.Json的命名&#xff0c;之前一直覺得…

將Teams Template升級到dotnet core 3.1

為了方便開發者開發Teams應用&#xff0c;我在2018年做了dotnet c#的一套模板&#xff0c;這套模塊一共有三種類型&#xff0c;一個是Teams OutgoingWebhook&#xff0c;一個是MessagingExtension&#xff0c;還有一個就是Tab。 今天特地去nuget上看了一下&#xff0c;下載量還…

【動態規劃】cf1034C. Region Separation

質因數分解套路的復雜度分析的動態規劃 題目大意 有一顆$n$個節點有點權的樹&#xff0c;初始整棵樹為$1$號區域&#xff0c;要求滿足下列規則&#xff1a; 除非$i$是最后一個等級&#xff0c;否則每一個$i$級區域都要被分成至少兩個$i1$級區域對于每種等級&#xff0c;每個點必…

阿里大魚短信介入demo分享

下面是關于大魚短信平臺對接的例子&#xff0c;發短信的話&#xff0c;可以用這個&#xff0c;很好用 /*** 通過阿里短信接口發送短信驗證碼* ***/ public class SendSmsUtil {private static Logger logger Logger.getLogger(SendSmsUtil.class);/*** 生成驗證碼* return*/pu…

GraphAPI 1.0中新增加的Teams API

這篇繼續介紹BUILD大會里的內容&#xff1a;兩個新加入GraphAPI 1.0的關于Teams的API。 這兩個新增api是關于在頻道Channel里發送消息和回復消息的。實際上這兩個api在beta版本中早就已經加入&#xff0c;上個月build大會中公布的只是把這兩個api正式發布到1.0版本&#xff0c…

【數據結構】線性表(一):順序列表

線性表(linear_list)是最常用且最簡單的一種數據結構&#xff0c;簡言之&#xff0c;一個線性表是n個數據元素的有序序列。 例如&#xff1a;&#xff08;a1 , ... , ai-1 , ai , ai1 , ... , an)&#xff1a;ai-1 是 ai 的直接前驅&#xff0c;ai1 是 ai 的直接后驅。 并且&am…