- 服務端開發:技術、方法與實用解決方案
- 郭進
- 14957字
- 2023-10-19 18:15:54
1.2 服務端開發技術棧
正如前文提及的那樣,現階段的服務端開發早已不再是簡單地圍繞著數據庫編排CRUD服務。很多時候,服務端應用的第一行代碼尚未寫就,工程師便需要與產品、運營、法務等人員及網絡、中間件、操作系統、搜索、數據、算法、運維、安全等技術體系打交道,互聯網企業對工程師的要求越來越高。
單從技術棧來看,服務端開發涉及編程語言、開發工具、開發框架、數據庫與數據存儲、中間件、操作系統、應用部署、運維監控等知識體系。
1.2.1 編程語言
對服務端開發來說,編程是最基本的能力。目前,全球已經投入使用的編程語言超過50種,其中多數可用于服務端開發,但術業有專攻,不同語言的流行度和學習成本不一樣,各自的特性也有較大差異。在選擇開發語言時,可以參考TIOBE排行榜。TIOBE排行榜是基于業界資深軟件工程師、課程和第三方廠商的數量,使用搜索引擎和第三方數據統計出的排名,每月更新一次。排名反映的是編程語言的熱度。工程師可以用它來評估自身編程技能是否跟上了趨勢,也可以通過它來了解世界范圍內開發語言的走勢。
1.選擇編程語言的一般原則
在實踐中,如何選擇服務端編程語言呢?易學習、功能強大、生態豐富是樸素而直接的判斷要素,但與此同時也充滿爭議,因為這些要素缺乏具備公信力的評判標準,感性評估則往往因人而異。在軟件工程師圈子里談及編程語言時,假設筆者說一句“PHP是世界上最好的語言”,則必然會引起工程師們的激烈討論,眾多Java、Python、C/C++、Go等語言的愛好者會一起“群毆”筆者的觀點。那么,關于編程語言的選擇難道就沒有可遵循的原則嗎?當然不是,通常有4個選擇依據。
(1)編程語言須服務于系統架構
合適的編程語言應根據具體的場景來選擇,而不是基于工程師自身的偏好。簡而言之,即根據場景選擇語言,而不是以語言去應付場景。例如引擎層是以C/C++為主,而算法層則是以Python為主。在一些特定的領域,Lisp、Scala等冷門語言亦有應用。
(2)盡量復用前人積累
軟件工程一旦發展到比較龐大的規模,即使采用了先進的編程語言,如果不能很好地復用前人的積累,而不得不重新造輪子,也必然會導致效率降低。
(3)盡量避免冷門語言
一門編程語言的興起通常都是從一個典型的軟件產品開始的。比如日本人設計的Ruby語言,它的代表作是Gitlab。商業公司如果選用它,就不得不面對冷門語言工程師招聘困難的問題,即便招聘到了資深的冷門語言專家,軟件的開發、維護,以及工程師的發展也將是問題。
(4)盡量選擇生態豐富的語言
微服務開始起步后,給更多小眾語言提供了更好的生存環境。Service Mesh技術讓小眾語言也可以通過接口或者系統調用獲得更多中間件體系提供的便利,但當前尚處于前沿,還遠未到完全成熟應用的階段。在微服務之下的SOA(Service-Oriented Architecture,面向服務的架構),大多數還是建立在傳統語言之上。比如阿里堅持深耕Java體系多年,一個重要的原因是其他語言短期內難以比擬Java的生態優勢。事實上,不少語言在編程效率上優于Java,但一旦用來做大型工程,在達到一定規模時通常會陷入自洽性矛盾:要么放棄語言的靈活性,要么放棄工程的可持續性。
2.互聯網企業常用的服務端編程語言
可用于服務端開發的編程語言很多,企業在選擇編程語言時會根據自身的實際情況權衡,分出主次,即以1種編程語言為主要開發語言,1~3種編程語言為輔。這不難理解,選擇一種編程語言為主,持續深耕,對于軟件開發、維護,技術積累、傳承,都是非常有利的,但同時,一種編程語言很難滿足眾多復雜業務場景的需要,因此需要選擇幾種輔助編程語言。在此,筆者列舉了部分互聯網企業服務端開發的主流編程語言,如表1-1所示,供讀者參考。
表1-1 部分互聯網企業服務端開發的主流編程語言

