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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發布時間:2023/12/9 linux 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux: Nginx proxy_pass域名解析引发的故障 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

業務架構:

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

故障描述

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

故障排查

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

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

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

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

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

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

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

直接訪問 后端api 接口

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

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

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

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

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

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

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

看到 172.17.0.5.8080 返回的, 先 telnet 問問先:

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

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

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

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

谷歌搜了下 link 工作原理:

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

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

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 的地址隱射才對吧?,試下先

雖然返回了 auth product is None,但其實這是有效的請求。

再看看 compose_api_1 容器的日志:

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

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

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

查看下 compose_ui_1 的 nginx 日志

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

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

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

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

尼瑪這真是太神奇了。

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

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

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

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

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

故障定位

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

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

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

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

改善措施

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

  • 為什么 compose_ui_1 指定的 compose_api_1 會出錯?
  • 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


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

    總結

    以上是生活随笔為你收集整理的Linux: Nginx proxy_pass域名解析引发的故障的全部內容,希望文章能夠幫你解決所遇到的問題。

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