DNS SRV:使用DNS伺服器做服務發現
DNS SRV 是 DNS 記錄中一種,用來查詢指定服務的地址。與常見的A記錄、CNAME 不同的是,SRV中除了記錄伺服器的地址,還記錄了服務的埠,並且可以設定每個服務地址的優先順序和權重。RFC-2782 給出DNS SRV的建議標準,它是在2000年的時候提出來的。
訪問服務的時候,本地的服務從 DNS 伺服器查詢到一個地址列表,根據優先順序和權重,從中選取一個地址作為本次請求的目標地址。
一個支援SRV的 LDAP client 通過查詢域名,可以得知 LDAP 服務的 IP 地址和服務埠:
_ldap._tcp.example.com
這個域名的格式是 rfc-2782 中推薦的格式,_ldap表示LDAP服務,_tcp表示通過TCP協議訪問LDAP服務。
SRV 的 DNS 型別程式碼為 33。SRV的記錄格式為:
_Service._Proto.Name TTL Class SRV Priority Weight Port Target Service: 服務名稱,字首“_”是為防止與DNS Label(普通域名)衝突。 Proto:服務使用的通訊協議,_TCP、_UDP、其它標準協議或者自定義的協議。 Name:提供服務的域名。 TTL:快取有效時間。 CLASS:類別 Priority: 該記錄的優先順序,數值越小表示優先順序越高,範圍0-65535。 Weight:該記錄的權重,數值越高權重越高,範圍0-65535。 Port:服務埠號,0-65535。 Target:host 地址。
客戶端查詢到多條記錄的時候,使用優先順序最高的記錄。對相同優先順序的記錄,按照權重選擇,記錄的權重越高,被選擇的可能性越高。
選擇的時候,將所有記錄的權重值累加,得到一個選擇區間[0,sum],每個記錄在[0,sum]中佔據一段連續的、長度為自身權重值區間。然後生成一個[0,sum]中的隨機數,隨機數落在的區間所屬的記錄就是被選擇的記錄。
注意事項
- 在使用DNS SRV的時候,要注意DNS Client是否按照預期的方式處理收到的SRV記錄。當前DNS SRV只能夠負責提供服務地址列表,對這個列表如何解讀,完全取決於Client的實現。
- rfc-1035 中規定,通過UDP協議傳輸DNS響應時,UDP報文的負載不能超過512位元組,在新增 SRV 記錄的時候,要特別注意。通過TCP傳輸時沒有512位元組的限制。
- 當一個服務地址有多個相同優先順序的SRV記錄的時候,Client會按照這些SRV的權重分配請求。下一次向服務發起的請求可能傳送到了不同的地址。
- 在通過SRV記錄的權重來分配請求的時候,使用的是本地快取的DNS記錄,所以不能實時地感知到服務的地址列表變化。除非將 TTL 設定的非常短暫,但這樣將會頻繁地查詢DNS伺服器。
Client查詢服務地址的過程
rfc-2782中已經做了很好地介紹,這裡就不表述了。
配置舉例
下面是DNS中 master file,可以看到有 example.com 域名提供了一個名為_foobar._tcp 的服務,這個服務有兩個 SRV 記錄,分別指向了 sys-box.example.com:1099 和 server.example.com:1099
$ORIGIN example.com. @SOA server.example.com. root.example.com. ( 2019030102 3600 3600 604800 86400 ) NSserver.example.com. NSns1.ip-provider.net. NSns2.ip-provider.net. ; _foobar._tcpSRV 0 1 1099 slow-box.example.com. SRV 0 3 1099 fast-box.example.com. ; if neither slow-box or fast-box is up, switch to ; using the sys-box and the server SRV 1 0 1099 sys-box.example.com. SRV 1 0 1099 server.example.com. serverA172.30.79.10 slow-boxA10.30.79.11 sys-boxA10.30.79.12 fast-boxA10.30.79.13 ; NO other services are supported *._tcpSRV0 0 0 . *._udpSRV0 0 0 .