1.2.2 開發工具
工欲善其事,必先利其器。從事服務端開發工作,選擇稱手的工具很重要。常用的開發工具包括集成開發環境、代碼管理工具及建模工具。
1.集成開發環境
集成開發環境(Integrated Development Environment,IDE)是指用于提供程序開發環境的應用程序,一般包括代碼編輯器、編譯器、調試器和圖形用戶界面等工具。它是集成了代碼編寫功能、分析功能、編譯功能、調試功能等于一體的開發軟件服務套件,所有具備這一特性的軟件或者軟件套(組)都可以叫集成開發環境。如微軟的Visual Studio系列、JetBrains的IDE系列等。IDE可以獨立運行,也可以和其他程序并用。
IDE眾多,如何選擇呢?針對服務端主流編程語言,筆者推薦兩個系列的IDE給大家。
(1)VSCode
VSCode(Visual Studio Code)是由微軟開發的一款功能強大的現代化輕量級IDE,社區版免費。VSCode具有強大的插件擴展能力,幾乎支持所有主流語言(C++、Java、Go、Python等)的項目開發。該IDE支持語法高亮、代碼自動補全(又稱IntelliSense)、代碼重構等功能,并且內置了命令行工具和Git版本控制系統。用戶可以更改主題和鍵盤快捷方式實現個性化設置,也可以通過內置的擴展程序商店安裝擴展以拓展軟件功能。
(2)JetBrains系列
JetBrains是一家捷克的軟件開發公司,該公司出品了支持Java、C++、Python、Go等主流編程語言的系列知名IDE,堪稱IDE界的集大成者。其中最具代表性的是IntelliJIDEA,在業界被公認為最好的JavaIDE,它在智能代碼助手、代碼自動提示、重構、JavaEE支持、版本工具(Git、SVN等)、JUnit、CVS整合、代碼分析、GUI設計等方面表現優異,深受Java工程師認可。此外,JetBrains為Go語言提供了GoLand,為Python語言提供了PyCharm,這兩款IDE也廣受工程師贊譽,長期位于最受歡迎的IDE榜單前列。
2.代碼管理工具Git
在實踐中,一個軟件項目通常由多名工程師協作完成。工程師各自開發自己所負責部分的同時,還需兼顧整個項目。由幾個人協同開發的小項目尚可通過人力管理來應對,但幾十人、幾百人協作的項目呢?如果沒有一個強大的工具支撐,那將無疑是人力“黑洞”。著名的版本控制軟件Git便是在這種背景下誕生的。
Git最初是Linus Torvalds為了幫助管理Linux內核而開發的一個開放源碼的版本控制軟件。它是一個開源的分布式版本控制系統,可用于敏捷、高效地處理任何或小或大的項目。通過Git,工程師可以方便地創建代碼倉、創建開發分支、合并代碼、提交代碼、解決沖突、查看提交記錄等。
3.建模工具Visual Paradigm
服務端開發工程師的日常工作并不止于“編寫運行于服務器端的程序”。根據筆者的經驗,編程占據工作時間的比例通常不到30%,那么,其他時間在做什么呢?主要是做設計。設計的本質其實就是“與自己的溝通”“與合作伙伴的溝通”。通過溝通幫助自己厘清思路,同時讓合作者理解你的思路。在實際工作中,筆者將至少40%的時間用在溝通上,比如業務對焦、需求評審、服務端方案評審、客戶端方案評審、系統重構、風險評估等,溝通對象包括產品、運營、技術、質量、視覺、交互等。在跨團隊合作、跨部門合作甚至對外合作的場景中,“文山會?!蓖沟脺贤ǜ拥托А?/p>
為了提升設計環節的溝通效率,在較大的項目中,業界一般采用建模利器Visual Paradigm輔助。Visual Paradigm是一款UML建模工具,可以支持多種圖表類型,如類圖、業務用例圖、時序圖、狀態機圖、動態圖、組件圖、部署圖、對象圖、場景交互圖、領域模型圖、業務框架圖、組件關系圖等。
通過Visual Paradigm將需求分析、抽象建模、系統設計等環節有機地鏈接起來,循序漸進,從具體的業務用例到抽象的領域模型,再到技術實現方案,便于不同角色理解,提升溝通效率的同時提升設計質量、減少后續維護成本。Visual Paradigm在服務端開發生命周期中的應用如圖1-3所示。

