小T導讀:很多新用戶在配(pei)置(zhi)TDengine Database的(de)時(shi)候(hou),偶爾(er)會(hui)(hui)因為沒有(you)配(pei)置(zhi)好FQDN,導致出現“unable to resolve FQDN”問題。所以大(da)家(jia)會(hui)(hui)因為這個(ge)問題向TDengine的(de)研發團隊(dui)求(qiu)助。本文(wen)會(hui)(hui)講解FQDN的(de)相關設計和配(pei)置(zhi),希望能幫(bang)助用戶避(bi)免類似問題。
關于TDengine Database的(de)FQDN機制,很多用戶都表示:為什(shen)么TDengine要(yao)使(shi)用它,直接(jie)用IP不好嗎?
其實(shi)(shi)是(shi)這(zhe)樣,早在2.0之(zhi)前的(de)版(ban)本TDengine 確實(shi)(shi)是(shi)使用IP的(de)。但是(shi)考慮到很多生(sheng)產環境下IP都是(shi)會變動的(de),所以(yi)自2.0版(ban)本后,我們就引入了FQDN機制。
首先,為了避免(mian)混(hun)(hun)淆,我們要澄(cheng)清兩個概念,避免(mian)混(hun)(hun)淆,一(yi)個是(shi)(shi)TDengine的“fqdn參數”,一(yi)個是(shi)(shi)作(zuo)(zuo)為網絡服務的FQDN概念本身。當(dang)作(zuo)(zuo)為一(yi)個概念的時候(hou),FQDN又和域名、hostname這些(xie)概念有關,因此我們需要仔細理解(jie)。
所以,為了讓大家理清這個邏輯,在文章中我們會用“fqdn參數”和“FQDN”來分別指代參數和FQDN概念本身。

FQDN的全稱是Fully Qualified Domain Name。與域名相對(dui),我(wo)們暫(zan)且(qie)翻譯成全域名比較好理解一點。
FQDN分為(wei)兩部分組成:
1.Hostname:主機名,一(yi)般來(lai)說Linux當(dang)中運行hostname命令就(jiu)可以獲取,例如TDengine1;
2.Domain:域(yu)名,如。
所(suo)以一個全域名(ming)可以簡單理(li)解為(wei)一個帶(dai)著主機名(ming)的域名(ming)。
因此,上述情況下一個完整的FQDN就應該是 tdengine1.yakult-sh.com.cn。但是為了方便快速體驗,TDengine在安裝后會直接默認取本機的hostname——TDengine1作為fqdn參數的值。
概念(nian)和背景(jing)介(jie)紹完(wan)之后,接下來我們(men)進入配置階段:
首先我們要明確的一件事就是——只要你需要從客戶端遠程連接TDengine,那么服務端的fqdn參數強烈建議要手動配置而不是默認值。而且在配置的時候,不論是ip形式還是FQDN形式都是可以提供給客戶端用于連接的,配置方式如下:

在(zai)修改fqdn參數(shu)之后,我們要(yao)在(zai)/etc/hosts文(wen)件中(zhong)(或DNS服務)添加上TD1和對外的ip地址。

最后,修改(gai)/var/lib/taos/dnode/dnodeEPs.json里面的fqdn信(xin)息,數據(ju)庫服(fu)務就可(ke)以正常啟(qi)(qi)動了。(如果初次安裝數據(ju)庫,服(fu)務仍未啟(qi)(qi)動,則(ze)不會生成這些文件,可(ke)以忽(hu)略本步(bu)驟(zou))

了(le)解(jie)了(le)服務端配置的(de)正確配置方法后,接下來(lai),我(wo)們才要開始分(fen)析客戶端的(de)連接問(wen)題。
其實,不論在服務端fqdn參數中指定的值是不是IP,客戶端都是可以直接用IP來與服務端建立連接的。
如下(xia)圖所(suo)示,分別是Linux和Windows客戶端的(de)連接界(jie)面:

所以,這套機制的核心不在于taos -h的參數是IP還是fqdn參數值。而是在于從服務端取回的fqdn參數值能否被解析成正確的IP,它才是關乎于你能否順利操作數據的關鍵。
接下(xia)來,我(wo)要給大家(jia)舉兩個反例,也是(shi)大家(jia)經常遇到的兩個場景。

