精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從 0 開始構建一個億級請求的微服務架構

新聞 架構
本文講述了如何從 0 開始構建一個億級請求的系統的歷程,其中包括了服務拆分、微服務測試、容量預估以及上線的流程。穩定的系統不僅要依賴好的架構設計,而且需要對核心代碼,高頻訪問模塊精雕細琢。

 單體應用因其架構簡單、使用技術門檻低、研發快速上手、項目快速上線等特點是創業公司初級階段的必然產物。隨著平臺用戶規模的遞增,產品功能的豐富以及需求迭代的頻率也會加速,相對應的研發人數也逐步遞增,系統的性能問題、研發人員之間的協作問題、交付速度等一系列的問題就慢慢凸顯,這些問題會逐步演化成阻礙項目推進的“絆腳石”。此時微服務的出現似乎是一根救命稻草,但凡遇到系統性能、項目交付質量、項目進度等問題的時候就開始準備系統重構,認為往微服務方向轉型就一定能解決這些面臨的問題。那么一個在企業在單體應用架構中到底如何轉型微服務呢?在轉型之前還需要去了解下實施微服務的一些前置條件。

本文是根據潘志偉老師在 ArchSummit 全球架構師峰會上的演講整理出來的,講述了如何從 0 開始構建一個億級請求的系統的歷程,其中包括了服務拆分、微服務測試、容量預估以及上線的流程。穩定的系統不僅要依賴好的架構設計,而且需要對核心代碼,高頻訪問模塊精雕細琢,看似不起眼的一些小優化,長期積累起來就會有質的變化,正所謂細節決定成敗,做架構也是同樣的到底。

1. 微服務實施的前置條件

很多技術人員在聽到企業技術架構要轉型,打算從單體架構往微服務架構轉型,得知消息后就異常的興奮,認為自己馬上又能學到新的技術了,開始去關注到底是選型哪種技術架構,并運行框架提供的 Demo,認為成功運行 Demo 就具備了實施微服務的條件了,等待公司一聲令下,就踏上微服務之旅了。其實這是一種典型的技術人員考慮事情的思維,通過過往的經驗來看,更重要的是在實施微服務之前全員統一思想、充分培訓、 以及工程結構標準化。

統一思想: 因為在準備實施微服務的時候,首要條件就是獲得高層的認可,因為涉及到組織結構的調整以及后續人力資源的增補,另外在新架構上線后難免會出現問題,這個時候需要得到高層的支持。另外,在單體應用中其組織機構包括開發部、測試部、運維部、DBA 部,每個部門各司其職由高層統一指揮,看似很非常合理的組織結構,但是在項目或者迭代實際過程中會花費大量的時間去跨部門溝通,形成了孤島式功能團隊。

充分培訓: 微服務架構的開發人員具備“精”、“氣”、“神”的特質,否則在后續發展階段一定會出現各種難題。“精”是指熟悉業務,熟悉選型的開發框架,而不僅限完成 demo 運行,必須要熟悉原理,最好能熟悉源碼,做到面對問題不慌,“氣”是指大家對微服務架構這件事情的思想認知一致,能夠在一個頻道上對話,“神”是指需要了解其理論知識,比如什么是服務治理,什么是服務自治原則,明白為什么需要這樣而不是那樣。

工程結構標準化: 所有服務交付服務,從代碼風格比如類的命名,module 命名以及啟動方式都是一致的,減少研發人員對于未知的未知而產生的擔心。

在正式開始微服務之前,有必要了解下云原生的 12 要素,它針對微服務的一些設計思想做了充分的歸納和總結,云原生 12 要素的內容如下:

  • 基準代碼:一份基準代碼(Codebase),多份部署(deploy)
  • 依賴:顯式聲明依賴關系
  • 配置:在環境中存儲配置
  • 后端服務:把后端服務 (backing services) 當作附加資源
  • 構建、發布、運行:嚴格分離構建和運行
  • 進程:以一個或多個無狀態進程運行應用
  • 端口綁定:通過端口綁定 (Port binding) 來提供服務
  • 并發:通過進程模型進行擴展
  • 易處理(快速啟動和優雅終止可最大化健壯性)
  • 環境等價:開發環境與線上環境等價
  • 日志
  • 管理進程

其中第一條需要特別注意,它要求基準代碼或者軟件制品只允許有一份,可以部署到多個環境,不因為環境的改變而需要重新編譯或者針對不同的環境編譯多個制品。記住,測試即交付的原則,即你測試的軟件制品和交付到生產的軟件制品是一樣的。重點強調環境配置和制品庫分離,如果是測試環境的配置,那么軟件運行起來就是測試環境,如果是生產環境的配置,那么軟件運行起來就是生產環境。發現很多程序員都喜歡把配置文件寫到工程里面,例如 application-dev.properties、application-test.properties、application-prod.properties 等,然后在系統啟動的時候增加 spring.profiles.active=dev 來說明環境,其實這種做法是非常的不優雅,首先違背了云原生 12 要素第一個條件,其次測試環境、生成環境的所有的配置信息都暴露在代碼中,容易導致信息泄露,最后增加運維部署難度,一旦環境變量標識錯誤就會導致軟件運行失敗。

从 0 开始构建一个亿级请求的微服务架构

總結為三條:切實需要使用微服務來解決實際問題;組織結構思想認知一致;前期有完善系統性針對微服務的培訓。

2. 微服務實施的具體步驟

有些人認為使用 Dubbo 或者 SpringCloud 把系統內部接口調用換成 RPC 或者 Rest 調用,就完成了微服務改造了,其實這是只是微服務的冰山一角,完整的去實施微服務必須從全局考慮統一規劃,包括前后端分離,服務無狀態、統一認證以及運維體系的調整等。

前后端分離: 是指前端和后端的代碼分離,前端負責 HTML 頁面的編寫以及邏輯跳轉,后端負責提供數據接口給前端,前后端開發人員可以并行開發。前端對跳轉邏輯和 UI 交互負責,后端對接口的高可用負責。前端 html 層使用 VUE 框架,node.js 可以起到邏輯跳轉的控制,前后端通信采用 rest 方式,json 數據格式通信。前后端分離后的好處總結來說包含如下:

  • 各端的專家來對各自的領域進行優化,以滿足用戶體驗優化效果最優化;
  • 前后端交互界面更加清晰,采用接口方式通信,后端的接口簡潔明了,更容易維護;
  • 前端多渠道集成場景更容易擴展,采用統一的數據和模型,可以支撐前端的 web UI 移動 App 等訪問,后端服務不需要改動;

从 0 开始构建一个亿级请求的微服务架构

服務無狀態: 是指該服務運行的實例不會在本地存執行有狀態的存儲,例如不存儲需要持久化的數據,不存儲業務上下文信息,并且多個副本對于同一個請求響應的結果是完全一致的,一般業務邏輯處理都被會定義為無狀態服務。

