日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇

發(fā)布時間:2024/3/24 javascript 63 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一.基礎(chǔ)概念

1.架構(gòu)演進

在系統(tǒng)架構(gòu)與設(shè)計的實踐中,從宏觀上可以總結(jié)為三個階段;

單體架構(gòu) :就是把所有的功能、模塊都集中到一個項目中,部署在一臺服務(wù)器上,從而對外提供服務(wù)(單體架構(gòu)、單體服務(wù)、單體應(yīng)用)。直白一點:就是只有一個項目,只有一個 war;

分布式架構(gòu) :就是把所有的功能、模塊拆分成不同的子項目,部署在多臺不同的服務(wù)器上,這些子項目相互協(xié)作共同對外提供服務(wù)。直白一點:就是有很多項目,有很多 wr 包,這些項目相互協(xié)作完成需要的功能,不是一個 war 能完成的,一個 war 包完成不了;

微服務(wù)架構(gòu) :分布式強調(diào)系統(tǒng)的拆分,微服務(wù)也是強調(diào)系統(tǒng)的拆分,微服務(wù)架構(gòu)屬于分布式架構(gòu)的范疇;

并且到目前為止,微服務(wù)并沒有一個統(tǒng)一的標準的定義

2.分布式和微服務(wù)區(qū)別?

分布式,就是將巨大的一個系統(tǒng)劃分為多個模塊,這一點和微服務(wù)是一樣的,都是要把系統(tǒng)進行拆分,部署到不同機器上,因為一臺機器可能承受不了這么大的訪問壓力,或者說要支撐這么大的訪問壓力需要采購一臺性能超級好的服務(wù)器其財務(wù)成本非常高,有這些預(yù)算完全可以采購很多臺普通的服務(wù)器了,分布式系統(tǒng)各個模塊通過接口進行數(shù)據(jù)交互,其實分布式也是一種微服務(wù),因為都是把模塊拆分變?yōu)楠毩⒌膯卧?#xff0c;提供接口來調(diào)用

它們的本質(zhì)的區(qū)別體現(xiàn)在“目標”上,何為目標,就是你采用分布式架構(gòu)或者采用微服務(wù)架構(gòu),你最終是為了什么,要達到什么目的?分布式架構(gòu)的目標是什么?就是訪問量很大一臺機器承受不了,或者是成本問題,不得不使用多臺機器來完成服務(wù)的部署;而微服務(wù)的目標是什么?只是讓各個模塊拆分開來,不會被互相影響,比如模塊的升級或者出現(xiàn) BUG 或者是重構(gòu)等等都不要影響到其他模塊,微服務(wù)它是可以在一臺機器上部署;

3.什么是微服務(wù)?

簡單的說,微服務(wù)架構(gòu)就是將一個完整的應(yīng)用從數(shù)據(jù)存儲開始垂直拆分成多個不同的服務(wù),每個服務(wù)都能獨立部署、獨立維護、獨立擴展,服務(wù)與服務(wù)間通過諸如 RESTful API 的方式互相調(diào)用。

4.服務(wù)治理

服務(wù)治理可以說是微服務(wù)架構(gòu)中最為核心和基礎(chǔ)的模塊, 它主要用來實現(xiàn)各個微服務(wù)實例的自動化注冊與發(fā)現(xiàn)。 為什么我們在微服務(wù)架構(gòu)中那么需要服務(wù)治理模塊呢?微服務(wù)系統(tǒng)沒有它會有什么不好的地方嗎?

在最初開始構(gòu)建微服務(wù)系統(tǒng)的時候可能服務(wù)并不多, 我們可以通過做一些靜態(tài)配置來 完成服務(wù)的調(diào)用。 比如,有兩個服務(wù) A 和 B, 其中服務(wù) A 需要調(diào)用服務(wù) B 來完成一個業(yè)務(wù) 操作時,為了實現(xiàn)服務(wù) B 的高可用, 不論采用服務(wù)端負載均衡還是客戶端負載均衡, 都需 要手工維護服務(wù) B 的具體實例清單。 但是隨著業(yè)務(wù)的發(fā)展, 系統(tǒng)功能越來越復(fù)雜, 相應(yīng)的 微服務(wù)應(yīng)用也不斷增加, 我們的靜態(tài)配置就會變得越來越難以維護。 并且面對不斷發(fā)展的業(yè)務(wù), 我們的集群規(guī)模、 服務(wù)的位置 、 服務(wù)的命名等都有可能發(fā)生變化, 如果還是通過手 工維護的方式, 那么極易發(fā)生錯誤或是命名沖突等問題。 同時, 對于這類靜態(tài)內(nèi)容的維護 也必將消耗大量的人力。

為了解決微服務(wù)架構(gòu)中的服務(wù)實例維護問題, 產(chǎn)生了大量的服務(wù)治理框架和產(chǎn)品。 這 些框架和產(chǎn)品的實現(xiàn)都圍繞著服務(wù)注冊與服務(wù)發(fā)現(xiàn)機制來完成對微服務(wù)應(yīng)用實例的自動化 管理。

5.服務(wù)注冊

在服務(wù)治理框架中, 通常都會構(gòu)建一個注冊中心, 每個服務(wù)單元向注冊 中心登記自己提供的服務(wù), 將主機與端口號、 版本號、 通信協(xié)議等一些附加信息告 知注冊中心, 注冊中心按服務(wù)名分類組織服務(wù)清單。 比如, 我們有兩個提供服務(wù) A 的進程分別運行于 192.168.0.100:8000 和 192.168.0.101:8000 位置上, 另外還有三個提供服務(wù) B 的進程分別運行千 192.168.0.100:9000、 192.168.0.101:9000、 192.168.0.102:9000 位置上。 當(dāng)這些進程均啟動, 并向注冊中心注冊自己的服務(wù)之后, 注冊中心就會維護類似下面的一個服務(wù)清單。 另外, 服務(wù)注冊中心還需要以心跳的方式去監(jiān)測清單中的服務(wù)是否可用, 若不可用 需要從服務(wù)清單中剔除, 達到排除故障服務(wù)的效果。

Spring Cloud 支持得最好的是 Nacos,其次是 Eureka,其次是 Consul,再次是 Zookeeper。

6.服務(wù)發(fā)現(xiàn)

服務(wù)消費者向注冊中心請求已經(jīng)登記的服務(wù)列表,然后得到某個服務(wù)

由于在服務(wù)治理框架下運作, 服務(wù)間的調(diào)用不再通過指定具體的實例地 址來實現(xiàn), 而是通過向服務(wù)名發(fā)起請求調(diào)用實現(xiàn)。 所以, 服務(wù)調(diào)用方在調(diào)用服務(wù)提 供方接口的時候, 并不知道具體的服務(wù)實例位置。 因此, 調(diào)用方需要向服務(wù)注冊中 心咨詢服務(wù), 并獲取所有服務(wù)的實例清單, 以實現(xiàn)對具體服務(wù)實例的訪問。 比如, 現(xiàn)有服務(wù) C 希望調(diào)用服務(wù) A, 服務(wù) C 就需要向注冊中心發(fā)起咨詢服務(wù)請求,服務(wù)注 冊中心就會將服務(wù) A 的位置清單返回給服務(wù) C, 如按上例服務(wù) A 的情況,C 便獲得 了服務(wù) A 的兩個可用位置 192.168.0.100:8000 和 192.168.0.101:8000。 當(dāng)服務(wù) C 要發(fā)起調(diào)用的時候,便從該清單中以某種輪詢策略取出一個位置來進行服 務(wù)調(diào)用,這就是后續(xù)我們將會介紹的客戶端負載均衡。 這里我們只是列舉了一種簡 單的服務(wù)治理邏輯, 以方便理解服務(wù)治理框架的基本運行思路。 實際的框架為了性 能等因素, 不會采用每次都向服務(wù)注冊中心獲取服務(wù)的方式, 并且不同的應(yīng)用場景 在緩存和服務(wù)剔除等機制上也會有一些不同的實現(xiàn)策略。

7.什么是 Spring Cloud?

Spring Cloud 是一個基于 Spring Boot 實現(xiàn)的云應(yīng)用開發(fā)工具,它為基于 JVM 的云應(yīng)用開發(fā)中的配置管理、服務(wù)發(fā)現(xiàn)、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分布式會話和集群狀態(tài)管理等操作提供了一種簡單的開發(fā)方式。