已(yi)知,服務端(duan)的IP地址為192.168.56.161,fqdn參數設置為TD1。
出現場景(jing)1的原因(yin)是(shi)——在(zai)這(zhe)個客戶(hu)端(duan)的hosts文件(或者DNS服務)中(zhong),沒有(you)寫TD1。上圖(tu)中(zhong),客戶(hu)端(duan)用taos -h 192.168.56.161連接到TDengine服務端(duan),取回TD1作為通訊地址(zhi)。當執行查詢的時候,TDengine試圖(tu)把TD1解析成ip卻發現TD1并不在(zai)其中(zhong)——這(zhe)就是(shi)Unable to resolve FQDN。
場景2:

已知(zhi),服務端的IP地址(zhi)為192.168.56.161,fqdn參數設(she)置(zhi)為TD1。
當查詢(xun)數據的(de)(de)時候,TDengine試(shi)圖把TD1在(zai)hosts文(wen)件(或DNS服務)中解(jie)析成IP。但是由(you)于IP地址寫(xie)錯了。因此客戶端解(jie)析出來的(de)(de)IP地址并(bing)不可用,從而無法建立連接——也就出現了“Unable to establish connection”的(de)(de)問題。
針(zhen)對(dui)以上(shang)這兩個常見問題,我們只要把(ba)服(fu)(fu)務(wu)端(duan)的(de)fqdn參(can)數(shu)值和IP,正確地(di)寫入(ru)到(dao)客戶端(duan)的(de)hosts(或DNS服(fu)(fu)務(wu))文件中就(jiu)好了。
那么(me),前面提到過(guo)的(de)“如果(guo)需要客戶端遠程連接TDengine,我們就一(yi)定要手動修改(gai)服務端的(de)fqdn參(can)數值”又是為(wei)什么(me)呢?
是這樣的:因為TDengine會默認讀取本機的hostname作為fqdn參數的值,所以很多新安裝的數據庫服務的fqdn參數都是“localhost”,或是“ubuntu”之類的名字。這時候如果你的客戶端hostname恰好也是localhost或者ubuntu,解析后,客戶端就會直接連到127.0.0.1(自己)——unable to establish connection發生了。
這個問題是新用戶遇到頻率超高的典型問題,所以最好的辦法還是自己寫一個新的fqdn值。
上述只(zhi)是針對單節點(dian)數據庫的(de)連接情(qing)況(kuang),在集群(qun)中(zhong)情(qing)況(kuang)稍有(you)不同,但原(yuan)理始終一致。
如下圖(tu)所示:A, B, C三臺(tai)機器上分別部署TDengine形成集(ji)群。每個節(jie)點都是通過自身(shen)的(de)hosts(DNS服務(wu))文件解(jie)析FQDN后(hou),尋址到IP后(hou)通過網絡(luo)層(ceng)互相(xiang)通訊。

比如:當TD-A節點發送消息給TD-B的時(shi)候,需要在TD-A自身(shen),找到(dao)TD-B對應(ying)的IP。因(yin)此(ci)我們需要在節點A的hosts(DNS服務)中(zhong)添加節點B。
同(tong)理,當(dang)TD-B節點在主動給TD-A發送(song)消息時,也需要(yao)在TD-B自身當(dang)中,找到(dao)TD-A對(dui)應的IP。因此我們需要(yao)在節點B的hosts(DNS服務)中添加節點A。
TD-C同上。
因(yin)此,如果節(jie)點之間(jian)互相(xiang)通訊時出現Unable to resolved FQDN,一定是某一方的hosts文(wen)件(DNS服務(wu))里,找不到對應的FQDN。
接下來(lai)我們加入(ru)客(ke)戶(hu)端:
(這(zhe)里我(wo)們要提一下TDengine的(de)架構,其(qi)實在每一個安裝(zhuang)包中(zhong)(zhong)都是自帶客(ke)(ke)戶(hu)(hu)端(duan)的(de),所以上面提到(dao)的(de)情況(kuang)中(zhong)(zhong)客(ke)(ke)戶(hu)(hu)端(duan)已經(jing)在參與了,本段(duan)提及(ji)的(de)客(ke)(ke)戶(hu)(hu)端(duan)特指(zhi)客(ke)(ke)戶(hu)(hu)端(duan)與服務端(duan)分離的(de)情況(kuang))
客戶端和集群之間(jian)的(de)通訊,通常是我們出錯的(de)重災區。因為TDengine點對點的(de)設(she)計,容(rong)易(yi)讓用戶忽(hu)略掉除(chu)連接目標以外的(de)集群服(fu)務(wu)器的(de)網絡問題。
一個正(zheng)常(chang)的客(ke)(ke)戶(hu)端遠程連接集群的架構圖應(ying)該如下圖所(suo)示——TD-A,TD-B,TD-C都需(xu)要存在于客(ke)(ke)戶(hu)端的hosts(DNS服務(wu))當(dang)中。

