所有開發者都在潛意識中接受 localhost == 127.0.0.1 的概念,就像 1+1=2 這一數學概念一樣,但正如數學家試圖證明為什麼 1+1 是2,我今天突然對這部分感到好奇。因此,我開始深入研究這個原理,結果重新理解了 Linux 的通訊機制。這讓我體會到了開發者的邏輯嚴密性,在了解這個過程中,我不禁感到驚嘆。以下是我在這個過程中學到的內容整理。

1. localhost是如何連接到127.0.0.1的?

問題: 為什麼調用 localhost 會連接到127.0.0.1呢?

回答: 當 Linux 系統發生網絡請求時,它會將域名轉換為IP地址。在這個過程中,首先檢查 /etc/hosts 文件。基本上,/etc/hosts 文件中包含以下設置:

127.0.0.1    localhost

其中 127.0.0.1 指的是環回(loopback)接口,意味著 自我。因此當在瀏覽器或終端中調用 http://localhost 時,Linux 會通過 /etc/hosts 文件直接將這個請求連接到 127.0.0.1,而不經過 DNS。因此,localhost 這個名字在 Linux 中實際上充當了一個 自我的別名(alias)

2. /etc/hosts 文件究竟是什麼,它的作用是什麼?

問題: /etc/hosts 文件究竟是如何運作的?

回答: /etc/hosts 文件是在 Linux 的 主機名稱解析過程中最基本的機制之一。當發生網絡請求時,Linux 按如下順序將域名轉換為 IP 地址:

  1. 檢查 /etc/hosts 文件: Linux 的 glibc 庫中提供的 getaddrinfo() 函數是所有網絡請求的起點。這個函數在解釋域的 IP 地址時首先檢查 /etc/hosts 文件。如果 /etc/hosts 中已經定義了該域名,Linux 將使用這個信息立即返回 IP 地址,而不經過 DNS 伺服器。
  2. 請求 DNS 伺服器: 如果該域名在 /etc/hosts 文件中未定義,則通過設定的 DNS 伺服器查詢 IP 地址。

/etc/hosts 文件對所有網絡請求均適用,並且在瀏覽器、curl、ping 以及 Python 的 requests 模塊等網絡請求庫中同樣有效。

3. 利用 /etc/hosts 可以實現什麼?

問題: 添加域名到 /etc/hosts 文件會產生什麼效果?

回答: 如果在 /etc/hosts 文件中添加所需的域名和 IP 地址,那麼在調用該域名時,將不會經過 DNS,直接連接到設定的 IP。例如:

127.0.0.1    localhost
127.0.0.1    app1.local
127.0.0.1    app2.local

如上所示的設置將會導致:

  • 當請求進入 app1.local 和 app2.local 時,Linux 將其 路由到 127.0.0.1
  • 在開發環境中設置 虛擬域名測試應用間的內部通信 時非常有用。
  • 請求的域名雖然具有 和 localhost 相同的效果,但可以獨立處理每個域名。

4. Nginx 和 Gunicorn 如何與 /etc/hosts 協作?

問題: 像 Nginx 和 Gunicorn 這樣的伺服器可以與 /etc/hosts 文件進行聯動嗎?

回答: 像 Nginx 這樣的 web 伺服器在 Linux 網絡層上運作,因此會遵循 /etc/hosts 中設置的域名。例如:

  • 如果 /etc/hosts 中設置了 127.0.0.1 app1.local,那麼 Nginx 將請求路由到映射到 127.0.0.1 的應用程序。
  • 在 Nginx 中設置虛擬主機(virtual host)以便根據域名隔離請求。示例:
server {
    server_name app1.local;
    location / {
        proxy_pass http://127.0.0.1:8000;  # app1 服務
    }
}

server {
    server_name app2.local;
    location / {
        proxy_pass http://127.0.0.1:8001;  # app2 服務
    }
}

通過這個設定,兩個應用可以在同一伺服器上獨立運行。

5. /etc/hosts 在開發環境中有什麼用處?

問題: /etc/hosts 文件實際上在什麼情況下會有用?

回答: /etc/hosts 文件在開發和測試環境中特別在以下情況下會非常有用:

  • 本地域名測試: 可以在本地環境中測試特定域名。例如:將 https://test.local 映射到本地應用。
  • DNS 繞過: 在不設置實際 DNS 伺服器的情況下臨時連接到其他 IP。例如:將 example.com 連接到另一個伺服器 IP。
  • 應用間的內部通訊: 在同一伺服器上運行的多個應用之間,使用 /etc/hosts 可以減少 DNS 請求並優化通訊速度。

6. 在動態 IP 和 DNS 緩存問題中 /etc/hosts 的價值

個人經驗: 使用動態 IP 的開發者通常是通過 DDNS(動態 DNS)來解決IP變更的問題。但這裡有一個問題:Linux 主機有 DNS 緩存,因此在 TTL(生存時間) 到期之前,將一直使用之前的 IP。這可能會在應用間通信中導致發送舊 IP 的 TCP 請求時出現問題,除非手動使用 sudo resolvectl flush-caches 命令來刪除緩存。

為了解決這個問題,利用 /etc/hosts 可以繞過 DNS,將特定域名始終路由到固定的 IP。這讓我有過因為 IP 變更問題而產生的通信障礙得以根本上避免 的經驗。這樣簡單的設置成為解決問題的關鍵,讓我感到非常印象深刻。

總結

通過這一切過程,我意識到無意識中使用的 localhost 和 /etc/hosts 文件,其實與 Linux 的基本網絡機制緊密相連。當我感受到 Linux 開發者是如何邏輯嚴謹地設計這一基本結構的時候,甚至有一種敬畏感。單單一個文件卻能在開發環境和運行環境中扮演這麼重要的角色,實在令人驚訝。

這次經驗讓我再次認識到理解技術本質的過程是多麼有益。😊

Illustration of the /etc/hosts file usage