什麼是微服務?java
傳統的單機應用程序隨着應用規模和複雜度的增加,多個團隊在一個應用上進行開發,每當各個團隊須要修改代碼時,整個應用程序都須要從新構建、從新測試和從新部署。算法
而微服務容許將一個大型的應用分解爲具備嚴格職責定義的便於管理的組件系統,即分解和分離應用程序的功能,使它們徹底獨立,造成多個小的,鬆耦合的分佈式服務。編程
每一個微服務均可以獨立地去構建、部署和測試。json
微服務的特性:數組
1)、靈活性:能夠將解耦的服務進行組合和從新安排,以快速交付新的功能。一個正在使用的代碼單元越小,更改代碼越不復雜,測試部署代碼所需的時間越短。緩存
2)、有彈性:使應用程序在出現不可恢復的錯誤的狀況下可以優雅地降級服務器
3)、可伸縮性:解耦的服務能夠輕鬆地跨多個服務器進行水平分佈,從而能夠適當地對功能/服務進行伸縮網絡
一句話總結——小型的、簡單的和解耦的服務=可伸縮的、有彈性和靈活的應用程序。多線程
如何編寫健壯的服務?架構
1)、大小合適:如何確保正確地劃分微服務的大小,以免微服務承擔太多的職責?請記住,適當的大小容許快速更改應用程序,並下降整個應用程序中斷的整體風險。
2)、位置透明:在微服務應用程序中,多個服務實例能夠快速啓動和關閉時,如何管理服務調用的物理細節?
3)、有彈性
4)、可重複
5)、可伸縮
微服務拆分原則:
通常首先須要從總體上梳理公司的業務,包括過去、如今及將來預見幾年內的業務進展,梳理公司的發展戰略。
將業務模塊化,分解出各個業務模塊之間的依賴及業務模塊之間的邊界。按照業務邊界及業務之間的依賴順序進行系統拆分。
分佈式服務框架顯示需求:
RPC框架要有服務治理機制,通常來講,服務治理機制包括服務依賴梳理、負載均衡、服務分組灰度發佈、鏈路監控、服務質量統計、服務自動發現、自動下線與
服務註冊中心等功能。能夠簡單認爲RPC框架與服務治理結合起來,就構成了一套完整的分佈式服務框架。SOA架構最重要就是選擇一個合適的RPC框架。
分佈式服務框架整體架構和所需技術:
分佈式服務框架主要包括服務消費端、服務提供端、服務數據網絡傳輸的序列化與反序列化、服務數據的通訊機制、服務註冊中心、服務治理這幾個組成部分。
分佈式服務框架序列化與反序列化實現
序列化(Serialization)是將對象的狀態信息轉換爲可存儲或傳輸的形式過程。簡言之,把對象轉換爲字節序列的過程就是對象的序列化。
反序列化(Deserialization)是序列化的逆過程,將字節數組反序列化爲對象,把字節序列恢復爲對象的過程稱爲對象的反序列化。
序列化的好處:
1)、經過將對象序列化爲字節數組,使得不共享內存經過網絡鏈接的系統之間可以進行對象的傳輸。
2)、經過將對象序列化爲字節數組,可以將對象永久存儲到存儲設備
3)、解決遠程接口調用JVM之間內存沒法共享的問題
評估一個序列化算法優劣的兩個重要指標:
1)、序列化後碼流的大小
2)、序列化自己的速度及系統資源開銷大小(包括內存、CPU等)
Java默認序列化
Java的序列化主要經過對象輸出流java.io.ObjectOutputStream與對象輸入流java.io.ObjectInputStream來實現,被序列化的類須要實現Serializable接口。
使用transient聲明的字段,序列化機制會忽略該字段。
可是Java默認的序列化只支持Java語言,不支持跨語言,且性能欠佳,序列化後產生的碼流過大。
XML序列化框架
XML序列化的優點在於可讀性好,利於調試。由於使用標籤來表示數據,致使序列化後碼流大,並且效率不高。常見的實現有XStream與Java自帶的
XML序列化和反序列化兩種方式。
JSON序列化
JSON(JavaScript Object Notation)是一種輕量級的數據交換方式。相比XML,JSON的碼流更小,並且保留了XML可讀性好的優點。常見的JSON
序列化開源工具備:Jackson、fastjson、GSON。
fastjson要求序列化對象的屬性必須實現get/set方法才能完成對該屬性的序列化。fastjson的優點在於很是易用的API操做及高性能
Hessian序列化框架
Hessian是一個支持跨語言傳輸的二進制序列化協議。相比於Java默認的序列化機制,Hessian具備更好的性能與易用性,並且支持多種不一樣的語言。
實現分佈式服務框架服務的發佈與引入
Spring Boot
SpringBoot基於約定優於配置的理念,極大地簡化了利用Spring開發所需的各類配置工做,幾乎能夠作到零配置。並且Spring Boot是微服務實現中使用的
核心技術。Spring Boot經過簡化構建基於REST的微服務的核心任務,大大簡化了微服務開發。Spring Boot還極大地簡化了將HTTP類型的動詞(GET、PUT、
POST和DELETE)映射到URL、JSON協議序列化與Java對象的相互轉化,以及將Java異常映射回標準HTTP錯誤代碼的工做。
分佈式服務框架可以使用FactoryBean接口實現遠程服務的發佈與引入。
Spring中的FactoryBean接口:
public interface FactoryBean<T> { T getObject() throws Exception; 返回JavaBean的具體實例,若是isSingleton()返回true,則該實例將會放到Spring容器中單實例緩存池中 Class<?> getObjectType(); 返回Java Bean類型 boolean isSingleton(); 返回Java Bean對象實例是不是單例對象
}
Spring中獲取一個Bean實例的執行流程
AbstractBeanFactory#getBean 經過指定bean的名稱獲取Bean實例
AbstractBeanFactory#doGetBean 執行獲取Bean的具體邏輯
AbstractBeanFactory#getObjectForBeanInstance 直接返回beanInstance或者從FactoryBean獲取Bean實例
FactoryBeanRegistrySupport#getObjectFromFactoryBean 從FactoryBean獲取bean的實例
FactoryBeanRegistrySupport#doGetObjectFromFactoryBean 執行具體的從FactoryBean中獲取bean的邏輯
FactoryBean#getObject 調用FactoryBean接口的實現類的getObject方法,返回具體的Bean實例
咱們能夠自定義MyFactoryBean實現FactoryBean接口,在getObject方法中建立並返回bean的實例。在配置文件中class指定MyFactoryBean全路徑便可。
Spring支持集成RPC框架介紹:
Spring對常見的RPC框架提供了相應的集成支持,統一標準化了RPC服務發佈與引入編程模型,簡化了RPC服務及調用的開發流程,支持以下的遠程
調用技術:
1)、Remote Method Invocation(RMI):經過類RmiProxyFactory(引入服務)與類RmiServiceExporter(暴露服務)分別完成RMI服務的引入與發佈。
2)、HTTP Invoker:Spring提供的一種遠程調用技術,使用Java內置的序列化算法,以及經過HTTP協議進行數據的傳輸。相應的支持類是
HttpInvokerProxyFactoryBean和HttpInvokerServiceExporter。與RMI的相同點在於序列化算法相同,都是Java內置的序列化算法。不一樣點在於RMI
傳輸協議爲TCP/IP協議,而HTTP Invoker爲HTTP協議。HTTP協議傳輸性能低於TCP/IP協議,可是不會被防火牆攔截。
3)、Hessian:是一個輕量級的Web服務實現工具,它採用的是二進制協議,所以很適合發送二進制數據。它的一個基本原理就是把遠程服務對象以二進
制的方式進行發送和接收。Spring經過HessianProxyFactoryBean和HessianServiceExporter來完成基於Hessian序列化協議的服務的引入與發佈。
4)、JAX-WS:Spring經過JAX-WS提供對WS服務的支持。相似的提供了JaxWsClientFactoryBean和SimpleJaxWsServiceExporter來完成WS服務的
引入與發佈
5)、JMS:響應的支持類爲JmsInvokerProxyFactoryBean和JmsInvokerServiceExporter
這些xxxFactoryBean支持類都實現了FactoryBean接口。
分佈式服務框架底層通訊實現
通訊的本質是IO
Linux下實現的IO模型:
Linux的內核將全部外部設備都看作一個文件來操做,對一個文件的讀寫操做會調用內核提供的系統命令,返回一個file descriptor(fd,文件描述符)。對一個socket
的讀寫也會有相應的描述符,稱爲socket描述符。描述符就是一個數字,它執行內核中的一個結構體(文件路徑,數據區等一些屬性)。
由於程序運行在操做系統上,編程語言實現的IO操做API最終依賴於操做系統的IO實現。先理清阻塞、非阻塞、同步、異步這幾個概念:
阻塞:調用方發起調用請求,在沒有返回結果以前,調用方線程被掛起,出於一直等待狀態
非阻塞:與阻塞相對,調用方發起調用請求,當前線程不會等待掛起,而會當即返回。後續能夠經過輪詢等手段來獲取調用結果狀態。
同步:所謂同步,就是在發出一個功能調用時,在沒有獲得結果以前,該調用就不返回
異步:與同步相對,當一個異步過程調用發出後,調用者不會馬上獲得結果,經過回調等措施來處理這個調用。
Linux實現了5中IO模型
一、阻塞IO模型
默認狀況下,全部的文件操做都是阻塞的,在進程空間中調用recvform(recvform函數,用於從Socket套接口上接收數據),其系統調用直到數據包到達且被
複製到應用進程的緩衝區中或者發生錯誤才返回,在此期間會一直等待,進程在從調用recvform開始到它返回的整段時間內都是被阻塞的。
二、非阻塞IO模型
recvform從應用層到內核的時候,若是該緩衝區沒有數據的話,就直接返回一個EWOULDBLOCK錯誤,通常都是對非阻塞IO模型進行輪詢來檢查這個狀態,看
內核是否是有數據到來。
三、IO複用模型
Linux提供select/poll,進程經過將一個或多個fd傳遞給select或者poll系統調用,阻塞在select操做上,這樣select/poll能夠幫咱們偵測多個fd是否處於就緒狀態。
select/poll是順序掃描fd是否就緒,並且支持的fd數量有限,所以它的使用受到了一些制約。Linux還提供了一個epoll系統調用,epoll使用基於事件驅動的方式
代替順序掃描,所以性能更高。當有fd就緒時,當即回調函數rollback。
(Java核心類庫Selector就是基於epoll的多路複用技術實現)
四、信號驅動IO模型
首先開啓套接口信號驅動IO功能,並經過系統調用sigaction執行一個信號處理函數(此係統調用當即返回,進程繼續工做,它是非阻塞的)。當數據準備就緒時,
就爲該進程生成一個SIGIO信號,經過信號回調通知應用程序調用recvform來讀取數據,並通知主循環函數處理數據。(好了告訴我,我來處理,我先去忙)
五、異步IO
告知內核啓動某個操做,並讓內核在整個操做完成後(包括將數據從內核複製到用戶本身的緩衝區)通知咱們。與信號驅動模型的主要區別是:信號驅動IO是由內
核通知咱們什麼時候能夠開始一個IO操做;異步IO模型由內核通知咱們什麼時候已經完成。(等處理好了再告訴我)
IO多路複用技術:在IO編程過程當中,當須要同時處理多個客戶端接入請求時,能夠利用多線程或者IO多路複用技術進行處理。IO多路複用技術經過把多個IO的阻塞到
同一個select的阻塞上,從而可使系統在單線程的狀況下同時處理多個客戶端請求。並且與傳統的多線程模型比,最大的優點是開銷小,系統不須要建立新的額
外進程或這線程,也不須要維護這些進程和線程的運行,下降了系統的維護工做量,節省了系統資源。
分佈式服務框架服務治理
1)、服務的註冊與發現
2)、軟負載
3)、服務質量監控與服務指標數據採集(統計QPS,天天調用總量,響應時間等指標)
4)、記錄負責人
5)、服務分組路由(對某個服務升級以後,須要灰度發佈或者AB測試(一部分用A服務,另外一部分用B服務),要求服務有自動分組能力,
能夠將某個消費組的請求只打到對應的服務組上)
6)、服務依賴關係分析(理清依賴關係,自動畫出依賴關係圖,能夠正確安排系統發佈順序)
7)、服務降級:若某個非關鍵服務出錯率很高,對業務鏈路形成了影響,使用一鍵降級將該服務從調用鏈路中摘除
8)、服務權重調整:若某些機器配置好,有更高的吞吐能力,能支持更高的QPS,則對該機器配置更高的服務權重。
9)、服務調用鏈路追蹤:調用鏈路橫跨多個服務,多個應用的話,對每一次調用分配一個惟一的標識將服務之間的調用串聯起來,有助於排查線上問題