記得在微服務重構的初級階段發生過一次特別有代表性的線上故障,有個研發人員負責驗證碼登陸模塊開發,把驗證碼存入了本地緩存中,由于我們開發、測試環境都是單實例部署,所以并沒有發現問題,當線上是多實例部署,所以會導致大量用戶登陸失敗的場景。這個線上故障的核心問題點在于沒有清楚的認識無狀態服務和有狀態服務的的使用場景。

从 0 开始构建一个亿级请求的微服务架构

統一認證: 統一認證與授權是開始實施服務化的最基礎條件,也是最基礎的一項應用。在過去的單體應用中,可以基于攔截器和 Session 實現基本的登錄與鑒權。在微服務架構中,服務都被設計為無狀態模式,顯然攔截器和 Session 模式已經不符合架構要求了,需要由統一認證服務來完成認證鑒權以及和第三方聯合登陸的要求,我們使用 token 機制來做統一認證,主要流程如下:

  • 用戶輸入用戶名和密碼提交給認證服務鑒權;
  • 認證服務驗證通過后生成 token 存入分布式存儲;
  • 把生成的 token 返回給調用方;
  • 調用方每次請求中攜帶 token,業務系統拿到 token 請求認證服務;
  • 認證服務通過后業務系統處理業務邏輯并返回最終結果。

从 0 开始构建一个亿级请求的微服务架构

完成前后端分離,服務無狀態改造、統一認證處理后, 基本上完成了微服務輪廓的改造。接下來就需要去識別單體應用最需要改造成微服務的模塊,推薦是一個模塊甚至一個接口這樣的進度去拆分單體應用,而不建議一次性全部重構完畢。

3. 服務拆分理論和原理及方法

談到微服務,議論的最多,吵架的最多的就是服務拆分問題,服務拆分是否合理直接影響到微服務架構的復雜性、穩定性以及可擴展性。然而并沒有任何一本書籍或者規范來介紹如何拆分服務,那么如何正確的做服務的拆分? 目前各家做法也都是根據架構師經驗以及業務形態和用戶規模等因素綜合考慮。在工作中曾經遇到以下二種服務拆分的模式:

  • 一個方法一個服務:視業務規模和業務場景而定;
  • 基于代碼行數的劃分:簡單粗暴,不推薦;

有人說按方法拆分服務太過于細致,應該要按業務功能來拆。其實當業務達到一定規模的時候,按方法拆分是一種非常有效的做法,以用戶服務舉例,在初始階段的時候,用戶服務具備了用戶的增刪改查功能,當用戶規模上升之后需要對增刪改查功能做優先級劃分。大家都知道在互聯網中流量獲客是最貴的,運營團隊通過互聯網投放廣告獲客,用戶在廣告頁上填寫手機號碼執行注冊過程,如果此時注冊失敗或者注冊過程響應時間過長,那么這個客戶就可能流失了,但是廣告的點擊費用產生了,無形中形成了資源的浪費。所以此時需要按方法維度來拆分服務,把用戶服務拆分為用戶注冊服務(只有注冊功能),用戶基礎服務(修改、查詢用戶信息)。

在做服務拆分的時候,每個服務的團隊人數規模也是非常重要的,人數過多可能會變成單體應用,溝通決策會緩慢,人數太少工作效率又會降低,一般來說會遵循 2 個披薩原則和康威定律:

2 個披薩原則: 兩個披薩原則最早是由亞馬遜 CEO 貝索斯提出的,他認為如果兩個披薩不足以喂飽一個項目團隊,那么這個團隊可能就顯得太大了,所以一個服務的人數劃分為 5-7 人比較合適。因為人數過多的項目將不利于決策的形成,而讓一個小團隊在一起做項目、開會討論,則更有利于達成共識,并能夠有效促進企業內部的創新。

康威定律: 你想要架構成為什么樣,就將團隊分成怎樣的結構。比如前后端分離的團隊,架構就是基于前后端分離。在基于微服務設計的團隊里,一個很好的理念是自管理,團隊內部對于自己所負責的模塊高度負責,進行端對端的開發以及運維。

整個單體應用有那么多的功能,到底哪些業務功能需要拆分,哪些業務功能又不需要拆分呢?可以遵循服務拆分的方法論:當一塊業務不依賴或極少依賴其它服務,有獨立的業務語義,為超過 2 個或以上的其他服務或客戶端提供數據,應該被拆分成一個獨立的服務模,而且拆分的服務要具備高內聚低耦合。

从 0 开始构建一个亿级请求的微服务架构

關于服務拆分模式,使用比較多的是業務功能分解模式和數據庫模式,因為容易理解而且使用起來比較簡單,效果也很好。

業務功能分解模式: 判斷一個服務拆分的好壞,就看微服務拆分完成后是否具備服務的自治原則,如果把復雜單體應用改造成一個一個松耦合式微服務,那么按照業務功能進行分解是最簡單的,只需把業務功能相似的模塊聚集在一起。比如:

  • 用戶管理:管理用戶相關的信息,例如注冊、修改、注銷或查詢、統計等。
  • 商品管理:管理商品的相關信息。
  • 數據庫模式:在微服務架構中,每個服務分配一套單獨的數據庫是非常理想方案,這樣就緩解了單個數據庫的壓力,也不會因為某個數據庫的問題而導致整個系統出現問題。

微服務初始階段服務拆分不需要太細,等到業務發展起來后可以再根據子域方式來拆分,把獨立的服務再拆分成更小的服務,最后到接口級別服務。如果服務拆分的過小會導致調用鏈過長,以及引發沒有必要的分布式事務,此時階段性的合并非常重要。做為架構師不僅要學會拆分服務,也需要學會合并服務,需要周期性的去把拆分過小或者拆分不合理的服務要及時合并。

總得來說,在服務拆分的時候需要抓住以下重點:

  • 高內聚的拆分模式
  • 以業務為模塊拆分
  • 以迭代頻率和改動范圍拆分
  • 階段性合并
  • 定期復盤總結

4. 代碼結構如何做到提高研發效率

曾經有一項調查,當一個程序員到新公司或者接手項目最怕的事情是什么,超過 90% 的人的都認為最怕接手其他人的項目。從心理學角度來看,這個結果非常正常,害怕是因為對即將接手項目的未知,不清楚項目如何啟動,不清楚代碼是如何分層。大家試想看,當一個單體應用被劃分為 N 多個服務的時候,每個服務啟動方式,代碼層次各不相同,如何去維護呢?所以微服務啟動階段,首先要做的事情就是工程結構標準化和自動化,讓研發人員的重點精力去做業務,而不是去搭建框架。因此基于 velocity 自定義了一套微服務代碼自動生成框架,研發人員設計好表結構之后,框架根據表結構自動生成服務代碼,包含 API 接口,實現類,DAO 層以及 Mybatis 的配置文件,類的名稱,包名、module 名稱都有嚴格的定義。以用戶服務為例,生成后的代碼格式如下:

  1. basics-userservice 
  2. basics-userservice-api 
  3. basics-userservice-business 
  4. basics-userservice-façade 
  5. basics-userservice-model 
  6. basics-userservice-service 

