2019年TW的技术雷达
18年的開始了解TW公司,看到在2018年11月發(fā)布的技術(shù)雷達,感覺和自己一直以來想做的事情是非常相關(guān),就是在不斷地構(gòu)建自己的知識技能圖譜,能夠在未來清晰的看到自己的技術(shù)路線。 未來彌補個人視角的技術(shù)局限性,所以TW的技術(shù)雷達從多個優(yōu)秀的項目中總結(jié)而來,對比于TW的技術(shù)雷達路線,我覺得對自己(或者說是每個互聯(lián)網(wǎng)的技術(shù)人員),都是非常的具有指導性的。
TW 從全球技術(shù)熱點技術(shù)出發(fā),從多個角度解讀現(xiàn)有的一些熱門技術(shù)。敏感的捕捉技術(shù)發(fā)展中的一些變化,并且圖形化的展示出來。TW 的全球軟件開發(fā)視角,無疑給我們帶來了一個全新的技術(shù)觀視角。
就如技術(shù)雷達的出發(fā)點:洞察構(gòu)建未來的的技術(shù)和趨勢
先打一個預防針,技術(shù)雷達只是一個增加了解技術(shù)視角的方式,而不應(yīng)該被視為絕對的圣經(jīng)。
TW 從技術(shù)、工具、平臺、語言&框架 四個象限來解讀
技術(shù)雷達持續(xù)更新網(wǎng)址 https://www.thoughtworks.com/cn/radar
- 采用:強烈建議采用的技術(shù),如何適合項目使用,毫不猶豫的采用。
- 實驗:值得追求,重要的是如何理解這種能力。企業(yè)應(yīng)該在風險可控的項目中嘗試這種技。
- 評估:值得研究一番的技術(shù),以確認它將對你產(chǎn)生何種影響。你應(yīng)該投入一些精力來確定,它是否會對你所在的組織產(chǎn)生影響。
- 暫緩:別用這項技術(shù)啟動任何新項目。在已有項目上使用它沒有壞處,但是想在新開發(fā)的項目上使用這個技術(shù)的話需要三思而行。
圖中的三角形圖標表示新出現(xiàn)的位置出現(xiàn)了_顯著變化的條目_。圖形表示還沒有發(fā)生變化的部分。
技術(shù)雷達中的技術(shù)很多是在原有雷達上比較的,很多技術(shù)也很重要,但是新技術(shù)出現(xiàn)很多,為了避免新老技術(shù)標記混亂,所以將很多沒有發(fā)生變化的老技術(shù)在技術(shù)雷達上給省略了標記。
技術(shù)雷達的英文版鏈接 https://www.thoughtworks.com/cn/radar/techniques
技術(shù)
以下部分為強烈建議在項目中采用的技術(shù)
快速市場響應(yīng)能力是組織進行微服務(wù)轉(zhuǎn)型的主要驅(qū)動之一。然而只有沿長期業(yè)務(wù)領(lǐng)域邊界對服務(wù)(及其支持團隊)進行清晰劃分時,這種期望才可能實現(xiàn)。否則,現(xiàn)實需求只有在跨組織和跨服務(wù)的通力合作才下能完成,這自然會在規(guī)劃產(chǎn)品路線圖時產(chǎn)生沖突。良好的領(lǐng)域模型設(shè)計是解決此問題的方案,**事件風暴(EVENT STORMING)**也迅速成為我們最喜愛的方法之一,它使我們能夠迅速識別問題領(lǐng)
域中的關(guān)鍵概念,并用最好的方式與各方利益相關(guān)人制定解決方案。
以下部分為強烈建議在項目中嘗試的技術(shù)
快速反饋是我們構(gòu)建軟件的核心價值之一。很多年來,我們使用金絲雀發(fā)布來鼓勵對于新版本軟件要盡早反饋,同時對選定用戶做增量發(fā)布以降低風險。與這個技術(shù)相關(guān)的問題之一就是如何劃分用戶。對非常小的一部分用戶(比如1%)作金絲雀發(fā)布是變更的催化劑。從一小部分用戶開始可以讓團隊逐漸熟悉這項技術(shù),而快速捕獲用戶反饋可以讓不同團隊觀察新發(fā)布的影響,從中學習并按照需要調(diào)整方向——這是工程師文化里很寶貴的變化。我們稱之為萬能的1% 金絲雀(1% CANARY)。
大多數(shù)沒有足夠資源進行軟件定制化開發(fā)的組織,通常會選擇一些“開箱即用”的或基于SaaS平臺的解決方案來直接滿足需求。但是最近我們注意到,這些解決方案的范圍正在急劇擴張,與業(yè)務(wù)的各個環(huán)節(jié)糾纏在一起。這種擴張模糊了集成邊界,導致越來越難以估計軟件變更的復雜度,變更速度也越來越慢。為了降低這種風險,我們建議這些組織首先要設(shè)計出清晰的目標能力模型,然后使用被稱為限界購買的策略(BOUNDED BUY),即只選擇模塊化、解耦的,且只包含于單一業(yè)務(wù)能力(Business Capability)的 限界上下文(Bounded Context)中的廠商產(chǎn)品。我們應(yīng)該將這種對模塊化和獨立交付能力的要求,加入對供應(yīng)商選擇的驗收標準中去。
對敏感數(shù)據(jù)保持適當?shù)目刂剖窍喈斃щy的,尤其是在出于對數(shù)據(jù)備份和恢復的目的而將數(shù)據(jù)復制到主數(shù)據(jù)系統(tǒng)之外的時候。**密鑰粉碎(CRYPTO SHREDDING)**是通過故意覆蓋或刪除用于保護該數(shù)據(jù)的加密密鑰來使敏感數(shù)據(jù)無法讀取的做法。例如,可以使用隨機密鑰對數(shù)據(jù)庫中客戶個人詳細信息表的所有記錄進行一對一加密,然后使用另一張表來存儲密鑰。如果客戶行使了“被遺忘的權(quán)利”,我們可以簡單地刪除相應(yīng)的密鑰,從而有效地“粉碎”加密數(shù)據(jù)。 當我們有信心對小規(guī)模加密密鑰集合維持適當控制,但對較大數(shù)據(jù)集的控制信心不足時,此項技術(shù)非常有效。
2014年首次發(fā)布的DevOps狀態(tài)報告指出,高效團隊創(chuàng)造了高效的組織。最近,該報告背后的團隊編寫了Accelerate一書,描述了他們在報告中使用的科學方法。兩份材料的核心點都支持了軟件交付性能的四個關(guān)鍵指標(FOUR KEYMETRICS):前置時間,部署頻率,平均恢復時間(MTTR)和變更失敗百分比。作為幫助許多組織轉(zhuǎn)型的咨詢公司,反復使用這些指標測量,可以幫助組織確定他們是否在提高整體效能。每個指標都創(chuàng)造了一個良性循環(huán),并使團隊專注于持續(xù)改進:縮短交付周期,減少浪費的活動,從而使你可以更頻繁地部署;部署頻率迫使你的團隊改進他們的實踐和自動化流程;通過更好的實踐,自動化和監(jiān)控可以提高你從故障中恢復的速度,從而降低故障頻率。
自助使用、按需付費是當代云計算重要的特性(和優(yōu)勢)。但是,當使用單個賬號去部署大規(guī)模的服務(wù)時,事情就變得非常復雜。我們必須為該賬戶設(shè)置使用規(guī)則和流程,往往這些流程包含大量的審批步驟,從而降低我們的效率。設(shè)置**多云賬號(MULTI-ACCOUNT CLOUD SETUP)**是一個不錯的方案,我們可以申請多個賬號,并且為每個團隊指定一個賬號。當然這個方案增加了其他方面的復雜度,例如共享計費、不同 VPC 之間的通信、與云供應(yīng)的關(guān)系管理等。但是,也會提高我們的開發(fā)效率與安全性,審計只用于單服務(wù)的賬號相對容易,在發(fā)生數(shù)據(jù)泄漏時,我們所受到的影響也相對較小。設(shè)置多云賬號可以降低我們對云供應(yīng)商的粘性,因為單服務(wù)賬號能提供清晰的邊界,所以便于整體遷移到另一個云提供商。
可觀測性是運轉(zhuǎn)分布式系統(tǒng)與微服務(wù)架構(gòu)必不可少的一部分。我們依賴不同的系統(tǒng)輸出來推斷分布式組件的內(nèi)部狀態(tài),比如分布式追蹤、日志聚合、系統(tǒng)指標等,進而診斷問題所在,并找到根本原因。可觀測性生態(tài)系統(tǒng)的一個重要方面就是監(jiān)控——可視化以及分析系統(tǒng)的輸出——并且在檢測到異常時報警。傳統(tǒng)的監(jiān)控報警配置,都是通過圖形界面的操作完成。這種方法導致控制面板頁的配置不可重復,從而無法持續(xù)測試和調(diào)整報警,來避免報警疲勞或錯過重要的報警,進而偏離組織的最佳實踐。我們強烈建議使用代碼來配置可觀測性生態(tài)系統(tǒng),稱為可觀測性即代碼(OBSERVABILITY AS CODE),并且采取基礎(chǔ)設(shè)施即代碼的方式搭建其基礎(chǔ)設(shè)施。因此,在選擇提供可觀測性的工具時,要選擇支持通過代碼版本控制進行配置,并能通過基礎(chǔ)設(shè)施持續(xù)交付流水線執(zhí)行API或命令行的產(chǎn)品。可觀測性即代碼,是基礎(chǔ)設(shè)施即代碼中經(jīng)常被遺漏的一部分,我們認為這一點非常重要,需要明確指出。
通常,為了將風險外包給供應(yīng)商,企業(yè)在其最關(guān)鍵和風險最高的系統(tǒng)上往往鎖定某個特定供應(yīng)商,以求風險最低。不幸的是,這會讓企業(yè)可以選擇的解決方案變得更少,靈活性也更低。相反,企業(yè)應(yīng)該在業(yè)務(wù)風險最高的地方保持最大的供應(yīng)商獨立性。我們看到一種新的**風險相稱的供應(yīng)商策略(RISK-COMMENSURATE VENDOR STRATEGY)**正在興起,它鼓勵在高度關(guān)鍵系統(tǒng)中維持其供應(yīng)商的獨立性。而那些相對不太重要的業(yè)務(wù)可以利用供應(yīng)商提供的成熟解決方案,這可以讓企業(yè)更容易承受失去該供應(yīng)商所帶來的影響。隨著主流云提供商擴展其服務(wù)范圍,這種權(quán)衡變得愈發(fā)重要。例如,在開發(fā)工作開始時,使用AWS SecretManagement Service可以提高效率,并且還有易于集成AWS云生態(tài)的好處。但相比于自己實現(xiàn)密鑰管理解決方案,例如使用Vault時,AWS的方案難以遷移到不同的云供應(yīng)商。
隨著軟件架構(gòu)及其業(yè)務(wù)的演進,我們理應(yīng)密切關(guān)注應(yīng)用的運行成本,但發(fā)現(xiàn)并非所有的組織都如此。尤其是在使用無服務(wù)器架構(gòu)時,開發(fā)者們認為無服務(wù)器架構(gòu)會更便宜,因為他們只需按消耗的計算時間付費。然而幾家主要的云服務(wù)提供商在熱門的無服務(wù)器函數(shù)上定價十分精明,雖然無服務(wù)器在快速迭代上很有優(yōu)勢,但與專屬云(或內(nèi)部私有云)相比,它的開銷可能隨著使用量迅速增長。我們建議團隊將**應(yīng)用的運行成本納入架構(gòu)適應(yīng)度函數(shù)(RUN COST ASARCHITECTURE FITNESS FUNCTION)**來考量,這意味著:追蹤并權(quán)衡應(yīng)用的運行成本與交付價值;當它們之間產(chǎn)生較大出入時,就需要考慮改進軟件架構(gòu)了。
我們長期以來都警示人們,要抵制在代碼倉庫中保存密鑰信息的誘惑。在往期雷達中,我們曾推薦了將代碼和密鑰管理解耦,但如今我們發(fā)現(xiàn)了一系列提**供密鑰即服務(wù)(SECRETS AS A SERVICE)**的好工具。通過這些工具,系統(tǒng)能夠從外部服務(wù)中獲取秘密信息,而不是使用硬編碼或?qū)⑵渑渲迷谶\行環(huán)境中的方式。例如來自HashiCorp的Vault這樣的工具幫助你將密鑰與應(yīng)用程序分開管理,同時有助于你強制實施一些安全政策,例如周期性密鑰輪換。
雖然在本期雷達中大部分條目都是全新的,但我們認為依然值得繼續(xù)為**安全混沌工程(SECURITY CHAOSENGINEERING)**的實用性提名。本期雷達中我們將其移動到了試用階段,因為使用此技術(shù)的團隊確信他們的安全策略足以應(yīng)對常見的安全故障模式。不過,在使用這種技術(shù)時需要謹慎,我們不希望我們的團隊對安全問題變得不再敏感。
當涉及到大規(guī)模數(shù)據(jù)分析或機器智能問題,基于不同數(shù)據(jù)集合和參數(shù)進行可重復性分析就變得非常有價值。為了實現(xiàn)可重復性分析,數(shù)據(jù)和模型(包括算法方案,參數(shù)和超參數(shù))需要進入版本控制。因為數(shù)據(jù)量的緣故,**可重復性分析的版本化數(shù)據(jù)(VERSIONING DATA FORREPRODUCIBLE ANALYTICS)**比起版本化模型更加棘手。一些像DVC這樣的工具采用類似git工作流的方式,讓用戶提交和推送數(shù)據(jù)文件到遠程的云存儲,從而實現(xiàn)數(shù)據(jù)的版本化。這極大方便了協(xié)作者拉取特定版本的數(shù)據(jù)來進行可重復性分析。
以下部分為強烈建議在項目中評估的技術(shù)
CHAOS KATAS是一項為基礎(chǔ)設(shè)施和平臺工程師提供技能培訓和提升的技術(shù)。它將Kata的方法論與ChaosEngineering的相關(guān)技術(shù)(具體指在受控環(huán)境中模擬故障和停機)進行結(jié)合,對工程師進行系統(tǒng)化教學和培訓。這里的Kata是指觸發(fā)受控故障的代碼模式,它允許工程師發(fā)現(xiàn)問題,恢復故障,開展事后分析并找到根本原因。工程師通過重復執(zhí)行Kata能幫助他們真正掌握新的技能。
當為我們的應(yīng)用構(gòu)建Docker鏡像的時候,我們常常會考慮兩件事情:鏡像的安全性和大小。通常情況下我們使用容器安全掃描工具來檢測和修復常見的漏洞和風險 ,以及使用Alpine Linux來解決鏡像大小和分發(fā)性能問題。在此期雷達中,我們欣喜地發(fā)現(xiàn)了一個由Google開發(fā),用來解決容器安全性和大小問題的技術(shù),名叫DISTROLESS DOCKERIMAGES。通過這項技術(shù),鏡像占用的空間只包含應(yīng)用本身以及它的資源和語言運行時依賴,而不包含操作系統(tǒng)。它的優(yōu)勢包括減少其它因素對應(yīng)用安全掃描的干擾、減小安全攻擊面、降低漏洞修復開銷,以及減小鏡像大小以獲得更高性能。Google 已經(jīng)為不同的語言發(fā)布了一系列的distroless容器鏡像。你可以通過 Google 的構(gòu)建工具Bazel來創(chuàng)建distroless 應(yīng)用鏡像,它支持使用Distroless的語法規(guī)則或者簡單地采用多階段Dockerfiles的方式來創(chuàng)建Distroless 容器。值得注意的是 Distroless 容器默認情況下不提供 shell來進行調(diào)試,但你能很方便地在網(wǎng)上找到包含 busyboxshell 的 distroless 容器可調(diào)試版本。
作為敏捷領(lǐng)域的先驅(qū)和領(lǐng)導者,ThoughtWorks一直以實際行動踐行增量交付實踐,同時建議我們的客戶從“增量交付”的視角來審視他們已有的軟件。但是這個過程通常很困難,因為大多數(shù)供應(yīng)商都采用一次性交付的方式,這就會涉及到大量的數(shù)據(jù)遷移。然而最近我們成功的實踐了與供應(yīng)商一起增量交付(INCREMENTAL DELIVERY WITH COTS(commercial off-the-shelf)),以增量的方式向較小的用戶群發(fā)布特定的業(yè)務(wù)流程。我們建議您評估是否可以將此實踐應(yīng)用于您選擇的供應(yīng)商軟件,以幫助減少一次性交付的風險。
很長時間以來,我們一直在建議交付團隊對整個技術(shù)棧負責,其中也包括對基礎(chǔ)設(shè)施負責。 這意味著,在以安全可靠、合規(guī)的方式配置基礎(chǔ)設(shè)施這方面,交付團隊需要承擔起 更多的責任。 為了降低風險,采用云策略時大多數(shù)組織都 默認采用嚴格的、集中式的配置管理方式,但這也導致了嚴重的生產(chǎn)力瓶頸。 另外一種做法則是允許團隊自己管理自己的配置,并使用INFRASTRUCTURE CONFIGURATIONSCANNER這種方式來確保配置的安全性。Watchmen是個很有意思的工具,它旨在為由交付團隊自主擁有和運營AWS 賬戶配置提供基于規(guī)則驅(qū)動的掃描。Scout2是另一個配置掃描的例子,它可以提供安全合規(guī)的支持。
在更復雜的架構(gòu)和部署中,可能并不能容易立即發(fā)現(xiàn)某個依賴正在檢入的代碼的構(gòu)建已經(jīng)損壞。開發(fā)人員在嘗試修復已損壞的構(gòu)建時,會發(fā)現(xiàn)自己就像在打移動靶,因為該構(gòu)建會不斷被其上游依賴所觸發(fā)。下游構(gòu)建的提交前檢查(PRE-COMMIT DOWNSTREAM BUILD CHECKS) 是一個很簡單的技術(shù):用一個提交前(pre-commit)或推送前(pre-push)腳本來檢查這些下游構(gòu)建的狀態(tài),并事先警告開發(fā)人員某個構(gòu)建已經(jīng)壞掉了。
隨著大型組織向擁有和運營自己的微服務(wù)的更自主的團隊過渡,他們?nèi)绾卧诓灰蕾嚰型泄芑A(chǔ)架構(gòu)的情況下確保這些服務(wù)之間的必要一致性和兼容性?為了有效地協(xié)同工作,即使是自主的微服務(wù)也需要與一些組織標準保持一致。SERVICE MESH 提供一致的發(fā)現(xiàn)、安全性、跟蹤、監(jiān)控和故障處理,而無需共享API網(wǎng)關(guān)或ESB等設(shè)施。典型的實現(xiàn)是將每個服務(wù)進程和輕量級反向代理進程一起部署,反向代理進程可能在單獨的容器中。這些代理與服務(wù)注冊表,身份提供者,日志聚合器和其他服務(wù)進行通信。服務(wù)互操作性和可觀測性是通過此代理的共享實現(xiàn)而不是共享運行時實例獲得的。我們提倡采用去中心化的微服務(wù)管理方法已經(jīng)有一段時間了,并很高興看到這種一致模式的出現(xiàn)。Linkerd 和 Istio 等開源項目將逐步成熟,這使得service mesh 更容易實現(xiàn)。
當組織選擇 vanilla Hadoop 或Spark 發(fā)行版而不是某個供應(yīng)商的發(fā)行版時,他們必須決定如何配置和管理集群。 有時,我們會看到使用配置管理工具進行**“手搖式”啟動的 Hadoop 集群(“HANDCRANKING” OF HADOOPCLUSTERS USING CONFIG MANAGEMENT TOOLS)**,這些工具有 Ansible , Chef 等。 雖然這些工具非常適合整備不可變的基礎(chǔ)設(shè)施組件,但是對于管理有狀態(tài)的系統(tǒng),它們并不太管用,而且嘗試使用這些工具管理和演進集群通常會導致大量的工作。所以,我們建議使用 Ambari 等工具來配置和管理有狀態(tài)的Hadoop或Spark群集。
主流云供應(yīng)商在定價和快速發(fā)布新特性方面的競爭日益激烈,這使得消費者難以抉擇和保持粘性。我們越來越多地看到組織準備使用“任意云”,并不惜一切代價避免被單一供應(yīng)商鎖定。當然,這就導致了只使用通用云服務(wù)功能(GENERIC CLOUD USAGE) 。我們發(fā)現(xiàn),有的組織對云的使用僅限于所有供應(yīng)商都有的特性,而忽略供應(yīng)商提供的獨特能力;有的組織為了保持云無關(guān)性,斥巨資開發(fā)復雜且難以維護的抽象層。供應(yīng)商鎖定的問題是真實存在的。對此,我們建議采用多云策略,評估從一個云到另一個云的功能遷移成本及工作量,抵制使用特定云特性的好處。我們推薦將應(yīng)用程序置于廣泛采用的 Docker 容器中以提高工作負載的可移植性;使用開源的安全和身份協(xié)議以輕松遷移工作負載的身份;使用風險相稱的供應(yīng)商策略,僅在必要時維持云獨立性;在合適之處使用 Polycloud 混合匹配不同供應(yīng)商的服務(wù)。簡而言之,請用合理的多云策略,避免只使用通用云服務(wù)
微服務(wù)架構(gòu)的一個顯著特征是系統(tǒng)組件和服務(wù)是圍繞業(yè)務(wù)能力進行組織的。無論系統(tǒng)規(guī)模大小,微服務(wù)都需要將系統(tǒng)功能和信息進行有意義的分組和封裝,以便拆分后的微服務(wù)能彼此獨立地交付業(yè)務(wù)價值。而以前的服務(wù)架構(gòu)方式會根據(jù)技術(shù)特性組織服務(wù)。我們觀察過很多采用**分層式微服務(wù)架構(gòu)(LAYERED MICROSERVICES ARCHITECTURE)**的組織,他們在某些方面存在著明顯的矛盾。這些組織都陷入了以技術(shù)角色為主來劃分服務(wù)的誤區(qū),比如,用戶體驗API、進程 API 或系統(tǒng) API等。我們會很自然地將技術(shù)團隊按層劃分,這會導致想要交付任何有價值的業(yè)務(wù)變更,都需要緩慢而昂貴的多團隊合作。請務(wù)必小心這種分層方式帶來的影響,我們更推薦根據(jù)業(yè)務(wù)能力來劃分服務(wù)和團隊。
主數(shù)據(jù)管理 (MASTER DATA MANAGEMENT (MDM)) 是一個典型的企業(yè)“銀彈”解決方案:它聲稱可以將表面上相關(guān)的問題一次性解決,但它創(chuàng)建集中的單點來進行統(tǒng)一的變更、協(xié)調(diào)、測試和部署,極大地降低了組織響應(yīng)業(yè)務(wù)變化的能力。在將MDM方案集成到不同消費和生產(chǎn)系統(tǒng)的過程中,組織往往嘗試捕捉到所有的“主”數(shù)據(jù)并將它們映射到MDM中,這讓整個實施過程變得漫長而復雜。
微服務(wù)已成為現(xiàn)代云計算系統(tǒng)中的領(lǐng)先的架構(gòu)模式,但我們依舊認為團隊在使用該架構(gòu)時應(yīng)謹慎。 MICROSERVICEENVY特指那些盲目追趕微服務(wù)潮流的現(xiàn)象,很多團隊在實踐微服務(wù)時并沒有簡化其系統(tǒng)架構(gòu),大多數(shù)的實踐方案只是將一些簡單的服務(wù)聚合在一起而已。目前, Kubernetes等平臺簡化了復雜的微服務(wù)系統(tǒng)的部署問題,其他服務(wù)提供商們也正在推進他們的微服務(wù)治理方案,這些強大的工具都可能裹挾團隊走上微服務(wù)之路。 但請千萬謹記,微服務(wù)是通過開發(fā)復雜度來換取運維復雜度,并需要自動化測試、持續(xù)交付和DevOps文化提供堅實的支撐。
我們經(jīng)常看到在面向用戶的工作流中**使用請求 — 響應(yīng)事件 (REQUEST-RESPONSE EVENTS IN USER-FACINGWORKFLOWS)**的系統(tǒng)設(shè)計。這樣一來,要么UI被阻塞,要么用戶就必須等頁面收到響應(yīng)消息后重新加載。做出這類設(shè)計的主要依據(jù)往往是為了性能或是為了用統(tǒng)一的方式來處理后端之間的同步和異步通信。我們認為這樣做會在開發(fā)、測試和運維上所增加不必要的復雜度,遠遠超過了采用這種統(tǒng)一方式帶來的好處,我們強烈建議直接使用同步HTTP請求來處理后端服務(wù)之間的同步通信,而不必改成事件驅(qū)動的設(shè)計。如果做得好,使用HTTP通信很少會成為分布式系統(tǒng)的瓶頸
**機器人流程自動化(RPA)**是許多數(shù)字化轉(zhuǎn)型計劃的關(guān)鍵部分,因為它有望在不必對底層架構(gòu)和系統(tǒng)進行現(xiàn)代化改造的情況下節(jié)省成本。 這種僅關(guān)注自動化業(yè)務(wù)流程而不解決底層軟件系統(tǒng)或功能的方法的問題在于,引入額外的耦合會使底層系統(tǒng)更改起來更加困難。 這也會讓未來任何解決遺留IT環(huán)境的嘗試都變得更加困難。 很少有系統(tǒng)能夠忽視變化,因此RPA的進展需要與適當?shù)倪z留系統(tǒng)現(xiàn)代化戰(zhàn)略相結(jié)合。
平臺
采用
試驗
隨著企業(yè)數(shù)據(jù)需求的不斷增長和多樣化,對元數(shù)據(jù)管理的需求也在不斷地增長。**APACHE ATLAS 是一款用于滿足企業(yè)數(shù)據(jù)治理需求的元數(shù)據(jù)管理框架。**Atlas支持元數(shù)據(jù)類型建模、數(shù)據(jù)資產(chǎn)分類、數(shù)據(jù)來源追蹤和數(shù)據(jù)發(fā)現(xiàn)。但是,在搭建元數(shù)據(jù)管理平臺的時候,我們也必須小心避免重蹈主數(shù)據(jù)管理的覆轍。
我們在7年前首次將AWS移到“采納”環(huán),其服務(wù)的廣度、深度和可靠性從那時起就已獲得長足進步。然而,我們現(xiàn)在又將AWS移回“試驗”環(huán)。這不是因為其產(chǎn)品存在缺陷,而是因為其競爭對手。它的 GCP 和 Azure 這兩個競爭對手已經(jīng)相當成熟,這使得選擇云提供商變得越來越復雜。 所以我們會把“采納”環(huán)留給該領(lǐng)域未來的大贏家。多年來,AWS一直是該領(lǐng)域的默認選擇。但是考慮到組織自身的地理位置和監(jiān)管范圍,以及同云提供商之間戰(zhàn)略的一致性(或者缺乏一致性),當然還包括組織最重要的需求和云供應(yīng)商差異化產(chǎn)品之間的契合度。所以,我們認為組織是時候應(yīng)該在云供應(yīng)商之間做出權(quán)衡了。
Microsoft已經(jīng)在穩(wěn)健地改進AZURE,如今大型云提供商Amazon、Google和Microsoft在核心云體驗上并沒有太大的差別。這些云提供商似乎都在追求其他方面的差異性,比如功能、服務(wù)和成本結(jié)構(gòu)。Microsoft 對歐洲公司在法務(wù)上的需求表現(xiàn)出了真正的興趣。對此,他們有一個細致且合理的策略,比如提供了像Azure Germany和Azure Stack這樣各具特色的產(chǎn)品。這個策略為歐洲公司在預測GDPR
Headless CMS (Content Management Systems, 內(nèi)容管理系統(tǒng)) 正在成為數(shù)字化平臺的常見組件。CONTENTFUL是一個現(xiàn)代化的 headless CMS。我們的團隊已經(jīng)成功把它集成到開發(fā)工作流中。我們特別喜歡其“API 優(yōu)先”的特點,及其CMS as Code的實現(xiàn)。它支持強大的內(nèi)容建模原語代碼和內(nèi)容模型演化腳本,并允許將其視為其他數(shù)據(jù)存儲的schema,并將演進式數(shù)據(jù)庫設(shè)計實踐應(yīng)用到 CMS 開發(fā)中。我們所喜歡的其他特性包括:默認包含兩個 CDN以提供多媒體資源和 JSON文檔,本地化的良好支持和與Auth0集成的能力(盡管需要做出一些努力)。
隨著GOOGLE CLOUD PLATFORM (GCP)在可用地理區(qū)域和服務(wù)成熟度方面的擴展,全球的客戶在規(guī)劃云技術(shù)策略時可以認真考慮這個平臺了。與其主要競爭對手AmazonWeb Services相比,在某些領(lǐng)域, GCP 所具備的功能已經(jīng)能與之相媲美。而在其他領(lǐng)域又不失特色—尤其是在可訪問的機器學習平臺、數(shù)據(jù)工程工具和可行的 “Kubernetes即服務(wù)解決方案”(GKE)這些方面。在實踐中,我們的團隊對GCP工具和API良好的開發(fā)者體驗也贊賞有嘉。
我們在大大小小的組織中積累了豐富的公共云經(jīng)驗,一些公有云模式也隨之出現(xiàn)。其中一種模式是將組織級別管理的虛擬私有云,拆分為眾多較小的由團隊自治的子網(wǎng)。這個想法與設(shè)置多云賬號類似,它有助于將基礎(chǔ)設(shè)施按照團隊邊界進行分隔。**按照傳統(tǒng)的方式,我們需要反復為每個團隊配置VPC、子網(wǎng)、安全組和網(wǎng)絡(luò)訪問控制列表,與此相比,我們更推崇Google的共享VPC (SHARED VPC) 這一概念。共享VPC使組織、項目、VPC和子網(wǎng)成為網(wǎng)絡(luò)配置中的一級實體。**VPC可由組織的系統(tǒng)管理員管理,然后管理員可以將子網(wǎng)管理的權(quán)限委派給項目,項目與VPC中的子網(wǎng)一一對應(yīng)。這樣的方式簡化配置,同時使安全性和訪問控制更加透明。
TICK Stack 是一些開源組件的組合。這些組件組合成了一個平臺,以便人們存儲、可視化和監(jiān)控諸如指標和事件這樣的時間序列數(shù)據(jù)。這些組件包含了 Telegraf(用于收集和報告指標的服務(wù)器代理)、 InfluxDB( 高性能的時間序列數(shù)據(jù)庫)、 Chronograf(提供平臺用戶界面),以及 Kapacitor(能對來自 InfluxDB 的數(shù)據(jù)進行處理、流傳輸和批處理操作的數(shù)據(jù)處理引擎)。與基于拉模式的 Prometheus 不同,該平臺是基于推模式來收集數(shù)據(jù)的。InfluxDB是該平臺的核心組件,它是目前最優(yōu)秀的時間序列數(shù)據(jù)庫。該技術(shù)棧目前由InfluxData提供支持。雖然需要升級到該平臺的企業(yè)版才可以使用數(shù)據(jù)庫集群等功能,但將該平臺用做監(jiān)控仍然是相當不錯的選擇。我們當前在一些生產(chǎn)環(huán)境中使用了這一技術(shù)棧,并獲得了很好的體驗。
評估
已取代 Visual Studio Team Services 的 AZURE DEVOPS服務(wù),包括一組托管服務(wù),如Git倉庫、CI和CD流水線以及制品庫等。當使用Azure DevOps服務(wù)快速啟動項目時(即在 Azure 平臺上管理、構(gòu)建和發(fā)布應(yīng)用程序),我們獲得了良好的體驗。 但同時也遇到了一些挑戰(zhàn),如該平臺對CI和CD的“流水線即代碼”缺乏全面的支持,構(gòu)建代理在啟動時速度很慢,構(gòu)建和發(fā)布被分離到不同的流水線上來進行等,另外在使用該平臺時還遭遇了幾次停機。我們希望AzureDevOps服務(wù)能夠隨著時間的推移得以改進,以便為在Azure上托管應(yīng)用程序的開發(fā)人員提供良好的體驗,并與其他 Azure 服務(wù)無縫集成。
COCKROACHDB是一個開源分布式數(shù)據(jù)庫,其設(shè)計思路源自白皮書Spanner:谷歌的分布式數(shù)據(jù)庫。在CockroachDB中,數(shù)據(jù)自動按照區(qū)間進行切分,通常以64MB為單位,被分布到集群中的不同節(jié)點上。每一個區(qū)間都有一個共識組。由于使用了Raft共識算法,所以這些數(shù)據(jù)總是能夠保持同步。憑借這種獨特的設(shè)計,CockroachDB提供分布式事務(wù)和地理分區(qū)的功能,并支持SQL。不像依賴TrueTime(用原子時鐘進行線性化)的 Spanner,CockroachDB使用 NTP 進行時鐘同步,并且提供序列化功能(作為默認隔離級別)。如果所處理的是適合單個節(jié)點的結(jié)構(gòu)化數(shù)據(jù),那么可以選擇傳統(tǒng)的關(guān)系型數(shù)據(jù)庫。但如果數(shù)據(jù)需要跨節(jié)點進行容量伸縮、保持一致并且能夠在系統(tǒng)故障時保存下來,那么我們建議可以仔細研究一下CockroachDB。
DEBEZIUM是一個change data capture (CDC)平臺,可以將數(shù)據(jù)庫的變更以流的形式傳入 Kafka 主題中。CDC是一種流行的技術(shù),具有多個使用場景,包括將數(shù)據(jù)復制到其他數(shù)據(jù)庫中,為分析系統(tǒng)提供數(shù)據(jù),從單塊系統(tǒng)中提取微服務(wù),以及令緩存數(shù)據(jù)無效等。**我們一直在尋找這個領(lǐng)域的工具或平臺(包括在之前的技術(shù)雷達中討論過的 BottledWater),而 Debezium 是一個極佳的選擇。它使用了基于日志的CDC方法,意味著能以對數(shù)據(jù)庫日志文件的變更進行響應(yīng)的方式進行工作。**Debezium使用了Kafka連接,這使得它具有高度的容量伸縮性,以及對故障的系統(tǒng)韌性。它擁有包括Postgres、Mysql和MongoDB在內(nèi)的多個數(shù)據(jù)庫的CDC連接器。目前,我們正在一些項目上使用該平臺,并取得了很好的效果。
我們對 GLITCH 很感興趣。這是一個在線協(xié)作開發(fā)環(huán)境,允許用戶輕松復制和調(diào)整(或“重新混合”)現(xiàn)有的Web應(yīng)用程序,或者創(chuàng)建自己的Web應(yīng)用程序。該平臺源于“修補匠”精神,對于編程初學者是一個理想的選擇,同時也能夠支持更加復雜的應(yīng)用的開發(fā)。它主要關(guān)注JavaScript和 Node.js,對其他語言也提供有限的支持。通過集成實時編輯、托管、共享和自動化版本控制等功能,Glitch提供了一種令人耳目一新的獨特的協(xié)作編程方式。
谷歌云數(shù)據(jù)流(GOOGLE CLOUD DATAFLOW) 在傳統(tǒng)的ETL場景中非常有用。它可以從數(shù)據(jù)源讀取數(shù)據(jù)、轉(zhuǎn)換數(shù)據(jù)并將轉(zhuǎn)換后的數(shù)據(jù)存儲到接收器中。整個過程的配置和容量伸縮都是由該平臺進行管理。該平臺支持Java、Python和Scala,并提供連接各種數(shù)據(jù)源的包裝器。然而,該平臺的當前版本并不允許用戶添加其他庫,所以可能會導致它不適合進行某些類型的數(shù)據(jù)操作。同時用戶也無法動態(tài)地更改數(shù)據(jù)流的DAG(Directed Acyclic Graph,有向無環(huán)圖)。因此,如果用戶的ETL有基于參數(shù)的條件執(zhí)行流程,就可能需要做一些變通才能使用該平臺。
GVISOR是一個容器內(nèi)的user-space內(nèi)核。它不允許應(yīng)用程序訪問主機內(nèi)核的所有功能,只能訪問主機內(nèi)核的表層。不同于現(xiàn)有通過虛擬化硬件實現(xiàn)的沙盒技術(shù) KVM 和 Xen 或者基于規(guī)則執(zhí)行的方式實現(xiàn)的沙盒技術(shù)seccomp, SELinux和 AppArmor ,gVisor通過攔截應(yīng)用程序的系統(tǒng)調(diào)用這種特殊的方式來實現(xiàn)容器沙盒,并且不需要虛擬化硬件的轉(zhuǎn)換就能夠?qū)崿F(xiàn)訪問層內(nèi)核。gVisor包含一個名為runsc的Open Container Initiative(OCI) 運行時,它集成了Docker和Kubenets(實驗性支持) 。gVisor是一個相對較新的項目,所以我們建議您根據(jù)自身容器安全狀況對其進行評估。
在多數(shù)情況下,區(qū)塊鏈不適合存儲 blob 文件 (例如:圖像,音頻),當人們開發(fā) DApp 時,一種選擇是將blob文件存放在一些鏈下的集中式數(shù)據(jù)存儲中,這種做法通常會導致信任缺失,另一種選擇是將它們存儲在星際文件系統(tǒng) IPFS上,這是一種內(nèi)容可尋址、版本化、點對點的文件系統(tǒng)。它旨在高效地分發(fā)大規(guī)模數(shù)據(jù),并能阻止任何中心化機構(gòu)刪除數(shù)據(jù),文件存儲在不需要相互信任的對等節(jié)點上。IPFS 保存文件的每一個版本,這樣你將永遠不會丟失重要文件,我們將IPFS視為區(qū)塊鏈技術(shù)的好的補充。除了區(qū)塊鏈應(yīng)用程序外,IPFS還有一個愿景是對現(xiàn)有的網(wǎng)絡(luò)基礎(chǔ)設(shè)施進行去中心化重塑
構(gòu)建和運維微服務(wù)生態(tài)系統(tǒng)的一個老問題,是如何實現(xiàn)些橫切關(guān)注點,例如服務(wù)發(fā)現(xiàn)、服務(wù)到服務(wù)的安全性、原始服務(wù)到其它服務(wù)的安全性、可觀測性(包括遙測和分布式跟蹤)、滾動發(fā)布和系統(tǒng)韌性。在過去幾年中, service mesh 技術(shù)已經(jīng)成為我們對這個問題的默認答案。Service mesh 以配置為代碼的方式,在基礎(chǔ)設(shè)施層實現(xiàn)了這些橫切關(guān)注點。策略配置可以一致地應(yīng)用于整個微服務(wù)生態(tài)系統(tǒng)。這些策略可以在 serivice mesh 流量內(nèi)外(通過將 service mesh代理作為網(wǎng)關(guān)的方式)以及每個服務(wù)的流量(通過將相同的service mesh 代理作為 sidecar 容器的方式)上強制執(zhí)行。在密切關(guān)注不同開源 service mesh 項目 Linkerd 的進展的同時,我們已經(jīng)成功地在生產(chǎn)環(huán)境中使用了 ISTIO 。Istio易于配置的操作模型令人驚嘆。
作為應(yīng)用開發(fā)者,我們喜歡專心解決核心業(yè)務(wù)問題,而讓底層平臺來處理那些枯燥且困難的任務(wù)(如部署、容量伸縮及應(yīng)用程序管理)。雖然無服務(wù)器架構(gòu)往這個方向邁出了一步,然而大多數(shù)流行的產(chǎn)品都會與某個專有實現(xiàn)綁在一起。而這意味著供應(yīng)商綁定。KNATIVE試圖以開源無服務(wù)器平臺的方式來解決此問題。它良好地集成了流行的Kubernetes生態(tài)系統(tǒng)。利用 Knative ,可以對隨時請求的計算進行建模(其間可以從一些框架中進行選擇,如 Ruby onRails、Django和Spring 等),可以訂閱、交付和管理事件,可以集成用戶所熟悉的 CI和CD 工具,可以從源代碼構(gòu)建出容器。該平臺提供一組中間件組件,來構(gòu)建以源代碼為中心且基于容器(能夠?qū)崿F(xiàn)資源伸縮性)的應(yīng)用。這使得它成為一個頗有吸引力的平臺,當有無服務(wù)器需求時,值得對其進行評估。
我們對 PULUMI 非常感興趣。**它是云基礎(chǔ)設(shè)施自動化領(lǐng)域很有前途的新星。其優(yōu)勢在于,允許使用 TypeScript/JavaScript、 Python 和 Go 語言(無需YAML配置)來編寫配置。**Pulumi 專注于云原生架構(gòu)(包括容器、無服務(wù)器函數(shù)和數(shù)據(jù)服務(wù)),并為 Kubernetes 提供了良好的支持。
在區(qū)塊鏈技術(shù)領(lǐng)域, Ethereum(以太坊)是一個領(lǐng)先的開發(fā)者生態(tài)系統(tǒng)。我們看到了一些新興的解決方案,它們旨在將Ethereum這項技術(shù)傳播到一些企業(yè)環(huán)境中。這些企業(yè)通常需要網(wǎng)絡(luò)權(quán)限和交易隱私管理,另外還需要更高的吞吐量和更低的延遲。 QUORUM 就是其中的一個解決方案。Quorum最初由J.P. Morgan開發(fā),其定位是“企業(yè)版的Ethereum”。與創(chuàng)建了新的以太坊虛擬機(EVM)的Hyperledger Burrow 節(jié)點不同,Quorum的代碼源自以太坊官方客戶端的一個分支,所以能與以太坊一起進化。在保留了以太坊賬本的大多數(shù)功能的前提下,Quorum將共識協(xié)議從工作量證明機制更改為更高效的協(xié)議,并增加了私有交易支持。使用Quorum,開發(fā)人員可以使用他們的以太坊知識來構(gòu)建企業(yè)級的區(qū)塊鏈應(yīng)用,這些知識包括 Solidity語言和 Truffle 合約。然而根據(jù)我們的經(jīng)驗,Quorum還沒有為應(yīng)用于企業(yè)做好充足的準備;比如:它缺乏針對私有合約的訪問控制機制,無法用于負載均衡,并且只支持部分數(shù)據(jù)庫。所有的這些限制都為用戶的部署與設(shè)計帶來顯著的負擔。我們建議在使用Quorum的時候保持警惕,同時密切關(guān)注它的后續(xù)發(fā)展。
RESIN.IO 是一個物聯(lián)網(wǎng)(IoT)平臺。雖然只做把容器部署到設(shè)備中這一件事,但它做得很好。開發(fā)人員使用一個軟件即服務(wù)( SaaS)的門戶來管理設(shè)備,并為這些設(shè)備分發(fā)由 Dockerfile 定義的應(yīng)用。該平臺可以為多種硬件類型構(gòu)建容器,并通過無線的方式部署容器鏡像。Resin.io 使用balena 來管理容器。而balena是一個基于 Mobby 框架的容器引擎,由 Docker 出品。該平臺仍在開發(fā)中,有些功能尚需完善,也缺少一些特性(比如與私有容器注冊服務(wù)協(xié)同工作)。但是目前的特性集(包括從 Web 門戶使用 ssh 訪問一個設(shè)備上的容器)表明它的未來充滿希望。
ROOK是一款運行在Kubernetes集群中的開源云原生存儲編排工具。與Ceph集成之后的Rook,能將文件、塊和對象存儲系統(tǒng)引入到Kubernetes集群中,并能與使用這些存儲的其他應(yīng)用和服務(wù)一起無縫地運行。通過使用一些Kubernetes operator,Rook可以在控制層上編排Ceph,這樣就可以避免擠占應(yīng)用程序和Ceph之間的數(shù)據(jù)通道。存儲是云原生計算中的重要組件,雖然Rook現(xiàn)在仍然在CNCF進行孵化,但是我們相信,它將引領(lǐng)我們向著自給自足和跨公有云和本地化部署的可移植性更進一步。
利用谷歌具有開創(chuàng)性的高容量平臺的關(guān)鍵組件來構(gòu)建開源產(chǎn)品,似乎已成為一種趨勢。如同HBASE利用了谷歌的BigTable, Kubernetes 利用了谷歌的Borg, SPIFFE 正在利用谷歌的LOAS,來將一種稱為工作負載標識的關(guān)鍵云原生概念轉(zhuǎn)化為現(xiàn)實。 SPIFFE標準由開源軟件 SPIFFERuntime Environment (SPIRE) 提供支持,該軟件可自動為軟件工作負載提供加密且可證明的身份。雖然SPIRE還沒有為在生產(chǎn)環(huán)境使用做好準備,但我們看到了其在以下場景中的巨大價值:以平臺無關(guān)的方式,在現(xiàn)代分布式IT基礎(chǔ)設(shè)施中的工作負載之間,進行強身份驗證。 SPIRE支持許多用例,包括身份轉(zhuǎn)換、OAuth客戶端身份驗證、mTLS“無處不在的加密”和工作負載可觀察性。本期雷達所介紹的 Istio默認就使用SPIFFE。
暫緩
**數(shù)據(jù)饑餓軟件包(DATA-HUNGRY PACKAGES)**是一種解決方案,它需要將數(shù)據(jù)吸附到自身才能運行。在某些情況下,它們甚至可能需要成為這些數(shù)據(jù)的“主人”。一旦這種軟件包擁有了數(shù)據(jù),它就成為更新、修改或訪問這些數(shù)據(jù)的唯一方法。這種軟件包可能會解決諸如ERP這樣特定的業(yè)務(wù)問題。但是,組織的有關(guān)庫存或財務(wù)的“數(shù)據(jù)需求”,通常需要復雜的集成和對位于原始范圍之外的系統(tǒng)的更改。
低代碼平臺(LOW-CODE PLATFORMS) 使用圖形化用戶界面與圖形化配置來創(chuàng)建應(yīng)用程序。然而不幸的是,該平臺的推廣理念卻是軟件開發(fā)不再需要有經(jīng)驗的開發(fā)團隊。這種理念忽視了這樣的事實,即在創(chuàng)建高質(zhì)量軟件所需要的所有實踐中,編寫代碼僅僅是其中的一小部分,而諸如控制源代碼、測試和精心設(shè)計解決方案這些實踐,也同樣重要。盡管這種平臺有時也是有用的,但我們?nèi)越ㄗh要小心對待,特別是當他們肆無忌憚地宣稱其能實現(xiàn)更低成本和更高產(chǎn)出的時候。
工具
采用
試驗
Azure Container Service Engine (ACS-ENGINE) 是用于 Azure Resource Manager (ARM) 的模版生成器。aceengine 使用一個 JSON 文件進行集群配置,并生成 ARM所需的一系列文件。該工具可以靈活選用不同的容器編排工具,包括 Kubernetes 、 DC/OS 、 OpenShift 、 Swarmmode 與 Swarm ,也可以靈活配置集群的特征及代理。我們已經(jīng)在多個項目中應(yīng)用了 acs-engine,并推薦用它來管理 Azure Container Service 中的集群
我們看到安全工具與現(xiàn)代軟件交付過程的集成有了顯著進步。ARCHERY 是一個開源的安全工具,它的社區(qū)活躍,并正在將其與其他工具(包括 Zap )相結(jié)合。Archery 主要用于 Web 應(yīng)用程序,可以輕松地將安全工具集成到構(gòu)建與部署系統(tǒng)中。也可以通過 Archery 的工作面板,跟蹤漏洞及應(yīng)用程序和網(wǎng)絡(luò)的安全掃描結(jié)果。
ARCHUNIT是一個基于 Java 的測試庫,用于檢查代碼的結(jié)構(gòu)特性,如包和類的依賴關(guān)系、注解驗證,甚至還能檢查代碼分層是否一致。我們很喜歡 ArchUnit 的地方是,它可以在現(xiàn)有的測試環(huán)境中以單元測試的方式運行,盡管只支持基于 Java 的架構(gòu)。在CI環(huán)境或部署流水線中集成ArchUnit 測試套件,可以方便地在演進式架構(gòu)中實現(xiàn)架構(gòu)適應(yīng)度函數(shù)。
運行端到端測試時經(jīng)常會遇到一些棘手的問題,比如運行時間過長,測試過于零碎,還需要修復無頭模式下運行的測試所導致的 CI 失敗。我們的團隊借助 CYPRESS 很好地解決了性能差、響應(yīng)時間長、資源加載慢等常見問題。Cypress 是一款很有用的工具,可以幫助開發(fā)者構(gòu)建端到端測試,還可以將所有測試步驟保存為 MP4 視頻,便于檢查錯誤。
安全性仍然至關(guān)重要,而粗心地將安全憑據(jù)或其他機密提交到源代碼倉庫是一個主要的攻擊向量。 GIT-SECRETS是防止將密碼或其他敏感信息提交到 git 倉庫的小工具。也可以在公開代碼庫之前使用 git-secrets 掃描全部歷史提交,以確保沒有意外地提交憑據(jù)。git-secrets 內(nèi)建支持常見的 AWS 密鑰和憑據(jù),也可以為其他的提供商進行快速配置。
Firefox 無頭模式(HEADLESS FIREFOX)與用于前端測試的 Chrome 無頭模式一樣成熟。 與 Chrome 無頭模式類似,在 Firefox 無頭模式下運行瀏覽器測試時無需渲染 UI組件,因此大大加快了 UI 測試的速度。
使用云服務(wù)時面對的一個挑戰(zhàn)是如何在本地進行開發(fā)和測試。 LOCALSTACK 為 AWS 解決了這個問題。它提供了各種 AWS 服務(wù)的本地測試替身實現(xiàn),包括 S3 、 Kinesis 、Dynamodb 和 Lambda 等。它基于現(xiàn)有的最佳工具如Kinesalite 、 Dynalite 、 Moto 等構(gòu)建,并增加了進程隔離與錯誤注入的功能。 LocalStack 的使用很簡單,并附帶了一個簡單的 JUnit 運行器以及 JUnit 5擴展。我們在一些項目中使用過 LocalStack ,并對它印象深刻。
MERMAID 使用類似 markdown 的標記語言來生成圖表。Mermaid 為簡化文檔編寫而生,并且發(fā)展迅速。目前已經(jīng)為許多工具提供了插件支持,比如 Confluence 、 VisualStudio Code 和 Jekyll 。 可以試用一下 GitHub 上的在線編輯器。此外, Mermaid 還提供了很好用的命令行,可以使用圖表定義文件生成 SVG/PNG/PDF 。我們已經(jīng)在許多項目中使用了 Mermaid ,尤其欣賞的是,它可以用 markdown簡潔地描述圖形和流程圖,同時也可以將圖表定義文件存儲在代碼倉庫中。
PRETTIER 是一個頗有主張的 JavaScript 代碼自動格式化工具(也在逐漸支持其它語言)。它通過強制實施自己主張的代碼風格,增強了代碼的一致性和可讀性,并減少了開發(fā)人員在格式化上的工作量,以及團隊在代碼風格大討論上浪費的工作量。雖然你可能不同意 Prettier 所強制選擇的風格,不過我們發(fā)現(xiàn)它給團隊帶來的好處通常會大于這些風格方面的小問題。 Prettier 可以與版本管理系統(tǒng)的“提交前鉤子”或 IDE 插件一起使用。與任何格式化工具一樣,一次性地格式化整個代碼庫可能會給版本控制歷史帶來混亂,不過我們覺得這只是一個小問題。我們特別欣賞的是Prettier 不再使用基于 linter 的方法。借用來自 gofmt 的一句話:不僅驗證代碼,更保持它始終有效!
技術(shù)雷達在2015年引入了 Visual Studio Code ,而如今它已不再是唯一基于 .NET Core 的跨平臺 IDE 。最近,作為JetBrains 開發(fā)的 IDEA 平臺的一員, RIDER 已經(jīng)被廣泛使用。 Rider 的重構(gòu)功能是基于 ReSharper 實現(xiàn)的,因此那些習慣于 ReSharper 快速靈巧的開發(fā)人員對其情有獨鐘。不僅如此, Rider 還為 .NET 帶來了完整的 IDEA 平臺,大大提升了開發(fā)效率。不管你喜歡哪個平臺,都有必要嘗試一下Rider ,它現(xiàn)在比 Visual Studio Code 更有優(yōu)勢。活躍的生態(tài)和強有力的競爭使這些工具能夠持續(xù)改進,對整個社區(qū)來說是件好事。
SNYK 可以查找、修復及監(jiān)控 npm 、 Ruby 、 Python 、Scala 、 Golang 、 .NET 、 PHP 、 Java 與 Docker 依賴樹中的漏洞。將 Snyk 加入構(gòu)建流水線后,它會基于一個托管的漏洞數(shù)據(jù)庫,持續(xù)地監(jiān)控和測試你的庫依賴樹。在發(fā)現(xiàn)漏洞時,還可以給出可以解決該安全問題的最小的依賴版本。
隨著越來越多的團隊接受DesignOps,這個領(lǐng)域的實踐和工具也日漸成熟。 我們的許多團隊都在使用一整套支持UI組件快速迭代的環(huán)境(也稱為UI DEVENVIRONMENTS),以專注于用戶體驗設(shè)計人員與開發(fā)人員之間的協(xié)作。目前可用的環(huán)境有:Storybook , reactstyleguidist, Compositor 及 MDX。 這些工具既可以在組件庫或設(shè)計系統(tǒng)的開發(fā)過程中單獨使用,也可以嵌入到Web應(yīng)用項目中使用。 如果只是為了向組件中添加新功能,你可以只啟動Storybook dev服務(wù)器,而不需要啟動應(yīng)用、 BFF 或其他服務(wù).
VISUAL STUDIO CODE 是微軟推出的免費 IDE 編輯器,可以跨平臺使用。我們曾用它同時進行前端 React、TypeScript 和后端 GoLang 的開發(fā),而無需在不同的編輯器之間切換,體驗很好。 Visual Studio Code 中的工具、語言支持和擴展插件數(shù)量都在迅猛增長,也越來越好用。我們要特別推薦在實時協(xié)作及遠程結(jié)對編程時使用 VS LiveShare 。固然微軟或 Jetbrains 成熟的 IDE 對使用靜態(tài)類型語言(如 Java 、 .NET 或 C++ )的復雜項目支持得更好,但我們也發(fā)現(xiàn) Visual Studio Code 正逐漸成為基礎(chǔ)設(shè)施開發(fā)組和前端開發(fā)組的首選工具。
VS LIVE SHARE 是用于 Visual Studio Code 與 Visual Studio 的插件,提供實時合作編輯與調(diào)試代碼、語音通話、共享終端和暴露本地端口等功能,能夠減少遠程結(jié)對編程時遇到的障礙。我們特別欣賞的是,開發(fā)人員可以在使用Live Share 協(xié)作時沿用自己的編輯器配置,包括主題、快捷鍵和擴展。
評估
構(gòu)建、測試和部署移動應(yīng)用,尤其是由一條流水線從代碼倉庫打通到應(yīng)用商店的時候,會涉及許多復雜的步驟。雖然這些步驟可以由腳本或普通 CI/CD 工具提供的流水線自動完成,但對于專注移動應(yīng)用開發(fā),而不需要與后端的構(gòu)建流水線做集成的小組來說,使用專用工具可以降低復雜度和維護開銷。 BITRISE 配置簡單,并預置了一組完整的步驟,可以滿足絕大多數(shù)移動應(yīng)用開發(fā)所需。
CODEFRESH 是類似于 CircleCI 與 Buildkite 的托管型持續(xù)集成服務(wù)器。它以容器為中心,并將 Dockerfile 文件和容器托管集群視為一等公民。我們十分欣賞的是, CircleCI鼓勵流水線式的交付方式,并且支持分支與合并。我們的團隊對 CircleCI 的前期反饋良好,但還沒有驗證在大型項目及復雜流水線上的使用效果。
我們一直在尋找一些工具和技術(shù),使大型組織內(nèi)的交付團隊能夠獨立于其他部門工作,同時滿足安全與風險管控的要求。GRAFEAS 就是一個這樣的工具。組織可以使用它發(fā)布軟件工件(Docker鏡像、庫及軟件包)的權(quán)威元數(shù)據(jù),并在構(gòu)建腳本或其他自動化的合規(guī)性控制過程中使用這些元數(shù)據(jù)。 通過訪問控制機制,可以將發(fā)布審核或漏洞信息的團隊與構(gòu)建、部署軟件的團隊間的職責劃分清楚。請注意,雖然包括 Google 與 JFrog 在內(nèi)的多個組織已經(jīng)在工作流程中使用了 Grafeas ,但它目前仍處于 alpha 階段。
**HEPTIO ARK 是用于 Kubernetes 集群和持久化卷的災(zāi)難恢復管理工具。 Ark 使用一系列檢查點備份與恢復集群,配置使用簡單。**使用 Ark 可以顯著縮短基礎(chǔ)架構(gòu)發(fā)生故障時的恢復時間,還能輕松地將 Kubernetes 資源從一個集群遷移到另一個集群,或者復制生產(chǎn)環(huán)境用于測試和排錯。 Ark支持主流的云存儲提供商(包括 AWS , Azure 和 GoogleCloud ),并且從版本0.6.0開始,提供了插件系統(tǒng)用于兼容其他備份與卷存儲平臺。雖然 GKE 等 Kubernetes 托管環(huán)境已經(jīng)提供了這類服務(wù),但如果需要自行運維 Kubernetes ,不論是在本地還是云端,都請仔細考慮使用 Heptio Ark 進行災(zāi)難恢復。
JAEGER 是一個開源的分布式追蹤系統(tǒng)。與 Zipkin 類似, Jaeger 的設(shè)計靈感來源于谷歌的 Dapper,并遵循 OpenTracing 。 Jaeger 的誕生晚于 Zipkin 但普及迅速。這是因為 Jaeger 支持更多種語言的客戶端庫,并且在 Kubernetes 集群中安裝它也很簡單。我們已經(jīng)成功將Jaeger 與 Istio 配合使用,在 Kubernetes 集群中與 Envoy集成進行應(yīng)用程序追蹤。我們也很喜歡 Jaeger 的UI。隨著Jaeger 加入 CNCF ,我們預計 Jaeger 會在社區(qū)工作上投入更多的精力,同時也會與 CNCF 內(nèi)的其他項目產(chǎn)生更深度的融合。
KUBE-BENCH 是一款基礎(chǔ)設(shè)施配置掃描工具,基于 K8S的 CIS 評分自動檢查 Kubernetes 配置,涵蓋用戶身份驗證,權(quán)限控制和數(shù)據(jù)安全等方面。 我們的團隊發(fā)現(xiàn) kubebench 識別易受攻擊的配置方面很有價值。
OCELOT是基于.NET Core實現(xiàn)的輕量級API網(wǎng)關(guān)項目,它可以通過輕松的配置來實現(xiàn)路由轉(zhuǎn)發(fā)、請求聚合、服務(wù)發(fā)現(xiàn)、認證授權(quán)、限流熔斷、負載均衡等特性,它還集成了Service Fabric、Consul、Eureka等功能。目前Ocelot的功能已經(jīng)相當完整,它在.NET Core社區(qū)的活躍度也很高,.NET社區(qū)的開發(fā)者已經(jīng)對 Ocelot 進行了很多擴展,以支持gRPC 、 Orleans與 WebSocket 等通信協(xié)議。盡管市面上不乏優(yōu)秀的 API Gateway(如 Kong ),但 .NET 社區(qū)在構(gòu)建微服務(wù)時還是更青睞 Ocelot 。一方面是由于 Ocelot 能夠更好的與 .NET生態(tài)(如 IdentityServer4 )集成,另一方面騰訊已經(jīng)將其用于生產(chǎn)環(huán)境來構(gòu)建網(wǎng)關(guān),這無疑是給Ocelot在可用性方面注入了一劑強心劑。
暫緩
在調(diào)研用戶體驗時,往往需要收集并分析數(shù)據(jù),以便在設(shè)計產(chǎn)品時做出更好的決策。 OPTIMAL WORKSHOP 是一套數(shù)字化的調(diào)研工具。它提供了首次點擊、卡片分類等功能,可以幫助驗證原型以及改進網(wǎng)站導航和信息展示。OptimalWorkshop 還可以協(xié)助組織遠程調(diào)研,對于分布式的團隊特別有用。
越來越多的項目需要處理非結(jié)構(gòu)化的數(shù)據(jù),而從文本中提取出有意義的業(yè)務(wù)信息是一項關(guān)鍵技術(shù)。 STANFORDCORENLP 是一組基于 Java 的自然語言處理(NLP)工具集,支持英語、漢語和阿拉伯語等多種語言的命名實體識別、關(guān)系抽取、情感分析與文本分類,也提供了用于標記語料庫和訓練模型的工具。 Stanford CoreNLP 協(xié)助我們使用NLP 領(lǐng)域的最新研究成果來解決各種業(yè)務(wù)問題。
我們廣泛的應(yīng)用 Terraform 來實現(xiàn)代碼化配置(as-code)云基礎(chǔ)設(shè)施。TERRAGRUNT 是 Terraform 的一個輕量級的封裝,用來落地《Terraform: Up and Running 》 書中主張的實踐。我們發(fā)現(xiàn) Terragrunt 很有幫助,因為它通過一些便利的特性來促進版本化模塊和不同云環(huán)境的復用性,這些功能包括遞歸執(zhí)行子目錄下的代碼。我們希望Terragrunt 能再進化一些,能夠原生地支持持續(xù)交付的實踐,我們希望在持續(xù)交付的流水線上所有基礎(chǔ)設(shè)施的代碼都能被打包、版本化并能在不同環(huán)境下復用(我們團隊已經(jīng)通過替代方案實現(xiàn)了這些功能)。
我們團隊對 TESTCAFE 的反響很好。這是一個基于 JavaScript 的自動化瀏覽器測試工具,可以使用JavaScript 或 TypeScript 編寫測試,并在任何支持JavaScript 的瀏覽器中運行測試。 TestCafe 提供了開箱即用的并行執(zhí)行、HTTP請求模擬等有用的功能。 TestCafe 使用異步執(zhí)行模型而無需指定等待時間,有效提升了測試套件的穩(wěn)定性。
TRAEFIK 是一款開源的反向代理及負載均衡器。 如果只是需要具有簡單路由功能的邊緣代理,而非 NGINX 、HAProxy 這樣的重量級產(chǎn)品,就可以考慮 Traefik 。它提供了微服務(wù)所必不可少的免重載更新配置、度量、監(jiān)控與斷路器等功能,同時也很好地集成了Let’s Encrypt 以支持 SSL 。相比于 Traefik ,為了擴展、添加或移除微服務(wù), NGINX 、HAProxy 等工具可能需要額外的工具進行模板化配置;有時還需要重啟,給生產(chǎn)環(huán)境造成很大麻煩。
我們非常關(guān)注測試驅(qū)動開發(fā)過程中的快速反饋,并一直尋找新方法使它變得更快。 WALLABY.JS 是一款支持主流編輯器的商用擴展,可以持續(xù)運行 JavaScript 單元測試,并在代碼旁高亮顯示測試結(jié)果。它還可以識別及運行每項代碼改動所影響的最小測試集,并在代碼錄入的同時持續(xù)運行測試。
語言 & 框架
采用
試驗
隨著 微服務(wù) 架構(gòu)越來越多地被采用,相比以前,我們構(gòu)建了更多的分布式應(yīng)用程序。盡管解耦架構(gòu)帶來了許多好處,但證明整個系統(tǒng)正確性所需的工作量和復雜程度正急劇增加。 JEPSEN 提供了許多我們所需要的工具,來幫助我們驗證協(xié)調(diào)任務(wù)調(diào)度程序的正確性,測試分布式數(shù)據(jù)庫的最終一致性、 線性一致性(Linearizability)和 可串行性(Serializability)。我們在一些項目中使用了 Jepsen,令人驚喜的是,我們可以測試驅(qū)動配置,注入和修復故障,驗證系統(tǒng)恢復后的狀態(tài)。
MMKV 是微信開發(fā)的開源框架,為移動應(yīng)用提供高速的鍵值對存儲。 它利用 iOS 的內(nèi)存映射功能來避免直接保存修改,因此性能極高。 MMKV 也能夠在應(yīng)用程序異常崩潰時保存并快速恢復數(shù)據(jù)。
MOCKK 是用 Kotlin 編寫的模擬庫。它的核心理念是像 Coroutines 和 Lambda 表達式一樣,為 Kotlin 提供一等公民級別的語言特性支持。不同于 Mockito 或PowerMock 的蹩腳封裝,作為原生的開發(fā)庫,它能幫助開發(fā)團隊在測試 Kotlin 應(yīng)用時編寫干凈、簡潔的代碼。
TYPESCRIPT 是一門嚴謹?shù)恼Z言。一直以來,它不斷改進的開發(fā)工具和IDE支持給我們留下了深刻的印象。隨著基于瀏覽器的代碼庫數(shù)量不斷增長,類型安全變得尤為重要,而使用此 TypeScript 類型定義庫,可以讓我們在保證類型安全的同時從豐富的 JavaScript 庫中受益。TypeScript 的類型安全特性讓我們在使用 IDE 或其他工具進行代碼開發(fā)時獲得了更詳盡的上下文,從而保障了代碼修改和重構(gòu)的安全性。作為 JavaScript 的超集,TypeScript 的文檔和社區(qū)使學習曲線變得平緩。
評估
**Apache Beam 是個開源的統(tǒng)一編程模型,用于定義和運行批量/流式的并行數(shù)據(jù)處理流水線。**Beam 提供了可移植的 API 層,可以直接定義流水線,而不依賴于具體的執(zhí)行引擎(也稱為 runner)如 Apache Spark、 Apache Flink或 Google Cloud Dataflow。這些引擎的功能不盡相同,因此提供可移植的 API 是項艱巨的任務(wù)。Beam 積極地嘗試將各引擎的創(chuàng)新功能加入 Beam 模型,同時通過社區(qū)合作的方式,影響這些引擎的產(chǎn)品規(guī)劃,以達到微妙的平衡。Beam 提供了豐富的內(nèi)置I/O轉(zhuǎn)換器,以滿足大多數(shù)數(shù)據(jù)流水線的需求。如有特殊需求,也可以在 Beam 中實現(xiàn)自定義轉(zhuǎn)換器。可移植 API 以及可擴展 I/O 轉(zhuǎn)換器,是評估是否將 Apache Beam 用于處理數(shù)據(jù)流水線業(yè)務(wù)時最值得注意的地方。
我們常常對業(yè)務(wù)流程模型和標記法(BPMN)工具持懷疑態(tài)
度,因為它們普遍表現(xiàn)出低代碼環(huán)境相關(guān)的缺點。然而 OSS
BPMN 框架 CAMUNDA 不僅提供了一些這方面的創(chuàng)新,還
支持在 Java 代碼中以庫的方式直接集成它的工作流和決
策引擎,從而簡化了測試、版本管理和工作流重構(gòu)方面的工
作。不僅如此,Camunda 還可以與 Spring、Spring Boot 以及其他框架集成,這使它成為了我的不二之選。
FLUTTER是一個跨平臺的框架,可以使用Dart語言編寫原生 Mobile 應(yīng)用。借助 Dart,它能夠編譯成原生代碼,并直接 和目標平臺通訊,而不必借助橋接和上下文切換—這些可能導致框架中出現(xiàn)性能瓶頸,就像 React Native 或Weex 那樣。Flutter的熱重載(hot-reload)特性讓人驚嘆,它能在編 碼時為你提供超快的視覺反饋。目前,Flutter 仍在 Beta 階段,不過我們會持續(xù)關(guān)注它,了解其生態(tài)系統(tǒng)的成熟度
Kotlin 語言已不僅僅適用于移動應(yīng)用開發(fā)。新工具和框架的出現(xiàn)證明了其在 web 應(yīng)用程序開發(fā)上的價值。KTOR 就是其中之一。與其它支持 Kotlin 的 web 框架相比,Ktor 本身就是用 Kotlin 編寫的,并運用了諸如 coroutines 等語言特性來支持異步非阻塞的實現(xiàn)。除了具有輕量級架構(gòu)外,它還能靈活的與各種不同的日志、依賴注入和模板引擎工具結(jié)合使用,這讓 Ktor 成為了我們團隊在創(chuàng)建 RESTful 服務(wù)時一個有趣的選項
我們在與團隊的交流中了解到 Python 卷土重來并席卷了多個技術(shù)領(lǐng)域。事實上,它正成為最常用的編程語言。這一方面得益于數(shù)據(jù)科學家和機器學習領(lǐng)域推動了它的應(yīng)用,另一方面我們也看到有團隊正將其運用于微服務(wù)的構(gòu)建。NAMEKO 就是這樣一個超輕量級的微服務(wù)框架,也是Flask的 替代方案。與 Flask 不同的是,Nameko 只包含了WebSocket、HTTP、AMQP 支持等有限功能。它對可測試性的重視也得到我們的欣賞。如果你不需要 Flask 提供的模板等功能,那么 Nameko 值得一瞧。
POLLY.JS 是個用于測試 JavaScript 網(wǎng)站和應(yīng)用程序的簡單工具。它可以攔截和模擬 HTTP 交互,從而簡單快速地測試 JavaScript 代碼而無需啟動其依賴的服務(wù)或組件,我們的團隊對這一點情有獨鐘。
**PREDICTIONIO 是開源的機器學習服務(wù)框架。**無論是普通開發(fā)者還是數(shù)據(jù)科學家,都可以利用它創(chuàng)建用于預測的智能應(yīng)用。和所有其他智能應(yīng)用類似,**PredictionIO 由三個部分組成:數(shù)據(jù)收集和存儲、模型訓練以及模型部署和服務(wù)暴露。**開發(fā)者只需要基于它提供的相應(yīng)接口實現(xiàn)數(shù)據(jù)處理邏輯、模型算法和預測邏輯,無需在諸如存儲數(shù)據(jù)以及訓練模型之類的事情上投入額外精力。從我們的經(jīng)驗來看,在不要求高并發(fā)處理的情況下,PredictionIO 能支持不同大小的數(shù)據(jù)集。大多數(shù)時候我們使用 PredictionIO 來為中小企業(yè)構(gòu)建預測類智能服務(wù),或者在構(gòu)建復雜定制化預測引擎的過程中進行概念驗證。
在之前的技術(shù)雷達中,我們提到了使用 Headless Chrome進行前端測試。如今,隨著其他瀏覽器對 ChromeDevTools 協(xié)議(CDP)的引入,出現(xiàn)了一系列針對這些瀏覽器的自動化和測試相關(guān)支持庫。即使在無頭模式下,CDP 也支持對瀏覽器的細粒度控制。基于 CDP 協(xié)議,一些高級自動化測試框架被陸續(xù)創(chuàng)造出來,而 PUPPETEER 正是其中之一。它可以通過單頁應(yīng)用程序驅(qū)動 Headless Chrome 模式,從而實現(xiàn)基于時間追蹤的性能診斷等功能。我們的團隊在使用過程中發(fā)現(xiàn)它比基于 WebDriver 的其它工具更快,也更靈活。
量子計算目前已經(jīng)可供測試,但何時真正到來尚未明確。在硬件到位之前,我們已經(jīng)可以通過語言和模擬器來實驗和學習它。盡管IBM等公司已經(jīng)取得了不錯的進展,我們對微軟在 Q# 語言及其模擬器(本地32量子比特,Azure云上40量子比特)方面的工作更加關(guān)注。如果你想開始了解這項編程的前景,請查看他們在 GitHub 上的范例。
SAFE 技術(shù)棧是 Suave、 Azure、 Fable 和 Elmish 的簡稱。SAFE 囊括了一系列技術(shù),形成了前后端一致的 Web開發(fā)技術(shù)棧。SAFE 在服務(wù)端和瀏覽器端都使用了 F# 語言,因此注重于異步函數(shù)式類型安全的編程機制。它不僅提供了一些提高開發(fā)效率的功能比如熱加載;還允許我們替換技術(shù)棧里的某些模塊,例如服務(wù)器端 Web 框架或云提供商。
新編程語言的廣泛使用往往會催生支持成熟工程實踐的新工具,例如自動化測試, Kotlin 也不例外。Cucumber、 RSpec 和 Jasmine 這些測試工具廣為人知,它們采用 Gherkin 語言和需求規(guī)范(Specification)來編寫測試。在以上幾個工具啟發(fā)下誕生的測試框架 SPEK能讓開發(fā)團隊把像行為驅(qū)動開發(fā)這樣的成熟實踐帶到Kotlin 世界來。
在那些使用了AWS CloudFormation(而非Terraform)的項目中,我們嘗試了用 TROPOSPHERE 作為在AWS上定義基礎(chǔ)設(shè)施即代碼的方式。Troposphere 是一個Python 庫,可以使用 Python 代碼生成 JSON 格式的CloudFormation 描述。我們喜歡 troposphere 是因為它很容易發(fā)現(xiàn) JSON 錯誤,同時它也有類型檢測、單元測試以及 DRY 組合 AWS 資源等功能。
**WEBASSEMBLY 將“瀏覽器作為代碼執(zhí)行環(huán)境”向前推進了一大步。它是一種二進制編譯格式,幾乎以原生速度 跑在瀏覽器中,已經(jīng)獲得所有主流瀏覽器的支持并向后兼容。**它拓展了編寫前端功能的語言范圍,早期集中在C、C++ 和 Rust,并且也可以作為 LLVM 的編譯目標。在沙盒中執(zhí) 行時,它可以和 JavaScript 交互并且共享相同的權(quán)限和安全模型。當和Firefox 最新的流式編譯器一起使用時,也可 以提升頁面初始化速度。盡管還處在早期階段,但是這個 W3C 標準絕對值得研究。
Spring Framework 5 已發(fā)布一年有余,它采用了響應(yīng)式流 — 一套非阻塞背壓(backpressure)式異步流式處理標準。在傳統(tǒng)的 Spring MVC 模塊之外, WEBFLUX 為在Spring 生態(tài)下編寫 Web 應(yīng)用提供了一個響應(yīng)式替代品。經(jīng)過一系列應(yīng)用的試用,WebFlux 給我們的團隊留下了深刻的印象,并匯報說這種響應(yīng)式(函數(shù)式)實現(xiàn)增強了代碼的可讀性和系統(tǒng)的吞吐量。但他們也確實注意到,采用 WebFlux 需要在思維方式上做出一些重大轉(zhuǎn)變,建議在WebFlux vs. Spring MVC 的技術(shù)選型中考慮這一點。
暫緩
總結(jié)
以上是生活随笔為你收集整理的2019年TW的技术雷达的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑爱好者 2008年第23期(12月上
- 下一篇: C语言程序设计中十全十美,21世纪高校计