本文得到codingthearchitecture.com受權翻譯發表,轉載須要註明來自公衆號EAWorld。html
做者:Simon Brownjava
譯者:月滿西樓git
原題:Paas for Java developersweb
我從事軟件開發工做已有20多年,在此期間,我參與了各類不一樣的環境下,各種軟件系統的搭建工做,其中大部分系統都以Java和web技術爲核心,固然其餘技術也有所接觸。同時,我也有幸參與了從開始到交付的整個軟件開發過程。不過在基礎設施這一塊,我沒有參與太多。另外,我也建立過一些服務器,但大多數生產基礎設施的構建都是由基礎設施團隊完成的。我認爲這很常見。提供生產級基礎設施是一項專門的任務;須要瞭解安裝、配置和強化操做系統、數據庫、負載平衡器、防火牆等方面的知識。坦率來說,這都不是我特別感興趣的,尤爲身在軟件行業,咱們都須要不斷地去學習新知識、新技能,新技術的更新換代實在太快。算法
記得三年前,我在匈牙利布達佩斯的Craft Conference上,曾就個人一個名爲Structurizr的創新應用程序和與會者進行了屢次探討。這個程序的初期演示是在Rackspace的Ubuntu上運行的,但牽扯到了一系列基礎設施和操做上的問題,這些問題的解決不在個人能力範圍內。會中我收到的一個建議是, 我能夠去關注一下Pivotal Web Services這個 PaaS雲服務。我確實也在澤西運營一些當地學校的編程俱樂部時接觸過這個服務,但沒有考慮過它是否能承載我本身的應用程序。spring
Pivotal Web Services是一個基於Cloud Foundry的商業服務,提供「平臺即服務」(PaaS)。從本質上講,Cloud Foundry經過API提供了一個應用程序部署平臺,能夠將部署在公有云、私有云或是數據中心服務器上的底層基礎結構抽象出來。數據庫
假設你正要在Apache Tomcat Web服務器上構建一個Java web應用程序。那麼,在其能在網絡上運行以前,你須要在某處提供服務器,安裝Java和Apache Tomcat Web服務器。你還須要強化服務器、配置SSL、按期應用補丁等,若是你還想經過使用兩個實例來提升恢復能力,那還須要啓動第二個服務器,重複前面的步驟,並配置這兩個服務器,來支持例如負載平衡器。編程
固然,你還能夠,也可能會,使用Vagrant, Chef, Puppet, Docker等這些自動化配置和部署工具來自動化大部分的操做步驟。api
當Cloud Foundry命令行界面安裝完成以後,若是咱們想部署一個Java .WAR 或.JAR文件,只須要簡單地運行一個「cf push」命令,就能夠將它部署到Pivotal Web Services 這個PaaS雲服務上。僅此而已! 我還可使用「cf scale」命令來請求Pivotal Web Services來縱向擴展應用程序,例如添加更多的RAM,或把應用程序橫向擴展,例如添加更多實例。瀏覽器
若是須要更新應用程序,則要用到另外一個「cf push」命令。但這麼作會停止當前實例的運行,並將其替換爲新版本,所以會有一些服務中止時間。然而,Cloud Foundry PaaS雲平臺使得經過命令行接口來進行藍綠部署變得很是容易。如此一來,Java開發人員就能夠不具有底層基礎設施專業知識的前提下,也在幾分鐘內創建一個「零停機時間(zero-downtime)」(即服務不會中止)的連續交付通道。
正如Joshua McKenty在最近的一個關於思科雲的播客中所講的,Pivotal Web Services和Cloud Foundry爲開發者提供了一個更高的抽象層。軟件開發人員的職責是處理應用程序,而不是基礎設施或容器。
目前,業內關於Docker容器的討論很火熱。我認爲Docker是一項了不得的技術。可是,軟件開發人員更多的仍是要專一於處理應用程序,而不是去關注容器技術或基礎設施。我認爲關注Docker技術是對大多數軟件開發人員本職工做的干擾,對此,我會在另外一篇博客裏進行闡述。
在上文中,我介紹了平臺即服務(PaaS),並討論瞭如何使用Pivotal Web Services PaaS雲服務和Cloud Foundry PaaS雲平臺來實現應用程序的快捷部署,且無需擔憂任何底層基礎設施的問題。 一個比較常見的誤區是,你們總以爲使用Cloud Foundry PaaS雲平臺(以及Pivotal Web Services PaaS雲服務或其餘項目)會致使供應商鎖定(Vendor Lock-in),從而不能輕易轉換雲服務提供商。
回過頭來再看Structurizr,它是用於可視化和文件記錄軟件架構的一組工具,系統圖示以下:
總而言之,通過身份驗證的用戶使用Structurizr Client函數庫(Java 和.NET)可建立和上傳軟件架構模型,並經過web查看這些模型的內容。Structurizr使用SendGrid這個電子郵件服務平臺發送電子郵件,全部支付處理都是由Taxamo和 Braintree支付工具服務一塊兒完成的。這裏也用到了其餘一些雲服務(例如CloudFlare、Pingdom和Papertrail),但在圖表中沒有顯示。
從一個(C4模型)容器角度來看,Structurizr以下圖所示(圖表中忽略了外部服務,由於它們與這次討論無關):
從本質上講, Structurizr由一個運行在web瀏覽器(服務於HTML、CSS和JavaScript)的客戶端應用程序組成,而服務器端包含一個Java web應用程序服務https://structurizr.com,和另外一個Java應用程序服務https://api.structurizr.com,再加上一些數據存儲(MySQL數據庫管理系統, Redis緩存和Amazon S3雲存儲服務)。這兩個Java web應用程序都運行在Pivotal Web Services這個PaaS雲服務上。
這兩個Java web應用程序都基於Spring MVC框架,並按照「twelve-factor methodology」中所說明的一系列原則實現的。實際上,從技術角度來看,這兩個程序都只是設計在雲平臺上運行的典型Java web應用程序。兩個程序都是無狀態的,不會向本地文件系統寫入重要信息。
接下來讓咱們來談談供應商鎖定(Vendor Lock-in),正如Sam Newman說的那樣,「不要一提到供應商鎖定(Vendor Lock-in),就天然想到遷移成本」。 Structurizr的全部開發都是在Mac上使用IntelliJ IDEA完成的,而Vagrant虛擬機運行環境管理工具則被用來運行本地的MySQL數據庫系統和Redis緩存拷貝。在代碼庫中,沒有任何東西與Cloud Foundry PaaS雲平臺有關,我也沒有在本地運行Cloud Foundry相關的內容。Java應用程序是部署到本地運行的Apache Tomcat實例的標準Java EE.WAR文件。
推送(Push) Structurizr「Web應用程序」(使用「cf push」命令)會致使Web應用程序被部署到Pivotal Web Services 上,而且能夠在https://struct-web.cfapps.io的URL中使用。想要把這個web應用程序遷移到另外一個雲服務提供商的話,如下是我須要進行的一些操做。
1.首先我須要找到另外一個支持Java 8,Apache Tomcat 8.x服務器的PaaS雲服務,或者構建本身的服務器。另外,Java虛擬機(JVM)還要求安裝"Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files",這是由於web應用程序在存儲數據時使用了一些強度更高的加密算法。
2. 考慮到web應用程序多個實例在運行(顯然,Pivotal Web Services PaaS雲服務在單一的URL後進行處理),我須要對這個設置進行鏡像。
3. Structurizr.com域的域名服務器(DNS)正由CloudFlare管理,爲映射新的部署位置,一些別名(即CNAME)記錄須要更改。
就是這麼簡單。雖然說部署腳本須要更改,但不須要對代碼進行任何變更。Pivotal Web Services 這個PaaS雲服務確實提供了一些基於Cloud Foundry PaaS雲平臺的附加功能,好比它們的數據儀表板,這對監控和管理很很方便,但這些並非應用程序的關鍵組成部分。總之,我並遇到沒有任何供應商鎖定的問題(Vendor Lock-in),並且遷移成本很低。畢竟,個人Java web應用程序很普通,並不依賴於Cloud Foundry PaaS雲平臺。
至此,你可能會想,「等等,那數據存儲呢?」,這是另外一個話題。接下來,我將分享在Pivotal Web Services PaaS雲服務中可用的市場服務(Marketplace Service),以及爲何我不作推薦。
從這部分開始,我想說,我我的確實喜歡且推薦Pivotal Web Services PaaS雲服務和Cloud Foundry PaaS雲平臺來做爲部署Java應用程序的方法, 它們能顯著簡化部署流程,並帶來出色的性能表現。我在Pivotal Web Services PaaS雲服務上運行Structurizr已經三年多了,幾乎沒在覈心平臺上發現有什麼問題。但應用市場服務(Marketplace Service)則另當別論。
除了提供一個用於運行代碼的部署平臺以外,大多數像Pivotal Web Services、Heroku、AzurePaaS雲服務這類的平臺還會提供「應用市場服務(Marketplace Service)」集合。本質上,這些是附加服務,可讓用戶方便地訪問數據庫、信息傳遞提供程序、監視工具等,在我寫這篇文章時,Pivotal Web Services PaaS雲服務應用市場(Marketplace)包含不少當下比較流行的技術; 好比MySQL、 PostgreSQL、 Redis、 Memcached、MongoDB、RabbitMQ等。
假設你正構建一個Java web應用程序,並但願將數據存儲在MySQL數據管理系統中。你能夠有幾種處理方法:一種是在Amazon AWS之類的平臺上構建你本身的數據庫服務器。固然,這要求你有能力來實現,前文中我曾用很大篇幅來闡述利用PaaS平臺構建個性化基礎設施的優勢,但這種DIY方法不必定適用於每一個人。
另外一種選擇是找到一個「數據庫即服務(DaaS)」的提供商,由它來爲你建立和運行MySQL服務器。ClearDB就是一個例子,你能夠在Pivotal Web Services PaaS雲服務應用市場(Marketplace)上找到它。你只需經過應用市場(Marketplace)訂閱一個免費的ClearDB,並將其鏈接到數據庫,從而來構建你的解決方案。就是這麼簡單,MySQL數據庫在操做方面大都都須要維護;包括備份和複製。
當Java應用程序鏈接到ClearDB時,一樣也有幾種選擇。一是常規作法,將數據庫端點URL、用戶名和密碼放在配置中。也以用Cloud Foundry命令行接口來發出一個「cf bind」命令,將ClearDB數據庫實例綁定應用程序實例,並使用雲平臺的自動從新配置功能來進行操做。
若是您構建的是一個基於spring框架的應用程序,且已經配置了MySQL數據源(一些注意事項),那麼Cloud Foundry PaaS雲平臺將自動地從新配置數據源,指向已綁定到應用程序的MySQL數據庫。這項功能一經使用,你必定會以爲體驗很是不錯,由於又少了一件須要你擔憂的事。這還意味着,即便後續更改了URL、用戶名和密碼,你也不須要本身去更新。
幾年來我都是這麼操做的,在Structurizr changelog上你會發現版本號都快過1000了。每一個版本號都表明一個在Pivotal Web Services上的獨立(自動)部署。在我運行的這些大量部署中,大多數都部署成功了,偶爾,我也會收到一些由於服務(好比ClearDB)不能綁定到應用程序實例的失敗提示。
不過這都是些暫時性的錯誤,只須要從新啓動部署就能修復它們。但遇到其餘錯誤提示時,我不得不認可我實在沒有辦法解決它。PaaS的一個大問題就在於,一旦出錯,管理者就會陷入困境,由於沒法訪問到底層的基礎設施。好在這類錯誤出現頻度很低,現實中沒有讓我真正擔憂過,但仍是挺煩人的。
更鬧心的是我發現了一個Structurizr和UTF-8字符編碼的小bug。當用戶註冊賬戶時,記錄會被保存在MySQL裏,用戶會收到一封「請驗證您的電子郵件地址」的電子郵件。一旦註冊者的名字中包含了UTF-8字符,儘管第一封電子郵件不會有什麼問題,但後續就會出錯。這個問題出在MySQL沒法正確地存儲UTF-8字符上。
我在dev環境中重演了這個問題,能夠經過向JDBC URL添加一個字符編碼參數來修復。不過,推送這個補丁到實時環境也存在問題,由於Cloud Foundry又會自動從新配置個人數據源URL。簡單處理是不啓用自動從新配置,這很容易經過Java構建包來實現禁用,也不須要將MySQL數據庫實例綁定到Java應用程序。基於以上操做,如今我仍然會經過應用市場來使用ClearDB,但在配置中我會指定鏈接細節。
我所遇到的有關ClearDB的最後一個問題是在今年早些時候,當時我常常在日誌中看到錯誤消息,提示已經超過了能鏈接的最大數量。不一樣的ClearDB計劃會提供不一樣級別的性能和鏈接數量。我認爲應用市場提供的ClearDB數據庫是面向多租戶(Multi-tenant)的,它會設置一個鏈接限制來確保全部客戶的服務質量。這能夠理解,但我不明白爲何我會超過可以使用數量,由於我清楚地知道我運行的應用實例數量,並且也清楚每一個應用實例所限定的鏈接數量範圍。
因而,我在Apache基準測試中運行了一些負載測試,結果我沒法得知打開鏈接的數量,從而沒法判斷它們是否超過了鏈接池中所配置的最大限額。我再三查看ClearDB的數據指示儀表板,按說它能夠顯示打開鏈接的數量,但個人應用程序卻沒法鏈接,儀表板上只顯示了幾個實時鏈接。
回到供應商鎖定和遷移成本這個話題,將應用程序從ClearDB遷移到另外一個MySQL供應商的成本很低,特別是不使用Cloud Foundry的自動從新配置機制以後。所以,我能夠導出數據,並在Amazon RDS上建立一個MySQL數據庫。每月在不須要支付不少費用的前提下,我就能夠有個運行在多個可用性區域的MySQL數據庫,在rest中使用加密的數據,而且我確信JDBC鏈接是經過SSL進行的(由於這就是我配置它的方式)。
我早期使用的另外一個應用市場服務是SendGrid,它提供「電子郵件傳送即服務(E-mail delivery as a service)」。一樣的,運行一個「cf bind」命令就能夠將SendGrid服務綁定到應用程序。
但在這種狀況下,不會有自動從新配置,由於SendGrid公開了一個web API。這就提出了一個問題,即在哪裏找到API憑據。應用市場服務一個很好的特性是,只須要一個單點登陸的操做,就能經過關鍵Web服務 UI來訪問服務數據儀表板(例如ClearDB儀表板、SendGrid儀表板等),在服務儀表板上的某個位置找到服務憑證。
在獲取SendGrid的密碼後,我將它硬編碼到一個配置文件中,並將其推送到應用程序中。出乎我意料的是,程序嘗試鏈接SendGrid後提示了身份驗證失敗,由於密碼錯誤。因而我再次訪問了儀表板,發現密碼已經不同了,我不知道形成這樣的結果是不是由於運行了一個「cf bind」命令而致使SendGrid憑證被更改。
我沒有意識到服務憑證是在運行中的JVM的 VCAP_SERVICES 環境變量中設置的,憑證應該從那裏提取。這只是一個帶有JSON content 的常規環境變量。獲取它並解析所需的憑證,或是使用GitHub上衆多代碼示例或函數庫(library)就能夠完成此操做。從開發的角度來看,我如今對這個VCAP的數據有小小的依賴,我須要確保個人本地Apache Tomcat實例以相同的方式進行配置,並在啓動時使用VCAP_SERVICES環境變量。
一段時間以後,SendGrid已經將其Web API升級到了v3版 ,其中也包括了Java函數庫的新版本。 因此我也進行了升級,但卻致使了API調用的失敗。在登陸到SendGrid數據儀表板以後,我注意到如今能夠經過API密鑰進行鏈接。簡而言之,我放棄了VCAP的可調用數據,配置了SendGrid客戶端,用使用API密鑰的方法來調用API,這些也被我添加到了部署配置中。
我還使用過一段時間的Pivotal SSL Service,用來上傳SSL證書。當它與Cloud Foundry路由器同時工做,就能夠經過一個有效的SSL證書爲指定域名提供流量服務。在使用過程當中我也遇到一些問題,好比會致使運行中止。Java程序在cfapps.io域裏還能正常工做,但structurizr.com域則不行。
此後,我又換成了CloudFlare專用的SSL證書服務,每個月花費5美圓。我確實嘗試過免費的SSL證書服務,但一部分用戶仍是反饋了經過Structurizr's web API上傳軟件架構模型時,發現了一些「SSL握手」方面的問題。
曾經我也結合 Spring Session一塊兒,用了免費的Redis緩存服務,將其做爲存儲HTTP session信息的一種方式。不過,我很快就消耗完了免費的額度,同時發現經過Redis Labs直接切換到Redis Cloud計劃性價比會更高些。
使用與PaaS產品相配套的應用市場服務(Marketplace Service)確定有一些好處。你只須要選擇訂閱一項附加服務,就能夠開始使用了,既快又便捷。並且全部的服務均可以在同一個市場裏進行購買和管理,這點也很棒。在使用Cloud Foundry PaaS雲平臺時,我就經過VCAP_SERVICES進行配置;這樣全部的服務都在一塊兒。
若是你剛開始使用PaaS,我想你確定會考慮與其配套的那些應用市場服務。雖然你們具體狀況會有所不一樣,但我仍是不推薦用這些應用市場服務來從事生產活動。正如我在本文開頭所說,我使用Pivotal Web Services PaaS的核心功能差很少有三年,這期間系統一直都比較穩定。我所遇到的那些不穩定的狀況,都和應用市場服務有關。這些市場服務極可能致使你沒法獲知一些具體狀況,好比在特定狀況下,服務實際能帶來什麼樣的運行結果,以及服務具體在哪裏運行。
ClearDB數據庫計劃其實也有暗示,免費計劃(Spark DB)是「完美適用於概念驗證和初級開發」,而每個月100美圓的"Shock DB"計劃則「專爲高性能應用而設計」。這些計劃沒有在ClearDB網站上列出,所以很難判斷它們是多租戶服務 仍是單一租戶服務。考慮到須要進行網絡登陸,應用市場服務建立的一些訪問密碼看起來也至關簡短(好比8個字符)。
考慮到以上種種狀況,我更傾向於直接註冊一個服務,並以經常使用的方式來進行集成,我不認爲採用應用市場服務利大於弊。若是哪一天我須要從PaaS項目中移走。我還將進一步下降遷移成本。總的來講,Structurizr目前的現場部署方案圖以下所示:
Java應用程序託管在Pivotal Web Services PaaS雲服務上,其餘全部組件都在外部運行,但它仍然在亞馬遜(Amazon)的us-east-1 AWS區域。這應該有助於解決另外一個常見的,你們都認爲須要在PaaS環境中運行全部內容的誤區,但其實沒什麼能阻止你在PaaS上運行Java應用程序,並讓它們鏈接到你本身構建的數據庫服務器。如此一來,你能夠自由使用你選擇的技術,無論它是否在應用市場(Marketplace)上可用。固然,你還須要考慮適配性、性能和安全性。
以上是我對應用市場服務(Marketplace Service)經驗的總結。接下來,我將更多地討論構建/部署腳本,以及經過Cloud Foundry PaaS雲平臺實現零停機時間(zero-downtime)、藍綠部署方面的內容。
本文的前幾部分已經從多個不一樣的角度對Cloud Foundry PaaS雲平臺做了介紹; 包括high-level概念、供應商鎖定(vendor lock-in) 和Pivotal Web Services PaaS雲服務應用市場服務(Marketplace Service)。接下來,咱們將討論Cloud Foundry PaaS雲平臺如何實現「零停機時間(zero-downtime)」部署,並讓這個操做變得更爲簡易。
先簡要介紹下這個主題,假設有個Java web應用程序在某處運行。將該應用程序升級到新版本的一個簡單方法是先暫停程序,而後更新相關的部署構件(例如.JAR 或 .WAR文件),再重啓。一些web應用程序服務器也會爲應用程序的熱部署(hot swapping) 提供支持,但原理都同樣。
儘管這個方法是可行的,但在這個過程當中,用戶就會有一段時間沒法使用服務。多年來,技術人員也構想了許多技術方案來處理這個問題,業界最流行的就是藍綠部署,在這種部署方案裏,會有一個物理或是虛擬的路由器,將流量從應用程序的一個運行實例切換到另外一個。這聽起來很先進,但若是你使用Cloud Foundry,任何規模的開發團隊均可以輕鬆地進行藍綠部署。
在本文的前面部分我也提到過,Structurizr是由兩個java/spring web應用程序組成;一個服務於HTML、CSS和JavaScript的「Web應用程序」和一個容許客戶獲取或放置軟件架構的工做區的「API應用程序」。構建和部署過程由Amazon EC2服務器上運行的TeamCity觸發,等待提交到git存儲庫,這整個過程都是徹底自動化的。總而言之,藍綠部署的構建和部署過程遵循如下幾個步驟:
處理好依賴關係(dependencies)
初始化構建目錄、新增版本號等
編譯生產和測試代碼
運行單元/類(unit/class)測試
運行集成/組件測試
建立部署構件(例如.WAR文件)
將API應用程序推送至Pivotal Web Services
在API應用程序上運行e2e/系統測試
將Web應用程序推送至Pivotal Web Services
在Web應用程序上運行e2e/系統測試
激活API應用程序
激活Web應用程序
生成併發布新的軟件架構圖和文檔
假設構建和測試的過程都順利, 那麼這個過程當中,每一個API和Web應用程序都會被推送至Pivotal Web Services PaaS雲服務。構建服務器上安裝了Cloud Foundry命令行接口,構建腳本只需使用「cf push」命令來推送(Push).WAR文件。爲便於應用程序的推送(Push),咱們使用「--no-start」標記(flag),但不啓動它,這樣就能夠經過「cf env」命令來設置像配置這樣的應用程序環境變量。設置完配置後,在實際啓動應用程序以前,使用「cf scale」命令還能夠設置所需的實例和RAM數量。此時,應用程序還在運行,可是隻能經過包含版本號的臨時URL進行訪問(例如「https://structurizrweb - 123. cfapps.io」)。
在應用程序運行的同時,構建腳本能夠運行一系列端到端測試,好比「冒煙測試(smoke test)」 和系統測試並行的混合測試,以驗證新版本的應用程序是否按預期運行。這些測試包括一些像登陸、獲取/安裝軟件架構模型等場景。
若是成功經過了端到端測試,接下來就是激活這些程序的新版本。這須要使用Cloud Foundry命令行接口,將實時URL映射到應用程序的新版本("cf map-route"),而後將其從舊版本中刪除(「cf-unmap-路由」)。這個過程使用了Cloud Foundry路由器,它能夠實現對訪問當前運行程序的URL的配置。 若是這一切都成功了,那麼應用程序的前一個版本就會被刪除。整個構建過程只須要不到10分鐘。若是你感興趣,這裏還有一些關於如何進行藍綠部署的內容。
將實時URL切換到應用程序新版本的這個過程,是容許「零停機時間(zero-downtime)」部署的。這裏要提醒你們的是,切換到新版本後,任何只駐留在舊版程序內存空間中的信息都會丟失。例如,若是HTTP 會話(session)狀態只存儲在內存中,那麼一旦用戶在請求被導入到新的Apache Tomcat實例時,就會被迫退出。 處理這個問題有包括會話(session)複製在內的多種方法, 但Structurizr使用Spring session+Redis技術,將HTTP會話信息存儲在Apache Tomcat服務器實例以外,以便在部署過程當中保留會話信息,從而解決了會話共享問題。
如此一來……僅僅是使用Cloud Foundry命令行接口,咱們就簡單高效地完成了一個「零停機時間(zero-downtime)」部署過程。
原文地址:
http://www.codingthearchitecture.com/2017/09/27/paas_for_java_developers_part_1.html
http://www.codingthearchitecture.com/2017/09/28/paas_for_java_developers_part_2.html
http://www.codingthearchitecture.com/2017/09/29/paas_for_java_developers_part_3.html
http://www.codingthearchitecture.com/2017/10/10/paas_for_java_developers_part_4.html
(編者注:原文分爲四部分,此文爲所有內容的整合。)
做者簡介:
Simon Brown,全球知名軟件架構獨立諮詢師、講師,專一於軟件架構研究,他是C4軟件架構模型的建立者,也是Structurizr的創始人。
關於EAWorld:微服務,DevOps,數據治理,移動架構原創技術分享,長按二維碼關注