Spring Cloud 包含了多個子項目(針對分布式系統(tǒng)中涉及的多個不同開源產(chǎn)品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI 等項目。

Spring Cloud 為開發(fā)人員提供了一些工具用來快速構(gòu)建分布式系統(tǒng)中的一些常見模式和解決一些常見問題(例如配置管理、服務(wù)發(fā)現(xiàn)、斷路器智能路由、微代理、控制總線、一次性令牌、全局鎖、領(lǐng)導(dǎo)選舉、分布式會話、群集狀態(tài))。

8.微服務(wù)與 Spring-Cloud?

微服務(wù)只是一種項目的架構(gòu)方式、架構(gòu)理念,或者說是一種概念,就如同我們的 MVC 架構(gòu)一樣

Spring Cloud 便是對這種架構(gòu)方式的技術(shù)落地實現(xiàn);

9.Spring Cloud 版本

為了避免大家對版本號的誤解,避免與子項目版本號混淆,所以 Spring Cloud 發(fā)布的版本是一個按照字母順序的倫敦地鐵站的名字(“天使”是第一個版本,"布里克斯頓”是第二個),字母順序是從 A-Z,目前最新穩(wěn)定版本 Greenwich

SR3,當(dāng) Spring Cloud 里面的某些子項目出現(xiàn)關(guān)鍵性 bug 或重大更新,則發(fā)布序列將推出名稱以“.SRX”結(jié)尾的版本,其中“X”是一個數(shù)字,比如:Greenwich SRl、Greenwich SR2、Greenwich SR3;

Spring Cloud 是微服務(wù)開發(fā)的一整套解決方案,采用 Spring Cloud 開發(fā),每個項目依然是使用 Spring Boot

版本

  • Hoxton
  • Greenwich
  • Finchley
  • Edgware
  • Dalston
  • Camden
  • Brixton
  • Angel

10.Spring Cloud 整體架構(gòu)?

11.Spring Cloud 組件

它主要提供的模塊包括:

  • 服務(wù)發(fā)現(xiàn)(Eureka)
  • 斷路器(Hystrix)
  • 智能路有(Zuul)
  • 客戶端負載均衡(Ribbon)

12.Spring Cloud注解

  • @EnableEurekaServer: 用在springboot啟動類上,表示這是一個eureka服務(wù)注冊中心;
  • @EnableDiscoveryClient:用在springboot啟動類上,表示這是一個服務(wù),可以被注冊中心找到;
  • @LoadBalanced:開啟負載均衡能力;
  • @EnableCircuitBreaker:用在啟動類上,開啟斷路器功能;
  • @HystrixCommand(fallbackMethod=”backMethod”):用在方法上,fallbackMethod指定斷路回調(diào)方法;
  • @EnableConfigServer:用在啟動類上,表示這是一個配置中心,開啟Config Server;
  • @EnableZuulProxy:開啟zuul路由,用在啟動類上;
  • @SpringCloudApplication:
    @SpringBootApplication
    @EnableDiscovertyClient
    @EnableCircuitBreaker
    分別是SpringBoot注解、注冊服務(wù)中心Eureka注解、斷路器注解。對于SpringCloud來說,這是每一微服務(wù)必須應(yīng)有的三個注解,所以才推出了@SpringCloudApplication這一注解集合。
  • @ConfigurationProperties:Spring源碼中大量使用了ConfigurationProperties注解,比如server.port就是由該注解獲取到的,通過與其他注解配合使用,能夠?qū)崿F(xiàn)Bean的按需配置。

該注解有一個prefix屬性,通過指定的前綴,綁定配置文件中的配置,該注解可以放在類上,也可以放在方法上。

二.eureka

1.什么是 eureka?

Eureka 服務(wù)治理體系中的三個核心角色: 服務(wù)注冊中心、 服務(wù)提供者以及服務(wù)消費者。

Spring Cloud Eureka, 使用 Netflix Eureka 來實現(xiàn)服務(wù)注冊與發(fā)現(xiàn), 它既包含了服務(wù)端組件,也包含了客戶端組件,并且服務(wù)端與客戶端均采用 Java 編寫,所以 Eureka 主要適用 于通過 Java 實現(xiàn)的分布式系統(tǒng),或是與 NM 兼容語言構(gòu)建的系統(tǒng)。但是,由于 Eureka 服 務(wù)端的服務(wù)治理機制提供了完備的 RESTfulAPL 所以它也支持將非 Java 語言構(gòu)建的微服 務(wù)應(yīng)用納入 Eureka 的服務(wù)治理體系中來。只是在使用其他語言平臺的時候,需要自己來實 現(xiàn) Euerka 的客戶端程序。不過慶幸的是,在目前幾個較為流行的開發(fā)平臺上,都已經(jīng)有了 一些針對 Eureka 注冊中心的客戶端實現(xiàn)框架,比如.NET 平臺的 Steeltoe、 Node.js 的 euerkaj-sc-lient 等。

Eureka 服務(wù)端,我們也稱為服務(wù)注冊中心。它同其他服務(wù)注冊中心一樣,支持高可用 配置。它依托于強一致性提供良好的服務(wù)實例可用性,可以應(yīng)對多種不同的故障場景。如 果 Eureka 以集群模式部署,當(dāng)集群中有分片出現(xiàn)故障時,那么 Eureka 就轉(zhuǎn)入自我保護模 式。它允許在分片故障期間繼續(xù)提供服務(wù)的發(fā)現(xiàn)和注冊,當(dāng)故障分片恢復(fù)運行時,集群中 的其他分片會把它們的狀態(tài)再次同步回來。以在 AWS 上的實踐為例,Netflix 推薦每個可 用的區(qū)域運行一個 Eureka 服務(wù)端,通過它來形成集群。不同可用區(qū)域的服務(wù)注冊中心通過 異步模式互相復(fù)制各自的狀態(tài),這意味著在任意給定的時間點每個實例關(guān)于所有服務(wù)的狀 態(tài)是有細微差別的。

Eureka 客戶端,主要處理服務(wù)的注冊與發(fā)現(xiàn)。客戶端服務(wù)通過注解和參數(shù)配置的方式, 嵌入在客戶端應(yīng)用程序的代碼中,在應(yīng)用程序運行時,Euerka 客戶端向注冊中心注冊自身 提供的服務(wù)并周期性地發(fā)送心跳來更新它的服務(wù)租約。同時,它也能從服務(wù)端查詢當(dāng)前注 冊的服務(wù)信息并把它們緩存到本地并周期性地刷新服務(wù)狀態(tài)。

2.eureka 架構(gòu)

  • Service Provider:暴露服務(wù)的服務(wù)提供方。
  • Service Consumer:調(diào)用遠程服務(wù)的服務(wù)消費方。
  • EureKa Server:服務(wù)注冊中心和服務(wù)發(fā)現(xiàn)中心。

3.eureka 保護機制

在沒有 Eureka 自我保護的情況下,如果 Eureka Server 在一定時間內(nèi)沒有接收到某個微服務(wù)實例的心跳 I Eureka Server 將會注銷該實例,但是當(dāng)發(fā)生網(wǎng)絡(luò)分區(qū)故障時,那么微服務(wù)與 Eureka Server 之間將無法正常通信,以上行為可能變得非常危險了因為微服務(wù)本身其實是正常的此時不應(yīng)該注銷這個微服務(wù),如果沒有自我保護機制,那么 Eureka Server 就會將此服務(wù)注銷掉。

當(dāng) Eureka Server 節(jié)點在短時間內(nèi)丟失過多客戶端時(可能發(fā)生了網(wǎng)絡(luò)分區(qū)故障),那么就會把這個微服務(wù)節(jié)點進行保護。一旦進入自我保護模式,Eureka Server 就會保護服務(wù)注冊表中的信息,不刪除服務(wù)注冊表中的數(shù)據(jù)(也就是不會注銷任何微服務(wù))。當(dāng)網(wǎng)絡(luò)故障恢復(fù)后,該 Eureka Server 節(jié)點會再自動退出自我保護模式。

所以,自我保護模式是一種應(yīng)對網(wǎng)絡(luò)異常的安全保護措施,它的架構(gòu)哲學(xué)是寧可同時保留所有微服務(wù)(健康的微服務(wù)和不健康的微服務(wù)都會保留),也不盲目注銷任何健康的微服務(wù),使用自我保護模式,可以讓 Eureka 集群更加的健壯.穩(wěn)定

#禁用eurekd目我保護 eureka.server.enable-self-preservation=false

4.Eureka 與 Zookeeper?

著名的 CAP 理論指出,一個分布式系統(tǒng)不可能同時滿足 C(一致性街)、A(可用性)和 P(分區(qū)容錯性)。

由于分區(qū)容錯性在是分布式系統(tǒng)中必須要保證的,因此我們只能在 A 和 C 之間進行權(quán)衡,在此 Zookeeper 保證的是 CP,而 Eureka 則是 AP。

Eureka保證AP

Eureka 優(yōu)先保證可用性,Eureka 各個節(jié)點是平等的,某節(jié)點異常,剩余的節(jié)點依然可以提供注冊和服務(wù)查詢功能.

在向某個 Eureka 注冊時,如果發(fā)現(xiàn)連接失敗,則只要有一臺 Eureka 還在,就能保證注冊服務(wù)可用,但是數(shù)據(jù)可能不是最新的(不保證強一致性)。

Zookeeper保證CP

在 ZooKeeper 中,當(dāng) master 節(jié)點因為網(wǎng)絡(luò)故障與其他節(jié)點失去聯(lián)系時,剩余節(jié)點會重新進行 leader 選舉,但是問題在于,選舉 leader 需要一定時間,且選舉期間整個 ZooKeeper 集群都是不可用的,這就導(dǎo)致在選舉期間注冊服務(wù)癱瘓。在云部署的環(huán)境下,因網(wǎng)絡(luò)問題使得 ZooKeeper 集群失去 master 節(jié)點是大概率事件,雖然服務(wù)最終能夠恢復(fù),但是在選舉時間內(nèi)導(dǎo)致服務(wù)注冊長期不可用是難以容忍的。

5.Eureka 高可用集群?

相互注冊,去中心化

#端口號 server:port: 8769spring:application:name: eurka-servereureka:instance:hostname: eureka8769client:register-with-eureka: false #由于該應(yīng)用為注冊中心,所以設(shè)置 為 false, 代表不向注冊中心注冊自己。fetch-registry: false #由于注冊中心的職責(zé)就是維護服務(wù)實例, 它并不需要去檢索服務(wù), 所以也設(shè)置為 false。serviceUrl:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/

6.eureka 三要素?

在 “服務(wù)治理”示例中, 我們的示例雖然簡單, 但是麻雀雖小、 五臟俱全。 它已經(jīng)包含了整個 Eureka 服務(wù)治理基礎(chǔ)架構(gòu)的三個核心要素。

  • 服務(wù)注冊中心: Eureka 提供的服務(wù)端, 提供服務(wù)注冊與發(fā)現(xiàn)的功能, 也就是我們實現(xiàn)的 eureka-server。
  • 服務(wù)提供者:提供服務(wù)的應(yīng)用, 可以是 SpringBoot 應(yīng)用, 也可以是其他技術(shù)平臺且遵循 Eureka 通信機制的應(yīng)用。它將自己提供的服務(wù)注冊到 Eureka, 以供其他應(yīng)用發(fā)現(xiàn), 也就是我們實現(xiàn)的 spring-boot-service 應(yīng)用。
  • 服務(wù)消費者:消費者應(yīng)用從服務(wù)注冊中心獲取服務(wù)列表, 從而使消費者可以知道去何處調(diào)用其所需要的服務(wù),在面我們使用了 Ribbon 來實現(xiàn)服務(wù)消費,另外后續(xù)還會介紹使用 Feign 的消費方式。 很多時候, 客戶端既是服務(wù)提供者也是服務(wù)消費者。

7.Eureka 本地緩存

8.服務(wù)提供者

1.服務(wù)注冊

將服務(wù)所在主機、端口、版本號、通信協(xié)議等信息登記到注冊中心上;

“服務(wù)提供者” 在啟動的時候會通過發(fā)送 REST 請求的方式將自己注冊到 EurekaServer 上, 同時帶上了自身服務(wù)的一些元數(shù)據(jù)信息。Eureka Server 接收到這個 REST 請求之后, 將元數(shù)據(jù)信息存儲在一個雙層結(jié)構(gòu) Map 中, 其中第一層的 key 是服務(wù)名, 第二層的 key 是 具體服務(wù)的實例名。(我們可以回想一下之前在實現(xiàn) Ribbon 負載均衡的例子中, Eureka 信 息面板中一個服務(wù)有多個實例的清況, 這些內(nèi)容就是以這樣的雙層 Map 形式存儲的)

在服務(wù)注冊時, 需要確認一下 eureka.client.register-with-eureka=true 參數(shù)是否正確, 該值默認為 true。若設(shè)置為 false 將不會啟動注冊操作。

boolean register() throws Throwable {logger.info("DiscoveryClient_{}: registering service...", this.appPathIdentifier);EurekaHttpResponse httpResponse;try {httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo);} catch (Exception var3) {logger.warn("DiscoveryClient_{} - registration failed {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});throw var3;}if (logger.isInfoEnabled()) {logger.info("DiscoveryClient_{} - registration status: {}", this.appPathIdentifier, httpResponse.getStatusCode());}return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode(); }

2.服務(wù)同步

如架構(gòu)圖中所示, 這里的兩個服務(wù)提供者分別注冊到了兩個不同的服務(wù)注冊中心上, 也就是說, 它們的信息分別被兩個服務(wù)注冊中心所維護。 此時, 由于服務(wù)注冊中心之間因互相注冊為服務(wù), 當(dāng)服務(wù)提供者發(fā)送注冊請求到一個服務(wù)注冊中心時, 它會將該請求轉(zhuǎn)發(fā)給集群中相連的其他注冊中心,從而實現(xiàn)注冊中心之間的服務(wù)同步。通過服務(wù)同步,兩個服務(wù)提供者的服務(wù)信息就可以通過這兩臺服務(wù)注冊中心中的任意一臺獲取到。

3.服務(wù)續(xù)約

在注冊完服務(wù)之后,服務(wù)提供者會維護一個心跳用來持續(xù)告訴 Eureka Server: "我還活著”,以防止 Eureka Server 的 “剔除任務(wù) ” 將該服務(wù)實例從服務(wù)列表中排除出去,我們稱該操作為服務(wù)續(xù)約(Renew)。

關(guān)千服務(wù)續(xù)約有兩個重要屬性,我們可以關(guān)注并根據(jù)需要來進行調(diào)整:

而 “服務(wù)獲取” 的邏輯在獨立的一個 W 判斷中, 其判斷依據(jù)就是我們之前所提到的 eureka.clien.fetch-registry=true 參數(shù), 它默認為 true, 大部分情況下我們 不需要關(guān)心。 為了定期更新客戶端的服務(wù)清單, 以保證客戶端能夠訪問確實健康的服務(wù)實 例, “服務(wù)獲取” 的請求不會只限于服務(wù)啟動, 而是一個定時執(zhí)行的任務(wù), 從源碼中我們可 以看到任務(wù)運行中的 registryFetchintervalSeconds 參數(shù)對應(yīng)的就是之前所提到的 eureka.client.registry-fetch-interval-seconds=30 配置參數(shù), 它默認為 30 秒。

eureka.instance.lease-renewal-interval-in-seconds=30 eureka.instance.lease-expiration-duration-in-seconds=90 #參數(shù)用于定義服務(wù)續(xù)約任務(wù)的調(diào)用間隔時間,默認為30秒。 eureka.instance.lease-renewal-interval-in-seconds #參數(shù)用于定義服務(wù)失效的時間,默認為90秒。 eureka.instance.lease-expiration-duration-in-seconds private void initScheduledTasks() {int renewalIntervalInSecs;int expBackOffBound;if (this.clientConfig.shouldFetchRegistry()) {renewalIntervalInSecs = this.clientConfig.getRegistryFetchIntervalSeconds();expBackOffBound = this.clientConfig.getCacheRefreshExecutorExponentialBackOffBound();this.scheduler.schedule(new TimedSupervisorTask("cacheRefresh", this.scheduler, this.cacheRefreshExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.CacheRefreshThread()), (long)renewalIntervalInSecs, TimeUnit.SECONDS);}if (this.clientConfig.shouldRegisterWithEureka()) {renewalIntervalInSecs = this.instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();expBackOffBound = this.clientConfig.getHeartbeatExecutorExponentialBackOffBound();logger.info("Starting heartbeat executor: renew interval is: {}", renewalIntervalInSecs);this.scheduler.schedule(new TimedSupervisorTask("heartbeat", this.scheduler, this.heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.HeartbeatThread()), (long)renewalIntervalInSecs, TimeUnit.SECONDS);this.instanceInfoReplicator = new InstanceInfoReplicator(this, this.instanceInfo, this.clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2);this.statusChangeListener = new StatusChangeListener() {public String getId() {return "statusChangeListener";}public void notify(StatusChangeEvent statusChangeEvent) {if (InstanceStatus.DOWN != statusChangeEvent.getStatus() && InstanceStatus.DOWN != statusChangeEvent.getPreviousStatus()) {DiscoveryClient.logger.info("Saw local status change event {}", statusChangeEvent);} else {DiscoveryClient.logger.warn("Saw local status change event {}", statusChangeEvent);}DiscoveryClient.this.instanceInfoReplicator.onDemandUpdate();}};if (this.clientConfig.shouldOnDemandUpdateStatusChange()) {this.applicationInfoManager.registerStatusChangeListener(this.statusChangeListener);}this.instanceInfoReplicator.start(this.clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());} else {logger.info("Not registering with Eureka server per configuration");}}

9.服務(wù)消費者

1.獲取服務(wù)

到這里,在服務(wù)注冊中心已經(jīng)注冊了一個服務(wù),并且該服務(wù)有兩個實例。 當(dāng)我們啟動 服務(wù)消費者的時候,它會發(fā)送一個 REST 請求給服務(wù)注冊中心,來獲取上面注冊的服務(wù)清 單。為了性能考慮,EurekaServer 會維護一份只讀的服務(wù)清單來返回給客戶端,同時該緩 存清單會每隔 30 秒更新一次。

獲取服務(wù)是服務(wù)消費者的基礎(chǔ),所以必須確保 eureka.client.fetch-registry= true 參數(shù)沒有被修改成 false, 該值默認為 true。若希望修改緩存清單的更新時間,可 以通過 eureka.client.registry-fetch-interval-seconds=30 參數(shù)進行修改, 該參數(shù)默認值為 30, 單位為秒。

2.服務(wù)調(diào)用

服務(wù)消費者在獲取服務(wù)清單后,通過服務(wù)名可以獲得具體提供服務(wù)的實例名和該實例的元數(shù)據(jù)信息。 因為有這些服務(wù)實例的詳細信息, 所以客戶端可以根據(jù)自己的需要決定具 體調(diào)用哪個實例,在 ribbon 中會默認采用輪詢的方式進行調(diào)用,從而實現(xiàn)客戶端的負載均衡。

對于訪問實例的選擇,Eureka 中有 Region 和 Zone 的概念, 一個 Region 中可以包含多個 Zone, 每個服務(wù)客戶端需要被注冊到一個 Zone 中, 所以每個客戶端對應(yīng)一個 Region 和一個 Zone。 在進行服務(wù)調(diào)用的時候,優(yōu)先訪問同處一個 Zone 中的服務(wù)提供方, 若訪問不到,就 訪問其他的 Zone, 更多關(guān)于 Region 和 Zone 的知識,我們會在后續(xù)的源碼解讀中介紹。

3.服務(wù)下線

在系統(tǒng)運行過程中必然會面臨關(guān)閉或重啟服務(wù)的某個實例的情況, 在服務(wù)關(guān)閉期間, 我們自然不希望客戶端會繼續(xù)調(diào)用關(guān)閉了的實例。 所以在客戶端程序中, 當(dāng)服務(wù)實例進行正常的關(guān)閉操作時, 它會觸發(fā)一個服務(wù)下線的 REST 請求給 Eureka Server, 告訴服務(wù)注冊中心:“我要下線了”。服務(wù)端在接收到請求之后, 將該服務(wù)狀態(tài)置為下線(DOWN), 并把該下線事件傳播出去。

10.服務(wù)注冊中心

1.失效剔除

有些時候, 我們的服務(wù)實例并不一定會正常下線, 可能由于內(nèi)存溢出、 網(wǎng)絡(luò)故障等原因使得服務(wù)不能正常工作, 而服務(wù)注冊中心并未收到 “服務(wù)下線” 的請求。 為了從服務(wù)列表中將這些無法提供服務(wù)的實例剔除,EurekaSrevre 在啟動的時候會創(chuàng)建一個定時任務(wù), 默認每隔一段時間(默認為 60 秒) 將當(dāng)前清單中超時(默認為 90 秒)沒有續(xù)約的服務(wù)剔除出去。

2.自我保護

當(dāng)我們在本地調(diào)試基于 Eurkea 的程序時, 基本上都會碰到這樣一個問題, 在服務(wù)注冊中心的信息面板中出現(xiàn)類似下面的紅色警告信息:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

實際上, 該警告就是觸發(fā)了 EurekaServer 的自我保護機制。 之前我們介紹過, 服務(wù)注 冊到 EurekaSrevre 之后,會維護一個心跳連接,告訴 EurekaServer 自己還活著。EurkeaServer 在運行期間,會統(tǒng)計心跳失敗的比例在 15 分鐘之內(nèi)是否低于 85%,如果出現(xiàn)低于的情況(在 單機調(diào)試的時候很容易滿足, 實際在生產(chǎn)環(huán)境上通常是由于網(wǎng)絡(luò)不穩(wěn)定導(dǎo)致), Eureka Server 會將當(dāng)前的實例注冊信息保護起來, 讓這些實例不會過期, 盡可能保護這些注冊信 息。 但是, 在這段保護期間內(nèi)實例若出現(xiàn)問題, 那么客戶端很容易拿到實際已經(jīng)不存在的 服務(wù)實例, 會出現(xiàn)調(diào)用失敗的清況, 所以客戶端必須要有容錯機制, 比如可以使用請求重 試、 斷路器等機制。

由于本地調(diào)試很容易觸發(fā)注冊中心的保護機制, 這會使得注冊中心維護的服務(wù)實例不那么準確。 所以, 我們在本地進行開發(fā)的時候, 可以使用參數(shù)來關(guān)閉保護機制, 以確保注冊中心可以將不可用的實例正確剔除。

eureka.server.enableself-preservation =false

11.eureka 源碼

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({EnableDiscoveryClientImportSelector.class}) public @interface EnableDiscoveryClient {boolean autoRegister() default true; } //服務(wù)發(fā)現(xiàn)的核心類 package com.netflix.discovery;

package org.springframework.cloud.netflix.eureka;

org.springframework.cloud.client.discovery.DiscoveryClient 是 SpringCloud 的接口, 它定義了用來發(fā)現(xiàn)服務(wù)的常用抽象方法, 通過該接口可以有效地 屏蔽服務(wù)治理的實現(xiàn)細節(jié), 所以使用 SpringCloud 構(gòu)建的微服務(wù)應(yīng)用可以方便地切換不同服務(wù)治理框架, 而不改動程序代碼, 只需要另外添加一些針對服務(wù)治理框架的配置即可。 org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient 是對該接口的實現(xiàn), 從命名來判斷, 它實現(xiàn)的是對 Eureka 發(fā)現(xiàn)服務(wù)的封裝。 所以 EurekaDiscoveryClient 依賴了 Netflix Eureka 的 com.netflix.discovery. EurekaClient 接口, EurekaClient 繼承了 LookupService 接口, 它們都是 Netflix 開源包中的內(nèi)容, 主要定義了針對 Eureka 的發(fā)現(xiàn)服務(wù)的抽象方法, 而真正實現(xiàn)發(fā)現(xiàn)服務(wù)的 則是 Netflix 包中的 com.netftx.discovery.DiscoveryClient 類。

12.DiscoveryClient

DiscoveryClient 這個類用于幫助與 Eureka Server 互相協(xié)作。
EurekaClient 負責(zé)下面的任務(wù):

  • 向 Eureka Server 注冊服務(wù)實例

  • 向 Eureka Server 服務(wù)租約

  • 當(dāng)服務(wù)關(guān)閉期間, 向 Eureka Server 取消租約

  • 查詢 Eureka Server 中的服務(wù)實例列表

13.什么是 Region?

客戶端依次加載了兩個內(nèi)容, 第一個是 Region, 第二個 是 Zone, 從其加載邏輯上我們可以判斷它們之間的關(guān)系:

通過 getRegion 函數(shù), 我們可以看到它從配置中讀取了一個 Region 返回, 所以 一 個微服務(wù)應(yīng)用只可以屬于一個 Region, 如果不特別配置, 默認為 defaul。若我們要 自己設(shè)置, 可以通過 eureka.client.region 屬性來定義。

public static String getRegion(EurekaClientConfig clientConfig) {String region = clientConfig.getRegion();if (region == null) {region = "default";}region = region.trim().toLowerCase();return region; }

14.什么是 Zone?

通過 getAvailabilityZones 函數(shù), 可以知道當(dāng)我們沒有特別為 Region 配置 Zone 的時候, 將默認采用 defaultZone, 這也是我們之前配置參數(shù) eureka.client.serviceUrl.defaultZone 的由來。 若要為應(yīng)用指定 Zone, 可以通過 eureka.client.availability-zones 屬性來進行設(shè)置。從該函數(shù)的 return 內(nèi)容, 我們可以知道 Zone 能夠設(shè)置多個, 并且通過逗號分隔來配置。 由此, 我們可以判斷 Region 與 Zone 是一對多的關(guān)系

public String[] getAvailabilityZones(String region) {String value = (String)this.availabilityZones.get(region);if (value == null) {value = "defaultZone";}return value.split(",");}

當(dāng)我們在微服務(wù)應(yīng)用中使用 Ribbon 來實現(xiàn)服務(wù)調(diào)用時,對于 Zone 的設(shè)置可以在負載 均衡時實現(xiàn)區(qū)域親和特性: Ribbon 的默認策略會優(yōu)先訪問同客戶端處于一個 Zone 中的服 務(wù)端實例,只有當(dāng)同一個 Zone 中沒有可用服務(wù)端實例的時候才會訪問其他 Zone 中的實例。 所以通過 Zone 屬性的定義,配合實際部署的物理結(jié)構(gòu),我們就可以有效地設(shè)計出對區(qū)域性 故障的容錯集群。

15.服務(wù)消費基礎(chǔ)

服務(wù)消費基礎(chǔ)實現(xiàn)方式,不是傳統(tǒng)實現(xiàn)方式

@RestController public class DcController {@AutowiredLoadBalancerClient loadBalancerClient;@AutowiredRestTemplate restTemplate;@GetMapping("/consumer")public String dc() {ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-server");String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/dc";System.out.println(url);return restTemplate.getForObject(url, String.class);} }

可以看到這里,我們注入了LoadBalancerClient和RestTemplate,并在/consumer接口的實現(xiàn)中,先通過loadBalancerClient的choose函數(shù)來負載均衡的選出一個eureka-client的服務(wù)實例,這個服務(wù)實例的基本信息存儲在ServiceInstance中,然后通過這些對象中的信息拼接出訪問/dc接口的詳細地址,最后再利用RestTemplate對象實現(xiàn)對服務(wù)提供者接口的調(diào)用。

16.什么是 consul?

consul 特性:

  • 服務(wù)發(fā)現(xiàn)
  • 健康檢查
  • Key/Value 存儲
  • 多數(shù)據(jù)中心

服務(wù)發(fā)現(xiàn)的接口DiscoveryClient是 Spring Cloud 對服務(wù)治理做的一層抽象,所以可以屏蔽 Eureka 和 Consul 服務(wù)治理的實現(xiàn)細節(jié),我們的程序不需要做任何改變,只需要引入不同的服務(wù)治理依賴,并配置相關(guān)的配置屬性就能輕松的將微服務(wù)納入 Spring Cloud 的各個服務(wù)治理框架中。

由于 Consul 自身提供了服務(wù)端,所以我們不需要像之前實現(xiàn) Eureka 的時候創(chuàng)建服務(wù)注冊中心,直接通過下載 consul 的服務(wù)端程序就可以使用。

三.Ribbon 和 feign

1.什么是負載均衡?

載均和分為硬件負載均衡和軟件負載均衡:

  • 硬件負載均衡:比如 F5、深信服、Array 等;
  • 軟件負載均衡:比如 Nginx、LVS、HAProxy 等;

2.服務(wù)端負載均衡

3.什么是 Ribbon?

Ribbon 是 Netfliⅸ 公司發(fā)布的開源項目(組件、框架、jar 包),主要功能是提供客戶端的軟件負載均衡算法,它會從 eureka 中獲取一個可用的服務(wù)端清單通過心跳檢測來易剔除故的服務(wù)端節(jié)點以保證清單中都是可以正常訪問的服務(wù)端節(jié)點。

當(dāng)客戶端發(fā)送請求,則 ribbon 負載均衡器按某種算法(比如輪詢、權(quán)重、最小連接數(shù)等從維護的可用服務(wù)端清單中取出一臺服務(wù)端的地址然后進行請求

Ribbon 是一個基于 HTTP 和 TCP 客戶端的負載均衡器。Ribbon 非常簡單,可以說就是一個 jar 包,這個 jar 包實現(xiàn)了負載均衡算法,Spring Cloud 對 Ribbon 做了二次封裝,可以讓我們使用 RestTemplate 的服務(wù)請求,自動轉(zhuǎn)換成客戶端負載均衡的服務(wù)調(diào)用。

Ribbon 可以在通過客戶端中配置的 ribbonServerList 服務(wù)端列表去輪詢訪問以達到均衡負載的作用。當(dāng) Ribbon 與 Eureka 聯(lián)合使用時,ribbonServerList 會被 DiscoveryEnabledNIWSServerList 重寫,擴展成從 Eureka 注冊中心中獲取服務(wù)端列表。同時它也會用 NIWSDiscoveryPing 來取代 IPing,它將職責(zé)委托給 Eureka 來確定服務(wù)端是否已經(jīng)啟動。

Ribbon 支持多種負載均衡算法,還支持自定義的負載均衡算法。

使用 Ribbon 實現(xiàn)負載均衡的調(diào)用(spring cloud -> 封裝 ribbon + eureka + restTemplate)

Ribbon 默認是采用懶加載,即第一次訪問時才會去創(chuàng)建 LoadBalanceClient,請求時間會很長。

而饑餓加載則會在項目啟動時創(chuàng)建,降低第一次訪問的耗時,通過下面配置開啟饑餓加載:

ribbon:eager-load:enabled: trueclients: user

4.IRule

public interface IRule {Server choose(Object var1);void setLoadBalancer(ILoadBalancer var1);ILoadBalancer getLoadBalancer(); }

5.ILoadBalancer

一個服務(wù)對應(yīng)一個 LoadBalancer,一個 LoadBalancer 只有一個 Rule,LoadBalancer 記錄服務(wù)的注冊地址,Rule 提供從服務(wù)的注冊地址中找出一個地址的規(guī)則。

通過 LoadBalancerIntercepor 攔截器,可以攔截請求 url 和服務(wù) id,然后結(jié)合 IRule 進行路由處理

public interface ILoadBalancer {void addServers(List<Server> var1);Server chooseServer(Object var1);void markServerDown(Server var1);/** @deprecated */@DeprecatedList<Server> getServerList(boolean var1);List<Server> getReachableServers();List<Server> getAllServers(); }

6.負載均衡策略

Ribbon 提供七種負載均衡策略,默認的負載均衡策略是輪訓(xùn)策略。RoundRobinRule

public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {private static final IRule DEFAULT_RULE = new RoundRobinRule(); }

通過 choose 方法選擇指定的算法。完整的算法包含如下:

策略名稱解釋描述
RandomRule隨機算法實現(xiàn)
RoundRobinRule輪詢負載均衡策略,依次輪詢所有可用服務(wù)器列表
RetryRule先按照 RoundRobinRule 策略獲取服務(wù),如果獲取服務(wù)失敗會在指定時間內(nèi)重試
AvaliabilityFilteringRule過濾掉那些因為一直連接失敗的被標記為 circuit tripped 的后端 server,并過濾掉那些高并發(fā)的的后端 server(active connections 超過配置的閾值)
BestAvailableRule會先過濾掉由于多次訪問故障二處于斷路器跳閘狀態(tài)的服務(wù),然后選擇一個并發(fā)量最小的服務(wù)
WeightedResponseTimeRule根據(jù)響應(yīng)時間分配一個 weight,響應(yīng)時間越長,weight 越小,被選中的可能性越低
ZoneAvoidanceRule復(fù)合判斷 server 所在區(qū)域的性能和 server 的可用性選擇 server,新版本默認的負載均衡策略
  • RoundRobinRule: 輪詢策略。Ribbon 默認采用的策略。若經(jīng)過一輪輪詢沒有找到可用的 provider,其最多輪詢 10 輪(代碼中寫死的,不能修改)。若還未找到,則返回 null。

  • RandomRule: 隨機策略,從所有可用的 provider 中隨機選擇一個。。

  • RetryRule: 重試策略。先按照 RoundRobinRule 策略獲取 server,若獲取失敗,則在指定的時限內(nèi)重試。默認的時限為 500 毫秒。

  • BestAvailableRule: 最可用策略。選擇并發(fā)量最小的 provider,即連接的消費者數(shù)量最少的 provider。其會遍歷服務(wù)列表中的每一個 server,選擇當(dāng)前連接數(shù)量 minimalConcurrentConnections 最小的 server。

  • AvailabilityFilteringRule: 可用過濾算法。該算法規(guī)則是:過濾掉處于熔斷狀態(tài)的 server 與已經(jīng)超過連接極限的 server,對剩余 server 采用輪詢策略。

7.負載均衡原理

Ribbon 負載均衡基本原理:
1、Ribbon 會攔截 Eureka Client 客戶端發(fā)出的 http 請求,獲得服務(wù)名(userservice)
2、從 Eureka 中拉取動態(tài)服務(wù)列表(8081、8082。。。。。)
3、從里面選一個服務(wù)(如 8081)出來(輪詢、隨機等算法)
4、去調(diào)用這個服務(wù)

8.ribbon組件

主要有以下組件:

  • IRule,定義如何選擇規(guī)則和策略
  • IPing,接口定義了我們?nèi)绾巍皃ing”服務(wù)器檢查是否活著
  • ServerList,定義了獲取服務(wù)器的列表接口,存儲服務(wù)列表
  • ServerListFilter,接口允許過濾配置或動態(tài)獲得的候選列表服務(wù)器
  • ServerListUpdater,接口使用不同的方法來做動態(tài)更新服務(wù)器列表
  • IClientConfig,定義了各種api所使用的客戶端配置,用來初始化ribbon客戶端和負載均衡器,默認實現(xiàn)是DefaultClientConfigImpl ILoadBalancer, 接口定義了各種軟負載,動態(tài)更新一組服務(wù)列表及根據(jù)指定算法從現(xiàn)有服務(wù)器列表中選擇一個服務(wù)

@LoadBalanced注解,開啟客戶端的負載均衡:

  • RestTemplate
  • LoadBalancerAutoConfiguration
    • @ConditionalOnClass(RestTemplate.class)
    • @ConditionalOnBean(LoadBalancerClient.class)
  • SmartInitializingSingleton 加載@LoadBalanced注解的RestTemplate到RestTemplateCustomizer
  • LoadBalancerInterceptor攔截器攔截RestTemplate請求

9.遠程調(diào)用有哪些?

  • Httpclient(apache)
  • Httpurlconnection (jdk)
  • restTemplate (spring)
  • OkHttp(android)
  • feign(Spring cloud)

10.什么是 Feign?

Feign 是一個聲明式的 Web Service 客戶端,它使得編寫 Web Serivce 客戶端變得更加簡單。我們只需要使用 Feign 來創(chuàng)建一個接口并用注解來配置它既可完成。它具備可插拔的注解支持,包括 Feign 注解和 JAX-RS 注解。Feign 也支持可插拔的編碼器和解碼器。Spring Cloud 為 Feign 增加了對 Spring MVC 注解的支持,還整合了 Ribbon 和 Eureka 來提供均衡負載的 HTTP 客戶端實現(xiàn)。

Feign 在Ribbon+RestTemplate 的基礎(chǔ)上做了進一步封裝,在Feign 封裝之后,我們只需創(chuàng)建一個接口并使用注解的方式來配置,即可完成對服務(wù)提供方的接口綁定簡化了使用 Ribbon + RestTemplate 的調(diào)用,自動封裝服務(wù)調(diào)用客戶端.

Feign 中也使用 Ribbon,自動集成了 ribbon

11.feignclient 冪等性

Retryer是重試器,其實現(xiàn)方法有兩種,第一種是系統(tǒng)默認實現(xiàn)方式,第二種是可以自定義重試器,一般少用,通過默認實現(xiàn)重試類Default可以看到其構(gòu)造函數(shù)中的重試次數(shù)為5。

public Default() {this(100, SECONDS.toMillis(1), 5); }public Default(long period, long maxPeriod, int maxAttempts) {this.period = period;this.maxPeriod = maxPeriod;this.maxAttempts = maxAttempts;this.attempt = 1; }

因此解決Feign調(diào)用的冪等性問題最簡單也就最常用的就是讓Feign不重試。

12.ip 不能訪問

使用了@LoadBalanced 注解后不能再使用 192.168.28.1(ip)調(diào)用,必須要使用注冊中心中注冊的服務(wù)名稱

所以在使用 RestTemplate 的時候,有些場景下我們只是單純的用 ip 進行調(diào)用(如調(diào)用第三方接口服務(wù)),此時的 RestTemplate 就不能夠加@LoadBanlanced 注解。還有一種辦法是直接在需要使用 RestTemplate 的地方,直接 new 一個新的 RestTemplate 對象。如下

public void test(){RestTemplate restTemplate = new RestTemplate();//這里的接口地址就可以直接放協(xié)議+ip+端口,原理與上面一樣restTemplate.exchange("接口地址",xxx,xxx,xxx); }

13.feign 超時

Spring Cloud 中 Feign 客戶端是默認開啟支持 Ribbon 的,最重要的兩個超時就是連接超時 ConnectTimeout 和讀超時 ReadTimeout,在默認情況下,也就是沒有任何配置下,Feign 的超時時間會被 Ribbon 覆蓋,兩個超時時間都是 1 秒。

#ribbon配置 ribbon:#建立連接超時時間ConnectTimeout: 5000#建立連接之后,讀取響應(yīng)資源超時時間ReadTimeout: 5000#Feign配置 feign:client:config:#這里填具體的服務(wù)名稱(也可以填default,表示對所有服務(wù)生效)app-order:#connectTimeout和readTimeout這兩個得一起配置才會生效connectTimeout: 5000readTimeout: 5000

四.hystrix

1.什么是 Hystrix?

在 Spring Cloud 中使用了 Hystrix 來實現(xiàn)斷路器的功能。Hystrix 是 Netflix 開源的微服務(wù)框架套件之一,該框架目標在于通過控制那些訪問遠程系統(tǒng)、服務(wù)和第三方庫的節(jié)點,從而對延遲和故障提供更強大的容錯能力。Hystrix 具備擁有回退機制和斷路器功能的線程和信號隔離,請求緩存和請求打包,以及監(jiān)控和配置等功能。

Hystrix 原理是命令模式,在遇到不同的情況下,請求 fallback,降級處理

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @EnableCircuitBreaker public @interface EnableHystrix { }

2.Hystrix 有哪些功能?

核心功能:

  • 超時
  • 異常
  • 限流

斷路器的作用

  • 防止單個服務(wù)的故障導(dǎo)致器依賴和相關(guān)的服務(wù)容器的線程資源被耗盡:
  • 減少負載,并負責(zé)通過請求的快速失敗功能而不是讓請求進行排隊.
  • 盡可能提供服務(wù)降級的功能,以免用戶免受故障影響
  • 使用隔離技術(shù)來限制某個服務(wù)出現(xiàn)問題所帶來的影響
  • 盡可能提供實時監(jiān)控信息,提供監(jiān)控和警報來優(yōu)化發(fā)現(xiàn)故障的時間
  • 允許使用配置修改相關(guān)的參數(shù)(如請求超時時可以觸發(fā)熔斷)
  • 對服務(wù)調(diào)用消費者內(nèi)部的故障進行保護,而不僅僅是在網(wǎng)絡(luò)流量上進行保護降級,限流
  • 一個簡單的場景就是家里的保險絲,當(dāng)電流過大時保險絲熔斷,使得家里的其他電器不至于造成大規(guī)模的損壞:
    在微服務(wù)中,當(dāng)大量請求到達產(chǎn)品微服務(wù),這會導(dǎo)致其服務(wù)響應(yīng)變得緩慢,或者因為內(nèi)存不足等原因使得服務(wù)器出現(xiàn)宕機或者數(shù)據(jù)庫出現(xiàn)問題;

    另一個原因,當(dāng)一個微服務(wù)中有很多請求時,會導(dǎo)致他調(diào)用其他微服務(wù)的時候(正常的服務(wù)線程)造成積壓,產(chǎn)生雪崩;

    3.Hystrix 超時配置

    #開啟feign開始hystrix的支持 feign:hystrix:enabled: truehystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 5000 #hystrix超時時間timeout:enabled: true #開啟hystrix超時管理 ribbon:ReadTimeout: 2000 #請求超時時間http:client:enabled: true #開啟ribbon超時管理ConnectTimeout: 2000 #連接超時時間
    • Dalston 版本之后默認關(guān)閉,注意開啟 feign 的 hystrix 的功能
    • ribbon 和 hystrix 都要設(shè)置,誰小以誰為準

    4.熔斷降級

    • 可以監(jiān)聽你的請求有沒有超時;(默認是 1 秒,時間可以改)
    • 異常或報錯了可以快速讓請求返回,不會一直等待;(避免線程累積)
    • 當(dāng)?shù)南到y(tǒng)馬上迎來大量的并發(fā)(雙十一秒殺這種或者促銷活動)

    此時如果系統(tǒng)承載不了這么大的并發(fā)時,可以考慮先關(guān)閉一些不重要的微服務(wù)(在降級方法中返回一個比較友好的信息),把資源讓給核心微服務(wù),待高峰流量過去,再開啟回來。

    5.服務(wù)限流

    通過 2 種方式進行限流

    • 線程數(shù)限制
    • 信號量限制

    限流配置,通過限制線程數(shù)進行限流,限流就是限制你某個微服務(wù)的使用量(可用線程),

    hystriⅸ 通過線程池的方式來管理微服務(wù)的調(diào)用,它默認是一個線程池(大小 10 個)管理你的所有微服務(wù),你可以給某個微服務(wù)開辟新的線程池.

    @HystrixCommand(fallbackMethod = "addServiceFallback",commandProperties = {@HystrixProperty(name = "execution.timeout.enabled", value = "true"),@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "6000")},threadPoolProperties = {@HystrixProperty(name = "coreSize", value = "2"),@HystrixProperty(name = "maxQueueSize", value = "1"),@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")} )
    • commandProperties 可以配置 hystrix 的各種配置
    • hreadPoolProperties 屬性用于控制線程池的行為,要求為我們建立一個大小為 coreSize 的,且在之前創(chuàng)建一個隊列的線程池,隊列大小為 maxQueueSize 對應(yīng)的 value 的值
    • 這個隊列的作用是:控制在線程池中線程繁忙時允許堵塞的請求數(shù)(即 value 值),一旦請求數(shù)超過了隊列大小,對線程池的任何請求都將失敗,直到隊列中有空間為止。此外,對于 maxQueueSize 的值也有說明,當(dāng) value=-1 時,則將使用 Java SynchronousQueue 來保存所有傳入的請求,同步隊列本質(zhì)上會強制要求正在處理中的請求數(shù)量永遠不要超過線程池中的可用數(shù)量;將 maxQueueSize 設(shè)置為大于 1 的值將導(dǎo)致 Hystrix 使用 Java LinkedBlockingQueue。這使得即使所有的線程都忙于處理請求,也能對請求進行排隊。

    6.commandProperties

    Command 屬性主要用來控制 HystrixCommand 命令的行為,它主要分下面的類別:

    • Execution:用來控制 HystrixCommand.run()的執(zhí)行
      • execution.isolation.strategy:該屬性用來設(shè)置 HystrixCommand.run()執(zhí)行的隔離策略。默認為 THREAD
      • execution.isolation.thread.timeoutInMilliseconds:該屬性用來配置 HystrixCommand 執(zhí)行的超時時間,單位為毫秒。
      • execution.timeout.enabled:該屬性用來配置 HystrixCommand.run()的執(zhí)行是否啟用超時時間。默認為 true。
      • execution.isolation.thread.interruptOnTimeout:該屬性用來配置當(dāng) HystrixCommand.run()執(zhí)行超時的時候是否要它中斷。
      • execution.isolation.thread.interruptOnCancel:該屬性用來配置當(dāng) HystrixCommand.run()執(zhí)行取消時是否要它中斷。
      • execution.isolation.semaphore.maxConcurrentRequests:當(dāng) HystrixCommand 命令的隔離策略使用信號量時,該屬性用來配置信號量的大小。當(dāng)最大并發(fā)請求達到該設(shè)置值時,后續(xù)的請求將被拒絕。
    • Fallback:用來控制 HystrixCommand.getFallback()的執(zhí)行
      • fallback.isolation.semaphore.maxConcurrentRequests:該屬性用來設(shè)置從調(diào)用線程中允許 HystrixCommand.getFallback()方法執(zhí)行的最大并發(fā)請求數(shù)。當(dāng)達到最大并發(fā)請求時,后續(xù)的請求將會被拒絕并拋出異常。
      • fallback.enabled:該屬性用來設(shè)置服務(wù)降級策略是否啟用,默認是 true。如果設(shè)置為 false,當(dāng)請求失敗或者拒絕發(fā)生時,將不會調(diào)用 HystrixCommand.getFallback()來執(zhí)行服務(wù)降級邏輯。
    • Circuit Breaker:用來控制 HystrixCircuitBreaker 的行為。
      • circuitBreaker.enabled:確定當(dāng)服務(wù)請求命令失敗時,是否使用斷路器來跟蹤其健康指標和熔斷請求。默認為 true。
      • circuitBreaker.requestVolumeThreshold:用來設(shè)置在滾動時間窗中,斷路器熔斷的最小請求數(shù)。例如,默認該值為 20 的時候,如果滾動時間窗(默認 10 秒)內(nèi)僅收到 19 個請求,即使這 19 個請求都失敗了,斷路器也不會打開。
      • circuitBreaker.sleepWindowInMilliseconds:用來設(shè)置當(dāng)斷路器打開之后的休眠時間窗。休眠時間窗結(jié)束之后,會將斷路器設(shè)置為“半開”狀態(tài),嘗試熔斷的請求命令,如果依然時候就將斷路器繼續(xù)設(shè)置為“打開”狀態(tài),如果成功,就設(shè)置為“關(guān)閉”狀態(tài)。
      • circuitBreaker.errorThresholdPercentage:該屬性用來設(shè)置斷路器打開的錯誤百分比條件。默認值為 50,表示在滾動時間窗中,在請求值超過 requestVolumeThreshold 閾值的前提下,如果錯誤請求數(shù)百分比超過 50,就把斷路器設(shè)置為“打開”狀態(tài),否則就設(shè)置為“關(guān)閉”狀態(tài)。
      • circuitBreaker.forceOpen:該屬性默認為 false。如果該屬性設(shè)置為 true,斷路器將強制進入“打開”狀態(tài),它會拒絕所有請求。該屬性優(yōu)于 forceClosed 屬性。
      • circuitBreaker.forceClosed:該屬性默認為 false。如果該屬性設(shè)置為 true,斷路器強制進入“關(guān)閉”狀態(tài),它會接收所有請求。如果 forceOpen 屬性為 true,該屬性不生效。
    • Metrics:該屬性與 HystrixCommand 和 HystrixObservableCommand 執(zhí)行中捕獲的指標相關(guān)。
      • metrics.rollingStats.timeInMilliseconds:該屬性用來設(shè)置滾動時間窗的長度,單位為毫秒。該時間用于斷路器判斷健康度時需要收集信息的持續(xù)時間。斷路器在收集指標信息時會根據(jù)設(shè)置的時間窗長度拆分成多個桶來累計各度量值,每個桶記錄了一段時間的采集指標。例如,當(dāng)為默認值 10000 毫秒時,斷路器默認將其分成 10 個桶,每個桶記錄 1000 毫秒內(nèi)的指標信息。
      • metrics.rollingStats.numBuckets:用來設(shè)置滾動時間窗統(tǒng)計指標信息時劃分“桶”的數(shù)量。默認值為 10。
      • metrics.rollingPercentile.enabled:用來設(shè)置對命令執(zhí)行延遲是否使用百分位數(shù)來跟蹤和計算。默認為 true,如果設(shè)置為 false,那么所有的概要統(tǒng)計都將返回-1。
      • metrics.rollingPercentile.timeInMilliseconds:用來設(shè)置百分位統(tǒng)計的滾動窗口的持續(xù)時間,單位為毫秒。
      • metrics.rollingPercentile.numBuckets:用來設(shè)置百分位統(tǒng)計滾動窗口中使用桶的數(shù)量。
      • metrics.rollingPercentile.bucketSize:用來設(shè)置每個“桶”中保留的最大執(zhí)行數(shù)。
      • metrics.healthSnapshot.intervalInMilliseconds:用來設(shè)置采集影響斷路器狀態(tài)的健康快照的間隔等待時間。
    • Request Context:涉及 HystrixCommand 使用 HystrixRequestContext 的設(shè)置。
      • requestCache.enabled:用來配置是否開啟請求緩存。
      • requestLog.enabled:用來設(shè)置 HystrixCommand 的執(zhí)行和事件是否打印到日志的 HystrixRequestLog 中。

    7.threadPoolProperties

    threadPoolProperties = {@HystrixProperty(name = "coreSize",value = "2"),@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize",value="true"),@HystrixProperty(name = "maximumSize",value="2"),@HystrixProperty(name = "maxQueueSize",value="2")},
    • 如果請求量少,達不到 coreSize,通常會使用核心線程來執(zhí)行任務(wù)。

    • 如果設(shè)置了 maxQueueSize,當(dāng)請求數(shù)超過了 coreSize, 通常會把請求放到 queue 里,待核心線程有空閑時消費。

    • 如果 queue 長度無法滿足存儲請求,則會創(chuàng)建新線程執(zhí)行直到達到 maximumSize 最大線程數(shù),多出核心線程數(shù)的線程會在空閑時回收。

    8.常用限流方式?

    • Hystriⅸ 限流
    • Nginx
    • Redis+Lua
    • Sentinel
    • 基于限流算法自己實現(xiàn)(令牌桶、漏桶慎法)

    9.熔斷器什么場景下會失效

  • feign 未開啟 hystrix 功能
  • 超時時間配置不正確
  • 未開啟熔斷器的功能,false
  • 超時時間沒有考慮 ribbon 的情況
  • 10.什么是 Dashboard?

    Hystrix Dashboard 是一個通過收集 actuator 端點提供的 Hystrix 流數(shù)據(jù),因此在這些被斷路器保護的應(yīng)用中需要開啟 Hystrix 流的 Actuator 端點,并將其圖表化的客戶端。如果需要通過圖表化的界面查看被斷路器保護的方法相關(guān)調(diào)用信息、或者實時監(jiān)控這些被斷路器保護的應(yīng)用的健康情況,就可以使用 Hystrix Dashboard。

    11.Dashboard 使用

    #監(jiān)控鏈接 http://localhost:8080/hystrix.stream http://localhost:8080/actuator/hystrix.stream#請求下hystrix的接口 http://localhost:8080/portal/hystrix/1

    #訪問鏈接 http://localhost:9909/hystrix

    portal中需要加入

    @Bean public ServletRegistrationBean getServlet() {HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);registrationBean.setLoadOnStartup(1);registrationBean.addUrlMappings("/hystrix.stream");registrationBean.setName("HystrixMetricsStreamServlet");return registrationBean; }

    dashboard中需要加入

    hystrix:dashboard:proxy-stream-allow-list: "localhost"

    12.儀表盤解讀

    • 實心圓:共有兩種含義。它通過顏色的變化代表了實例的健康程度

    • 該實心圓除了顏色的變化之外,它的大小也會根據(jù)實例的請求流量發(fā)生變化,流量越大該實心圓就越大。所以通過該實心圓的展示,就可以在大量的實例中快速的發(fā)現(xiàn)故障實例和高壓力實例。

    • 曲線:用來記錄 2 分鐘內(nèi)流量的相對變化,可以通過它來觀察到流量的上升和下降趨勢。

    在圖表中,左上角的圓圈代表了該方法的流量和狀態(tài):

    • 圓圈越大代表方法流量越大
    • 圓圈為綠色代表斷路器健康、黃色代表斷路器偶發(fā)故障、紅色代表斷路器故障

    右上角的計數(shù)器(三列數(shù)字):

    第一列從上到下

    • 綠色代表當(dāng)前成功調(diào)用的數(shù)量

    • 藍色代表短路請求的數(shù)量

    • 藍綠色代表錯誤請求的數(shù)量

    第二列從上到下

    • 黃色代表超時請求的數(shù)量

    • 紫色代表線程池拒絕的數(shù)量

    • 紅色代表失敗請求的數(shù)量

    第三列

    • 過去 10s 的錯誤請求百分比

    Thread Pools:

    Hystrix 會針對一個受保護的類創(chuàng)建一個對應(yīng)的線程池,這樣做的目的是 Hystrix 的命令被調(diào)用的時候,不會受方法請求線程的影響(或者說 Hystrix 的工作線程和調(diào)用者線程相互之間不影響)

    左下角從上至下:

    • Active 代表線程池中活躍線程的數(shù)量

    • Queued 代表排隊的線程數(shù)量,該功能默認禁止,因此默認情況下始終為 0

    • Pool Size 代表線程池中線程的數(shù)量(上面圖我搞錯了,困得死 MMP

    右下角從上至下:

    • Max Active 代表最大活躍線程,這里展示的數(shù)據(jù)是當(dāng)前采用周期中,活躍線程的最大值

    • Execcutions 代表線程池中線程被調(diào)用執(zhí)行 Hystrix 命令的次數(shù)

    • Queue Size 代表線程池隊列的大小,默認禁用,無意義

    13.turbine 的作用

    監(jiān)控數(shù)據(jù)聚合

    Turbine 是聚合服務(wù)器發(fā)送事件流數(shù)據(jù)的一個工具,Hystrix 的監(jiān)控中,只能監(jiān)控單個節(jié)點,實際生產(chǎn)中都為集群,因此可以通過 Turbine 來監(jiān)控集群下 Hystrix 的 metrics 情況,同一個服務(wù)負載均衡情況下,可以監(jiān)控多個實例.hosts>1

    14.turbine 使用

    http://localhost:8081/portal/hystrix/1 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-turbine</artifactId> </dependency> @EnableTurbine @EnableEurekaClient @EnableHystrixDashboard @SpringBootApplication public class HystrixTurbineApplication {public static void main(String[] args) {SpringApplication.run(HystrixTurbineApplication.class, args);}}

    #端口號 server:port: 9999spring:application:name: hystrix-turbine-service #服務(wù)名稱#服務(wù)提供者 eureka:client:service-url:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/instance:lease-renewal-interval-in-seconds: 2 #每間隔2s,向服務(wù)端發(fā)送一次心跳,證明自己依然"存活”lease-expiration-duration-in-seconds: 10 #告訴服務(wù)端,如果我10s之內(nèi)沒有給你發(fā)心跳,就代表我故障了,將我踢出掉prefer-ip-address: true #告訴服務(wù)端,服務(wù)實例以IP作為鏈接,而不是取機器名instance-id: springcloud-service-turbine-9999 #告訴服務(wù)端,服務(wù)實例的id,id要是唯一的# 開啟Feign對Hystrix的支持 feign:hystrix:enabled: trueclient:config:default:connectTimeout: 5000 # 指定Feign連接提供者的超時時限readTimeout: 5000 # 指定Feign從請求到獲取提供者響應(yīng)的超時時限# 開啟actuator的所有web終端 management:endpoints:web:exposure:include: "*"# 設(shè)置服務(wù)熔斷時限 hystrix:dashboard:proxy-stream-allow-list: "localhost"command:default:execution:isolation:thread:timeoutInMilliseconds: 3000turbine:app-config: portal-servicecluster-name-expression: new String("default")combine-host-port: trueinstanceUrlSuffix: /actuator/hystrix.stream #turbine默認監(jiān)控actuator/路徑下的端點,修改直接監(jiān)控hystrix.stream#cluster-name-expression: metadata['cluster']#aggregator:# cluster-config: ribbon#instanceUrlSuffix: /hystrix.stream #turbine默認監(jiān)控actuator/路徑下的端點,修改直接監(jiān)控hystrix.stream

    15.@SpringCloudApplication

    @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker public @interface SpringCloudApplication { }
    • @SpringBootApplication
    • @EnableDiscoveryClient
    • @EnableCircuitBreaker

    組合注解,SpringBootApplication,注冊中心客戶端 EnableDiscoveryClient,支持 hystrix 的 EnableCircuitBreaker

    16.超時時間

    Ribbon 和 Hystrix和Feign 的超時時間配置的關(guān)系

    • 在 Spring Cloud 中使用 Feign 進行微服務(wù)調(diào)用分為兩層:Hystrix 的調(diào)用和 Ribbon 的調(diào)用,Feign 自身的配置會被覆蓋。
    • Hystrix 的超時時間和 ribbon 的超時時間存在一定的關(guān)系
    • 說明下,如果不啟用 Hystrix,Feign 的超時時間則是 Ribbon 的超時時間,Feign 自身的配置也會被覆蓋
    Hystrix的超時時間=Ribbon的重試次數(shù)(包含首次) * (ribbon.ReadTimeout + ribbon.ConnectTimeout)Ribbon重試次數(shù)(包含首次)= 1 + ribbon.MaxAutoRetries + ribbon.MaxAutoRetriesNextServer + (ribbon.MaxAutoRetries * ribbon.MaxAutoRetriesNextServer)

    五.zuul

    1.微服務(wù)網(wǎng)關(guān)?

    服務(wù)網(wǎng)關(guān)是微服務(wù)架構(gòu)中一個不可或缺的部分。通過服務(wù)網(wǎng)關(guān)統(tǒng)一向外系統(tǒng)提供 REST API 的過程中,除了具備服務(wù)路由、均衡負載功能之外,它還具備了權(quán)限控制等功能。Spring Cloud Netflix 中的 Zuul 就擔(dān)任了這樣的一個角色,為微服務(wù)架構(gòu)提供了前門保護的作用,同時將權(quán)限控制這些較重的非業(yè)務(wù)邏輯內(nèi)容遷移到服務(wù)路由層面,使得服務(wù)集群主體能夠具備更高的可復(fù)用性和可測試性。

    Zuu 包含了對請求的路由和過濾 兩個最主要的功能:

    其中路由功能負責(zé)將外部請求轉(zhuǎn)發(fā)到具體的微服務(wù)實例上是實現(xiàn)外部訪問統(tǒng)一入口的基礎(chǔ),過濾功能則負責(zé)對請求的處理過程進行干預(yù),是實現(xiàn)請求校驗、服務(wù)聚合等功能的基礎(chǔ);

    Zuul 和 Eureka 進行整合,將 Zuul 自身注冊為 Eureka 服務(wù)治理下的應(yīng)用,同時從 Eureka 中獲得其他微服務(wù)的信息,也即以后的訪問微服務(wù)都是通過 Zuul.

    2.Zuul 網(wǎng)關(guān)的作用

    網(wǎng)關(guān)有以下幾個作用:

    • 統(tǒng)一入口:未全部為服務(wù)提供一個唯一的入口,網(wǎng)關(guān)起到外部和內(nèi)部隔離的作用,保障了后臺服務(wù)的安全性。
    • 鑒權(quán)校驗:識別每個請求的權(quán)限,拒絕不符合要求的請求。
    • 動態(tài)路由:動態(tài)的將請求路由到不同的后端集群中。
    • 減少客戶端與服務(wù)端的耦合:服務(wù)可以獨立發(fā)展,通過網(wǎng)關(guān)層來做映射。

    3.zuul 的功能?

    使用 Zuul 的過濾器, 可以對請求的一些列信息進行安全認證/權(quán)限認證/身份識別/限流/記錄日志等功能。只需要自定義 Filter 后繼承 ZuulFilter 類即可。重寫其 filterType、filterOrder、shouldFilter 以及 run 方法。 filterType 表示 filter 執(zhí)行的時機:

    其 value 值含義如下所示:

    • pre:在請求被路由之前調(diào)用 比如:登錄驗證
    • routing: 在請求被路由之中調(diào)用
    • post: 在請求被路由之后調(diào)用
    • error: 處理請求發(fā)生錯誤時調(diào)用
    • filterOrder 表示執(zhí)行的優(yōu)先級,值越小表示優(yōu)先級越高
    • shouldFilter 則表示該 filter 是否需要執(zhí)行

    4.路由配置

    zuul:sensitiveHeaders: Cookie,Set-Cookie,Authorizationroutes:portal:path: /portal-service/** #訪問路徑:http:/localhost:8888/portal-service/portal/1service-id: portal-servicegoods:path: /goods-service/** #http:/localhost:8888/goods-service/kwanGoodsInfo/1service-id: goods-servicehost:connect-timeout-millis: 5000 #超時時間prefix: /api #訪問路徑:http:/localhost:8888/api/portal-service/portal/1 http:/localhost:8888/api/goods-service/kwanGoodsInfo/1retryable: trueignored-services: portal-service #感略某個服務(wù)名,禁止通過該服務(wù)名訪可# ignored-services: * #禁止通過所有的服務(wù)名訪間ignored-patterns: /**/feign/** #不給匹配此棋式的路徑進行路由·那么你到時候訪間不到LogFilter:route:disable: true #用LogFilter過濾器

    4.過濾器

    filter 是 zuul 的核心組件,zuul 大部分功能都是通過過濾器來實現(xiàn)的。zuul 中定義了 4 種標準過濾器類型,這些過濾器類型對應(yīng)于清求的典型生命周期。

    • PRE:這種過濾器在請求被路由之前調(diào)用。可利用這種過濾器實現(xiàn)身份驗證、在集群中選擇請求的微服務(wù)、記錄調(diào)試信息等。
    • ROUTING:這種過濾器將請求路由到微服務(wù)。這種過濾器用于構(gòu)建發(fā)送給微服務(wù)的請求,并使用 Apache HttpClient:或 Netfilx Ribbon 請求微服務(wù)
    • POST:這種過濾器在路由到微服務(wù)以后執(zhí)行。這種過濾器可用來為響應(yīng)添加標準的 HTTP Header 收集統(tǒng)計信息和指標、將響應(yīng)從微服務(wù)發(fā)送給客戶端等。
    • ERROR:在其他階段發(fā)生錯誤時執(zhí)行該過濾器。

    5.過濾器禁用

    zuul 過濾器的禁用,Spring Cloud 默認為 Zuul 編寫并啟用了一些過濾器,例妝如 DebugFilter,

    FormBodyWrapperFilter 等,這些過濾器都存放在 spring-cloud-netflix-zuul 這個 jr 包里,一些場景下,想要禁用掉部分過濾器,該怎么辦呢?只需在 application.properties 里設(shè)置 zuul…disable=true 例如,要禁用上面我們寫的過濾器,這樣配置就行了:

    zuul.LogFilter.route.disable=true

    6.Zuul 的熔斷降級

    zuul 是一個代理服務(wù),但如果被代理的服務(wù)突然斷了,這個時候 zuul 上面會有出錯信息,例如,停止了被調(diào)用的微服務(wù);一般服務(wù)方自己會進行服務(wù)的熔斷降級,但對于 zuul 本身,也應(yīng)該進行 zuul 的降級處理:

    Zuul 的 fallback 容錯處理邏輯,只針對 timeout 異常處理,當(dāng)請求被 Zuul 路由后,只要服務(wù)有返回(包括異常),都不會觸發(fā)Zuul的fallback容錯邏輯。

    因為對于 Zuul 網(wǎng)關(guān)來說,做請求路由分發(fā)的時候,結(jié)果由遠程服務(wù)運算的。那么遠程服務(wù)反饋了異常信息,Zuul 網(wǎng)關(guān)不會處理異常,因為無法確定這個錯誤是否是應(yīng)用真實想要反饋給客戶端的。

    六.config

    1.分布式配置中心

    Spring Cloud Config 為服務(wù)端和客戶端提供了分布式系統(tǒng)的外部化配置支持。

    配置服務(wù)器默認采用 git 來存儲配置信息,這樣就有助于對環(huán)境配置進行版本管理,并且可以通過 git 客戶端工具來方便的管理和訪問配置內(nèi)容。當(dāng)然他也提供本地化文件系統(tǒng)的存儲方式

    配置中心用途 :

    • 變量獲取
    • 加解密
    • 自動刷新
    • 高可用
    • 安全認證

    2.為什么需要分布式配置中心

    在分布式微服務(wù)體系中,服務(wù)的數(shù)量以及配置信息日益增多,比如各種服務(wù)器參數(shù)配置、各種數(shù)據(jù)庫訪問參數(shù)配置、各種環(huán)境下配置信息的不同、配置信息修改之后實時生效等等,傳統(tǒng)的配置文件方式或者將配置信息存放于數(shù)據(jù)庫中的方式已無法滿足開發(fā)人員對配置管理的要求,如:

    • 安全性:配置跟隨源代碼保存在代碼庫中,容易造成配置泄漏
    • 時效性:修改配置,需要重啟服務(wù)才能生效
    • 局限性:無法支持動態(tài)調(diào)整:例如日志開關(guān)、功能開關(guān)

    3.常用分布式配置中心框架

    • Apollo(阿波羅):攜程框架部門研發(fā)的分布式配置中心,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r推送到應(yīng)用端,并且具備規(guī)范的權(quán)限、流程治理等特性,適用于微服務(wù)配置管理場景
    • diamond:淘寶開源的持久配置中心,支持各種持久信息(比如各種規(guī)則,數(shù)據(jù)庫配置等)的發(fā)布和訂閱
    • XDiamond:全局配置中心,存儲應(yīng)用的配置項,解決配置混亂分散的問題,名字來源于淘寶的開源項目 diamond,前面加上一個字母 X 以示區(qū)別。
    • Qconf:奇虎 360 內(nèi)部分布式配置管理工具,用來替代傳統(tǒng)的配置文件,使得配置信息和程序代碼分離,同時配置變化能夠?qū)崟r同步到客戶端,而且保證用戶高效讀取配置,這使的工程師從瑣碎的配置修改、代碼提交、配置上線流程中解放出來,極大地簡化了配置管理工作;
    • Disconf:百度的分布式配置管理平臺,專注于各種分布式系統(tǒng)配置管理的通用組件和通用平臺,提供統(tǒng)一的配置管理服務(wù);
    • Spring Cloud Config:Spring Cloud 微服務(wù)開發(fā)的配置中心,提供服務(wù)端和客戶端支持;

    4.什么是 Spring Cloud Config?

    Spring Cloud Config 是一個解決分布式系統(tǒng)的配置管理方案。它包含 Client 和 Server 兩個部分,Server 提供配置文件的存儲、以接口的形式將配置文件的內(nèi)容提供出去,Client 通過接口獲取數(shù)據(jù)、并依據(jù)此數(shù)據(jù)初始化自己的應(yīng)用。

    Spring cloud 使用 git 或 svn、也可以是本地存放配置文件,默認情況下使用 git。

    5.配置路由規(guī)則

    /{application)-{profile}.properties

    http://localhost:8888/application-dev.properties

    /{label}/{application}-{profile}.properties

    http://localhost:8888/master/application-dev.properties

    /[application}-{profile}.yml

    http://localhost:8888/master/application-dev.yml

    /{label}/{application}-{profile}.yml

    http://localhost:8888/master/application-dev.properties

    其中:

    {application}表示配置文件的名字,對應(yīng)的配置文件即 application,

    {profile}表示環(huán)境,有dev、test、online 及默認,

    {label}表示分支,默認我們放在 master 分支上,

    通過瀏覽器上訪問http:/localhost:8888/application,/dev/master

    6.加解密

    加解密是借助 JCE 實現(xiàn)的,默認情況下我們的 JRE 中自帶了 JCE(Java Cryptography Extension),但是默認是一個有限長度的版本,我們這里需要一個不限長度的 JCE,JCE 是對稱加密,安全性相對非對稱加密低一點,但是使用更加方便一點

    下載完成之后解壓,把得到到兩個 Jar 包復(fù)制到$JAVA_HOME\jre\lib\security 目錄下。

    在我們的 configserver 項目中的 bootstrap.yml 配置文件中加入如下配置項:

    encrypt:key: Thisismysecretkey

    訪問下面連接進行單個數(shù)據(jù)加密,這里是 post 請求,不是 get

    #加密 http://localhost:7001/encrypt#解密 http:/192.168.6.817001/decrypt

    可能會報錯,需要添加賬號密碼

    username='{cipher)516269d5f6af298bf843b31c847ad705d8305e784c394c7395a55a0742d8b69d'

    需要使用{cipher}的密文形式,單引號不要忘記了。然后 push 到遠程。

    加解密在 config-server 服務(wù)中進行的,解密過程不需要在客戶端進行配置

    7.加密過程安全認證

    1.添加依賴

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId> </dependency>

    2.config 配置

    在 config 的配置文件中配置

    spring:security:user:password: user123 #配置登陸的密碼是user123name: user #配置登陸的賬戶是user

    或者

    顯式指定賬號密碼,指定賬戶密碼的優(yōu)先級要高于 URI

    spring:cloud:config:label: ${spring.profiles.active} #指定Git倉庫的分支,對應(yīng)config server 所獲取的配置文件的{label}discovery:enabled: true #表示使用服務(wù)發(fā)現(xiàn)組件中的configserver ,而不是自己指定config server的uri,默認為falseservice-id: microservice-config-server #服務(wù)發(fā)現(xiàn)中configserver的serverIdfail-fast: true #失敗快速響應(yīng)username: userpassword: user123

    3.客戶端配置

    spring:cloud:config:uri: http://user:user123@localhost:7001/

    7.局部刷新

    Spring Boot 的 actuator 提供了一個刷新端點/refresh,添加依賴

    spring-boot-starter-actuator,可用于配置的刷新;

    <!--springboot的一個監(jiān)控actuator--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>

    在 Controller 上添加注解@RefreshScope,添加這個注解的類會在配置更新時得到特殊的處理;

    打開 web 訪問端點

    management,endpoints.web.exposure.include=“*”

    訪問http:/localhost:8080/actuator/refresh 進行手動刷新配置;必須要 post 方式訪問這個接口

    8.詳解@RefreshScope

    8.全局刷新

    全局刷新需要使用到消息總線

    前面使用/actuator/refresh 端點手動刷新配置雖然可以實現(xiàn)刷新,但所有微服務(wù)節(jié)點的配置都需要手動去刷新,如果微服務(wù)非常多,其工作量非常龐大。因此實現(xiàn)配置的自動刷新是志在必行,Spring Cloud Bus 就可以用來實現(xiàn)配置的自動刷新;

    Spring Cloud Bus 使用輕量級的消息代理(例如 RabbitMQ、Kafka 等)廣播傳播狀態(tài)的更改(例如配置的更新)或者其他的管理指令,可以將 Spring Clou Bus 想象成一個分布式的 Sprina Boot Actuator;

    #形置rabbitmq spring.rabbitmq.host=192.168.10.128 spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password-guest #開啟spring cloud bus默認是開啟的,也可以省略速形置 spring.cloud.bus.enabled=true 打開所有的web訪問端點 management.endpoints.web.exposure.include=*

    各個微服務(wù)(客戶端),其他各個微服務(wù)用于接收消息,那么也需要有 spring cloud bus 的依賴和 RabbitMQ 的連接信息;I

    然后 post 方式請求地址,如果返回成功,則 RabbitMQ 將收到消息,然后微服務(wù)會消費消息,config 的所有客戶端的微服務(wù)配置都會動態(tài)刷新;

    http:/localhost::8888/actuator//bus-refresh

    2.什么是總線

    在微服務(wù)架構(gòu)的系統(tǒng)中,通常會使用輕量級的消息代理來構(gòu)建一個共用的消息主題,并讓系統(tǒng)中所有微服務(wù)實例都連接上來。由于該主題中產(chǎn)生的消息會被所有實例監(jiān)聽和消費,所以稱它為消息總線。在總線上的各個實例,都可以方便地廣播一些需要讓其他連接在該主題上的實例都知道的消息。

    3.消息總線原理

    ConfigClient 實例都監(jiān)聽 MQ 中同一個 topic(默認是 springCloudBus)。當(dāng)一個服務(wù)刷新數(shù)據(jù)的時候,它會把這個信息放入到 Topic 中,這樣其它監(jiān)聽同一 Topic 的服務(wù)就能得到通知,然后去更新自身的配置。

    通過使用 Spring Cloud Bus 與 Spring Cloud Config 的整合,并以 RabbitMQ 作為消息代理,實現(xiàn)了應(yīng)用配置的動態(tài)更新。

    4.SpringCloudBus

    Spring Cloud Bus 是用來將分布式系統(tǒng)的節(jié)點與輕量級消息系統(tǒng)鏈接起來的框架,它整合了 Java 的事件處理機制和消息中間件的功能。
    Spring Clud Bus 目前支持 RabbitMQ 和 Kafka。

    Spring Cloud Bus 能管理和傳播分布式系統(tǒng)間的消息,就像一個分布式執(zhí)行器,可用于廣播狀態(tài)更改、事件推送等,也可以當(dāng)作微服務(wù)間的通信通道。

    利用消息總線觸發(fā)一個服務(wù)端 ConfigServer 的/bus/refresh 端點,而刷新所有客戶端的配置

    當(dāng)我們將系統(tǒng)啟動起來之后,“Service A”的三個實例會請求 Config Server 以獲取配置信息,Config Server 根據(jù)應(yīng)用配置的規(guī)則從 Git 倉庫中獲取配置信息并返回。

    此時,若我們需要修改“Service A”的屬性。首先,通過 Git 管理工具去倉庫中修改對應(yīng)的屬性值,但是這個修改并不會觸發(fā)“Service A”實例的屬性更新。我們向“Service A”的實例 3 發(fā)送 POST 請求,訪問/bus/refresh接口。此時,“Service A”的實例 3 就會將刷新請求發(fā)送到消息總線中,該消息事件會被“Service A”的實例 1 和實例 2 從總線中獲取到,并重新從 Config Server 中獲取他們的配置信息,從而實現(xiàn)配置信息的動態(tài)更新。

    而從 Git 倉庫中配置的修改到發(fā)起/bus/refresh的 POST 請求這一步可以通過 Git 倉庫的 Web Hook 來自動觸發(fā)。由于所有連接到消息總線上的應(yīng)用都會接受到更新請求,所以在 Web Hook 中就不需要維護所有節(jié)點內(nèi)容來進行更新,從而解決了通過 Web Hook 來逐個進行刷新的問題。

    通過destination參數(shù)來指定需要更新配置的服務(wù)或?qū)嵗?/p>

    七.Sleuth

    1.什么是 Sleuth?

    Spring Cloud Sleuth 是 Spring Cloud 提供的分布式系統(tǒng)服務(wù)鏈追蹤組件,它大量借用了 Google 的 Dapper,Twitter 的 Zipkin。學(xué)習(xí) Spring Cloud Sleuth,最好先對 Zipkin 有一些了解,對 span、trace 這些概念有相應(yīng)的認識。

    2.為什么需要 Sleuth?

    鏈路追蹤:通過 Sleuth 可以很清楚的看出一個請求都經(jīng)過了那些服務(wù),可以很方便的理清服務(wù)間的調(diào)用關(guān)系等。

    性能分析:通過 Sleuth 可以很方便的看出每個采樣請求的耗時,分析哪些服務(wù)調(diào)用耗時,當(dāng)服務(wù)調(diào)用的耗時隨著請求量的增大而增大時, 可以對服務(wù)的擴容提供一定的提醒。

    數(shù)據(jù)分析,優(yōu)化鏈路:對于頻繁調(diào)用一個服務(wù),或并行調(diào)用等,可以針對業(yè)務(wù)做一些優(yōu)化措施。

    可視化錯誤:對于程序未捕獲的異常,可以配合 Zipkin 查看。

    • 快速發(fā)現(xiàn)問題
    • 判斷故障影響范圍
    • 梳理服務(wù)依賴以及依賴的合理性
    • 分析鏈路性能問題以及實時容量規(guī)劃

    單純的理解鏈路追蹤,就是將一次分布式請求還原成調(diào)用鏈路,進行日志記錄,性能監(jiān)控并將一次分布式請求的調(diào)用情況集中展示。比如各個服務(wù)節(jié)點上的耗時、請求具體到達哪臺機器上、每個服務(wù)節(jié)點的請求狀態(tài)等等。

    3.鏈路追蹤相關(guān)產(chǎn)品

    常見的鏈路追蹤技術(shù)有下面這些 :

    cat:由大眾點評開源,基于 Java 開發(fā)的實時應(yīng)用監(jiān)控平臺,包括實時應(yīng)用監(jiān)控,業(yè)務(wù)監(jiān)控 。 集成方案是通過代碼埋點的方式來實現(xiàn)監(jiān)控,比如: 攔截器,過濾器等。 對代碼

    的侵入性很大,集成成本較高。風(fēng)險較大。

    zipkin:由 Twitter 公司開源,開放源代碼分布式的跟蹤系統(tǒng),用于收集服務(wù)的定時數(shù)據(jù),以解決微服務(wù)架構(gòu)中的延遲問題,包括:數(shù)據(jù)的收集、存儲、查找和展現(xiàn)。該產(chǎn)品結(jié)合

    spring-cloud-sleuth 使用較為簡單, 集成很方便, 但是功能較簡單。

    pinpoint:Pinpoint 是韓國人開源的基于字節(jié)碼注入的調(diào)用鏈分析,以及應(yīng)用監(jiān)控分析工具。特點是支持多種插件, UI 功能強大,接入端無代碼侵入。

    skywalking:本土開源的基于字節(jié)碼注入的調(diào)用鏈分析,以及應(yīng)用監(jiān)控分析工具。特點是支持多種插件, UI 功能較強,接入端無代碼侵入。目前已加入 Apache 孵化器。

    Sleuth:SpringCloud 提供的分布式系統(tǒng)中鏈路追蹤解決方案。

    注意: SpringCloud alibaba 技術(shù)棧中并沒有提供自己的鏈路追蹤技術(shù)的,我們可以采用Sleuth +Zinkin來做鏈路追蹤解決方案

    4.基本術(shù)語?

    Sleuth 基本概念涉及到三個專業(yè)術(shù)語: spanTraceAnnotations

    span :基本工作單位,每次發(fā)送一個遠程調(diào)用服務(wù)就會產(chǎn)生一個 Span。Span 是一個 64 位的唯一 ID。通過計算 Span 的開始和結(jié)束時間,就可以統(tǒng)計每個服務(wù)調(diào)用所花費的時間。。

    Trace :一系列 Span 組成的樹狀結(jié)構(gòu),一個 Trace 認為是一次完整的鏈路,內(nèi)部包含 n 多個 Span。Trace 和 Span 存在一對多的關(guān)系,Span 與 Span 之間存在父子關(guān)系。

    Annotations :用來及時記錄一個事件的存在,一些核心 annotations 用來定義一個請求的開始和結(jié)束。

    開始與結(jié)束:

    • cs(Client Sent) :客戶端發(fā)起一個請求,這個 annotation 描述了這個 span 的開始;
    • sr(Server Received) :服務(wù)端獲得請求并準備開始處理它,如果 sr 減去 cs 時間戳便可得到網(wǎng)絡(luò)延遲;
    • ss(Server Sent) :請求處理完成(當(dāng)請求返回客戶端),如果 ss 減去 sr 時間戳便可得到服務(wù)端處理請求需要的時間;
    • cr(Client Received) :表示 span 結(jié)束,客戶端成功接收到服務(wù)端的回復(fù),如果 cr 減去 cs 時間戳便可得到客戶端從服務(wù)端獲取回復(fù)的所有所需時間。

    核心: 為什么能夠進行整條鏈路的追蹤? 其實就是一個 Trace ID 將 一連串的 Span 信息連起來了。根據(jù) Span 記錄的信息再進行整合就可以獲取整條鏈路的信息。

    5.什么是 zipkin

    Zipkin 是一種分布式跟蹤系統(tǒng)。它有助于收集解決微服務(wù)架構(gòu)中的延遲問題所需的時序數(shù)據(jù)。它管理這些數(shù)據(jù)的收集和查找。Zipkin 的設(shè)計基于 Google Dapper 論文。應(yīng)用程序用于向 Zipkin 報告時序數(shù)據(jù)。Zipkin UI 還提供了一個依賴關(guān)系圖,顯示了每個應(yīng)用程序通過的跟蹤請求數(shù)。如果要解決延遲問題或錯誤,可以根據(jù)應(yīng)用程序,跟蹤長度,注釋或時間戳對所有跟蹤進行篩選或排序。選擇跟蹤后,您可以看到每個跨度所需的總跟蹤時間百分比,從而可以識別有問題的應(yīng)用程序。

    6.zipkin 的坑

    SpringBoot2.2.x 以后的版本 集成 zipkin 的方式改變了,原來是通過@EnablezipkinServer注解,現(xiàn)在這個注解不起作用了。

    服務(wù)端應(yīng)該通過下載 jar 包,然后 運行 jar 包來集成 。 可以選擇版本下載,要選擇后綴為 -exec.jar 的,之后切換到 jar 包在的路徑,然后用 java -jar 的方式啟動就可以了(默認端口號是 9411 ,所以如果提供了 zipkin client,需要把它的配置文件中的端口號改成 9411,對應(yīng)的配置應(yīng)該是 zipkin: base-url: http://localhost:9411)

    spring:cloud:config:fail-fast: false #客戶端連接失敗時開啟重試,需要結(jié)合spring-retry、spring-aoplabel: main #獲取配置文件的分支名name: application-portal8081 #獲取的文件名profile: portal8081 #文件后綴uri: http://localhost:7001 #配置中心服務(wù)端地址zipkin:base-url: http://localhost:9411

    7.zipkin 下載安裝

    1.下載地址

    https://repo1.maven.org/maven2/io/zipkin/zipkin-server/

    2.下載 jar 包

    可以使用迅雷下載,或者科學(xué)上網(wǎng)

    3.啟動服務(wù)端

    啟動報錯,看看端口是否被占用

    java -jar zipkin-server-2.23.9-exec.jar

    4.訪問控制臺

    http://127.0.0.1:9411/zipkin

    8.客戶端配置

    1.pom 依賴

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zipkin</artifactId> </dependency>

    2.配置文件

    #端口號,指定端口,不然默認是8080,會出現(xiàn)沖突 server:port: 8081spring:cloud:config:fail-fast: false #客戶端連接失敗時開啟重試,需要結(jié)合spring-retry、spring-aoplabel: main #獲取配置文件的分支名name: application-portal8081 #獲取的文件名profile: portal8081 #文件后綴uri: http://localhost:7001 #配置中心服務(wù)端地址zipkin:base-url: http://localhost:9411 #zipkin地址 默認值就是0.1,代表收集10%的請求追蹤信息。discovery-client-enabled: falsesender:type: websleuth:sampler:percentage: 0.1 #收集百分比 eureka:client:service-url:defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/

    9.控制臺

    需要調(diào)用一下服務(wù),才能在控制臺查詢到

    • 可以看到請求過的鏈路信息
    • 包含的微服務(wù)
    • 耗時信息
    • 還能通過篩選條件進行查詢
    • 可以通過 trace id 進行查詢
    http://127.0.0.1:9411/zipkin

    詳細面板可以看到 :

    • 具體的統(tǒng)計信息
    • 統(tǒng)計耗時信息,開始時間以及結(jié)束時間,以及每一段的耗時信息
    • 標簽信息,接口信息
    • 請求方式,請求方法
    • Span ID
    • Trace ID
    • 服務(wù)名
    • 服務(wù)數(shù)
    • 深度
    • 跨度總數(shù)

    10.依賴關(guān)系圖

    11.采樣數(shù)據(jù)

    zikpin 日志采樣率設(shè)置為 0.1,就是 10 次只能有一次被記錄下來。當(dāng)時看到這個問題很郁悶,那 9 次的請求咋辦,日志不完整怎么排查錯誤呢?

    日志其實是完整的,日志可以用 logback 收集并保存成文件。所有的請求信息 都會被這個文件所記錄,只是 zikpin 側(cè)重于鏈路追蹤,并不是排查錯誤,更多的是我們知道服務(wù)直接調(diào)用耗時和服務(wù)直接依賴關(guān)系而已。所以不需要完整日志,只需要 0.1 比例就夠了

    sleuth:sampler:probability: 0.1

    而這個采樣其實只是對 zipkin 有效,只是在 zipkin 界面顯示 0.1 的日志而已,并不是后臺日志也都是只收集 0.1。

    而 logback 會把我們所有請求信息全部記錄下來,不會遺漏,這樣的話就可以順利排錯。

    12.數(shù)據(jù)持久化

    zipkin 中的數(shù)據(jù)默認是保存在內(nèi)存中的,重啟 sleuth 服務(wù),數(shù)據(jù)會被清空,這顯然是不合適的.

    zipkin 可以集成 elasticsearch,或者 mysql 進行數(shù)據(jù)的持久化,這樣服務(wù)重啟,數(shù)據(jù)不丟失.

    總結(jié)

    以上是生活随笔為你收集整理的【檀越剑指大厂—SpringCloudNetflix】SpringCloudNetflix高阶篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    国产一区二区三区视频在线 | 亚洲黄在线观看 | 亚洲少妇天堂 | 91精品国产乱码久久 | 在线观看成人一级片 | 超级碰碰碰免费视频 | 亚洲综合丁香 | 韩日精品中文字幕 | 五月婷婷狠狠 | 久草在线免费播放 | 91成人短视频在线观看 | av888av.com| 98精品国产自产在线观看 | 亚洲国产精品久久久久婷婷884 | 成人中心免费视频 | 欧美精品久久久久久久免费 | 色综合久久久久综合 | 又黄又刺激的视频 | 精品国产乱码 | 插综合网 | 天堂av一区二区 | 激情视频国产 | av中文字幕在线播放 | 国产精品18久久久 | 天天色天天搞 | 国产91精品一区二区麻豆网站 | 国产 日韩 欧美 在线 | 91精品免费在线观看 | 高清精品视频 | 中文字幕在线观看视频一区二区三区 | 久久专区 | 精品视频成人 | 丁香综合激情 | 91精品国产自产老师啪 | 亚洲播放一区 | 在线香蕉视频 | 亚洲国产精久久久久久久 | 日日夜操 | av日韩在线网站 | 99久久精品免费视频 | 国产99免费视频 | 日韩专区av| 国产免费中文字幕 | 99视频精品免费观看, | 午夜精品三区 | 在线看片91 | 青春草视频 | 久操伊人 | 亚洲美女精品区人人人人 | 久久精品视频99 | 天天色天天综合 | 欧美亚洲三级 | 在线免费观看av网站 | 久久成人高清视频 | 免费观看成人av | 999在线精品| 欧美一级片在线免费观看 | 中文字幕一区二区三区乱码不卡 | 午夜精品久久久久久久久久久久久久 | 国产精品无av码在线观看 | 国产精品免费久久久久影院仙踪林 | 国产在线精品二区 | 国产在线观看二区 | 开心激情婷婷 | 极品久久久 | 91最新视频在线观看 | 综合色站导航 | 亚洲精品在线一区二区 | 中文字幕丝袜美腿 | 欧美日韩在线视频一区二区 | 欧美一级大片在线观看 | 午夜久久久久久久久久影院 | 国产亚洲成av片在线观看 | 日韩精品一区二区免费 | 欧洲亚洲激情 | 五月天亚洲婷婷 | www.久久成人 | 天天色天天射天天操 | 亚洲色影爱久久精品 | 国产999精品| 久久9999久久免费精品国产 | 中文字幕在线观看网 | 五月婷婷中文网 | 国产在线不卡精品 | 美女久久精品 | 91插插插免费视频 | 日韩欧美视频一区二区 | 天天操夜夜摸 | 精品一区二区电影 | 国产在线91在线电影 | 欧美a级成人淫片免费看 | 91久久偷偷做嫩草影院 | 九色精品免费永久在线 | 91桃花视频 | 最近字幕在线观看第一季 | 激情深爱.com | 久久五月婷婷丁香社区 | 97电影在线 | 免费看黄在线 | 免费黄色在线播放 | 五月婷视频 | 91九色网站| 成年人免费在线播放 | 天天草综合网 | 国产精品久久久影视 | 高清av免费看 | 人人爽夜夜爽 | 国产a级片免费观看 | 在线日韩中文 | 久久久天天操 | 久久九九久久 | 国产精品igao视频网入口 | 亚洲精品视频久久 | 亚洲 中文 在线 精品 | 久久精品视频在线看 | 人人干人人做 | 婷婷伊人综合 | 成 人 a v天堂 | 天天色.com| 国产 色 | 韩国一区二区三区在线观看 | 91精品视频观看 | 久久久久久国产一区二区三区 | 91私密保健 | 久久视频在线 | 午夜久操 | 日韩欧三级| 日日日日| 最新中文字幕在线观看视频 | 精品日韩在线 | 在线观看成人小视频 | 亚洲在线国产 | 亚洲免费一级 | 欧美 日韩 国产 成人 在线 | 丝袜足交在线 | 久久久久久久电影 | 麻豆一区二区三区视频 | 亚洲污视频 | 精品国产伦一区二区三区 | 高潮久久久久久久久 | 亚洲,播放 | 色妞色视频一区二区三区四区 | 亚洲无在线 | 国产美女在线免费观看 | 久久区二区 | 国产精品 日韩 欧美 | 成人精品久久 | 五月天综合色激情 | 在线观看日韩 | 97视频在线免费播放 | 狠狠色伊人亚洲综合网站野外 | 色偷偷人人澡久久超碰69 | 日韩av手机在线看 | 免费在线观看的av网站 | 欧美va在线观看 | 国产精品久久久久久久久久久久久 | 久久99国产精品久久 | 成人在线电影观看 | 久久综合国产伦精品免费 | 日本在线成人 | 日韩高清成人在线 | 日本在线观看黄色 | 国产高清在线a视频大全 | 亚洲三级网站 | 日韩网站视频 | 黄色软件在线观看免费 | 在线免费av观看 | 国产精品欧美久久久久无广告 | 男女啪啪网站 | 国产黄色大片 | 国内精品免费久久影院 | 日韩久久精品一区二区 | 国产小视频在线看 | 97人人爽人人 | 久久综合给合久久狠狠色 | 中文字幕av全部资源www中文字幕在线观看 | 在线午夜电影神马影院 | 麻花豆传媒一二三产区 | 久久精品三级 | 亚洲成av人片在线观看 | 亚洲综合激情 | 福利视频精品 | 最新国产精品拍自在线播放 | 99久e精品热线免费 99国产精品久久久久久久久久 | 色姑娘综合| 精品国产伦一区二区三区观看说明 | 韩国av在线 | 亚洲黄色小说网 | 天天操天天拍 | av中文天堂在线 | 在线影院av | 久久精品欧美一区二区三区麻豆 | 日韩激情免费视频 | www视频免费在线观看 | 久久久国产精品一区二区中文 | av在线一二三区 | 亚洲精品欧美成人 | 亚洲另类人人澡 | 久草香蕉在线视频 | 黄色网址中文字幕 | 久久综合久久综合久久 | 日韩艹 | 91.dizhi永久地址最新 | 国产123av | 精品在线观看免费 | 91在线看网站 | 丁香狠狠| 国产视频丨精品|在线观看 国产精品久久久久久久久久久久午夜 | www.久久久com| 国产精品一区在线观看你懂的 | 久草在线免费看视频 | 欧美不卡视频在线 | 国产精品美女 | 99精品国产一区二区三区不卡 | 久久亚洲精品国产亚洲老地址 | av中文国产| 五月激情在线 | 亚洲黄色一级视频 | 久久人人爽人人爽人人片 | 999成人免费视频 | 欧美国产日韩一区二区 | 久久最新视频 | 玖操| 五月婷香 | 2022国产精品视频 | 在线精品亚洲 | 日韩欧美在线视频一区二区 | 啪啪免费视频网站 | 日本精品一区二区三区在线观看 | 在线综合 亚洲 欧美在线视频 | 午夜av剧场| 久久久久久久久久久久99 | 国产亚洲精品久 | 亚洲精品小视频 | 黄色软件视频大全免费下载 | 欧美视频在线观看免费网址 | 天天干人人干 | 国产在线污 | 五月婷婷综合网 | 国产丝袜网站 | 99精品福利| 日韩字幕 | 黄网站www | 国产精品乱看 | 区一区二区三区中文字幕 | 国产精品小视频网站 | 99久久久成人国产精品 | 在线黄色免费 | 中文字幕日韩一区二区三区不卡 | 国产专区精品视频 | 激情综合中文娱乐网 | 欧美999| 国产精品99爱 | 免费国产视频 | 日韩毛片久久久 | 免费在线a | www.亚洲黄| 国产一级久久久 | 国产日韩欧美自拍 | 欧美日韩免费观看一区=区三区 | 成人午夜免费福利 | 国产v欧美 | 在线免费日韩 | 国产一级大片在线观看 | 337p欧美| 综合色爱| 久久调教视频 | 手机成人免费视频 | 97国产大学生情侣白嫩酒店 | 97电影院在线观看 | 精品在线观看一区二区 | 久久激情视频网 | 一区二区三区动漫 | 国产成人久久av免费高清密臂 | 最新av中文字幕 | 国产精品九九久久久久久久 | 91在线视频播放 | 国产精品永久在线观看 | 91在线91拍拍在线91 | 99亚洲精品 | 久久婷婷五月综合色丁香 | 国产精品成人免费一区久久羞羞 | 亚洲国产婷婷 | 黄色软件在线观看视频 | 久草在线91 | www九九热 | 日日添夜夜添 | 久久亚洲精品电影 | 国产精品国产三级国产专区53 | 亚洲精品国产日韩 | 91av99| 久久久久免费精品国产 | 日韩 精品 一区 国产 麻豆 | 一区二区三区高清 | 麻豆视频免费看 | 久久精品国产一区 | www五月婷婷 | 成人全视频免费观看在线看 | 狠狠的操你| 国产三级精品三级在线观看 | 久福利| 五月婷婷综合网 | 亚洲黄色区 | 欧美午夜性 | 中文字幕国产精品一区二区 | 91精品一区二区在线观看 | 国产伦理精品一区二区 | 国产精品视频全国免费观看 | 操久在线 | 91麻豆免费看 | 久久男女视频 | 日本精品视频网站 | 免费在线观看中文字幕 | 国产精品麻豆一区二区三区 | 天天激情在线 | 久久综合婷婷综合 | 国产黄a三级三级 | 丁香花中文字幕 | 成年人国产在线观看 | 免费黄a | 福利视频一二区 | 久久综合五月 | av免费片| 久久精品美女视频 | 免费高清影视 | 91视频久久久 | 久久人人爽人人爽人人片av软件 | 久久久久日本精品一区二区三区 | 欧美激情第八页 | 天天天天色射综合 | 人人澡视频 | 成人午夜电影免费在线观看 | 欧美另类高清 videos | 日日操天天操夜夜操 | 超碰人人超 | 天天天天色综合 | 国产91勾搭技师精品 | 欧美日韩不卡一区二区 | 九九久久精品 | 夜夜操天天摸 | 一区二区不卡视频在线观看 | 视频成人| 四虎8848免费高清在线观看 | 国产69久久久欧美一级 | 91麻豆精品国产91久久久无限制版 | www.天天射.com | 日韩免费中文 | 伊人久久国产 | 久久精品综合网 | 黄色一级免费电影 | 久久九九免费视频 | 国产日韩视频在线观看 | 久草在线视频资源 | 欧美在线观看视频一区二区三区 | 久久久久电影网站 | 极品中文字幕 | 欧美国产日韩在线观看 | 99超碰在线观看 | 三级av免费 | 亚洲视频在线观看免费 | 波多野结衣视频网址 | 999久久a精品合区久久久 | 黄色福利视频网站 | 国产精品免费一区二区 | 4438全国亚洲精品在线观看视频 | 国产小视频在线播放 | 天天拍天天爽 | 亚洲精品18日本一区app | 夜夜躁天天躁很躁波 | 日韩在线观看一区二区 | 日韩精品视频一二三 | 9在线观看免费高清完整版在线观看明 | 中文字幕在线观看第一区 | 911国产| 成人中文字幕在线 | 黄色的片子 | 国产日韩精品在线观看 | 久久a国产| 91九色蝌蚪视频网站 | 手机在线永久免费观看av片 | 国产一区播放 | 日韩精品久久久久久久电影竹菊 | 国产精品自拍av | 一区二区不卡 | 久久久免费观看完整版 | 免费十分钟 | 婷五月激情 | 亚洲久草视频 | 在线观看成人av | 国产一区二区免费看 | 国产专区日韩专区 | 欧美国产日韩一区二区三区 | 日本高清中文字幕有码在线 | 2018亚洲男人天堂 | 中文视频在线播放 | 日韩欧美有码在线 | 中文字幕91| 国精产品一二三线999 | 中文字幕欧美三区 | 色五月成人 | 成人在线免费观看视视频 | 亚洲japanese制服美女 | 久久久久久久久久毛片 | av在线免费观看网站 | 在线观看日韩精品视频 | 日韩av快播电影网 | av电影在线免费观看 | 久久综合亚洲鲁鲁五月久久 | 97在线观看免费 | 久草视频在线观 | 四虎成人精品永久免费av九九 | 狠狠色丁香九九婷婷综合五月 | 久久久久99精品国产片 | 成人免费在线视频观看 | 色综合天天视频在线观看 | 久香蕉| 国产无遮挡又黄又爽在线观看 | 黄色电影小说 | 欧美中文字幕第一页 | 久久久性 | 久久99国产一区二区三区 | 91在线九色| 国产一区二区久久久久 | 日av免费 | 亚洲国产免费网站 | 最新99热 | 日韩一区二区三区免费视频 | 97在线视频免费 | 欧美老人xxxx18| 成年人在线免费看片 | 99亚洲精品| 狠狠狠干| 美女很黄免费网站 | 久久免费视频在线观看 | 91av大全| 午夜视频在线观看网站 | 中文字幕在线观看网址 | 国产精品久久久久久久久大全 | 日韩一级电影在线 | 国产亚洲精品久久19p | 日韩精品高清视频 | 欧美一级黄色片 | 亚洲欧洲中文日韩久久av乱码 | 亚洲精品久久久久999中文字幕 | 成人免费视频免费观看 | 国内丰满少妇猛烈精品播 | 免费午夜视频在线观看 | 免费人成在线观看 | 9在线观看免费高清完整版 玖玖爱免费视频 | 99热这里有 | 久草视频免费播放 | 国产精品手机在线播放 | 久久国产精品第一页 | 免费大片av | 国产精品video爽爽爽爽 | 99热国产精品 | 久久avav| 在线观看视频色 | 国产在线不卡一区 | 国产美女在线免费观看 | 天天弄天天干 | 夜夜操天天干, | 最新超碰在线 | 国产精品久久久久久婷婷天堂 | 91av九色 | 狠狠狠狠狠狠操 | 色婷婷狠狠操 | 免费v片 | 中字幕视频在线永久在线观看免费 | 日本精品久久久一区二区三区 | 色在线免费观看 | 国产原创av片| 国精产品999国精产品岳 | 国产高清视频免费观看 | 999久久国产精品免费观看网站 | 国产成人精品综合久久久 | 精品国产欧美一区二区 | 久草在线视频首页 | 免费成人在线电影 | 亚洲精品66| 久久久久久久久久影院 | 国产日产欧美在线观看 | 国内精品视频一区二区三区八戒 | 亚洲视频999| 中文字幕中文字幕在线中文字幕三区 | 成年人看片 | 久久视频精品在线 | 国偷自产视频一区二区久 | 日韩在线视频免费播放 | 日韩网站在线观看 | 91av视频观看 | 欧美韩国日本在线 | 国产精品国产亚洲精品看不卡15 | 国产视频1区2区3区 久久夜视频 | 97国产精品视频 | 日韩精品久久久久久久电影99爱 | 成年人在线免费看视频 | 在线亚洲午夜片av大片 | 国产免费观看高清完整版 | 在线免费看黄网站 | 91大神精品视频在线观看 | 日韩在线网址 | 涩五月婷婷 | 免费看搞黄视频网站 | 中文字幕在线观看网站 | 久久精品精品电影网 | 天天综合区 | 91人人揉日日捏人人看 | 天天摸天天操天天爽 | 偷拍视频一区 | 国产系列精品av | 91视频在线免费 | 高清免费在线视频 | 四虎欧美 | 日韩欧美不卡 | 亚洲精品免费在线播放 | 久久av中文字幕片 | 国产小视频国产精品 | 九九精品视频在线观看 | 国产精品毛片一区 | 国产成人久久精品亚洲 | 亚洲精品一区二区三区新线路 | 色综合久久久久综合99 | 成人a在线观看高清电影 | 久久久久久国产精品 | 玖玖国产精品视频 | 色婷婷亚洲 | 日韩r级在线 | 欧洲激情综合 | 久久在线免费观看 | 日韩美女免费线视频 | 日韩精品中文字幕在线不卡尤物 | 日韩av高清 | 超碰大片 | 日韩欧美综合视频 | 免费在线观看av | 国外调教视频网站 | 人人爽人人爽av | 亚洲成人资源网 | 国产一区二区在线播放视频 | 午夜电影久久久 | 国产免费资源 | 日韩黄视频 | 日韩欧美高清视频在线观看 | 成人观看 | 欧美日韩一二三四区 | a午夜在线 | 亚洲视频99 | 在线免费观看一区二区三区 | av韩国在线 | 日本不卡123区 | 亚洲视频,欧洲视频 | 国产精品福利久久久 | 在线看欧美 | 国内一级片在线观看 | 国产精品一区二区三区在线看 | 久久99久久99精品免视看婷婷 | 欧美日韩国产精品爽爽 | 欧美日韩国产一区二区在线观看 | 亚洲日本中文字幕在线观看 | 成人黄色大片网站 | 成人久久18免费网站麻豆 | 在线观看亚洲国产 | 精品久久久久久久久久久久久久久久 | 樱空桃av| 亚洲成人av一区二区 | 日韩av片免费在线观看 | 免费三级网 | 91精品国自产在线偷拍蜜桃 | 日韩91精品| 成片视频免费观看 | 四虎永久免费在线观看 | 亚洲精品高清在线观看 | 激情网五月婷婷 | 亚洲最新av网址 | a电影在线观看 | 一区二区不卡 | 国产精品第一视频 | 欧美91精品 | 国产一卡在线 | 免费看污在线观看 | 久久久久国产精品免费网站 | 亚洲成人资源在线观看 | 色网站国产精品 | 欧美成人一二区 | 免费h精品视频在线播放 | 国产国产人免费人成免费视频 | 国产九色91 | 日日夜夜精品视频天天综合网 | 亚洲天堂网在线观看视频 | 在线观看黄网 | 黄免费在线观看 | 91九色蝌蚪视频 | 丁香综合激情 | 亚洲mv大片欧洲mv大片免费 | 亚洲高清视频在线观看免费 | 成人久久久久久久久久 | 成 人 黄 色 免费播放 | 91综合久久一区二区 | 色播六月天 | 久久一区二区三区超碰国产精品 | 亚洲黄色在线观看 | 精品资源在线 | 精品福利片 | 国产又粗又猛又黄 | 久久精品国产一区二区三 | 国产精品亚洲精品 | 中文av资源站 | 少妇性xxx | 人人搞人人爽 | 中文字幕在线视频一区 | 免费美女av | 久久视频国产 | 国产精品久久久久久久久免费看 | 一本一道波多野毛片中文在线 | 制服丝袜一区二区 | 成人cosplay福利网站 | 欧美一级免费在线 | 亚洲美女免费精品视频在线观看 | 人人添人人澡人人澡人人人爽 | 人人揉人人揉人人揉人人揉97 | 国产福利小视频在线 | 欧美午夜性 | 激情综合色综合久久综合 | 亚洲人成人在线 | 国产精品久久久久久久久久久久 | 在线观看av黄色 | 国产精品成人自产拍在线观看 | 国产成人精品一区二区三区免费 | 日韩二区精品 | 日韩亚洲国产精品 | 国产亚洲精品久久久久久移动网络 | 婷婷视频在线播放 | 亚洲91精品| 久久激情小说 | 国产一区二区三区免费视频 | 中文字幕在线观看亚洲 | 久久综合久色欧美综合狠狠 | 日韩精品中文字幕一区二区 | 91污视频在线观看 | 亚洲免费观看视频 | 天天操天天操天天操 | 九九视频在线播放 | 天天爱天天射天天干天天 | 国产一区二区在线免费视频 | 夜夜视频 | 操久| 久久国产精品区 | 91九色蝌蚪视频网站 | 激情久久久久久久久久久久久久久久 | 国产精品1区2区 | 久久精品视频国产 | 国产亚洲精品久久久久久久久久久久 | 黄在线 | 国产高清在线免费 | 久草免费在线视频观看 | 久久久毛片| 国产黄色片一级 | 91丨九色丨国产女 | 国产精品欧美激情在线观看 | 99视屏| 人人爱人人做人人爽 | 欧美一级裸体视频 | 碰天天操天天 | 国产91精品久久久久久 | 久久99国产精品久久99 | 亚洲天天在线 | 中文字幕一区二区三区精华液 | 久久99国产精品久久 | 亚洲视频 一区 | 又色又爽又激情的59视频 | 伊人首页| 四虎影视成人永久免费观看亚洲欧美 | 人人爽人人爽人人片 | 99热这里只有精品久久 | 国产1区2区3区精品美女 | 日韩精品三区四区 | 午夜精品久久久久久久久久久久 | 久久人人精品 | 国产中文字幕在线 | 在线精品视频免费播放 | 亚洲国产精品va在线看黑人动漫 | 久久黄视频 | 国内综合精品午夜久久资源 | 国产精品99蜜臀久久不卡二区 | 久久99久久99精品免费看小说 | 色婷婷综合久久久久 | 国产精品一区在线观看 | 日韩在线在线 | 国产视频每日更新 | 91免费国产在线观看 | 91在线资源 | 久久久亚洲国产精品麻豆综合天堂 | 狠狠狠狠狠狠狠狠 | 国产伦精品一区二区三区高清 | 在线观看久久 | 丁香婷婷综合激情五月色 | 成人av在线观 | 久久尤物电影视频在线观看 | 日韩一区二区三 | 国产精品1000 | 日韩欧美精选 | 国产香蕉视频在线观看 | 国产亚洲精品女人久久久久久 | 亚洲在线免费视频 | 91福利免费 | 久久久免费播放 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 夜夜操天天干, | 免费高清影视 | 91九色网站 | 青青五月天 | 亚洲男人天堂2018 | 国产欧美精品在线观看 | 日韩精品在线视频免费观看 | 成人国产电影在线观看 | 特级毛片网 | 视频国产 | 高清精品在线 | 欧美日韩综合在线 | 麻豆久久久久久久 | 激情视频免费在线 | 在线免费观看不卡av | 国产视频在 | 在线免费91 | 国产福利电影网址 | 日韩一区二区三区免费电影 | 91视频高清完整版 | 五月天精品视频 | 中国一级片在线观看 | 国产日韩欧美中文 | 欧美午夜视频在线 | 国产精品专区在线 | 日韩欧美精品在线 | 欧美精品久久久久久 | 天天色综合1 | 911精品美国片911久久久 | 久久国产一区二区三区 | 国产手机视频 | 国产中文字幕第一页 | 很黄很黄的网站免费的 | 国产精品成人aaaaa网站 | 国内精品免费久久影院 | 欧美久草视频 | 国产成人黄色片 | 久艹视频在线免费观看 | 在线国产日本 | 久久久久久久久久久久久久电影 | 四虎影院在线观看av | 久久精品毛片 | 久久久久久久久福利 | 久久综合九色99 | 亚洲欧美日韩一区二区三区在线观看 | 天天干,天天操,天天射 | 国产成人777777 | 日韩毛片久久久 | 欧美精彩视频 | 在线观看免费视频你懂的 | 国产网站在线免费观看 | 精品人妖videos欧美人妖 | 又湿又紧又大又爽a视频国产 | 9999在线观看 | 美腿丝袜一区二区三区 | 91九色蝌蚪国产 | 免费看污污视频的网站 | 国产伦精品一区二区三区… | 麻豆小视频在线观看 | 日韩av在线一区二区 | 特级西西444www大精品视频免费看 | 九九九九精品 | 午夜在线资源 | 亚洲a成人v | 亚洲综合视频在线播放 | 亚洲区视频在线观看 | 18岁免费看片 | 精品在线小视频 | 99久久久国产精品免费99 | 亚洲永久精品一区 | 国产美女精品在线 | 欧美在线观看视频一区二区 | 激情综合中文娱乐网 | 黄色三级在线观看 | 五月天亚洲婷婷 | 亚洲无人区小视频 | 精品国产伦一区二区三区 | 91久久人澡人人添人人爽欧美 | 国产精品精 | 五月婷香蕉久色在线看 | 激情视频免费观看 | 久久人人97超碰com | 国产欧美最新羞羞视频在线观看 | 日韩黄色免费电影 | 国产精品久一 | 国产99久久精品一区二区永久免费 | 怡红院久久 | 丁香激情五月 | 日韩在线不卡av | 国产精品96久久久久久吹潮 | 国产一级电影 | 在线观看免费 | 成人资源网 | 久久久在线 | 亚洲欧美日韩精品一区二区 | 日韩欧美电影 | 四虎影视成人精品 | 欧美视频www | av综合在线观看 | 日韩在线免费不卡 | 欧美激情综合网 | 国产成人免费精品 | 99精品乱码国产在线观看 | 少妇搡bbb | 麻豆视频免费入口 | 天天搞天天干天天色 | 91丨九色丨91啦蝌蚪老版 | 青青草在久久免费久久免费 | 亚洲国产精品久久久久久 | 中文字幕有码在线播放 | 91人人网| 最近的中文字幕大全免费版 | 亚洲午夜精品久久久 | 国产成人在线网站 | 成人免费一区二区三区在线观看 | 欧美另类老妇 | 永久黄网站色视频免费观看w | av一本久道久久波多野结衣 | 天天操天天舔天天爽 | 黄网站色成年免费观看 | 中文字幕在线观看第一区 | ,久久福利影视 | 久久tv视频 | 欧美孕交vivoestv另类 | 九九视频免费观看视频精品 | 精品久久久久久综合日本 | 久久男女视频 | 色88久久| 激情丁香综合五月 | 激情电影在线观看 | 精品国产伦一区二区三区免费 | 日日麻批40分钟视频免费观看 | 超碰人人干人人 | 欧美一二三区在线播放 | 国产一级精品绿帽视频 | 久久久资源 | 国产美女被啪进深处喷白浆视频 | 久热久草在线 | 久久久久久久久久久福利 | 国产日女人| 91中文字幕在线 | 国产精品黑丝在线观看 | 在线观看视频黄 | 色在线免费 | 亚洲国产免费 | 97精品国产97久久久久久 | 97av视频| 亚洲精品小视频在线观看 | 日韩av伦理片 | 久操视频在线免费看 | 99精品视频在线观看 | 天天操天天操天天操天天操 | 日韩电影在线观看一区二区三区 | 人人插人人爱 | av免费黄色 | 国产精品999久久久 久产久精国产品 | 久草在线费播放视频 | 亚洲在线日韩 | 久久99国产综合精品免费 | 一区二区av| 国产精品剧情在线亚洲 | 91国内在线视频 | 日本巨乳在线 | 人人玩人人添人人 | 激情六月婷婷久久 | 国产一区二区三区久久久 | 97自拍超碰 | 色黄视频免费观看 | 国产韩国日本高清视频 | 日韩有码在线观看视频 | 不卡视频在线看 | 丁香综合 | 人人澡澡人人 | 国产麻豆果冻传媒在线观看 | 婷婷九月丁香 | 国产不卡视频在线 | 亚洲成人第一区 | 午夜精品av | 国产偷在线 | 精品国内自产拍在线观看视频 | 久久成人午夜 | 国产一级做a爱片久久毛片a | 国产在线久草 | 精品xxx | 日韩成人免费观看 | 极品美女被弄高潮视频网站 | 99视频免费 | av在线在线| 天天摸天天弄 | 亚洲精品91天天久久人人 | 亚洲欧洲日韩在线观看 | 网址你懂的在线观看 | 国产视频精选 | 欧美日韩视频在线观看免费 | 日韩午夜在线播放 | 丁香免费视频 | 狠狠操夜夜操 | 国产精品久久久久久一二三四五 | 玖玖在线看 | 麻豆视频在线免费 | 天天草综合网 | 久久精品国产99国产 | 久久精品中文字幕一区二区三区 | 91探花系列在线播放 | 午夜av免费观看 | 国产精品嫩草影院123 | 国产 一区二区三区 在线 | 日韩激情片在线观看 | 成人久久久久久久久 | 成年人在线观看视频免费 | 日韩综合在线观看 | 成人黄色免费在线观看 | 一区二区三区av在线 | 一区二区中文字幕在线播放 | 一级黄色片在线免费观看 | 欧美日韩在线视频观看 | 亚洲午夜精品一区二区三区电影院 | 一级黄色片在线免费看 | 久久玖| 久久视频精品在线 | 午夜视频播放 | 欧美国产日韩激情 | 亚洲欧美婷婷六月色综合 | 四川bbb搡bbb爽爽视频 | 9在线观看免费高清完整版在线观看明 | 一本一本久久a久久 | 国产精品福利午夜在线观看 | 久草在线观看资源 | 久久,天天综合 | 欧美视频日韩视频 | 国产精品1000 | 91精品国产乱码在线观看 | 96国产在线| 中文字幕资源在线观看 | 蜜桃视频日本 | 在线免费观看黄色大片 | 91中文在线观看 | 欧美精品久久 | 夜夜天天干 | 美国三级黄色大片 | 欧美日韩一区二区视频在线观看 | av福利免费 | 亚洲视频www| 一本一道久久a久久综合蜜桃 | 成人亚洲精品久久久久 | 日本中文字幕在线免费观看 | 国产精品午夜在线观看 | 成人va在线观看 | 91成人在线免费观看 | 国产欧美最新羞羞视频在线观看 | 91麻豆精品国产91久久久使用方法 | 中文字幕视频三区 | 91最新在线视频 | 国产亚洲精品xxoo | 久久精品欧美一区 | 免费a视频在线 | 欧美网址在线观看 | 成人免费观看视频网站 | 国产极品尤物在线 | 九九热1 | 久色网 | 日韩久久精品一区二区 | 米奇影视7777 | 97理论电影 | 亚洲欧美日本一区二区三区 | 精品国产精品久久 | 91精品在线免费视频 | 亚洲三级黄色 | 欧美日本国产在线观看 | 色黄www小说 | 成人av片免费观看app下载 | 国产精品免费久久 | 国产精品欧美久久久久久 | 国产区av在线 | 一区二区三区在线免费观看视频 | 日韩中文在线观看 | 免费网站污 | 国产精品99页 | 国产亚洲成av人片在线观看桃 | 久久线视频 | 最近2019年日本中文免费字幕 | 五月婷婷综合在线观看 | 亚洲精品国产综合99久久夜夜嗨 | 激情婷婷在线 | 欧美99精品 | 最新婷婷色 | 91探花在线 | 欧美成人在线免费 | av一级片| 最近中文字幕大全中文字幕免费 |