圖1-3 Visual Paradigm在服務端開發生命周期中的應用
1.2.3 開發框架
1.什么是框架
在軟件工程中,框架(Framework)的定義為:整個或部分系統的可重用設計,表現為一組抽象構件及構件實例間交互的方法。一個框架是一個可復用的設計構件,它規定了應用的體系結構,闡明了整個設計、協作構件之間的依賴關系、責任分配和控制流程,為構件復用提供了上下文關系。
框架是實現了某應用領域通用功能的底層服務,軟件開發者可以在通用功能已經實現的基礎上開始具體的系統開發??蚣芴峁┝怂袘闷谕哪J行為的類集合,具體的應用通過重寫子類或組裝對象來支持應用專用的行為。通俗地說,框架是完成了某種應用的半成品,它可以提供一些常用的工具類和基礎通用化的組件,基于此,軟件開發者可以專注于自身業務的開發。
2.為什么要使用框架
軟件系統發展到今天已經很復雜了,特別是服務器端軟件,它涉及資源、網絡、中間件、離線計算、搜索引擎、實時計算、運維、測試、安全等一系列技術體系。因此,為開發出完善、健壯的軟件,對工程師的要求將會非常高。如果采用成熟、穩健的框架,那么一些基礎的通用工作(如事務處理、安全性、數據流控制等)就可以交給框架處理,工程師只需要專注于完成具體的業務邏輯設計,就可大大降低開發難度。從軟件工程師的角度看,使用框架最明顯的好處是復用,包括設計復用和分析復用。
?設計復用:框架提供可復用的抽象算法及高層設計,并能將大系統分解成更小的構件,而且能描述構件間的內部接口。這些標準接口使得在已有構件的基礎上通過組裝建立各種各樣的系統成為可能。只要符合接口定義,新的構件就能插入框架中,構件設計者就能復用構架的設計。
?分析復用:框架的使用者若按照框架的思想和規范來分析、描述、設計軟件工程,就可以將軟件工程劃分為符合一定標準的構件,那么使用同一框架的工程師之間就能進行高效的溝通。簡言之,統一了語言之后,使用同一框架的工程師就可采用統一的工程語言來溝通。
一種技術的終極目標是為業務發展而服務。從業務的角度來講,首先,框架服務于企業的業務發展和戰略規劃;其次,框架可提高企業的競爭力,包括降低研發成本、提高質量、縮短周期等;最后,框架實現上述目標的方式是進行有效的知識積累。軟件開發是一種知識活動,因此知識的高效積累至關重要。框架能夠采用一種結構化的方式對某個特定的業務領域進行描述,也就是將這個領域相關的技術以代碼、文檔、模型等方式固化下來。綜合來看,合理地使用框架可以帶來以下諸多好處。
?顯著提升代碼的可復用性,從而提高軟件生產效率和質量。
?軟件代碼結構規范化,從而降低工程師之間的溝通成本和后期維護成本。
?提高知識積累效率,通過設計框架和領域構件使得知識得以體系化積累。
?降低軟件研發難度,工程師可更專注于業務領域,使需求分析更充分。
?提高協同工作效率,基于統一的規范和原型,有助于多人協同工作。
?大粒度地復用可降低平均研發費用,縮短開發周期,減少開發人員,降低維護成本。
3.框架的分類
框架與類庫是不同的,框架強調的是軟件的設計重用性和系統的可擴充性,以縮短大型應用軟件系統的開發周期,提高開發質量。相較于傳統的基于類庫的面向對象重用技術,應用框架更注重于面向專業領域的軟件重用。應用框架具有領域相關性,構件根據框架進行復合而生成可運行的系統??蚣艿牧6仍酱螅渲邪念I域知識就越完整??紤]到面向的領域和編碼實現,軟件開發框架一般可分為如下3類。
1)基礎類庫。基礎類庫是一種最基礎的框架,涵蓋多數項目所需要的基礎類。例如,Java集合框架主要包括兩種類型的容器:一種是集合(Collection),存儲一個元素集合;另一種是圖(Map),存儲鍵/值對映射。Collection接口又分List、Set和Queue三種子類型,再下面是一些抽象類,最后是具體實現類,常用的有ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap等。
2)基礎框架?;A框架一般是針對于某特定領域,實現特定領域所需要的常用功能。例如Hibernate,它是一個對象關系映射框架,支持幾乎所有主流的關系型數據庫,如MySQL、Oracle、SQL Server和DB2等,開發者只須在配置文件中指定好當前使用的數據庫,而不必關注不同數據庫之間的差異。Hibernate提供了一系列數據訪問接口,工程師可以通過這些接口輕松地使用面向對象思想對數據庫進行操作。
3)平臺框架。平臺框架一般需整合或實現某種編程語言開發所需要的常用功能。例如Spring,它是一個綜合型框架,致力于J2EE應用的各層的解決方案,而不是僅僅專注于某一層的解決方案。一些場景下,Spring可以作為應用開發的“一站式”選擇,并貫穿表現層、業務層及持久層。Spring功能強大,可提供IOC、AOP及Web MVC等功能。Spring可以單獨應用于構建應用程序,也可以和Struts、Webwork、Tapestry等眾多Web框架組合使用。
4.常用框架舉例
針對部分主流服務端編程語言,筆者列舉了對應的常用框架,如表1-2所示。
表1-2 部分編程語言的常用框架舉例

1.2.4 數據庫與數據存儲
信息時代,數據已悄然成為企業的核心資產。由于數據庫是數據唯一的持久層,幾乎所有的業務流程最終都依賴數據庫中的數據,因此作為服務端開發工程師,掌握數據庫及數據存儲技術尤為重要。本節將著重介紹數據與數據庫的基本概念、分類以及常用數據庫的特點和選型指標等。關于數據庫及數據存儲實戰,筆者將在后文中專門介紹。
1.數據與數據庫
數據是數據庫中存儲的基本對象,是按一定順序排列組合的物理符號。數據有多種表現形式,可以是數字、文字、圖像,甚至是音頻或視頻,它們都可以經過數字化后存入計算機。數據庫是數據的集合,具有統一的結構形式并存放于統一的存儲介質內,是多種應用數據的集成,并可被各個應用程序所共享。
數據庫是數據管理的有效技術,是由一批數據構成的有序集合,被存放在結構化的數據表里。數據表之間相互關聯,反映客觀事物間的本質聯系。數據庫能有效地幫助一個組織或企業科學地管理各類信息資源。
2.數據分類
對于用戶而言,在通過個人計算機、手機等設備使用軟件應用時,接觸到的都是圖形化界面,無法直接接觸到數據庫。信息時代,數據庫無處不在,生活的諸多方面都是建立在數據庫的基礎上的。例如,登錄App時,用戶的賬號和密碼都存儲在服務器的數據庫中;購買火車票、機票時,余票信息、個人購票記錄也存儲在數據庫中;網上購物、訂外賣、訂酒店、訂電影票等信息也都存儲在數據庫中。
數據庫是存儲數據的,沒有數據的數據庫,就不能稱為數據庫,個性推薦、運營分析等也需要大量的數據。那么數據從哪里來呢?在互聯網領域,數據按來源大致可以分為以下兩類。不同類型的數據,收集方式也存在差異。
(1)用戶必要數據
比如電商平臺的用戶購物記錄、收藏記錄,這些數據需要存儲到服務端的數據庫中,當用戶查看記錄時,前端發起請求,經由服務端從數據庫中獲取對應數據,并顯示出來。
(2)運營、分析數據
這類數據通常對用戶不可見,而是企業為了實現個性推薦、運營分析所使用的數據。獲取這類數據的方式主要是埋點,即在產品流程(用戶與軟件客戶端交互流程)的關鍵環節植入相關統計代碼,用來追蹤用戶的行為,并上傳到服務器,通過數據庫存儲起來。比如,為了實現個性化推薦,電商平臺會統計用戶的瀏覽時間、點擊商品等關鍵信息,基于這些數據來實現。
3.客戶端、服務端和數據庫
軟件客戶端和服務端的協作都需要有相應的服務器端程序提供服務。在簡單的應用場景中,服務端主要圍繞數據庫編排CRUD服務。客戶端、服務端和數據庫的關系如圖1-4所示。