為了讓研發效率更快,架構更清晰,又從架構層面把代碼再拆分為聚合服務層和原子服務層,每一層對應的功能不一樣。

  • 聚合層:收到終端請求后,聚合多個原子服務數據,按接口要求把聚合后的數據返回給終端,需要注意點是聚合層不會和數據庫交互;
  • 原子服務層:數據庫交互,實現數據的增刪改查,結合緩存和工具保障服務的高響應;要遵循單表原則,禁止 2 張以上的表做 jion 查詢,如有分庫分表,那么對外要屏蔽具體規則。

需要說明的是,聚合層和業務比較貼近,需要了解業務更好的服務業務,和 App 端交互非常多,重點是合理設計的前后端接口,減少 App 和后端交互次數。原子服務則是關注性能,屏蔽數據庫操作,屏蔽分庫分表等操作。

从 0 开始构建一个亿级请求的微服务架构

最后還得提下系統日志,日志記錄的詳細程度直接關系到系統在出現問題時定位的速度, 同時也可以通過對記錄日志觀察和分析統計,提前發現系統可能的風險,避免線上事故的發生。對于服務端開發人員來說,線上日志的監控尤其重要,能夠通過日志第一時間發現線上問題并及時解決。然而通過觀察收集后的日志信息內容的時候才發現日志規范這塊內容一直都沒有重視過,記日志永遠看心情,日志記錄的內容也是憑感覺。因此在實施微服務的之前,必須要先確定日志的規范,為了便于后面的日志采集、處理和分析。例如統一約定日志格式如下:

  • 時間|事件名稱|traceID|耗時時間|用戶 ID|設備唯一標識|設備類型|App 版本|訪問 IP|自定義參數
  • 時間:日志產生時候系統的當前時間,格式為 YYYY-MM-DD HH:MM:SS;
  • 事件名稱:預先定義好的枚舉值,例如 Login、Logout、search 等;TraceID:當前請求的唯一標識符;
  • 耗時時間:當前事件執行完成所消耗的時間;
  • 用戶 ID:當前登陸用戶的唯一 ID,非登陸用戶為空;
  • 設備唯一標識:當前設備的唯一標識,假如某用戶登錄前開始操作 App,這個時間記錄下設置唯一標識后,可以通該標識關聯到具體用戶;
  • 設備類型:當前設備的類型,如 Android 或者 iOS;
  • App 版本:當前訪問設置的 App 版本號;
  • 訪問 IP:當前設備所在 IP 地址;
  • 自定義參數用:自定義參數,參數之間使用 & 分割,例如 pid=108&ptag=65

工程結構、代碼框架和日志在開發過程中最容易被忽略的,但卻非常的重要,前期合理的規劃有助于規?;茝V的時候減輕壓力,在規劃階段要重點關注以下內容:

  • 代碼未編工具先行;
  • 統一微服務工程結構;
  • 統一服務啟動方式(jar war);
  • 統一緩存調用方式(架構封裝統一提供 jar 包和底層存儲無關);
  • 統一 MQ 調用方式(架構封裝統一提供 jar,和具體 MQ 類型無關) ;
  • 統一日志格式;
  • 統一多服務依賴調用方式 (串行調用方式、并行調用方式);
  • 統一熔斷、降級處理流程;

5. 架構“三板斧”如何切入到微服務框架中

要提高系統穩定性,那么好的設計、精心打磨代碼、運維監控這 3 個環境必不可少。例如在產品詳情頁這個功能上,聚合層會調用原子服務 26 個 RPC 接口,為了降低客戶端的響應時間,在設計第一版的時候把聚合后的結果放入到分布式緩存中,但是用戶訪問高峰期的時候分布式緩存 QPS 非常高,會一定程度上影響系統的性能,而且一旦緩存失效又需要再次調用這些 RPC 接口,響應時間變長。為了更精細化使用緩存,使用了二級緩存設計思路,仔細分析這些接口后發現,數據的緩存失效時間可以設置不同的時間,沒必要整體過期,接口請求的時候先默認使用本地緩存,當本地緩存失效后再調用 RPC 接口,這樣可以有效的降低 RPC 接口調用次數。

在使用緩存的時候不可避免的會遇到緩存穿透、緩存擊穿、緩存雪崩等場景,針對每種場景的時候需要使用不同的應對策略,從而保障系統的高可用性。

緩存穿透: 是指查詢一個一定不存在緩存 key,由于緩存是未命中的時候需要從數據庫查詢,正常情況下查不到數據則不寫入緩存,就會導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透, 有 2 個方案可以解決緩存穿透:

方案 1:可以使用布隆過濾器方案,系統啟動的時候將所有存在的數據哈希到一個足夠大的 bitmap 中,當一個一定不存在的數據請求的時候,會被這個 bitmap 攔截掉,從而避免了對底層數據庫的查詢壓力

方案 2:返回空值:如果一個查詢請求查詢數據庫后返回的數據為空(不管是數據不存在,還是系統故障),仍然把這個空結果進行緩存,但它的過期時間會很短,比如 1 分鐘,但是這種方法解決不夠徹底。

緩存擊穿: 緩存 key 在某個時間點過期的時候,剛好在這個時間點對這個 Key 有大量的并發請求過來,請求命中緩存失敗后會通過 DB 加載數據并回寫到緩存,這個時候大并發的請求可能會瞬間把后端 DB 壓垮,解決方案也很簡單通過加鎖的方式讀取數據,同時寫入緩存。

緩存雪崩: 是指在設置緩存時使用了相同的過期時間,導致緩存在某一時刻同時失效,所有的查詢都請求到數據庫上,導致應用系統產生各種故障,這樣情況稱之為緩存雪崩,可以通過限流的方式來限制請求數據庫的次數。

从 0 开始构建一个亿级请求的微服务架构

緩存的使用在一定程度上可以提高系統的 QPS,但是上線后還是發現偶爾會出現超時的問題,假設每個服務響應時間為 50 毫秒,那么 26*50=1300 毫秒,已經超過了設置 1 秒超時時間,為解決偶發性超時問題,就需要把串行的調用調整為并行調用:

線程池并行調用: 為了提高接口響應時間,把之前串行調用方式修改為把請求封裝為各種 Future 放入線程池并行調用,最后通過 Future 的 get 方法拿到結果。這種方式暫時解決了詳情頁訪問速度的問題,但是運行一段時間后發現在并發量大的時候整個聚合層服務的 Tomcat 線程池全部消耗完,出現假死的現象。

服務隔離并行調用: 由于所有調用外部服務請求都在同一個線程池里面,所以任何一個服務響應慢就會導致 Tomcat 線程池不能及時釋放,高并發情況下出現假死現象。為解決這個問題,需要把調用外部每個服務獨立成每個線程池,線程池滿之后直接拋出異常,程序中增加各種異常判斷,來解決因為個別服務慢導致的服務假死。

線程隔離服務降級: 方式 2 似乎解決了問題,但是并沒有解決根本問題。響應慢的服務仍然接收到大量請求,最終把基礎服務壓垮,需要判斷當服務異常超過一定次數之后,就直接返回設置好的返回值,而不用去調用 RPC 接口。這時候程序中存在大量判斷異常的代碼,判斷分支太多,考慮不完善接口就會出差。

从 0 开始构建一个亿级请求的微服务架构

在進行服務化拆分之后,系統中原有的本地調用就會變成遠程調用,這樣就引入了更多的復雜性。比如說服務 A 依賴于服務 B,這個過程中可能會出現網絡抖動、網絡異常,服務 B 變得不可用或者響應慢時,也會影響到 A 的服務性能,甚至可能會使得服務 A 占滿整個線程池,導致這個應用上其它的服務也受影響,從而引發更嚴重的雪崩效應。所以引入了 Hystrix 或 Sentinel 做服務熔斷和降級;需要針對如下幾項做了個性化配置:

  • 錯誤率:可以設置每個服務錯誤率到達制定范圍后開始熔斷或降級;
  • 人工干預:可以人工手動干預,主動觸發降級服務;
  • 時間窗口:可配置化來設置熔斷或者降級觸發的統計時間窗口;
  • 主動告警:當接口熔斷之后,需要主動觸發短信告知當前熔斷的接口信息。

从 0 开始构建一个亿级请求的微服务架构

雖然服務拆分已經解決了模塊之間的耦合,大量的 RPC 調用依然存在高度的耦合,不管是串行調用還是并行調用,都需要把所依賴的服務全部調用一次。但是有些場景不需要同步給出結果的,可以引入 MQ 來降低服務調用之間的耦合。例如用戶完成注冊動作后需要調用優惠券服務發放優惠券,在調用積分服務發放積分,還需要初始化財務模塊,再計算營銷活動,最后需要把本次注冊信息上報給信息流,這種做法帶來了 2 個問題,第一個問題是整個注冊鏈路太長,容易發生失敗,第二個問題,任何依賴用戶注冊行為的服務都需要修改服務注冊接口。但是使用 MQ 解耦就非常簡單了,只需要往 MQ 發送一個注冊的通知消息,下游業務如需要依賴注冊相關的數據,只需要訂閱注冊消息的 topic 即可,從而實現了業務的解耦。使用 MQ 的好處包括以下幾點:

  • 解耦:用戶注冊服務只需要關注注冊相關的邏輯,簡化了用戶注冊的流程;
  • 可靠投遞:消息投遞由 MQ 來保障,無需程序來保障必須調用成功;
  • 流量削峰:大流量的新用戶注冊,只需要新增用戶服務,并發流量由 MQ 來做緩沖,消費方通過消費 MQ 來完成業務邏輯;
  • 異步通信(支持同步):由于消息只需要進入 MQ 即可,完成同步轉異步的操作;
  • 提高系統吞吐、健壯性:調用鏈減少了,系統的健壯性和吞吐量提高了;

日常開發中,對于 MQ 做了如下約定:

  • 應用層必須支持消息冪等
  • 支持消息回溯
  • 支持消息重放
  • 消息的消費的機器 IP 以及消息時間

从 0 开始构建一个亿级请求的微服务架构

緩存、并行調用、消息隊列這些手段都使用上之后,系統的穩定性也是有了質的提升,超時現象也極少發生。隨著業務的高速發展,每周上線的功能也是逐步增多,每個業務都會需要鑒權、限流、驗簽等邏輯,需要每個聚合服務都需要根據規則自己實現一遍,權限認證每個模塊各自處理,狀態碼各種各樣,比如接口返回需要重新登陸狀態碼,有些服務返回 code=-8,有些則返回 code=-1;前端根據每個業務模塊來匹配解析不同的驗證碼,在上線的發版時候出現一些有趣的現象,很多人圍著運維在修改 Nginx 的配置,此時開發又遇到了新的瓶頸:

  • 上線新接口需要運維在 Nginx 中配置
  • 接口復用性不高
  • 權限認證每個模塊各自處理,狀態碼各種各樣
  • 限流熔斷降級各自處理
  • 開發效率不高
  • 接口文檔沒有最新的,誰負責的接口無人知道

為此使用 Netty 框架和 Dubbo 泛化功能自研了一套網關,在網關上集成了用戶權限認證、限流、熔斷降級等功能,讓業務開發人員只關心業務實現,而無需關注非業務。

網關可以理解為一個反向路由,它屏蔽內部細節,為調用者提供統一入口,接收所有調用者請求,通過路由機制轉發到服務實例,同時網關也是“過濾器”集合,可以實現一系列與業務無關的橫切面功能,如安全認證、限流熔斷、日志監控,同時網關還有如下特性:

協議轉換: 將不同的協議轉換成“通用協議”,然后再將通用協議轉化成本地系統能夠識別的協議,例如把 HTTP 協議統一轉換為 Dubbo 協議。

鏈式處理: 消息從第一個插件流入,從最后一個插件流出,每個步驟的插件對經過的消息進行處理,整個過程形成了一個鏈條。優勢在于它將處理請求和處理步驟分開,每個處理的插件,只關心這個插件上需要做的處理操作,處理步驟和邏輯順序由“鏈”來完成。

異步請求: 所有的請求都會通過 API 網關訪問應用服務,無論業務量如何變化,網關的吞吐量要保持穩定狀態。

从 0 开始构建一个亿级请求的微服务架构

在架構層面把網關分為接入層、分發層和監控層,網關和后端服務通信使用 Dubbo 的泛化方式,負載均衡也直接使用 Dubbo 默認的隨機策略。

  • 接入層:負責接收客戶端請求,調度、加載和執行組件,把非法請求攔截在系統之外;
  • 分發層:將請求路由到上游服務端,并處理其返回的結果;
  • 監控層:監控日志、生成各種運維管理報表、自動告警等;
  • 管理和監控系統主要是為核心系統服務的,起到支撐的作用。