在(zai)以(yi)上整個(ge)使(shi)用FQDN的(de)鏈路(lu)當(dang)中,有(you)任何(he)1個(ge)不通都會出問題,但是這類錯誤通常(chang)都具有(you)隱蔽性:我們知道TDengine是一(yi)款分(fen)布式的(de)大(da)數據(ju)處理引擎(qing),所以(yi)它(ta)的(de)數據(ju)不只存在(zai)于一(yi)個(ge)節點上,也不是只有(you)一(yi)份。這時(shi)候(hou)如果你的(de)客戶端沒(mei)有(you)完全添加所有(you)的(de)fqdn到hosts(DNS服務)中,就可能會出現(xian)(xian)下面這種現(xian)(xian)象:
前幾天你搭建(jian)了集(ji)群,show dnodes看到節點都(dou)是ready,隨便查詢了幾張表都(dou)OK,寫入幾個表也沒問題——測試(shi)過了,萬(wan)事(shi)大(da)吉(ji)。
但是(shi)未(wei)來的(de)某(mou)一天(tian),你(ni)突然發現在寫入某(mou)張表的(de)時候TDengine報錯了,但是(shi)寫入一些其(qi)他表就沒問題——這是(shi)怎(zen)么回事呢(ni)?難道是(shi)bug?

并不是那樣。
首先(xian),集(ji)群中的數據(ju)庫(ku)一般都是(shi)多副(fu)本的,這意味著一個虛(xu)擬數據(ju)節(jie)(jie)(jie)(jie)點(dian)(vnode)有多個副(fu)本,以Master-slave形式存在。而TDengine的查詢操(cao)作可以在任意(Master或者(zhe)Slave)節(jie)(jie)(jie)(jie)點(dian)進行(xing),但(dan)是(shi)寫(xie)入(ru)操(cao)作只能在 Master 節(jie)(jie)(jie)(jie)點(dian)上進行(xing)。所以,如(ru)果當你(ni)寫(xie)入(ru)的那個表的Master節(jie)(jie)(jie)(jie)點(dian)恰巧(qiao)就在你(ni)無法(fa)通過fqdn連接到(dao)的節(jie)(jie)(jie)(jie)點(dian)上時,這個寫(xie)入(ru)操(cao)作就會(hui)報(bao)錯。
事實上,集群連(lian)接的報(bao)(bao)錯邏輯和單(dan)機版是類似的:如(ru)果(guo)客戶端(duan)服務(wu)器沒有(you)在(zai)hosts(DNS服務(wu))文件中(zhong)配置(zhi)正確的FQDN名字(zi),就(jiu)會報(bao)(bao)——unable to resolve FQDN。如(ru)果(guo)配置(zhi)了(le)(le)FQDN名字(zi)但(dan)是ip配錯了(le)(le),就(jiu)會報(bao)(bao)——unable to establish connection或者(zhe)database not ready。
所以,這部分問(wen)題(ti)一般都(dou)是配置疏漏導致,官方(fang)文檔原文如下(xia):
“客戶(hu)端也需要配置,確保它可以正確解析每(mei)個節(jie)點的fqdn配置,不(bu)管是通(tong)過(guo)DNS服務,還(huan)是 hosts 文(wen)件(jian)。”
因此,最簡單的確認配(pei)置方法就是去查看所有節點(dian)的hosts(DNS服務)內容,看看他們(men)關(guan)于集群節點(dian)的配(pei)置信息是否一模(mo)一樣就可(ke)以了。
能看到這里并仔細思考過的讀者們,我相信你一定已經掃清了關于FQDN的障礙了。而且,因為一些特定場景下出現的FQDN問題會結合著TDengine的典型的產品特性,所以借助這個問題你可以更加深入地理解TDengine的體系架構,為自己未來的使用做好更多的鋪墊。
最后偷偷告訴大家,未來TDengine會在錯誤提示方面做出更多優化——以FQDN為例,將會告訴大家是從哪個節點到哪個節點 “unable to resolve FQDN”,這樣我們在遇到相關問題后,處理起來就會更加得心應手了。


