圖1-4 客戶端、服務端和數據庫的關系
4.數據庫分類
數據庫大致可以分為兩大類,即SQL數據庫和NoSQL數據庫。SQL(Structured Query Language)數據庫指關系型數據庫,主要代表有SQL Server、Oracle、MySQL、PostgreSQL、SQLite。NoSQL(Not Only SQL)泛指非關系型數據庫,主要代表有MongoDB、Redis、HBase、Memcached。SQL、NoSQL數據庫在存儲數據類型和存儲方式上差異較大。
關系型數據庫適合存儲結構化數據,如用戶的賬號、積分、等級、注冊時間等。這些數據通常需要做結構化查詢,比如過濾出積分大于1000的所有用戶,使用SQL查詢就非常方便。在這類場景下,關系型數據庫就略勝一籌。
隨著互聯網的發展,海量數據場景越來越多,如發微博、發微信、發評論等。一方面,這些數據規模大,增長速度難以預計;另一方面,這些數據類型比較復雜,可能同時包括文字、圖片、音頻、視頻等,使用關系型數據庫無法直接存儲。關系型數據庫在應對這些場景時顯得有些力不從心,逐漸暴露出許多難以克服的難題,因此出現了針對大規模數據場景,以性能卓越和應用便捷為目標的數據庫產品—NoSQL數據庫。NoSQL數據庫是“非關系實體模型”的數據庫,NoSQL的意思是“不只是SQL”(Not only SQL),而不是“不是SQL”(No SQL)。顯然,NoSQL數據庫的出現并不是要完全否認或替代關系型數據庫,而是作為傳統關系型數據庫的一個合理補充。
5.服務端常用數據庫
(1)常用關系型數據庫
1)Oracle。甲骨文公司開發的商業數據庫,不開源,支持所有主流平臺,性能好,功能強,穩定性好,安全性好,支持大數據量。在很長的一段時期,甲骨文憑借其在服務器、數據庫軟件、存儲設備上的優勢,幾乎壟斷了全球商用數據庫系統的市場。但是,Oracle數據庫非常復雜,收費高,以至于在互聯網飛速發展、數據量爆炸式增長的背景下,這種昂貴、擴展性不足的商業數據庫已不再是企業的優選方案。2009年年底,阿里開始“去IOE”,其中“O”指的便是Oracle數據庫,即用MySQL和自研數據庫替代Oracle。目前,頭部互聯網企業已經很少大規模使用Oracle。
2)SQL Server。SQL Server最初由Microsoft、Sybase和Ashton-Tate三家公司共同研發,后來由Microsoft獨立研發。作為一款商業數據庫,SQL Server具有易用性、可伸縮性,以及優秀的數據管理、分析功能,是一款高性價比的商業數據庫。但是,它開放性較差,僅支持Windows平臺。
3)MySQL。MySQL最初由瑞典的DataKonsultAB公司研發,該公司被Sun公司收購,后來Sun公司又被Oracle公司收購,因此MySQL目前屬于Oracle旗下產品。MySQL軟件采用了雙授權政策,分為社區版和商業版。由于體積小、速度快、總體擁有成本低,MySQL通常是中小型網站的數據庫首選。
4)PostgreSQL。PostgreSQL使用BSD協議的完全開源的、免費的關系型數據庫管理系統,支持多種操作系統,功能強大,可以和多種開源工具配合。PostgreSQL不僅僅是關系型數據庫,還同時支持JSON數據、全文檢索以及其他擴展。
(2)常用非關系型數據庫
1)Redis。Redis是現在最受歡迎的NoSQL數據庫之一,具備如下特性:基于內存運行,性能高;支持分布式,理論上可以無限擴展;是鍵值對存儲系統;使用ANSI C語言編寫,遵守BSD協議,支持網絡,是可持久化的日志型數據庫,提供多種語言的API。
相比于其他數據庫類型,Redis具備的優勢是:讀寫速度極快、支持豐富的數據類型、操作具有原子性等。由于Redis性能出色,已被Twitter、阿里、百度等公司在開源版本的基礎上繼續深度開發與定制。
2)HBase。HBase(Hadoop Database)是一個高可靠性、高性能、面向列、可伸縮的分布式存儲系統,它本質上是一個數據模型,可以提供快速隨機訪問海量結構化數據的能力。HBase的適用場景如下:
第一,寫密集型應用。HBase支持每天寫入量巨大,而讀數量相對較小的應用,比如IM的歷史消息、游戲的日志等。
第二,不需要復雜查詢條件來查詢數據的應用。HBase只支持基于rowkey的查詢。對于HBase來說,單條記錄或者小范圍的查詢是可以接受的,大范圍的查詢由于分布式的原因,在性能上可能有點影響,而對于像SQL的join等查詢,HBase無法支持。
第三,對性能和可靠性要求非常高的應用。由于HBase本身沒有單點故障,因此可用性非常高。
6.數據庫特點及選型指標
前文已經提及不同數據庫的特點和適用場景,此外簡要概括一下關系型數據庫和非關系型數據庫的特點。
(1)關系型數據庫的主要特點
?表結構較嚴格,支持行列式存儲結構化數據。
?需要預定義數據類型。
?部分支持事務特性,可保證較強的數據一致性。
?支持SQL語言,增刪改查功能強大,大都支持多表join操作。
?較為通用,技術較成熟。
?不適合處理大數據,當數據讀寫量較大時,通常需要分庫分表。
?高并發性能不足,擴展較為復雜。
(2)非關系型數據庫的主要特點
?表結構較靈活,如列存儲、鍵值對存儲、文檔存儲、圖形存儲;支持非結構化數據。
?部分不需要預定義數據類型,甚至不需要預定義表。
?不支持事務特性,數據一致性能力弱。
?非SQL查詢語言或類SQL查詢語言,但功能都比較弱;通常不支持多表join操作,或有限支持。
?支持大數據量,且多數支持分布式。
?高并發性能較強,易擴展。
數據庫選型一般需要考慮的指標有數據量、并發量、實時性、一致性要求、讀寫分布、讀寫類型、安全性、運維成本。當然,不同的應用場景需要關注的指標不同,例如“雙11”大促活動,數據量和并發量是最重要的兩個指標;而對于銀行轉賬等金融業務,一致性要求是最關鍵的指標。
1.2.5 中間件
中間件(Middleware)是一種應用于分布式系統的基礎軟件。從縱向層次來看,中間件位于各類應用、服務與操作系統、數據庫系統以及其他系統軟件之間,主要解決分布式環境下數據傳輸、數據訪問、應用調度、系統構建、系統集成和流程管理等問題。目前,中間件并沒有很嚴格的定義,但業界普遍接受IDC的定義:中間件是一種獨立的系統軟件服務程序,管理計算資源和網絡通信,幫助分布式應用軟件在不同的技術之間共享資源。從這個意義上可以用一個等式來表示中間件:中間件=平臺+通信。這也就限定了只有用于分布式系統中才能叫中間件,同時也把它與支撐軟件和實用軟件區分開來。
為了讓讀者直觀地感受中間件與應用軟件、支撐軟件(如操作系統)的關系,我們來看一個例子,如圖1-5所示:客戶端請求傳遞到服務端,不是直接由應用承接,而是要經過負載均衡中間件(如Nginx)進行處理后,才由具體的應用進一步處理,而應用之間的協作一般也需要借助中間件;當然,中間件和應用都需要服務器的操作系統和硬件支撐。

