命名服務(wù),顧名思義,就是幫助我們對資源進行命名的服務(wù),命名的目的當然是為了更好的定位了。這里所提到的資源在不同場景中包括但不限于計算機(主機)名和地址、應(yīng)用提供的服務(wù)的地址或者遠程對象等。 本文主要介紹Java中的命名服務(wù)、簡單的命名服務(wù)的實現(xiàn)策略以及在分布式場景中如何實現(xiàn)命名服務(wù)。 JNDI要介紹命名服務(wù),不得不提 Java 命名和目錄接口(Java Naming and Directory Interface,JNDI),他是J2EE中重要的規(guī)范之一,標準的J2EE容器都提供了對JNDI規(guī)范的實現(xiàn)。 在沒有JNDI的場景中,我們要配置一個JDBC驅(qū)動鏈接數(shù)據(jù)庫時我們需要做以下操作:
上面的代碼中,把數(shù)據(jù)庫鏈接相關(guān)的字符串直接寫到了代碼中,這不是一個好的做法。有過web開發(fā)經(jīng)驗的人都知道,在真正的web開發(fā)中我們并不需要這樣定義JDBC的連接,我們一般都是把哪些固定的字符串配置到配置文件中,然后在代碼中直接從配置中讀取。甚至有很多數(shù)據(jù)庫處理的框架(Hibernate\mybatis)會幫我們把創(chuàng)建數(shù)據(jù)庫鏈接等操作全部都封裝好。 使用 JNDI 得到數(shù)據(jù)源:
為了讓 JNDI 解析 java:comp/env/jdbc/mydatasource 引用,部署人員必須把
上面介紹的JNDI是一種Java的命名服務(wù)。他充分的反映出命名服務(wù)的特點——對某一資源進行命名,然后通過名稱來定位唯一的資源。 到這里,我們可以確定的是:命名服務(wù)的目的是定義一個唯一的名字。這個名字的作用是可以用來定義唯一的資源。那么,我們想一想,在日常開發(fā)中我們?nèi)绾谓o一組資源中的每一個某一個進行一個唯一的命名呢?在數(shù)據(jù)庫開發(fā)中,通常有兩種方案: 數(shù)據(jù)庫自增ID在數(shù)據(jù)庫中,為了標識唯一記錄,可以使用自增ID,只要指定某個字段是自增的,那么數(shù)據(jù)庫就會幫我們維護這個字段的自增。不同數(shù)據(jù)庫的實現(xiàn)原理不一樣,即使是MySql數(shù)據(jù)庫,不同的引擎的實現(xiàn)方式也不盡相同。InnoDB 中AUTO_INCREMENT的實現(xiàn)原理可以參考:innodb-auto-increment-handling 但是,無論如何,自增ID的實現(xiàn)都是基于單庫單表的。也就是說一旦涉及到分庫分表及分布式環(huán)境,就不能依賴數(shù)據(jù)庫的自增字段來唯一標識一條記錄了。也就是說,他生成的ID也就不再能保證是唯一的了。 UUIDUUID(Universally Unique Identifier)全局唯一標識符,是指在一臺機器上生成的數(shù)字,它保證對在同一時空中的所有機器都是唯一的。按照開放軟件基金會(OSF)制定的標準計算,用到了以太網(wǎng)卡地址、納秒級時間、芯片ID碼和許多可能的數(shù)字。由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關(guān),如果你在生成一個UUID之后,過幾秒又生成一個UUID,則第一個部分不同,其余相同),時鐘序列,全局唯一的IEEE機器識別號(如果有網(wǎng)卡,從網(wǎng)卡獲得,沒有網(wǎng)卡以其他方式獲得),UUID的唯一缺陷在于生成的結(jié)果串會比較長。 UUID是由一組32位數(shù)的16進制數(shù)字所構(gòu)成,也就是說若每納秒產(chǎn)生1兆個UUID,要花100億年才會將所有UUID用完。 在Java中,可以通過 UUID是可以保證唯一性的,因為在這個長度為32位的ID中包含了時間、時鐘序列、全局唯一IEEE機器識別號等。但是,他有兩個比較明顯的缺點,那就是長度過長和沒有任何含義。長度自然不必說,他有32位16進制數(shù)字。對于『550e8400-e29b-41d4-a716-446655440000』這個字符串來說,我想任何一個程序員都看不出其表達的含義。一旦使用它作為全局唯一標識,就意味著在日后的問題排查和開發(fā)調(diào)試過程中會遇到很大的困難。 上面介紹了兩種傳統(tǒng)的數(shù)據(jù)庫中生成唯一標識的方法:自增ID和UUID。他們的優(yōu)缺點正好相反:
那么,有沒有一種方法可以在分布式環(huán)境生成一組自增的、唯一的ID呢? Zookeeper的命名服務(wù)Zookeeper是一個開放源碼的分布式服務(wù)協(xié)調(diào)組件,是Google Chubby的開源實現(xiàn)。是一個高性能的分布式數(shù)據(jù)一致性解決方案。他將那些復(fù)雜的、容易出錯的分布式一致性服務(wù)封裝起來,構(gòu)成一個高效可靠的原語集,并提供一系列簡單易用的接口給用戶使用。(http://www./archives/tag/zookeeper) Zookeeper 的命名服務(wù)與 JNDI 能夠完成的功能是差不多的,它們都是將有層次的目錄結(jié)構(gòu)關(guān)聯(lián)到一定資源上,但是 Zookeeper 的命名服務(wù)更加是廣泛意義上的關(guān)聯(lián),也許你并不需要將名稱關(guān)聯(lián)到特定資源上,你可能只需要一個不會重復(fù)名稱,就像數(shù)據(jù)庫中產(chǎn)生一個唯一的數(shù)字主鍵一樣。 Zookeeper可以實現(xiàn)命名服務(wù)有兩個重要的前提
上面說過,我們想在分布式環(huán)境生成一組自增的、唯一的ID,那么看看zookeeper如何保證這兩點。
下面是一個用開源客戶端ZKClient實現(xiàn)的命名服務(wù)的例子:
以上代碼就可以在 總結(jié)一些比較常見的分布式框架(RPC、RMI)等都需要用到命名服務(wù),如何解決分布式場景中的統(tǒng)一命名是一個至關(guān)重要的話題。 通過本文的介紹,可以知道Zookeeper可以解決分布式場景中的統(tǒng)一命名問題。通過本文,讀者不必立刻很深入的理解其中的原理,只需要知道zookeeper是可以做分布式的命名服務(wù)的就可以了,在以后的工作中遇到類似的場景可以想到zookeeper就夠了。 【公告】版權(quán)聲明 (全文完)如未加特殊說明,此網(wǎng)站文章均為原創(chuàng),轉(zhuǎn)載必須注明出處。HollisChuang's Blog ? 關(guān)于命名服務(wù)的知識點都在這里了 |
|