在通信協議上前端和網關交互采用 HTTP 方式,數據格式是 JSON 格式,并定義了一套網關接口規范,前端只需要根據接口協議封裝好報文就可以了,JSON 格式的接口協議為

  1.     "apiId" : "ACQ002"
  2.     "requestParams": [ 
  3.         { 
  4.             "id"23
  5.             "username""testUser" 
  6.         } 
  7.     ] 

在 Dubbo 的泛化調用的時候,需要方法名、參數類型以及具體的值 Object result = genericService.$invoke("方法名", new Object []{"參數類型"}, new Object[]{"具體值"}),但是在前后端的接口協議中并沒有看到參數類型,其主要原因是為了安全,在接口配置過程中會把 apiId 對應的方法名稱、參數類型寫入數據庫,網關啟動后這些配置都會加載到本地緩存,運行過程中可通過 ACQ002 找到具體的配置信息,并完成泛化調用。

从 0 开始构建一个亿级请求的微服务架构

所以,這里做個總結:

  • 網關讓服務具有可復用性;
  • 多個服務調用盡可能并行化調用;
  • 本地緩存 + 遠程緩存完美搭配,提供統一調用方式;
  • 服務高可用熔斷降級必不可少,但是參數配置需要清晰;
  • MQ 的解耦和消峰功能是微服務有效搭配。

6. 微服務后服務的測試方法

當從單體應用轉變到微服務架構的時候,測試的方式也在慢慢改變,在單體應用時候更關注單元測試,提倡單元測試代碼覆蓋率。當在微服務初期階段只有部分服務,此時 API 測試占比非常大,會從 API 最終輸出的結果上來分析接口是否正確,因為單元測試已經保證不了接口的正確性,真正在微服務階段會引入契約測試,來加速集成測試,因為依賴的服務過多,服務之間協調會變動相當麻煩。

从 0 开始构建一个亿级请求的微服务架构

當我們在談服務的高可用性的時候,一般會從流量入口分流策略、下游服務調用、應用進程、消息服務、數據緩存、數據存儲以及系統運維策略等 7 個維度綜合來考慮。這其中涉及到開發、測試、運維等多種角色。尤其是針對測試人員而言,這些保障系統高可用的措施能否測試全面?以熔斷測試和降級測試舉例:

熔斷測試: 從服務的性能角度,當系統負載達到某個熔斷狀態的時候,服務是否能正確熔斷;同時,從功能角度驗證熔斷后系統的行為是否跟預期相符;

降級測試: 從業務的穩定性角度,要能區分出核心業務和非核心業務,在需要降級的時候不能影響核心業務;當某個服務降級后,從功能角度驗證系統行為是否跟預期相符。

雖然熔斷、降級在架構設計階段就規劃到系統中,但是這種業務場景在測試階段如何去驗證呢?

从 0 开始构建一个亿级请求的微服务架构

例如當測試工程師在針對 API 接口測試的時候,該接口依賴 X 和 Y 這 2 個服務,測試過程中所依賴的任何一個服務出現異常就會導致接口測試失敗,如果 Service-A 依賴 Service-B,Service-C,Service-X,Service-Y,那么此時修改了 Service-X 之后其他服務是否有影響,這些在測試階段都沒有辦法去驗證,由于很多不確定因素導致微服務測試結果存在很多不確定性,這種情況下可以研發契約測試平臺,通過自定義的報文來解決多級依賴的問題。

从 0 开始构建一个亿级请求的微服务架构

契約測試 ,又稱之為消費者驅動的契約測試 (Consumer-Driven Contracts,簡稱 CDC),契約測試最開始的概念由 Martin Fowler 提出,根據消費者驅動契約,可以將服務分為消費者端和生產者端,而消費者驅動的契約測試的核心思想在于是從消費者業務實現的角度出發,由消費者自己來定義需要的數據格式以及交互細節,并驅動生成一份契約文件。然后生產者則根據契約文件來實現自己的邏輯,并在持續集成環境中持續驗證。契約測試核心原則是以消費者提出接口契約,交由服務提供方實現,并以測試用例對契約結果進行約束,所以服務提供方在滿足測試用例的情況下可以自行更改接口或架構實現而不影響消費者。

从 0 开始构建一个亿级请求的微服务架构