圖1-5 中間件與應用軟件、支撐軟件(如操作系統)的關系
中間件在過去的十年間大放異彩,龐大的中間件群體帶來了巨大的效率提升。如果說開發框架使軟件研發工程師能夠通過代碼掌控一切,那么,中間件則通過集中式服務來降低工程師的編程工作量。常用的中間件有消息中間件、事務中間件、數據中間件等。
1.消息中間件
消息中間件也稱消息隊列,是分布式系統中重要的組件,主要解決應用耦合、異步消息、流量削峰等問題。它可以實現高性能、高可用、可伸縮和最終一致性架構,是大型分布式系統不可缺少的中間件。消息隊列在電商系統、消息通信、日志收集等應用中發揮著關鍵作用。以阿里為例,它研發的消息隊列(RocketMQ)在歷次天貓“雙十一”活動中支撐了萬億級的數據洪峰,為大規模交易提供了有力保障。
作為提升應用性能的重要手段,分布式消息隊列技術在互聯網領域得到了越來越廣泛的關注。常用的分布式消息隊列開源軟件有Kafka、ActiveMQ、RabbitMQ及RocketMQ。
為了便于讀者理解消息中間件,我們以簡化版電商架構為例進行具體介紹。如圖1-6所示,在傳統強耦合訂單場景中,客戶在電商網站下訂單,訂單系統接收到請求后,立即調用庫存系統接口扣減庫存。

圖1-6 商品下單簡化流程
上述模式存在如下巨大風險:
?假如庫存系統無法訪問(升級、業務變更、故障等),則訂單減庫存將失敗,從而導致訂單失??;
?短時間內大量的請求、頻繁查詢庫存、修改庫存等,庫存系統負載極大。
我們引入消息中間件,解除強耦合性,處理流程又會怎樣呢?如圖1-7所示,訂單系統中,用戶下單后,訂單系統完成持久化處理,將消息寫入消息中間件,返回用戶訂單,此時客戶可以認為下單成功。消息中間件提供異步的通信協議,消息的發送者將消息發送到消息中間件后可以立即返回,不用等待接收者的響應。消息會被保存在隊列中,直到被接收者取出。庫存系統中,從消息中間件中獲取下單信息,庫存系統根據下單信息進行操作。

