一篇好TM長的關於配置中心的文章
配置 (Configuration)
配置(Configuration) 這個概念每個技術人都不陌生,可以說一個不提供幾個配置引數的系統都不好意思上線跟別的系統打招呼。那麼為什麼會是這個樣子呢,究其本質是我們人類無法掌控和預知一切,對映到軟體領域上,我們總是需要對系統的某些功能特性預留出一些控制的線頭,以便我們在未來需要的時候,可以人為的撥弄這些線頭從而控制系統的行為特徵,我把它叫做 “系統執行時(runtime)飛行姿態的動態調整“。
舉個簡單的例子,
logLevel = INFO
系統正常飛行的時候,我們希望其只輸出INFO級別的日誌資訊,在生產環境中我們甚至希望只輸出WARNING/ERROR級別的日誌,系統出毛病了,再將日誌輸出動態的調整成包含診斷資訊的DEBUG級別或者TRACE級別。
軟體的老友 - 配置檔案
在那個單機即系統的時代,我們基本都是在用配置檔案來儲存配置項,一個配置項,就是如上面的logLevel那樣的一個含有 = 表示式,如下:
<figure class="highlight plain" style="display: block; margin: 20px 0px; overflow: auto; padding: 15px; font-size: 13px; color: rgb(77, 77, 76); background: rgb(247, 247, 247); line-height: 1.6;">
|
<pre style="overflow: auto; font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", monospace; font-size: 13px; margin: 0px; padding: 1px; color: rgb(77, 77, 76); background: rgb(247, 247, 247); line-height: 1.6; border: none;">config_key = config_value // value1 or value2, you can choose one from the config_value set
</pre>
|
</figure>
一般來說config_value
應該是一個有限空間的值集合,應該是有選擇餘地的,如果config_value
沒得選擇,那麼我只能認為這個配置項一定特麼在逗我。而一個配置檔案一般是一組配置項的集合或者叫配置集,一個系統根據邏輯模組劃分,可以有1到多個配置檔案。如下圖 :
在集中式開發時代,配置檔案基本足夠用了,因為那時配置的管理通常不會成為一個很大的問題,簡單一點來說,系統上了生產之後,如果需要修改一個配置,登入到這臺生產機器上,vi修改這個配置檔案,然後reload一下並不是什麼很大的負擔。
如下圖:
所以曾經的企業級應用架構標準J2EE裡並沒有制定關於配置管理這一塊的任何標準。
當然一些Follow J2EE標準的廠商,如以前Oracle的中介軟體WebLogic在實際實踐時,因為很多大企業客戶的環境也挺複雜的,所以WebLogic在這一塊還是做了一些工作,其支援一個叫做Deployment Plan的特性,如下圖:
其背後的本質就是開發人員(dev)打出來的應用war包裡面的配置檔案都是一些PlaceHolder, 在部署人員(ops)部署war包的時候,為目標環境提供與之匹配的的depoloy plan xml檔案,WebLogic Server本身在deploy這個stage將war包配置項的placeholder值替換成plan裡面的值。
分散式系統給系統配置管理帶來的挑戰
關於什麼是分散式系統,本文不再贅述,毫無疑問今天阿里的系統就是一個大型的、服務化的、複雜的、分散式系統實現之一。在這個領域有3本書值得反覆閱讀<<分散式系統概念與設計>> <<分散式系統原理與泛型>> 以及 Distributed Systems For System Architects,有意思的是這三本書只有最後一本在21.3小節簡單的提了一下 Configuration Of Distributed Systems,裡面簡單的說了一下靜態配置和動態配置的概念和區別 “…System configuration may be static or dynamic…”. 這說明什麼? 這說明我們阿里技術人包括我們中介軟體今天面臨的很多問題和領域已經進入深水區,已經沒有人會直接給你提供這個領域清晰的解決方案,我們自己正站在前沿,而我們的成功的或者失敗的探索,其經驗和成果都應該總結並分享給整個業界。
在過去的大約15年左右,軟體工程學在如何持續演進軟體以適應一直要變的需求的方法論上有了很多的突破和大量的實踐,在這個領域,從物件導向設計方法論,到極限程式設計,到敏捷開發、持續整合、單元測試等等,理論和實踐都已經比較成熟了,關鍵是配合這一套方法論的配套的工具和軟體集都變得非常的成熟。
這裡面的一個非常有意思的東西是關於系統的演進或者進化論(Software Evolution),一個系統或者說軟體從被創造出來之後會經歷研發、測試、到最後的go live,上了生產系統。那麼這個之後,如何持續並且無痛的為其新增新行為或者調整已有行為的表現特徵? 這確實非常複雜,尤其是要達到無痛的這個目標,畢竟線上系統,調整即意味著可能出故障。系統的動態配置管理毫無疑問是其中的一個小部分,如果每一個系統行為的任何一個微調都需要將整個系統停機,重啟或者甚至重新構建、釋出部署來實現,那要達到無痛這個目標恐怕難度更高。
在分散式系統中,一次構建、釋出、上線是非常非常重的一個過程,它不像單機時代那樣重啟一臺機器、一個程式就可以了,在分散式系統中,它涉及到將軟體包(例如war)分發到可能超過幾千臺機器,然後將幾千臺機器上的應用程式一一重啟這麼一個過程,超過2000臺機器的一個應用一次完整的釋出過程需要多長時間,相信很多核心繫統的小二都深有體會。
那麼如何在不停應用叢集的情況下,調整整個叢集的執行時的行為特徵(即系統執行時的飛行姿態),是一個分散式系統必須回答的一個問題。從這個角度講, 我們認為:
現在我們很容易理解,其實我們平時常見的分散式系統的配置變更,諸如:
- 執行緒池、連線池大小
- 開關、預案、限流配置
- toggleFeature
- 資料來源主備容災切換
- 路由規則
- 我是等等等等
背後的本質都是在做分散式系統執行時行為特徵(飛行姿態)的調整。
每一個分散式系統都應該有一個動態配置管理系統
是的,你一定注意到了,這裡的說法跟圖片上的有點不一樣,這裡想強調的是,未必都需要配置中心,在一個分散式系統規模還較小時,比如一個公司就二個應用叢集,那無論你是用配置檔案+auto-reload還是用redis,zookeeper什麼都可以,這個動態配置管理系統不一定要是一個獨立存在的,可以跟其它的系統,例如註冊中心,甚至作為訊息中介軟體的一個子系統都沒有關係。但是重要的是知道一定要有這麼一個東西,它給自己的系統提供了動態調整行為的能力,而配置管理系統基本固有的特性一定要實現。
動態配置和靜態配置的區別
曾經我也傻傻分不清楚其區別是啥,這很正常。動態和靜態這是一個相對的概念,海枯石爛,永遠不變的那不叫配置,可能是撩妹的鬼話,即使這個配置可能是放在一個看起來很像配置檔案的文字里,配置一定是可能修改其值的,而是否是動態配置主要是看這個配置是不是跟應用的版本構建釋出(build-deploy lifetime)強繫結的。如果一個配置項,跟軟體的版本構建是不耦合的,在應用程式執行時,可能需要變更配置值的就是動態配置,哪怕是變更頻率可能非常低,也許你設計了一個配置項,發現最後下來3年也沒變更過一次,那也是動態配置,相反,配置變更只發生在軟體版本構建和釋出的那個點,那麼就是靜態配置,哪怕你構建很頻繁,1個小時就來一回,那也是個靜態配置,舉個簡單的例子:
<figure class="highlight plain" style="display: block; margin: 20px 0px; overflow: auto; padding: 15px; font-size: 13px; color: rgb(77, 77, 76); background: rgb(247, 247, 247); line-height: 1.6;">
|
<pre style="overflow: auto; font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", monospace; font-size: 13px; margin: 0px; padding: 1px; color: rgb(77, 77, 76); background: rgb(247, 247, 247); line-height: 1.6; border: none;">build-version = 3.4.6-1569965
</pre>
|
</figure>
這個配置項,永遠只在某個軟體版本被構建出來時會變更其值,一旦這個版本被構建出來,並且在程式執行時,是一定沒有變更訴求的,這就是一個跟構建繫結的靜態配置。而文章開始時舉得logLevel的例子,則是一個動態配置的例子。
所以看一下你的系統的配置項,你會發現動態配置其實更多,而跟行為演進相關的幾乎都是動態配置。
為什麼是淘寶
我在進來阿里做Diamond之後,思考過一個有意思的事情,為什麼獨立的配置中心這個東西會首先出現在淘寶? 你去國內著名的競價排名搜尋引擎百度上搜”配置中心”,你會發現資訊不是特別多,但是排在前面的都是XDiamond, SuperDiamond這種Diamond一族, 反正我們沒有為讓配置中心跟Diamond這個名字關聯給百度付過1毛錢,所以這個搜尋結果應該是個自然結果,側面也反應了在國內說起配置中心在生產上大規模運用是獨此一家,別無分號。
而在業界,如下圖,Spring Boot/Cloud微服務將註冊中心(discovery service)和配置中心(configuration service)提出來還處在佈道階段,
而且從Spring的實現方式的技術侷限性來看,應該是還沒有哪個公司基於這個配置中心的方案在生產上實際支援大規模分散式系統,畢竟,翻遍所有blog和文章,還沒有哪個老外開始提到,這個基於git的方案應該怎麼去做多資料中心以及容災相關的非功能性需求。
回到那個問題,為什麼是淘寶,我們都知道在國內業界淘寶率先開啟了去IOE,全面採用MYSQL,在這個過程中,在國內,大規模的系統性的解決分庫分表這個命題的毫無疑問是阿里以及阿里中介軟體,在這個過程中,誕生了業內著名的TDDL.而與TDDL關聯的一個核心問題是,分庫分表之後,這多個庫的資料來源的配置資訊存放在哪裡,並對應用遮蔽多庫這個事實? 好吧後面的事情也許你知道了,放在配置中心裡! 但還是要提的是曾經並沒有Diamond, 都在註冊中心(ConfigServer)裡,後來Diamond從ConfigServer分了出來,這個過程,很多人看到的是資料是持久化和非持久化的區別以及當時產品的穩定性方面的考量,直到今天也還是如此,但是,通過這麼多年實踐和演進下來,才恍然大悟,拆分的背後其實是服務發現(Service Discovery)和動態配置管理服務(Dynamic Configuration Management)根本就是兩個不同的東西,而在當時可能僅是一種直覺。
莫道君行早,更有早行人
有時候我們會因為在某個領域我們走的早一點而產生一點點的”優越感”和“虛榮感”, 曾經我們以為Dynamic Configuration For Distributed System這個領域的實踐我們不能說在業界獨佔鰲頭,但是絕對位居前列。但是下面這兩個老哥再次提醒我們,技術人踏實前行,不要有不必要的想法:
這兩位老哥在1985年4月,在IEEE TRANSACTIONS ON SOFTWARE ENGINEERING 上發表了一篇名為 Dynamic Configuration for Distributed Systems的論文(Paper),奶奶的,1985年!!什麼概念,當時我4歲,還在玩泥巴,穿開襠褲。而Diamond現在的主力技術架構研發同學都還沒出生呢!!我們能做的,只能是向這兩位前輩再次致敬!
在這篇論文中,雖然從現在的觀點來看,當時人們對分散式系統的認識跟現在有很大的區別,但是其中的問題識別的非常的準確:
“….Dynamic systemc onfiguration is the ability to modify and extend a system while it is running. The facility is a requirement in large distributed systems where it may not be possible or economic to stop the entire system to allow modification to part of its hardware or software. It is also useful during production of the system to aid incremental integration of component parts, and during operation to aid system evolution.The paper introduces a model of the configuration process which permits dynamic incremental modification and extension. Using this model we determine the properties required by languages and their execution environments to support dynamic configuration…”
並且很清晰的區分了靜態配置和動態配置的基本模型:
配置與環境
另一個值得從技術上玩味的是關於“配置”的“環境”屬性,這個表達可能有點抽象,比較難理解,這有點像技術上常提的一個叫Context的概念,很多Component會關聯一個Context,Component+Context才是一個完整的執行時故事。環境恰恰也是熱帖中大家可能會產生的疑問之一,為何Diamond會暴露這麼多的環境讓應用去選擇? 而進一步對中介軟體更熟稔一點的人會問,在單元化場景中,為何註冊中心是一個大叢集模式,而配置中心又是一個小叢集模式?
另一方面,多個環境恰恰也是加重分散式系統需要依賴一個獨立的配置管理系統的要素之一,可以說哪個公司的環境越複雜,分散式應用和服務越多,哪個公司誕生出獨立的配置中心繫統的可能性也就越大。
舉幾個容易理解的表述,來幫助理解配置的環境屬性,
“在開發環境中將logLevel設定為DEBUG,在預發環境logLevel設定為INFO,生產環境裡logLevel設定為WARNING”
“在日常環境執行執行緒池的最大執行緒數應該設定為15,而生產環境上這個值應該大一點,預設設為150”
“線上上環境中,中心機房,應用資料來源需要連線A庫,而S機房,應用應該就近連線使用B庫”
“只有在T環境,雙向同步開關才應該關閉”
“這次的改動有點大,新的特性僅線上上的H單元把該特性開放出來,其它的單元環境先不要開放出來”
是的,相信你一定發現了,我們的某個配置項,其具體的值域的定義往往跟具體的環境相關聯,現實中相當一部分配置在不同的環境必須設定不同的值,但是也有相當的另一部分配置在不同的環境要設定為完全一致的值。所以從某個應用的視角看,其100個配置項,可能有50個是每個環境要不同的值的,而另50個是不區分環境,所有環境其配置值都是需要完全一致的。這種異化給配置管理系統的設計帶來了複雜性,而且這個最終語義的解釋,很顯然不應該在配置中心繫統本身,應該交給應用,配置管理系統應該做的是提供方便的互動方式保證這兩種不同的一致性訴求同時得到很好的滿足,這種訴求分為3個方面,如下示意圖:
是的,相信你一定發現了,我們的某個配置項,其具體的值域的定義往往跟具體的環境相關聯,現實中相當一部分配置在不同的環境必須設定不同的值,但是也有相當的另一部分配置在不同的環境要設定為完全一致的值。所以從某個應用的視角看,其100個配置項,可能有50個是每個環境要不同的值的,而另50個是不區分環境,所有環境其配置值都是需要完全一致的。這種異化給配置管理系統的設計帶來了複雜性,而且這個最終語義的解釋,很顯然不應該在配置中心繫統本身,應該交給應用,配置管理系統應該做的是提供方便的互動方式保證這兩種不同的一致性訴求同時得到很好的滿足,這種訴求分為3個方面,如下示意圖:
Diamond 這三個能力都有提供,其中1,2一般都是在配置中心的提供的客戶端類庫和OPS中體現。其中3這個實現是比較困難的,因為多個環境之間一般來說,都是有一些諸如遠距離網路或者網路隔離之類的物理約束的,要做分散式一致性以及諸如分割槽容忍性之類的考量,目前Diamond只支援線上多單元一致性約束規則,但是因為歷史原因大家沒有真正用起來,規則本身的抽象度也不夠好,不夠通用。現在我們正在做改造,未來會將一致性規則做的更通用,後面會引導大家用起來,這樣對於那些多環境保持一致的那些配置項,環境複雜性就可以對應用遮蔽掉,如果一個應用的配置項全是要各環境一致的,那麼你就有福了,天空飄來五個字,”這麼多環境就不是個事”。
另外,一個配置中心也應該具備的能力是配置集的匯出\匯入功能,可以讓應用將A環境中的配置集方便的匯出和匯入到環境B中的能力,這對3個場景都有重大意義,一個場景是線上的配置值是經過實踐驗證的,現在在日常或者預發新建了應用環境,希望將線上的配置copy到線下用起來,第二個是,線下的應用終於調通要發預發或線上了,調較好的配置希望一下子發到線上去,當然這個根據我們的經驗,一定要慎重,第三個是新建站或者機房,應用需要在新的機房將所有配置遷移過去,Diamond很快就會將這種能力開放出來。
理解了上面講的這些,相信你就更能理解Spring Framework 裡的兩把刷子(抽象) Environment 和 PropertySource 是咋回事了, 詳細參見:
Spring 3.1 M1: Unified Property Management
https://spring.io/blog/2011/02/15/spring-3-1-m1-unified-property-management/
配置的三個屬性
- 環境屬性
- 稀疏變更屬性
- 快速傳播
環境屬性我們上文已經討論過。
稀疏變更講的是配置的變更基本上都是稀疏的,因為系統的行為不可能非常頻繁的需要動態調整,你每100毫秒調整一次系統的行為,估計系統要對你罵娘了。
而快速傳播講的是配置不變則已,一變往往要求目標叢集的所有節點要幾乎同時收到變更,然後幾乎整齊劃一的統一調整行為。切庫的場景來講,主備切換之後,應用叢集寫新的主庫這個行為切換的稀稀拉拉,整個收斂了一天,應用肯定是受不了的,而這個屬性決定了對配置中心對配置變更推送SLA的高要求。
配置中心(Diamond)和註冊中心(ConfigServer)的不同
在我們的眼裡,用土話講,這就是烏龜與王八的區別,想用拜金一點的話講,這就是金條和鑽石的區別,說的洋氣一點這叫Apple and Pear,但是當初起的名字的給我們帶來了大麻煩,現在我們的服務註冊中心現在叫Config Server, 你說坑不坑。不過很多中介軟體產品的名字同時承載了一段8年的歷史,這名字也體現中介軟體持續做技術產品,堅持就是一種力量的信念在裡面,n代人持續發展一個產品,說實話,只管生不管養的現象在中介軟體不能說沒有,但確實是很少的。1個8年的產品就像八歲的孩子,已經上小學了,硬要給它改個名字,從朱屎山改成朱寶山,他的同學認不認還要打個非常大的問號,而且還要跑到派出所重新上戶口,也是個麻煩事。
所以產品的取名字有大學問和大恐怖,大家取名之前一定要找算命先生給好好算一算,本來我在成為碼農之前那也是仙風道骨,江湖人送外號郭半仙,那時候可以釘釘發個紅包找我算一下。但成為碼農之後嘛,就特麼不說了,說起來全是淚,以前get到的很多技能點全丟了,現在就瞅著電腦和程式碼最順眼。
2者具體的不同,參見未來會寫的<<應用配置中心和服務註冊中心究竟有什麼不一樣?>>
關於配置,業界最新動態
業界著名的專職配置中心產品幾乎沒有(Diamond傲嬌ing~), 基本都是在用git, redis, zookeeper, consul 這些湊活著搞一下,所以要了解配置中心的同學,直接瞭解Diamond就可以了。:-)
但是針對於配置管理的客戶端程式設計類庫這一塊有一些類庫牛吹得是很大的,感興趣的同學可以瞭解一下:
-
Apache Commons Configuration (https://commons.apache.org/proper/commons-configuration/)
這個類庫是在是太繁瑣了,用起來總感覺有點殺雞用牛刀,力用的太大的感覺。
-
owner (http://owner.aeonbits.org/)
簡單易上手,特性看起來很多,但是在很多關鍵常用的特性反倒是沒有。
-
cfg4j (http://www.cfg4j.org/)
簡單易上手,cfg4j 支援跟多種後端整合,做配置中心的解決方案,api設計也非常的不錯,我們正在設計的新diamond
annotation api的時候借鑑了不少其想法。 -
Spring Framework (http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#__propertysource)
Spring的東西一般都還是很不錯的,如果你的應用本身在用Spring,毫無疑問,就這個了,用上面的那些類庫實在沒有必要。
Spring Cloud Config Server
如果你仔細讀一下其內容,而你又瞭解Diamond的話,你會發現這就是Diamond這些年在解決的問題啊,Spring 終於從大量配置檔案逐漸走向了配置中心(externalized configuration in a distributed system),而這一次我們走在了前面。
看看owner 的宣傳,
Java 他媽 properties reinvented! Java Properties的重新發明! 屌不屌?! 我僧僧的覺得,我們中國碼農有時候就是差了這種提煉和昇華的能力,剛入行時覺得維護和修改前人留下的爛程式碼實在是個很苦逼,很Low的事情,但是Martin Fowler把這叫做”重構”,然後還寫了一本書,然後我們讀了之後,居然還覺得他媽的,講的真的非常的有道理!把改爛程式碼變成叫重構之後,有了理論指導,突然覺得這真是個高逼格的事情!
配置(configuration)與後設資料(metadata)
很多人沒有這種這兩個概念的區分,但是對於配置中心,二者其實是有微妙的差別的.
配置如前文有闡述,配置的修改基本上都是由人來驅動,並且在ops上實現變更。
而後設資料的本質是一小段程式後設資料,它很多時候是程式產生,程式消費,由程式通過呼叫Diamond的客戶端api來實現變更,中間不會有ops 或者人的介入。
知道這個有什麼意義?毫無疑問,配置這種需求選型比較明確,而後設資料這種,可以選的pub-sub系統太多了,諸如訊息佇列產品,分散式coordinator產品如zookeeper, 帶pub-sub 能力的k-v store 如Redis等等都可以,所以如果是後設資料這種,選什麼需要慎重,其間運用之妙,存乎一心,要充分評估和把握自己的需求。
Diamond 不光是應用配置儲存,其目前儲存的資料,很大一部分是metadata,所以Diamond 其實也是一個後設資料儲存中心。
結束語
這麼長的文章,你居然能堅持看到這裡,說明你是真正的、脫離了低階趣味的,純粹的碼農,猿類中的精英!配置中心,它沒有高精尖的技術,難懂的演算法,海量的資料,做這個東西只需要一個精神就夠了。
owner之前一直在搞配置檔案的支援,現在owner也開始轉型搞跟zookeeper整合之類的,做配置中心的解決方案了,所以本文開頭說業界正在走向配置中心解決方案不是在忽悠,是確實是這個趨勢。
企業級網際網路架構Aliware,讓您的業務能力雲化:https://www.aliyun.com/aliware
<footer class="post-footer" style="display: block; color: rgb(85, 85, 85); font-family: Lato, "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">
</footer>
相關文章
- 關於一篇文章引發的匿名函式的思考函式
- 這是一篇關於程式設計師學習的文章程式設計師
- 寫一篇好的技術文章有多難?
- 關於寫文章發文章的Reading List
- 在 CSDN 上面看到的一篇關於 Laravel 關聯表模型和多對多關係的文章Laravel模型
- 一篇和Redis有關的鎖和事務的文章Redis
- 並查集詳解(轉的別人寫的一篇蠻好的文章)並查集
- [轉載] 一篇比較好的 Cypress 特點介紹文章
- 關於HBase2.0,看這一篇文章就夠了
- 關於Tungsten Fabic版本問題,這一篇文章說清了
- 基於zookeeper的分散式配置中心(一)分散式
- 有關於 QQ api 的文章網站API網站
- 關於Code Review的文章讀後感View
- 一篇文章帶你搞定 SpringSecurity 配置多個HttpSecurity 和實現對於方法安全的控制SpringGseHTTP
- 可能是最淺顯易懂的一篇文章,關於Python引用、賦值、複製Python賦值
- 一篇文章理解 golang 中切片與陣列的關係Golang陣列
- 程式設計師如何寫好一篇技術文章?程式設計師
- 【SpringBoot】SpringBoot 配置這一篇文章就夠了Spring Boot
- 關於MySQL使用的時長MySql
- 我的第一篇文章
- 面試題-關於Java執行緒池一篇文章就夠了面試題Java執行緒
- 好傢伙,分散式配置中心真好用分散式
- 一篇適合入門的PID文章
- 一篇文章搞定Python中的類Python
- 一篇文章弄懂 JavaScript 中的 importJavaScriptImport
- Q複製的一篇好文章
- 測試釋出一篇正常的文章
- 關於“資料中心”的最強入門科普
- 關於網站開通付費文章的嘗試網站
- [BUG反饋]兩個關於釋出文章的BUG
- 關於 RxJava 最友好的文章—— RxJava 2.0 全新來襲RxJava
- 關於 Laravel 之道系列文章入駐社群文件的通知Laravel
- 關於MySQL資料庫效能優化方法,看這一篇文章就夠了!MySql資料庫優化
- Laravel 框架如何優雅的寫出文章的上一篇和下一篇Laravel框架
- 這是一篇成為 git 高手的文章Git
- 一篇文章快速搞懂 Apache SkyWalking 的 OALApache
- 10、一篇經典的域滲透文章
- IDC關於資料中心的十大預測