成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

微服務必須具備的 3 個基本功能!

開發 后端
在我們對微服務架構有了整體的認識,并且具備了服務化的前提后,一個完整的微服務請求需要涉及到哪些內容呢?一起來看看吧。

[[403423]]

 在我們對微服務架構有了整體的認識,并且具備了服務化的前提后,一個完整的微服務請求需要涉及到哪些內容呢?

這其中包括了微服務框架所具備的三個基本功能:

  •  服務的發布與引用
  •  服務的注冊與發現
  • 服務的遠程通信

服務的發布與引用

首先我們面臨的第一個問題是,如何發布服務和引用服務。具體一點就是,這個服務的接口名是啥,有哪些參數,返回值是什么類型等等,通常也就是接口描述信息。

常見的發布和引用的方式包括:

  •  RESTful API / 聲明式Restful API
  •  XML
  •  IDL

一般來講,不管使用哪種方式,服務端定義接口與實現接口都是必要的,例如: 

  1. @exa(id = "xxx" 
  2. public interface testApi {  
  3.     @PostMapping(value = "/soatest/{id}" 
  4.     String getResponse(@PathVariable(value = "id") final Integer index, @RequestParam(value = "str") final String Data);  
  5.     }  

具體實現如下: 

  1. public class testApiImpl implements testApi{  
  2.     @Override  
  3.     String getResponse(final Integer index, final String Data){  
  4.         return "ok"; 
  5.      }      

聲明式Restful API

這種常使用HTTP或者HTTPS協議調用服務,相對來說,性能稍差。

首先服務端如上定義接口并實現接口,隨后服務提供者可以使用類似restEasy這樣的框架通過servlet的方式發布服務,而服務消費者直接引用定義的接口調用。

除此之外還有一種類似feign的方式,即服務端的發布依賴于springmvc controller,框架只基于客戶端模板化http請求調用。這種情況下需接口定義與服務端controller協商一致,這樣客戶端直接引用接口發起調用即可。

XML

使用私有rpc協議的都會選擇xml配置的方式來描述接口,比較高效,例如dubbo、motan等。

同樣服務端如上定義接口并實現接口,服務端通過server.xml將文件接口暴露出去。服務消費者則通過client.xml引用需要調用的接口。

但這種方式對業務代碼入侵較高,xml配置有變更時候,服務消費者和服務提供者都需要更新。

IDL

IDL是接口描述語言,常用于跨語言之間的調用,最常用的IDL包括Thrift協議以及gRpc協議。例如gRpc協議使用Protobuf來定義接口,寫好一個proto文件后,利用語言對應的protoc插件生成對應server端與client端的代碼,便可直接使用。

但是如果參數字段非常多,proto文件會顯得非常大難以維護。并且如果字段經常需要變更,例如刪除字段,PB就無法做到向前兼容。

一些tips

不管哪種方式,在接口變更的時候都需要通知服務消費者。消費者對api的強依賴性是很難避免的,接口變更引起的各種調用失敗也十分常見。所以如果有變更,盡量使用新增接口的方式,或者給每個接口定義好版本號吧。

在使用上,大多數人的選擇是對外Restful,對內Xml,跨語言IDL。

一些問題

在實際的服務發布與引用的落地上,還會存在很多問題,大多和配置信息相關。例如一個簡單的接口調用超時時間配置,這個配置應該配在服務級別還是接口級別?是放在服務提供者這邊還是服務消費者這邊?

在實踐中,大多數服務消費者會忽略這些配置,所以服務提供者自身提供默認的配置模板是有必要的,相當于一個預定義的過程。每個服務消費者在繼承服務提供者預定義好的配置后,還需要能夠進行自定義的配置覆蓋。

但是,比方說一個服務有100個接口,每個接口都有自身的超時配置,而這個服務又有100個消費者,當服務節點發生變更的時候,就會發生100*100次注冊中心的消息通知,這是比較可怕的,就有可能引起網絡風暴。

服務的注冊與發現

假設你已經發布了服務,并在一臺機器上部署了服務,那么消費者該怎樣找到你的服務的地址呢?

也許有人會說是DNS,但DNS有許多缺陷:

  •  維護麻煩,更新延遲
  •  無法在客戶端做負載均衡
  •  不能做到端口級別的服務發現

其實在分布式系統中,有個很重要的角色,叫注冊中心,便是用于解決該問題。

使用注冊中心尋址并調用的過程如下:

  •  服務啟動時,向注冊中心注冊自身,并定期發送心跳匯報存活狀態。
  •  客戶端調用服務時,向注冊中心訂閱服務,并將節點列表緩存至本地,再與服務端建立連接(當然這兒可以lazy load)。發起調用時,在本地緩存節點列表中,基于負載均衡算法選取一臺服務端發起調用。
  •  當服務端節點發生變更,注冊中心能感知到后通知到客戶端。

注冊中心的實現主要需要考慮以下這些問題:

  •  自身一致性與可用性
  •  注冊方式
  •  存儲結構
  •  服務健康監測
  •  狀態變更通知

一致性與可用性

一個老舊的命題,即分布式系統中的CAP(一致性、可用性、分區容錯性)。我們知道同時滿足CAP是不可能的,那么便需要有取舍。常見的注冊中心大致分為CP注冊中心以及AP注冊中心。

CP注冊中心

比較典型的就是zookeeper、etcd以及consul了,犧牲可用性來保證了一致性,通過zab協議或者raft協議來保證一致性。

AP注冊中心

犧牲一致性來保證可用性,感覺只能列出eureka了。eureka每個服務器單獨保存節點列表,可能會出現不一致的情況。關注公眾號Java技術棧,在后臺回復:cloud,可以獲取我整理的 Spring Cloud 系列教程,非常齊全。

從理論上來說,僅用于注冊中心,AP型是遠比CP型合適的。可用性的需求遠遠高于一致性,一致性只要保證最終一致即可,而不一致的時候還可以使用各種容錯策略進行彌補。

保障高可用性其實還有很多辦法,例如集群部署或者多IDC部署等。Consul就是多IDC部署保障可用性的典型例子,它使用了wan gossip來保持跨機房狀態同步。

注冊方式

有兩種與注冊中心交互的方式,一種是通過應用內集成sdk,另一種則是通過其他方式在應用外間接與注冊中心交互。Spring Boot 系列教程整理好了:https://github.com/javastacks/spring-boot-best-practice

應用內

這應該就是最常見的方式了,客戶端與服務端都集成相關sdk與注冊中心進行交互。例如選擇zookeeper作為注冊中心,那么就可以使用curator sdk進行服務的注冊與發現。

應用外

consul提供了應用外注冊的解決方案,consul agent或者第三方Registrator可以監聽服務狀態,從而負責服務提供者的注冊或銷毀。而Consul Template則可以做到定時從注冊中心拉取節點列表,并刷新LB配置(例如通過Nginx的upstream),這樣就相當于完成了服務消費者端的負載均衡。

存儲結構

注冊中心存儲相關信息一般采取目錄化的層次結構,一般分為服務-接口-節點信息。

同時注冊中心一般還會進行分組,分組的概念很廣,可以是根據機房劃分也可以根據環境劃分。

節點信息主要會包括節點的地址(ip和端口號),還有一些節點的其他信息,比如請求失敗的重試次數、超時時間的設置等等。

當然很多時候,其實可能會把接口這一層給去掉,因為考慮到接口數量很多的情況下,過多的節點會造成很多問題,比如之前說的網絡風暴。

服務健康監測

服務存活狀態監測也是注冊中心的一個必要功能。在zookeeper中,每個客戶端都會與服務端保持一個長連接,并生成一個session,在session過期周期內,通過客戶端定時向服務端發送心跳包來檢測鏈路是否正常,服務端則重置下次session的過期時間,如果session過期周期內都沒有檢測到客戶端的心跳包,那么就會認為它已經不可用了,將其從節點列表中移除。

狀態變更通知

在注冊中心具備服務健康檢測能力后,還需要將狀態變更通知到客戶端。在zookeeper中,可以通過監聽器watcher的process方法來獲取服務變更。

服務的遠程通信

在上面,服務消費者已經正確引用了服務,并發現了該服務的地址,那么如何向這個地址發起請求呢?要解決服務間的遠程通信問題,我們需要考慮一些問題:

  •  網絡I/O的處理
  •  傳輸協議
  •  序列化方式

網絡I/O的處理

簡單來說,就是客戶端是怎么處理請求?服務端又是怎么處理請求的?關注公眾號Java技術棧,在后臺回復:面試,可以獲取我整理的 Java 網絡編程系列面試題和答案,非常齊全。

先從客戶端來說,我們創建連接的時機可以是從注冊中心獲取到節點信息的時候,但更多時候,我們會選擇在第一次請求發起調用的時候去創建連接。此外,我們往往會為該節點維護一個連接池,進行連接復用。

如果是異步的情況下,我們還需要為每一個請求編號,并維護一個請求池,從而在響應返回時找到對應的請求。當然這并不是必須的,很多框架會幫我們干好這些事情,比如rxNetty。

從服務端來說,處理請求的方式就可以追溯到unix的5種IO模型了。我們可以直接使用Netty、MINA等網絡框架來處理服務端請求,或者如果你有十分的興趣,可以自己實現一個通信框架。

傳輸協議

最常見的當然是直接使用Http協議,使用雙方無需關注和了解協議內容,方便直接,但自然性能上會有所折損。

還有就是目前比較火熱的http2協議,擁有二進制數據、頭部壓縮、多路復用等許多優良特性。但從自身的實踐上看,http2要走到生產仍有一段距離,一個最簡單的例子,升級到http2后所有的header names都變成小寫,同時不是case-insenstive了,這時候就會有兼容性問題。

當然如果追求更高效與可控的傳輸,可以定制私有協議并基于tcp進行傳輸。私有協議的定制需要通信雙方都了解其特性,設計上還需要注意預留好擴展字段,以及處理好粘包分包等問題。

序列化方式

在網絡傳輸的前后,往往都需要在發送端進行編碼,在服務端進行解碼,這樣主要是為了在網絡傳輸時候減少數據傳輸量。

常用的序列化方式包括文本類的,例如XML/JSON,還有二進制類型的,例如Protobuf/Thrift等。在選擇序列化的考慮上,一是性能,Protobuf的壓縮大小和壓縮速度都會比JSON快很多,性能也更好。二是兼容性上,相對來說,JSON的前后兼容性會強一些,可以用于接口經常變化的場景。

在此還是需要強調,使用每一種序列化都需要了解過其特性,并在接口變更的時候拿捏好邊界。例如jackson的FAIL_ON_UNKNOW_PROPERTIES屬性、kryo的CompatibleFieldSerializer、jdk序列化會嚴格比較serialVersionUID等等。 

 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2010-06-28 21:33:17

eMule協議

2019-04-16 08:21:46

2020-10-19 10:16:02

AWSDynamoDB功能

2010-04-16 09:06:18

WPF 4

2012-10-22 16:47:45

IBMdw

2010-01-05 15:27:04

.NET Framew

2010-03-02 17:43:31

WCF框架處理流程

2019-09-16 08:22:12

特權訪問管理PAM網絡安全

2015-07-07 14:17:56

物聯網操作系統

2011-04-19 10:17:25

2009-03-04 10:30:00

2010-01-20 18:20:50

2023-05-11 08:59:43

Nginx配置服務器

2010-01-04 10:47:08

智能交換機

2009-12-03 09:08:21

路由器基本功能

2017-01-15 17:15:27

Java基本功能

2011-04-29 14:04:56

一體機

2015-11-09 10:34:54

iOS 9.1 iPhone

2010-02-03 09:59:18

2009-12-08 13:58:12

Linux操作系統垃圾郵件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品区 | 日韩av一区二区在线观看 | 日韩一区二区不卡 | 日韩性生活网 | 中文字幕高清av | 亚洲欧美日韩电影 | 九九久久久 | 久久大陆 | 亚洲夜夜爽 | 日韩久久成人 | 日本中文字幕在线视频 | 午夜影院在线 | 欧美久久一区 | 日韩欧美国产一区二区三区 | 国产精品夜夜春夜夜爽久久电影 | 国产精品毛片无码 | 五月婷婷激情网 | 精品一区精品二区 | 久久毛片 | 欧美日韩综合视频 | 久久专区 | 成人久久 | 911网站大全在线观看 | 久久婷婷国产香蕉 | 久久久性 | 日韩欧美一区二区三区四区 | 午夜在线观看视频 | 久久精品国内 | av网址在线| 日日碰狠狠躁久久躁婷婷 | 久在线 | 美女国内精品自产拍在线播放 | 成人三级视频在线观看 | xx性欧美肥妇精品久久久久久 | 香蕉一区 | 国产欧美一区二区三区日本久久久 | 日韩有码在线播放 | 精品一区二区久久久久久久网站 | 亚洲免费一 | 免费黄色av网站 | 久久久久久免费毛片精品 |