圖1-7 引入消息中間件后的商品下單簡化流程
2.事務中間件
事務中間件又稱事務處理管理程序,是當前用得最廣泛的中間件之一,主要用于解決分布式環境下的事務一致性問題。在單機數據庫下,維持事務的ACID(Atomicity、Consistency、Isolation、Durability)特性很容易,但在分布式系統中并不容易,而分布式事務中間件可以保證分布式系統中的分布式事務的ACID特性。
通常,分布式事務中間件可支持DRDS、RDS、MySQL等多種數據源,并兼容消息隊列實現事務消息。通過各種組合,可以輕松實現分布式數據庫事務、多庫事務、消息事務、服務鏈路級事務等多種業務需求。常用的分布式事務中間件有GTS、TXC、Seata等。
3.數據中間件
數據中間件處于底層數據庫和應用系統之間,主要用于屏蔽異構數據庫的底層細節,是客戶端與后臺的數據庫之間進行通信的橋梁。數據中間件一般用于解決海量請求下數據訪問瓶頸及數據庫的容災問題,具備分布式數據庫全生命周期的運維管控能力,支持分庫、分表、平滑擴容、結果集合并、SQL解析、數據庫容災和分布式事務等特性。開源的數據中間件有Vitess、MyCat、Atlas、OneProxy等。
總體來看,目前開源的數據中間件比較少,廣受認可的更是寥寥無幾,大型互聯網企業幾乎都自研數據中間件,如阿里的DRDS、螞蟻的Zdal、京東數科的CDS、美團點評的Zebra等。
1.2.6 操作系統
操作系統是管理計算機硬件與軟件資源的計算機程序。操作系統需要管理和配置內存、決定系統資源供需的優先次序、控制輸入設備與輸出設備、操作網絡與管理文件系統等基本事務。操作系統也提供一個讓用戶與系統交互的操作界面。在計算機中,操作系統是最基本,也是最重要的基礎性系統軟件。
1.Linux系統的優勢
對于服務端開發工程師,學習并掌握操作系統知識極為重要。通常,服務端程序幾乎都是部署在Linux操作系統的服務器上的。為什么是Linux而不是常見的Windows或其他操作系統呢?主要有以下因素。
(1)開源
源代碼開放使得企業可以獲取整個操作系統的源碼,并根據自己的需求對操作系統進行二次開發,甚至打造“定制”的操作系統。同時,源碼開放使企業可以洞悉操作系統的實際運轉情況,而諸如Windows、MacOS這種閉源商用操作系統,則很難掌控。
(2)免費
Linux開源意味著企業不用為操作系統支付任何費用,而Windows是商用操作系統,大規模使用成本高昂。很多時候,成本是企業考量的最重要的因素之一。畢竟企業要生存、發展,在滿足需要的前提下節約成本,何樂不為呢?
(3)穩定
Linux系統以其穩定性而聞名,這也是企業非常注重的一個因素。企業里有很多服務器要求7×24小時不間斷穩定運行,而這更是Linux最擅長的地方。Linux更新升級或者配置某一項操作的時候,只須重新啟動對應的服務即可,無須重啟服務器。
(4)生態
在Linux開源之后,一批技術專家迅速聚集起來,他們不求回報地為Linux提供代碼、修復bug,提出新的想法,幫助Linux成長,直到如今形成了一個龐大的開源社區?,F在開發者想要學習或者獲取Linux的最新版本,都可以在開源社區上找到自己所需要的資料,在開發過程中遇到的問題也可以上社區和同行交流并尋求幫助。
2.Linux常用命令和操作
Linux系統相關的知識點非常多,市面上介紹Linux系統的書籍基本都是“大部頭”,通篇學習實屬不易,效果也很難保證。對于服務端開發工程師來說,可重點學習一些常用的命令和操作。
(1)Linux基礎
如圖1-8所示,Linux基礎知識包括Linux版本和基礎概念兩個部分。Red Hat、Ubuntu、CentOS都是Linux的常見版本。

圖1-8 Linux基礎知識
(2)常用幫助命令
Linux系統的命令數量有上千個,每個命令又有若干個甚至數十個適配不同情景的參數,單純通過記憶掌握這些命令是非常困難的。因此,Linux系統為使用者提供了幫助命令,只需要正確使用Linux的幫助命令,就能夠快速地定位到自己想要的命令和參數。Linux系統常用的幫助命令有3個,即man、help、info,基礎用法如表1-3所示。
表1-3 Linux系統常用幫助命令

(3)文件和目錄管理
文件和目錄管理命令是最基礎的Linux命令,基于這兩類命令,用戶可以在Linux系統下創建文件和目錄,也可以對已有文件和目錄進行查看、刪除、復制等操作。如表1-4所示,筆者列舉了幾個常用的文件和目錄管理命令。
表1-4 Linux系統常用的文件和目錄管理命令

(4)Vim文本編輯
與Windows操作系統不同,在安裝Linux系統的服務器上,為了節省內存、提高效率等,通常不會安裝圖形界面,而只能通過命令行來進行各種操作。因此,當我們在命令行下新增文件、更改文件、編寫腳本時,不可避免地要用到文本編輯器。目前,可供選擇的文本編輯器有很多,如Vim、emacs、pico、nano等,作為服務端開發工程師,應熟悉至少一款Linux文本編輯器的用法。
就受工程師歡迎的程度來看,Vim可以說是無出其右。Vim是一個高效、功能強大、可擴展的編輯器。Vim有自己的腳本語言,稱為Vim腳本(也稱為VimScript或VimL),用戶可以通過多種方式使用它來增強Vim,例如為其他編程語言啟用語法高亮、自動化語法檢查等。此外,Vim還具有高度可配置性,包含Vim核心全局設置(稱為vimrc)的文件可以在各個Vim安裝之間共享。
(5)文件系統與文件查找
作為服務端開發工程師,在日常定位問題時,最常用的手段是日志,因此掌握搜索、查看服務端運行日志的技能十分重要。在Linux系統上進行文件查找的命令主要有兩個:grep和find。這兩個命令的用法非常多,在此,筆者僅列舉幾個基礎用法,如表1-5所示。
表1-5 grep和find命令的基礎用法