以 Dubbo 框架為例來構建契約測試,使用 Dubbo 自定義 Filter 中可以方便的獲取到所調用方法的接口名稱、方法名以及參數,可以根據接口名稱 + 方法名的組合來定位。例如:

  1. public class  ContractTestFilter  implements  Filter { public  Result  invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {      Result result = null// 定義一個返回對象 ;      String interfaceName = invoker.getUrl().getPath(); // 獲取接口服務名稱      String methodName = invocation.getMethodName(); // 獲取接口方法名稱     Object[] arguments = invocation.getArguments(); // 獲取參數集合  String resp = httpPost(url, jsonObj.toString()); 
  2.             responeJSON = JSONObject.parseObject(resp); 
  3.             Object rst = null
  4.             //isPact=1 表示啟用契約測試 
  5.             if (responeJSON.getInteger("isPact") == 1) { 
  6.                 result = new RpcResult(); // 定義返回結果 
  7.                 ((RpcResult) result).setValue(rst); 
  8.                 ((RpcResult) result).setException(null); 
  9.             } else { 
  10.                 result = invoker.invoke(invocation); // 調用真實接口 
  11.                 // 然后把接口信息存到契約測試平臺 
  12.                 jsonObj.put("returnValue", JSON.toJSON(result.getValue())); 
  13.                 httpPost(CONTRACT_TEST_SERVER + "/test/pactAdd.do", jsonObj.toString()); 
  14.             } 
  15.         return result;        
  16.         } 

契約測試總體流程說明如下:Consumer 端請求 Provider 的之前,會先執行 ContractTestFilter ,使用 HTTPPost 方式是發送一個 JSON 數據格式的 post 請求,包含 interfaceName、methodName、arguments 發送到契約測試平臺,測試平臺根據傳遞參數組合成查詢條件來查詢該接口是否啟用了契約測試。如果啟用了契約測試,則直接返回設定的返回值,否則返回 false,Consumer 根據返回的結果再去調用 Provider 所提供的服務,把具體結果返回給調用方,同時再把返回結果和入參封裝成 JSON 數據格式發送到契約測試平臺,完成接口數據采集。

从 0 开始构建一个亿级请求的微服务架构

隨著注冊用戶量的逐步增多,平臺所提供多元化且豐富功能以及運營使用了有效的用戶觸達機制,用戶活躍度上升非???,此時平臺的穩定性越來越重要。雖然我們在架構層面做了熔斷、降級、多級緩存等措施,但是在過去的一段時間里還是發生了幾次大的線上故障,我們也針對這些事故做了詳細的復盤分析,出現事故的原因包括:磁盤寫滿、CPU 打滿、服務響應慢甚至超時、數據庫響應慢等等,分析過程中發現架構中雖然包括了熔斷、降級等手段,但是當事故發生的時候似乎這些機制都沒有生效。比如磁盤寫滿、CPU 打滿等故障在設計階段根本未考慮到,服務響應慢或者超時這個現象研發雖然可以通過硬編碼在開發階段來模擬,但是迭代正式提測后,測試是否需要測試架構中的熔斷降級策略呢?如果需要測試那誰來協助測試模擬各種異常情況?

為了解決這個難題,我們參考了互聯網公司的通用方法,通過模擬調用延遲、服務不可用、機器資源滿載等,查看發生故障的節點或實例是否被自動隔離、下線,流量調度是否正確,預案是否有效,同時觀察系統整體的 QPS 或 RT 是否受影響。在此基礎上可以緩慢增加故障節點范圍,驗證上游服務限流降級、熔斷等是否有效。通過模擬故障節點增加到請求服務超時,估算系統容錯紅線,衡量系統容錯能力在生產環境的分布式系統中進行一些試驗,用以考驗系統在動蕩環境下的健壯性,從而增強對系統穩定運行的信心,稱之為混沌工程,ChaosBlade 是阿里巴巴開源的一款遵循混沌工程實驗原理,提供豐富故障場景實現,幫助分布式系統提升容錯性和可恢復性的混沌工程工具。

从 0 开始构建一个亿级请求的微服务架构

例如需要做一次針對數據庫慢 SQL 對業務影響范圍的試驗,可以按照以下方式來執行:

  • 設定場景:數據庫調用延遲
  • 監控指標:慢 SQL 數,告警信息
  • 期望假設:慢 SQL 數增加,釘釘群收到慢 SQL 告警
  • 混沌實驗:對 user-provider 注入調用 user 數據庫延遲故障
  • 監控指標:慢 SQL 數增加,釘釘群收到告警,符合預期
  1. blade create mysql delay 
  2. --time 1000 
  3. --database demo 
  4. --table user 
  5. --sqltype select 
  6. --effect-percent 50 

當在 user-provider 所在服務器上執行命令后,客戶端正常發起調用,此時數據庫慢 SQL 數會增加,消費端出現調用超時,會觸發相關告警。

在單體應用中不可能發送的異常在分布式環境下會成為常態,超時、重試、服務異常這些對于測試人員來說都是挑戰。任何場景在測試環境不驗證通過就會變成線上生產事故,總體來說在測試階段需要注意以下內容:

  • 測試人員思想的改變,接口有數據返回不一定就是正確的
  • 丟棄 E2E 的思想,更多的去看服務和接口
  • 想要線上穩定,混沌工程必須動起來
  • 線上的事故或者 Bug 必須要定期復盤和總結

7. 服務上線流程以及容量預估

互聯網做促銷活動是非常正常的一件事情,當一次活動即將上線的時候,業務系統往往會被問到一些資源的問題,例如需要多少服務器,現有機器能否支撐當前的業務增長等,“拍胸脯”保證的方式還有幾個人能信服?我們需要科學而又嚴謹的評估,通過評估結果來確定需要的資源數量。在容量評估之前我們需要先了解下網站訪問量的常用衡量標準:

  • UV:獨立訪客;
  • PV:綜合瀏覽量;
  • 并發量:系統同時處理的請求數;
  • 響應時間:一般取平均響應時間;
  • QPS:每秒鐘處理的請求數,QPS = 并發量 / 平均響應時間;
  • 帶寬:PV / 統計時間(換算到秒)平均頁面大小(單位 KB)* 8

例如:運營需要做一次活動,通過短信和 PUSH 的方式觸達用戶,推送約 6500W 用戶預計 2 個小時內推送結束,根據這樣的活動規模,相關資源估算如下:

錯誤估算容量估算: 推送用戶量 /(2 x 60 x 60)=9028

單機正常 QPS=1000(水位 60% 極限)=600

因此需要服務器 9028/600=15 臺,根據測試大概需要 15 臺機器。

正確容量估算: 需要考慮短信、PUSH 的歷史轉化情況,不能單純看用戶數,通過歷史數據來看,短信點擊率在 10%,PUSH 點擊率在 6%,合計約 16% 的點擊率,一般 2 個小時內是高峰期,每個用戶約點擊 8-10 個頁面。

點擊用戶數:6500w x 16%=1040W

2 小時 =2x60x60=7200s

QPS=1040W/7200=1444

單機 QPS=1000(水位 60% 極限)=600

1444/600=2.4

預估需要新增 2.4 臺服務器,實際上需要適當增加一些緩沖,通過綜合計算再額外增加 3 臺服務器即可。

從預期 15 臺變成最終的 3 臺,中間有如此大的差距,最主要的原因是沒有考慮短信和 PUSH 的轉化率,這些在平時的運營過程中需要積累數據,切不可拍腦袋給出數字,在我們估算容量的時候這點千萬要注意。

从 0 开始构建一个亿级请求的微服务架构

8. 線上監控如何做?

遵循“誰構建,誰運維”這一理念,服務上線只是完成了構建的環節,更重要的是線上的運維和監控,需要提供服務狀態上報的機制。舉例來說,當某一個時刻 A 接口響應超時,需要追蹤到具體時刻系統的整體負載情況以及 A 接口的調用量趨勢,以及服務 A 接口的數據庫 CPU 占用率,慢 SQL 情況等。所以從解決問題角度來看,在服務監控上需要監控 QPS,錯誤返回數等維度,數據庫監控上需要監控連接數、CPU 占用率、慢 SQL 等等。從系統的穩定性來看,在線上監控需要針對服務狀態、數據庫、硬件等信息監控。

服務監控:

  • QPS
  • 錯誤返回數
  • 接口請求次數的 top
  • 接口 95th,99th 請求時間 top
  • JVM 堆內存 / 非堆內存
  • JVM 線程數
  • GC 的暫停時間和次數
  • Tomcat 的活躍線程
  • API 自己上報的業務數據

數據庫監控:

  • 數據庫連接數
  • 數據庫 CPU
  • 慢 SQL
  • 全表掃描 SQL

硬件監控:

  • CPU 使用率和負載
  • 磁盤空間
  • 網絡流量

9. 微服務實施總結

  • 實施微服務有難度,如非必須,不要輕易使用微服務;
  • 微服務的目的是解決研發的矛盾以及企業規劃相關,不要為了微服務而微服務;
  • 思想認知一致,充分的溝通和培訓是必不可少的;
  • 所有微服務都是不可信賴的;
  • 監控、監控、監控一切可監控的內容。

从 0 开始构建一个亿级请求的微服务架构

 

 

責任編輯:張燕妮 來源: 架構頭條
相關推薦

2017-05-08 14:27:49

PHP框架函數框架

2019-08-21 17:41:29

操作系統軟件設計

2019-01-29 14:29:03

微服務路由

2021-10-14 09:51:17

架構運維技術

2022-07-06 19:00:00

微服務框架鏈路

2021-05-20 13:22:31

架構運維技術

2024-02-06 09:55:33

框架代碼

2012-06-04 18:02:56

社區

2022-11-08 08:35:53

架構微服務移動

2017-05-25 12:40:06

SOA微服務系統

2018-08-15 10:51:01

JavaSpring MVC框架

2019-05-13 15:05:34

TomcatWeb Server協議

2020-08-26 15:10:37

微服務中臺數據

2025-10-16 07:15:00

2018-11-01 13:23:02

網關APIHTTP

2017-07-10 14:18:34

微服務架構可視化

2023-08-31 17:13:01

架構軟件開發

2018-05-30 10:04:38

容器技術微服務

2018-03-26 04:53:46

Serverless微服務架構

2016-09-14 17:48:44

點贊
收藏

51CTO技術棧公眾號

在线播放亚洲激情| 午夜av一区二区| 91久久久一线二线三线品牌| 久久久久久久久久久久久久免费看| 少妇精品在线| 日本乱码高清不卡字幕| 日本三级中文字幕在线观看| 天天摸天天干天天操| 久久不射网站| 欧美成人精品在线视频| 色欲av无码一区二区三区| 色综合一区二区日本韩国亚洲 | 黄视频免费在线看| 国产亚洲精品免费| 成人黄视频免费| 国产精品xxxxxx| 极品av少妇一区二区| 一区二区欧美亚洲| 日韩精品人妻中文字幕有码 | 大又大又粗又硬又爽少妇毛片| 91国内外精品自在线播放| 一区二区三区在线视频观看 | 国产chinese中国hdxxxx| 久久精品xxxxx| 欧美日韩精品在线播放| 欧美xxxx吸乳| av在线免费一区| 不卡的av电影在线观看| 91老司机在线| 日本视频www色| 99精品久久久| 欧美激情精品久久久久久变态| 成人激情五月天| 少妇精品导航| 亚洲电影中文字幕| 丰满人妻一区二区三区大胸| 亚州一区二区三区| 精品久久中文字幕| 久久久久福利视频| 成人黄色网址| 中文字幕制服丝袜一区二区三区| 日本不卡一区二区三区在线观看| 黄频在线免费观看| 国产精品原创巨作av| 国产精品亚洲激情| 中文在线免费观看| 日韩 欧美一区二区三区| 欧美中文字幕在线视频| 日韩成人免费在线视频| 亚洲一级一区| 欧美激情在线狂野欧美精品| 五月婷婷一区二区| 欧美+亚洲+精品+三区| 久久香蕉频线观| 来吧亚洲综合网| 国产高清一区| 久久成人av网站| 91在线播放观看| 午夜久久黄色| 国内精久久久久久久久久人| 日本三级2019| 国产欧美午夜| 青青久久aⅴ北条麻妃| 天堂网中文字幕| 三级欧美在线一区| 国产精品久久久久久久9999| 亚洲一级黄色大片| 国产综合色视频| 91视频在线免费观看| 亚洲国产精品久久久久久6q| 成人av在线电影| 久久精品久久精品国产大片| 免费动漫网站在线观看| 中文字幕乱码日本亚洲一区二区| 亚洲毛片aa| av免费在线免费| 精品二区三区线观看| 无遮挡又爽又刺激的视频 | 在线一区二区三区做爰视频网站| 老司机午夜av| 成人综合日日夜夜| 精品国产乱码久久久久久1区2区 | 亚洲午夜久久| 中文国产亚洲喷潮| 久久免费看少妇高潮v片特黄| 一区在线观看| 国产精品99久久久久久久久| 国产精品老熟女视频一区二区| 国产成人免费视频网站| 久久精品国产美女| 超碰在线免费播放| 好吊成人免视频| 亚洲免费999| 国产精品17p| 丝袜美腿精品国产二区| 国产亚洲精品久久777777| 日韩黄色一级片| 97免费高清电视剧观看| 欧美777四色影视在线| 亚洲女人的天堂| 成人黄色片视频| 日韩欧美激情电影| 一区二区国产精品视频| 欧美精品入口蜜桃| 日本最新不卡在线| 国产一区二区三区奇米久涩| 在线看免费av| 精品日本美女福利在线观看| 中文字幕一区二区在线观看视频| 天堂成人娱乐在线视频免费播放网站 | 无码精品人妻一区二区| 国产精品久线观看视频| 欧美日韩黄色一级片| 国产日韩中文在线中文字幕| 精品一区二区三区四区在线| 精品97人妻无码中文永久在线| 久久国产欧美| 国产欧美日韩综合精品二区| 激情成人四房播| 在线视频亚洲一区| 中文字幕免费高清视频| 欧美久久一级| 成人黄色影片在线| 北条麻妃在线| 色婷婷国产精品久久包臀| 四虎永久免费观看| 91超碰国产精品| 国产精品视频999| 欧美男男同志| 欧美午夜激情小视频| www.美色吧.com| 欧美激情1区| 91免费人成网站在线观看18| 在线免费黄色| 欧美制服丝袜第一页| 99久久久久久久久久| 亚洲精品人人| 激情视频一区二区| wwwwxxxx在线观看| 亚洲福利在线视频| 久久精品人妻一区二区三区| 懂色一区二区三区免费观看 | 麻豆影院在线观看| 欧美亚洲图片小说| 中文字幕有码在线播放| 天堂午夜影视日韩欧美一区二区| 久久精品99久久| 日本а中文在线天堂| 亚洲国产又黄又爽女人高潮的| 欧美激情国产精品免费| 国产成人啪免费观看软件| 国产乱子伦精品视频| 久久99成人| 欧美黑人极品猛少妇色xxxxx| 国产三区在线播放| 一区二区三区四区在线| av在线天堂网| 国产精品久久久久久久久久妞妞| 九色综合婷婷综合| 456亚洲精品成人影院| 国产亚洲视频在线| 亚洲系列在线观看| 亚洲在线中文字幕| 日韩aaaaa| 日韩中文字幕不卡| 亚洲欧美日韩国产yyy| 99tv成人影院| 欧美乱大交xxxxx另类电影| 亚洲第一天堂影院| 精品国产91乱高清在线观看| 精品人妻一区二区三区蜜桃视频| 日韩电影在线观看网站| 亚洲欧美精品| 日韩最新av| 日本精品久久久久久久| 91在线看黄| 精品乱人伦小说| 日本中文字幕第一页| 国产精品欧美经典| 91精品又粗又猛又爽| 午夜在线一区二区| 一区二区三区电影| 福利电影一区| 国产精品一区二区女厕厕| av在线影院| 精品亚洲夜色av98在线观看| 伊人免费在线观看高清版| 亚洲人成在线观看一区二区| 欧美在线一级片| 美女www一区二区| 国产www免费| 日韩电影在线视频| 国产免费一区二区三区| 亚洲精品555| 韩国v欧美v日本v亚洲| 在线视频二区| 日韩电影中文 亚洲精品乱码| 中文字幕在线观看欧美| 午夜亚洲国产au精品一区二区| 亚洲精品成人av久久| a美女胸又www黄视频久久| 亚洲欧美久久久久| 在线亚洲自拍| 在线观看免费黄色片| 亚洲理论电影| 99一区二区| 国产精品原创视频| 98视频在线噜噜噜国产| caoporn免费在线| 国产亚洲视频在线观看| 天天躁日日躁狠狠躁喷水| 7777精品伊人久久久大香线蕉经典版下载 | 久草免费在线视频| 欧美xxxx做受欧美| 91精彩在线视频| 亚洲男人天堂2024| 黄色小视频免费在线观看| 777奇米四色成人影色区| 99re这里只有精品在线| 亚洲成人av一区二区| 亚洲波多野结衣| 亚洲国产成人私人影院tom| 屁屁影院国产第一页| 国产999精品久久久久久绿帽| 国产又大又黄又粗的视频| 久久精品在线| 18禁免费无码无遮挡不卡网站| 欧美精品黄色| 操bbb操bbb| 欧美在线播放| 欧美aaa在线观看| 成人在线免费观看视频| 欧美日韩综合网| 亚洲专区视频| 欧美精品亚洲| 国产一区二区三区四区| 欧美精品一区二区三区在线四季| 日韩极品在线| 久久99久久精品国产| 卡通动漫国产精品| 韩国成人av| 亚洲午夜久久| 日本一区二区三不卡| 女人丝袜激情亚洲| 欧美一区1区三区3区公司| 你微笑时很美电视剧整集高清不卡 | 欧美精品激情blacked18| av超碰免费在线| 久久av中文字幕| 婷婷色在线播放| 欧美激情精品久久久久久| 国产啊啊啊视频在线观看| 久久久久九九九九| 涩涩av在线| 国产成人精品久久二区二区| 三级成人在线| 国产日韩综合一区二区性色av| 日韩成人综合网| 亚洲一区二区三区sesese| 视频一区国产| 国产日韩一区欧美| 亚洲视频分类| 日韩欧美视频一区二区三区四区| 日韩国产一区| 99re99热| 亚洲激情亚洲| 国产极品美女高潮无套久久久| 人妖欧美一区二区| 91精产国品一二三产区别沈先生| 国产精品系列在线播放| 中国xxxx性xxxx产国| 久久久欧美精品sm网站| 一级在线观看视频| 洋洋成人永久网站入口| 久久久精品福利| 欧美日韩在线直播| www.日日夜夜| 亚洲欧美一区二区三区久久| 五月婷婷在线观看| 久久久人成影片一区二区三区观看| 中文字幕21页在线看| 国产主播精品在线| 美国成人xxx| 影音先锋在线亚洲| 尤物精品在线| 中文字幕亚洲欧洲| 成人蜜臀av电影| 国产一二三四视频| 亚洲综合久久久久| 91在线视频免费播放| 欧美一区二区美女| 免费动漫网站在线观看| 欧美成人精品xxx| 在线精品亚洲欧美日韩国产| 国产女人18毛片水18精品| 久久激情av| 在线看视频不卡| 久久www成人_看片免费不卡| 1314成人网| 日本一区二区三区久久久久久久久不 | 国产精品av久久久久久麻豆网| 欧美成人精品欧美一级乱| 国产一区二区不卡| 一区二区三区伦理片| 一区2区3区在线看| 亚洲性在线观看| 亚洲人成五月天| 女子免费在线观看视频www| 国产精品丝袜高跟| 日韩成人午夜| 日本男女交配视频| 久久国产精品一区二区| 日韩中文字幕电影| 五月婷婷综合激情| 精品久久久久久亚洲综合网站| 一本大道亚洲视频| 亚洲涩涩在线| 国产麻豆一区二区三区在线观看| 久久要要av| 国产视频一区二区三区在线播放| 成人免费视频一区| 麻豆视频在线观看| 日韩一区二区免费在线电影 | 亚洲摸摸操操av| 影音先锋国产在线| 亚洲精品一区久久久久久| 高清视频在线观看三级| 999日本视频| 亚洲天天影视网| 人人爽人人爽av| 国产精品免费视频观看| 18国产免费视频| 亚洲丝袜在线视频| 台湾佬成人网| 欧美午夜精品久久久久久蜜| 国产欧美一级| 内射中出日韩无国产剧情| 精品美女久久久久久免费| 天堂av2024| 97香蕉久久夜色精品国产| 精品av导航| 可以在线看的av网站| 99国产精品一区| 天天爽夜夜爽夜夜爽精品| 亚洲精品mp4| 精品人人视频| 欧美不卡在线一区二区三区| 另类亚洲自拍| 日韩不卡av在线| 欧美裸体bbwbbwbbw| 免费黄色在线网站| 91欧美精品成人综合在线观看| 91视频综合| 免费欧美一级片| 亚洲午夜激情网站| 天天色棕合合合合合合合| 91av在线视频观看| 国产精品免费大片| 538任你躁在线精品免费| 综合网在线视频| 国内老熟妇对白xxxxhd| 久久久人成影片一区二区三区| 久久久免费毛片| 老熟妇仑乱视频一区二区| 国产精品网站一区| 国产人妖一区二区| 欧美精品国产精品日韩精品| 一本色道久久综合亚洲精品酒店 | 欧美不卡视频在线观看| 亚洲欧美日韩精品久久| 免费成人高清在线视频| 欧美一级中文字幕| 99re在线视频这里只有精品| 亚洲高清在线看| 九九热这里只有精品6| 欧美亚洲大陆| 777视频在线| 亚洲在线观看免费视频| 清纯唯美亚洲色图| 成人国产精品日本在线| 精品动漫3d一区二区三区免费| 四虎影成人精品a片| 正在播放一区二区| 国产网站在线| 一个色的综合| av在线不卡免费看| 91国在线视频| 性亚洲最疯狂xxxx高清| 日韩电影二区| 中国一级特黄录像播放| 欧美精品久久久久久久多人混战| av影视在线| 永久免费精品视频网站| 91丨porny丨首页| 国产乱色精品成人免费视频| 欧洲日韩成人av| 欧美久久成人| 国产麻豆视频在线观看| 亚洲人成77777在线观看网| jazzjazz国产精品久久|