除了上面列舉的知識點外,系統管理、磁盤分區、邏輯卷、shell、文本操作等也有必要學習掌握。
1.2.7 應用部署
工程師開發的代碼需要經過編譯、打包等流程,并最終部署到服務器上,才能運行并對外提供服務。在2014年前,生產環境應用部署一般是通過工程師編寫腳本實現的,而開發環境則基本是手動部署,效率普遍較低。經過多年的發展,目前一些頭部互聯網企業的研發平臺和流程已經非常完善,不僅可以支持不同研發環境下自動編譯、部署,而且能提供場景化分析、定制化質量和風險控制能力。研發平臺化、流程標準化雖然使研發更加簡單、高效、可靠,但對工程師屏蔽了背后的技術細節,某種程度上對初入職場的服務端開發工程師是不利的,應用部署不應該成為一個“黑盒”。鑒于此,在本節中,筆者將著重介紹一下互聯網企業生產環境的應用部署。應用部署的發展歷程大致可分為物理機部署、虛擬機部署和容器化部署3個階段。
1.物理機部署
物理機部署,顧名思義,就是將應用直接部署在物理機器上,如圖1-9所示。
在早期,物理機部署幾乎是部署應用的唯一方式,這種部署方式存在一些弊端。
(1)硬件資源浪費

圖1-9 物理機部署應用
當時服務器普遍采用高性能計算機,造價高昂。如果一臺物理機只部署一個應用,則硬件資源難以被充分利用,造成資源浪費。此外,在部署異構系統(不同架構的兩個或多個系統之間通常無法直接通信,也不能部署在同類服務器上)時須重新采購物理資源。
(2)進程間資源搶占
為了充分利用服務器資源,一種方案是將多個應用進程、數據庫、緩存進程等都部署在同一臺物理機上。這種部署方案固然能高效地利用昂貴的物理機,但有一個顯著的缺點是進程間資源搶占。例如,如果某個進程占用了100%的CPU資源,那么其他進程將無法提供服務。
2.虛擬機部署
物理機部署存在進程間資源搶占問題,其根本解決方案是實現進程間硬件資源隔離。虛擬機技術的出現使得這一問題得到了很好的解決。虛擬機技術的本質是硬件虛擬化,即每臺虛擬機事先從物理機分配好CPU核數、內存、磁盤等資源,每臺虛擬機通常只部署一個應用,不同的進程在不同的虛擬機上運行,從而解決了進程間資源隔離的問題。如圖1-10所示,一臺物理機會部署多個虛擬機,物理機上的所有虛擬機則依靠虛擬機管理系統進行管理。

圖1-10 虛擬機部署
虛擬機的出現使得用戶在一臺物理機上能夠獨立運行多個相互隔離的系統,通過對資源的抽象化使得主機資源能夠被有效復用,這對于企業降低成本十分有益。然而,虛擬機也會帶來一些問題。
(1)額外開銷
虛擬機部署的主要目的之一是減少物理服務器的數量,但它通常會導致采用更多的虛擬服務器。隨著虛擬機數量的增加,大量獨立系統開始運行,從而帶來許多額外開銷。IT生態系統中的其他組件(如存儲和網絡)也將受到新增容量的影響。此外,每當運行新的虛擬機時,都需要重新配置一遍環境,與在物理機上的情況基本無差異。重復的環境配置操作則會消耗開發和運維人員的工作時間。
(2)資源爭用
基于虛擬機管理系統,雖然可以對每個虛擬服務器進行資源分配調整,但如果其中一個虛擬機負擔過重,則仍然會影響運行在同一物理服務器上的其他虛擬機。例如對CPU周期、內存和帶寬等資源的爭用可能會嚴重影響系統響應。即使有足夠的資源,某些工作負載在虛擬機上的性能也可能不如在專用硬件服務器上運行時那么好。
(3)版本沖突
大應用集群的虛擬機第一次安裝時基本可以保障軟件的版本和庫依賴統一。但隨著時間的推移,開源軟件需要逐步升級,這個過程中,批量升級可能出現遺漏或升級失敗。此外,工程師可能會登錄服務器修改軟件的版本或配置,以滿足特定的需求。一段時間后,一個應用集群的虛擬機的軟件版本和配置就可能出現差異,導致線上故障。
3.容器化部署
為了解決虛擬機部署的不足,容器技術應運而生。容器化部署的本質是構建一個完整、獨立的運行環境,包含3個關鍵因素:環境隔離、資源控制和文件系統。2013年發布的Docker便是容器化部署的佼佼者,目前已成為首屈一指的容器平臺。它能提供輕量的虛擬化和一致性環境,允許將應用及其依賴的運行環境打包在一起,打包好的“集裝箱”(鏡像)能夠被分發到任何節點上執行,無須再進行配置環境的部署。如此一來就解決了開發和部署應用時環境配置的問題,規范了應用交付和部署,降低了部署測試的復雜度以及開發運維的耦合度,極大提升了容器移植的便利性,便于構建自動化的部署交付流程。
容器和虛擬機都是資源虛擬化發展的產物,但二者在架構上又有區別。虛擬機通過虛擬機管理系統(如Hypervisor)虛擬化主機硬件資源,然后構建客戶機操作系統,由宿主機進行程序管理。容器則直接運行于主機內核中,如圖1-11所示,應用在主操作系統的用戶空間上執行獨立任務,不需要從操作系統開始構建環境,賦予了應用從交付到部署再到運維的獨立性。

圖1-11 容器化部署
相較于虛擬機部署,容器化部署有以下優點。
(1)資源隔離
容器的本質是宿主機上的一個進程。Docker通過namespace實現了資源隔離,通過cgroups實現了資源限制。其中cgroups是Control Groups的縮寫,是Linux內核提供的一種可以限制、記錄、隔離進程組所使用的物理資源(如CPU、內存、I/O等)的機制。通過對資源進行隔離與限制,容器可以精確地為應用分配CPU、內存等資源,保證了應用間不會相互影響。
(2)高資源利用
相比于虛擬機,Docker不但啟動速度更快,所需的計算開銷更小,顯著提高了服務器的效率,而且遷移時更加輕量,得益于分層文件系統,開發者共享代碼更方便、快捷。容器沒有管理程序的額外開銷,它與底層共享操作系統,性能更加優異,系統資源負載更低,相比于傳統虛擬機,在同等條件下可以運行更多的應用實例,而且可以更充分地利用系統資源。
(3)高研發效率
容器化部署將應用相關的代碼與運行所需的全部環境、配置文件、依賴關系和庫等打包在一起?;谌萜魈峁┑沫h境一致性和標準化,一旦出現故障,系統可以快速回滾。相比于虛擬機鏡像,容器的壓縮和備份速度更快,鏡像可像普通進程一樣快速啟動。此外,工程師可以在一臺機器上啟動數百個相互隔離的容器,模擬現實場景進行測試。同時使用容器化部署,可以很方便地針對同一個項目生成多套不同的構建環境。
(4)版本控制
在應用集群部署時,每臺機器首先會拉取指定版本的鏡像文件,由于所有機器的鏡像文件一樣,因此容器的軟件版本相同。即使開發或運維中途修改了容器的軟件版本,但當容器銷毀時,軟件的改動也會隨容器的銷毀一起湮滅。當應用用已有的鏡像文件重新部署時,生成的容器與修改之前的容器完全一樣。容器如果要升級軟件版本,那就修改鏡像文件,這樣部署時集群內所有的機器重新拉取新的鏡像,軟件也跟著一起升級。軟件版本混亂的問題就得到了完美的解決。
(5)微服務架構基石
容器技術有助于將一個復雜的巨型應用拆分成一系列可以組合的松耦合服務。每個容器都可以被看作一個不同的微服務,可以獨立升級,而不需要考慮它們的同步?;谖⒎占軜?,工程師可專注于其所負責的微服務,而無須關注整個項目,降低了復雜度。與此同時,拆分開來的服務可重用,有助于提升研發效率,降低成本。此外,Docker支持多種編程語言,技術棧靈活,相對獨立的微服務還可按需擴縮容、多節點部署。
(6)可移植與易管理
由于鏡像不依賴主機的操作系統,因此具備良好的可移植性和跨平臺運行能力。在遷移的時候,無須重復安裝環境依賴。目前,越來越多的云平臺開始支持容器,使得應用程序在公有云、私有云中進行混合部署成為可能。借助于容器編排平臺如Kubernetes,容器化工作負載和服務的安裝、更新、調試、擴展、監控與日志等流程都可以實現自動化。
1.2.8 運維監控
運維監控對應用穩定運行、業務效果感知十分重要。日常運維監控一方面有助于預警、定位問題,從而令問題得以快速解決,避免影響擴大化,另一方面還可以幫助研發人員洞悉業務效果和發展趨勢,實現業務決策。
在互聯網企業,對于一個上線運行的產品,運維監控在其整個生命周期將一直存在。當產品用戶規模較小或業務場景較少時,運維監控通常由產品和研發兼任,甚至完全由研發負責;當產品的用戶量增長到一定規模或業務場景增加時,運維監控通常會逐步獨立出來,由專職人員負責。這類專職人員通常稱為SRE(Site Reliability Engineer,網站可靠性工程師)。對于服務端開發工程師,在運維監控方面,一般需要關注以下幾個方面。
(1)基礎監控
基礎監控即監控服務端應用部署的機器(通常是服務器集群)的系統指標,如CPU、負載、硬盤、內存、網絡等。監控這些指標并設置預警閾值,可以幫助工程師直觀地了解所負責應用系統的運行狀態,及時發現瓶頸并解決。
(2)服務監控
服務監控即對核心服務進行監控,重點指標包括平均耗時、成功率、調用來源、錯誤碼、調用量等。有了這些指標,一旦出現問題(如成功率下跌、耗時上漲等),工程師可以快速將問題排查范圍縮小到服務(接口)維度,此外還可以指導技術優化方向(如減少耗時、提高成功率等)。
(3)業務監控
業務監控即監控業務相關流程的關鍵節點(如商品查看、下單、退單等)和指標(如下單成功率、訂單總量等)。這類指標既有利于我們跟蹤業務發展趨勢,也有助于我們對業務進行相關分析并做出決策。
在實踐中,如何開展運維監控呢?基礎監控(CPU、負載、硬盤、內存、網絡等)一般可借助專業的監控工具(如Anturis、SeaLion、Icinga、Munin等),并非服務端開發工程師專長。事實上,對于服務端開發,最重要的依托是日志,如圖1-12所示。基于規范的日志可以快速構建、感知常用服務指標。站在業務角度,合理打印日志不僅能輔助定位問題原因,還可以多維度聚合分析各類場景。某種程度上,排查問題的過程,其本質就是日志結構化還原的過程。如果日志能結構化還原特定場景,那么該場景就能快速被定位。

圖1-12 基于日志監控可感知的信息