国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

分布式WebSocket集群解決方案

共 10880字,需瀏覽 22分鐘

 ·

2021-11-27 00:14

文章轉(zhuǎn)載來源:https://segmentfault.com/a/1190000017307713

| 問題起因

最近做項目時遇到了需要多用戶之間通信的問題,涉及到了WebSocket握手請求,以及集群中WebSocket Session共享的問題。

期間我經(jīng)過了幾天的研究,總結(jié)出了幾個實現(xiàn)分布式WebSocket集群的辦法,從zuul到spring cloud gateway的不同嘗試,總結(jié)出了這篇文章,希望能幫助到某些人,并且能一起分享這方面的想法與研究。

以下是我的場景描述

  • 資源:4臺服務(wù)器。其中只有一臺服務(wù)器具備ssl認證域名,一臺redis+mysql服務(wù)器,兩臺應(yīng)用服務(wù)器(集群)
  • 應(yīng)用發(fā)布限制條件:由于場景需要,應(yīng)用場所需要ssl認證的域名才能發(fā)布。因此ssl認證的域名服務(wù)器用來當(dāng)api網(wǎng)關(guān),負責(zé)https請求與wss(安全認證的ws)連接。俗稱https卸載,用戶請求https域名服務(wù)器(eg:https://oiscircle.com/xxx),但真實訪問到的是http+ip地址的形式。只要網(wǎng)關(guān)配置高,能handle多個應(yīng)用
  • 需求:用戶登錄應(yīng)用,需要與服務(wù)器建立wss連接,不同角色之間可以單發(fā)消息,也可以群發(fā)消息
  • 集群中的應(yīng)用服務(wù)類型:每個集群實例都負責(zé)http無狀態(tài)請求服務(wù)與ws長連接服務(wù)

| 系統(tǒng)架構(gòu)圖

在我的實現(xiàn)里,每個應(yīng)用服務(wù)器都負責(zé)http and ws請求,其實也可以將ws請求建立的聊天模型單獨成立為一個模塊。從分布式的角度來看,這兩種實現(xiàn)類型差不多,但從實現(xiàn)方便性來說,一個應(yīng)用服務(wù)http+ws請求的方式更為方便。下文會有解釋。

本文涉及的技術(shù)棧:

  • Eureka 服務(wù)發(fā)現(xiàn)與注冊
  • Redis Session共享
  • Redis 消息訂閱
  • Spring Boot
  • Zuul 網(wǎng)關(guān)
  • Spring Cloud Gateway 網(wǎng)關(guān)
  • Spring WebSocket 處理長連接
  • Ribbon 負載均衡
  • Netty 多協(xié)議NIO網(wǎng)絡(luò)通信框架
  • Consistent Hash 一致性哈希算法

相信能走到這一步的人都了解過我上面列舉的技術(shù)棧了,如果還沒有,可以先去網(wǎng)上找找入門教程了解一下。下面的內(nèi)容都與上述技術(shù)相關(guān),題主默認大家都了解過了...

| 技術(shù)可行性分析

下面我將描述session特性,以及根據(jù)這些特性列舉出n個解決分布式架構(gòu)中處理ws請求的集群方案。

WebSocketSession與HttpSession

在Spring所集成的WebSocket里面,每個ws連接都有一個對應(yīng)的session:WebSocketSession,在Spring WebSocket中,我們建立ws連接之后可以通過類似這樣的方式進行與客戶端的通信:

protected?void?handleTextMessage(WebSocketSession?session,?TextMessage?message)?{
???System.out.println("服務(wù)器接收到的消息:?"+?message?);
???//send?message?to?client
???session.sendMessage(new?TextMessage("message"));
}

那么問題來了:ws的session無法序列化到redis,因此在集群中,我們無法將所有WebSocketSession都緩存到redis進行session共享。每臺服務(wù)器都有各自的session。于此相反的是HttpSession,redis可以支持httpsession共享,但是目前沒有websocket session共享的方案,因此走redis websocket session共享這條路是行不通的。

有的人可能會想:我可不可以將sessin關(guān)鍵信息緩存到redis,集群中的服務(wù)器從redis拿取session關(guān)鍵信息然后重新構(gòu)建websocket session...我只想說這種方法如果有人能試出來,請告訴我一聲...

以上便是websocket session與http session共享的區(qū)別,總的來說就是http session共享已經(jīng)有解決方案了,而且很簡單,只要引入相關(guān)依賴:spring-session-data-redisspring-boot-starter-redis,大家可以從網(wǎng)上找個demo玩一下就知道怎么做了。而websocket session共享的方案由于websocket底層實現(xiàn)的方式,我們無法做到真正的websocket session共享。

| 解決方案的演變

Netty與Spring WebSocket

剛開始的時候,我嘗試著用netty實現(xiàn)了websocket服務(wù)端的搭建。在netty里面,并沒有websocket session這樣的概念,與其類似的是channel,每一個客戶端連接都代表一個channel。前端的ws請求通過netty監(jiān)聽的端口,走websocket協(xié)議進行ws握手連接之后,通過一些列的handler(責(zé)鏈模式)進行消息處理。與websocket session類似地,服務(wù)端在連接建立后有一個channel,我們可以通過channel進行與客戶端的通信

???/**
????*?TODO?根據(jù)服務(wù)器傳進來的id,分配到不同的group
????*/

???private?static?final?ChannelGroup?GROUP?=?new?DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
?
???@Override
???protected?void?channelRead0(ChannelHandlerContext?ctx,?TextWebSocketFrame?msg)?throws?Exception?{
???????//retain增加引用計數(shù),防止接下來的調(diào)用引用失效
???????System.out.println("服務(wù)器接收到來自?"?+?ctx.channel().id()?+?"?的消息:?"?+?msg.text());
???????//將消息發(fā)送給group里面的所有channel,也就是發(fā)送消息給客戶端
???????GROUP.writeAndFlush(msg.retain());
???}

那么,服務(wù)端用netty還是用spring websocket?以下我將從幾個方面列舉這兩種實現(xiàn)方式的優(yōu)缺點。

使用netty實現(xiàn)websocket

玩過netty的人都知道netty是的線程模型是nio模型,并發(fā)量非常高,spring5之前的網(wǎng)絡(luò)線程模型是servlet實現(xiàn)的,而servlet不是nio模型,所以在spring5之后,spring的底層網(wǎng)絡(luò)實現(xiàn)采用了netty。如果我們單獨使用netty來開發(fā)websocket服務(wù)端,速度快是絕對的,但是可能會遇到下列問題:

  1. 與系統(tǒng)的其他應(yīng)用集成不方便,在rpc調(diào)用的時候,無法享受springcloud里feign服務(wù)調(diào)用的便利性
  2. 業(yè)務(wù)邏輯可能要重復(fù)實現(xiàn)
  3. 使用netty可能需要重復(fù)造輪子
  4. 怎么連接上服務(wù)注冊中心,也是一件麻煩的事情
  5. restful服務(wù)與ws服務(wù)需要分開實現(xiàn),如果在netty上實現(xiàn)restful服務(wù),有多麻煩可想而知,用spring一站式restful開發(fā)相信很多人都習(xí)慣了。

使用spring websocket實現(xiàn)ws服務(wù)

spring websocket已經(jīng)被springboot很好地集成了,所以在springboot上開發(fā)ws服務(wù)非常方便,做法非常簡單

第一步:添加依賴

<dependency>
???<groupId>org.springframework.bootgroupId>
???<artifactId>spring-boot-starter-websocketartifactId>
dependency>

第二步:添加配置類

@Configuration
public?class?WebSocketConfig?implements?WebSocketConfigurer?{
@Override
public?void?registerWebSocketHandlers(WebSocketHandlerRegistry?registry)?{
????registry.addHandler(myHandler(),?"/")
????????.setAllowedOrigins("*");
}
?
@Bean
?public?WebSocketHandler?myHandler()?{
?????return?new?MessageHandler();
?}
}

第三步:實現(xiàn)消息監(jiān)聽類

@Component
@SuppressWarnings("unchecked")
public?class?MessageHandler?extends?TextWebSocketHandler?{
???private?List?clients?=?new?ArrayList<>();
?
???@Override
???public?void?afterConnectionEstablished(WebSocketSession?session)?{
???????clients.add(session);
???????System.out.println("uri?:"?+?session.getUri());
???????System.out.println("連接建立:?"?+?session.getId());
???????System.out.println("current?seesion:?"?+?clients.size());
???}
?
???@Override
???public?void?afterConnectionClosed(WebSocketSession?session,?CloseStatus?status)?{
???????clients.remove(session);
???????System.out.println("斷開連接:?"?+?session.getId());
???}
?
???@Override
???protected?void?handleTextMessage(WebSocketSession?session,?TextMessage?message)?{
???????String?payload?=?message.getPayload();
???????Map?map?=?JSONObject.parseObject(payload,?HashMap.class);
???????System.out.println("接受到的數(shù)據(jù)"?+?map);
???????clients.forEach(s?->?{
???????????try?{
???????????????System.out.println("發(fā)送消息給:?"?+?session.getId());
???????????????s.sendMessage(new?TextMessage("服務(wù)器返回收到的信息,"?+?payload));
???????????}?catch?(Exception?e)?{
???????????????e.printStackTrace();
???????????}
???????});
???}
}

從這個demo中,使用spring websocket實現(xiàn)ws服務(wù)的便利性大家可想而知了。為了能更好地向spring cloud大家族看齊,我最終采用了spring websocket實現(xiàn)ws服務(wù)。

因此我的應(yīng)用服務(wù)架構(gòu)是這樣子的:一個應(yīng)用既負責(zé)restful服務(wù),也負責(zé)ws服務(wù)。沒有將ws服務(wù)模塊拆分是因為拆分出去要使用feign來進行服務(wù)調(diào)用。第一本人比較懶惰,第二拆分與不拆分相差在多了一層服務(wù)間的io調(diào)用,所以就沒有這么做了。

| 從zuul技術(shù)轉(zhuǎn)型到spring cloud gateway

要實現(xiàn)websocket集群,我們必不可免地得從zuul轉(zhuǎn)型到spring cloud gateway。原因如下:

zuul1.0版本不支持websocket轉(zhuǎn)發(fā),zuul 2.0開始支持websocket,zuul2.0幾個月前開源了,但是2.0版本沒有被spring boot集成,而且文檔不健全。因此轉(zhuǎn)型是必須的,同時轉(zhuǎn)型也很容易實現(xiàn)。

在gateway中,為了實現(xiàn)ssl認證和動態(tài)路由負載均衡,yml文件中以下的某些配置是必須的,在這里提前避免大家采坑

server:
??port:?443
??ssl:
????enabled:?true
????key-store:?classpath:xxx.jks
????key-store-password:?xxxx
????key-store-type:?JKS
????key-alias:?alias
spring:
??application:
????name:?api-gateway
??cloud:
????gateway:
??????httpclient:
????????ssl:
??????????handshake-timeout-millis:?10000
??????????close-notify-flush-timeout-millis:?3000
??????????close-notify-read-timeout-millis:?0
??????????useInsecureTrustManager:?true
??????discovery:
????????locator:
??????????enabled:?true
??????????lower-case-service-id:?true
??????routes:
??????-?id:?dc
????????uri:?lb://dc
????????predicates:
????????-?Path=/dc/**
??????-?id:?wecheck
????????uri:?lb://wecheck
????????predicates:
????????-?Path=/wecheck/**

如果要愉快地玩https卸載,我們還需要配置一個filter,否則請求網(wǎng)關(guān)時會出現(xiàn)錯誤not an SSL/TLS record。

@Component
public?class?HttpsToHttpFilter?implements?GlobalFilter,?Ordered?{
??private?static?final?int?HTTPS_TO_HTTP_FILTER_ORDER?=?10099;
??@Override
??public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)?{
??????URI?originalUri?=?exchange.getRequest().getURI();
??????ServerHttpRequest?request?=?exchange.getRequest();
??????ServerHttpRequest.Builder?mutate?=?request.mutate();
??????String?forwardedUri?=?request.getURI().toString();
??????if?(forwardedUri?!=?null?&&?forwardedUri.startsWith("https"))?{
??????????try?{
??????????????URI?mutatedUri?=?new?URI("http",
??????????????????????originalUri.getUserInfo(),
??????????????????????originalUri.getHost(),
??????????????????????originalUri.getPort(),
??????????????????????originalUri.getPath(),
??????????????????????originalUri.getQuery(),
??????????????????????originalUri.getFragment());
??????????????mutate.uri(mutatedUri);
??????????}?catch?(Exception?e)?{
??????????????throw?new?IllegalStateException(e.getMessage(),?e);
??????????}
??????}
??????ServerHttpRequest?build?=?mutate.build();
??????ServerWebExchange?webExchange?=?exchange.mutate().request(build).build();
??????return?chain.filter(webExchange);
??}
?
??@Override
??public?int?getOrder()?{
??????return?HTTPS_TO_HTTP_FILTER_ORDER;
??}
}

這樣子我們就可以使用gateway來卸載https請求了,到目前為止,我們的基本框架已經(jīng)搭建完畢,網(wǎng)關(guān)既可以轉(zhuǎn)發(fā)https請求,也可以轉(zhuǎn)發(fā)wss請求。接下來就是用戶多對多之間session互通的通訊解決方案了。接下來,我將根據(jù)方案的優(yōu)雅性,從最不優(yōu)雅的方案開始講起。

| session廣播

這是最簡單的websocket集群通訊解決方案。場景如下:

教師A想要群發(fā)消息給他的學(xué)生們

  • 教師的消息請求發(fā)給網(wǎng)關(guān),內(nèi)容包含{我是教師A,我想把xxx消息發(fā)送我的學(xué)生們}
  • 網(wǎng)關(guān)接收到消息,獲取集群所有ip地址,逐個調(diào)用教師的請求
  • 集群中的每臺服務(wù)器獲取請求,根據(jù)教師A的信息查找本地有沒有與學(xué)生關(guān)聯(lián)的session,有則調(diào)用sendMessage方法,沒有則忽略請求

session廣播實現(xiàn)很簡單,但是有一個致命缺陷:計算力浪費現(xiàn)象,當(dāng)服務(wù)器沒有消息接收者session的時候,相當(dāng)于浪費了一次循環(huán)遍歷的計算力,該方案在并發(fā)需求不高的情況下可以優(yōu)先考慮,實現(xiàn)很容易。

spring cloud中獲取服務(wù)集群中每臺服務(wù)器信息的方法如下:

@Resource
private?EurekaClient?eurekaClient;
?
Application?app?=?eurekaClient.getApplication("service-name");
//instanceInfo包括了一臺服務(wù)器ip,port等消息
InstanceInfo?instanceInfo?=?app.getInstances().get(0);
System.out.println("ip?address:?"?+?instanceInfo.getIPAddr());

服務(wù)器需要維護關(guān)系映射表,將用戶的id與session做映射,session建立時在映射表中添加映射關(guān)系,session斷開后要刪除映射表內(nèi)關(guān)聯(lián)關(guān)系。

| 一致性哈希算法實現(xiàn)(本文的要點)

這種方法是本人認為最優(yōu)雅的實現(xiàn)方案,理解這種方案需要一定的時間,如果你耐心看下去,相信你一定會有所收獲。再強調(diào)一次,不了解一致性哈希算法的同學(xué)請先看這里,現(xiàn)先假設(shè)哈希環(huán)是順時針查找的。

首先,想要將一致性哈希算法的思想應(yīng)用到我們的websocket集群,我們需要解決以下新問題:

  • 集群節(jié)點DOWN,會影響到哈希環(huán)映射到狀態(tài)是DOWN的節(jié)點。
  • 集群節(jié)點UP,會影響到舊key映射不到對應(yīng)的節(jié)點。
  • 哈希環(huán)讀寫共享。

在集群中,總會出現(xiàn)服務(wù)UP/DOWN的問題。

針對節(jié)點DOWN的問題分析如下:

一個服務(wù)器DOWN的時候,其擁有的websocket session會自動關(guān)閉連接,并且前端會收到通知。此時會影響到哈希環(huán)的映射錯誤。我們只需要當(dāng)監(jiān)聽到服務(wù)器DOWN的時候,刪除哈希環(huán)上面對應(yīng)的實際結(jié)點和虛結(jié)點,避免讓網(wǎng)關(guān)轉(zhuǎn)發(fā)到狀態(tài)是DOWN的服務(wù)器上。

實現(xiàn)方法:在eureka治理中心監(jiān)聽集群服務(wù)DOWN事件,并及時更新哈希環(huán)。

針對節(jié)點UP的問題分析如下:

現(xiàn)假設(shè)集群中有服務(wù) CacheB上線了,該服務(wù)器的ip地址剛好被映射到key1和 cacheA之間。那么key1對應(yīng)的用戶每次要發(fā)消息時都跑去 CacheB發(fā)送消息,結(jié)果明顯是發(fā)送不了消息,因為 CacheB沒有key1對應(yīng)的session。

此時我們有兩種解決方案。

方案A簡單,動作大:

eureka監(jiān)聽到節(jié)點UP事件之后,根據(jù)現(xiàn)有集群信息,更新哈希環(huán)。并且斷開所有session連接,讓客戶端重新連接,此時客戶端會連接到更新后的哈希環(huán)節(jié)點,以此避免消息無法送達的情況。

方案B復(fù)雜,動作?。?/strong>

我們先看看沒有虛擬節(jié)點的情況,假設(shè) CacheC和 CacheA之間上線了服務(wù)器 CacheB。所有映射在 CacheC到 CacheB的用戶發(fā)消息時都會去 CacheB里面找session發(fā)消息。也就是說 CacheB一但上線,便會影響到 CacheC到 CacheB之間的用戶發(fā)送消息。所以我們只需要將 CacheA斷開 CacheC到 CacheB的用戶所對應(yīng)的session,讓客戶端重連。

接下來是有虛擬節(jié)點的情況,假設(shè)淺色的節(jié)點是虛擬節(jié)點。我們用長括號來代表某段區(qū)域映射的結(jié)果屬于某個 Cache。首先是C節(jié)點未上線的情況。圖大家應(yīng)該都懂吧,所有B的虛擬節(jié)點都會指向真實的B節(jié)點,所以所有B節(jié)點逆時針那一部分都會映射到B(因為我們規(guī)定哈希環(huán)順時針查找)。

接下來是C節(jié)點上線的情況,可以看到某些區(qū)域被C占領(lǐng)了。

由以上情況我們可以知道:節(jié)點上線,會有許多對應(yīng)虛擬節(jié)點也同時上線,因此我們需要將多段范圍key對應(yīng)的session斷開連接(上圖紅色的部分)。具體算法有點復(fù)雜,實現(xiàn)的方式因人而異,大家可以嘗試一下自己實現(xiàn)算法。

哈希環(huán)應(yīng)該放在哪里?

  • gateway本地創(chuàng)建并維護哈希環(huán)。當(dāng)ws請求進來的時候,本地獲取哈希環(huán)并獲取映射服務(wù)器信息,轉(zhuǎn)發(fā)ws請求。這種方法看上去不錯,但實際上是不太可取的,回想一下上面服務(wù)器DOWN的時候只能通過eureka監(jiān)聽,那么eureka監(jiān)聽到DOWN事件之后,需要通過io來通知gateway刪除對應(yīng)節(jié)點嗎?顯然太麻煩了,將eureka的職責(zé)分散到gateway,不建議這么做。
  • eureka創(chuàng)建,并放到redis共享讀寫。這個方案可行,當(dāng)eureka監(jiān)聽到服務(wù)DOWN的時候,修改哈希環(huán)并推送到redis上。為了請求響應(yīng)時間盡量地短,我們不可以讓gateway每次轉(zhuǎn)發(fā)ws請求的時候都去redis取一次哈希環(huán)。哈希環(huán)修改的概率的確很低,gateway只需要應(yīng)用redis的消息訂閱模式,訂閱哈希環(huán)修改事件便可以解決此問題。

至此我們的spring websocket集群已經(jīng)搭建的差不多了,最重要的地方還是一致性哈希算法?,F(xiàn)在有最后一個技術(shù)瓶頸,網(wǎng)關(guān)如何根據(jù)ws請求轉(zhuǎn)發(fā)到指定的集群服務(wù)器上?

答案在負載均衡。spring cloud gateway或zuul都默認集成了ribbon作為負載均衡,我們只需要根據(jù)建立ws請求時客戶端發(fā)來的user id,重寫ribbon負載均衡算法,根據(jù)user id進行hash,并在哈希環(huán)上尋找ip,并將ws請求轉(zhuǎn)發(fā)到該ip便完事了。流程如下圖所示:

接下來用戶溝通的時候,只需要根據(jù)id進行hash,在哈希環(huán)上獲取對應(yīng)ip,便可以知道與該用戶建立ws連接時的session存在哪臺服務(wù)器上了!

| spring cloud Finchley.RELEASE版本中ribbon未完善的地方

題主在實際操作的時候發(fā)現(xiàn)了ribbon兩個不完善的地方......

  • 根據(jù)網(wǎng)上找的方法,繼承AbstractLoadBalancerRule重寫負載均衡策略之后,多個不同應(yīng)用的請求變得混亂。假如eureka上有兩個service A和B,重寫負載均衡策略之后,請求A或B的服務(wù),最終只會映射到其中一個服務(wù)上。非常奇怪!可能spring cloud gateway官網(wǎng)需要給出一個正確的重寫負載均衡策略的demo。
  • 一致性哈希算法需要一個key,類似user id,根據(jù)key進行hash之后在哈希環(huán)上搜索并返回ip。但是ribbon沒有完善choose函數(shù)的key參數(shù),直接寫死了default!

難道這樣子我們就沒有辦法了嗎?其實還有一個可行并且暫時可替代的辦法!

如下圖所示,客戶端發(fā)送一個普通的http請求(包含id參數(shù))給網(wǎng)關(guān),網(wǎng)關(guān)根據(jù)id進行hash,在哈希環(huán)中尋找ip地址,將ip地址返回給客戶端,客戶端再根據(jù)該ip地址進行ws請求。

由于ribbon未完善key的處理,我們暫時無法在ribbon上實現(xiàn)一致性哈希算法。只能間接地通過客戶端發(fā)起兩次請求(一次http,一次ws)的方式來實現(xiàn)一致性哈希。希望不久之后ribbon能更新這個缺陷!讓我們的websocket集群實現(xiàn)得更優(yōu)雅一點。

| 后記

以上便是我這幾天探索的結(jié)果。期間遇到了許多問題,并逐一解決難題,列出兩個websocket集群解決方案。第一個是session廣播,第二個是一致性哈希。

這兩種方案針對不同場景各有優(yōu)缺點,本文并未用到ActiveMQ,Karfa等消息隊列實現(xiàn)消息推送,只是想通過自己的想法,不依靠消息隊列來簡單地實現(xiàn)多用戶之間的長連接通訊。希望能為大家提供一條不同于尋常的思路。


END


推薦閱讀

一鍵生成Springboot & Vue項目!【畢設(shè)神器】

Java可視化編程工具系列(一)

Java可視化編程工具系列(二)


順便給大家推薦一個GitHub項目,這個 GitHub 整理了上千本常用技術(shù)PDF,絕大部分核心的技術(shù)書籍都可以在這里找到,

GitHub地址:https://github.com/javadevbooks/books

Gitee地址:https://gitee.com/javadevbooks/books

電子書已經(jīng)更新好了,你們需要的可以自行下載了,記得點一個star,持續(xù)更新中..



瀏覽 48
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 久热在线视频| 91av导航| 中文字幕在线无码视频| 九色91PORNY国产| 日本一级黄| 免费操B| 日韩毛片一级| 欧美婷婷五月天| 18禁一区二区三区| 免费在线观看AV| 人人摸人人操人人摸| 91无码人妻精品一区二区三区四 | 538在线视频| 操你啦无码日韩| 亚洲色成人中文字幕在线| 欧美日韩精品一区| 成年人免费公开视频| 久久99网站| 强伦轩一区二区三区在线观看| 激情综合网五月| 亚洲天堂手机在线| 熟女熟妇人妻一区二区三区| 免费国产黄色视频网站| 日韩AV无码专区亚洲AV紧身裤| 久操视频一区二区三区| 中文有码在线观看| 99精品久久久久久无码| 国产精品污www在线观看| 啊啊啊亚洲| 国产免看一级a一片成人aⅴ| 性爱视频亚洲| 精产国品一区二区| 91麻豆精品国产91久久久久久久久| 免费黄色大片| 亚洲AV第一页| 污视频网站免费在线观看| 久久99影院| 久精品视频| 亚洲小黄片| 蝌蚪窝在线视频免费观看| 天天干天天日蜜臀色欲av| 国产黄色录像| 七十路の高齡熟妇无码| 欧美中文字幕在线播放| 嘉兴少妇按摩69XX| 手机无码在线播放| 午夜福利啪啪啪| 久久国产精品波多野结衣AV| 国产免费操逼视频| 高清无码在线观看免费| 北条麻妃人妻中文字幕91影视 | 无码国产av| 自拍偷拍福利视频网站| 日韩不卡精品| 天堂网址激情网址| 久久国产乱子伦精品免费女,网站 一区二区三区免费观看 | 国产第一精品| 欧美日韩无码视频| 久久久久亚洲AV无码网影音先锋 | 人妻无码一区二区三区| 国产91久久婷婷一区二区| 午夜视频18| 久久综合站| 国产操穴视频| 青青在线| 怡红院成人网| 欧美黄色一级视频| 成人国产精品| 亚洲操逼片| 91小视频在线观看| 日日爽| 日本成人黄色电影| 日韩成人免费观看| 欧美熟妇搡BBBB搡BBBBB| 屁屁影院CCYYCOM发布地| 91麻豆国产在线| 婷婷成人五月天| 日韩无任何视频在线观看| 黄色在线免费看| 日本女人操逼视频| 五月天婷婷视频| 亚洲A视频| 黄色AV免费看| 秋霞中文字幕| 免费看成人片| 日韩一区在线视频| 久久久91精品国产一区苍井空| 人人免费操| 午夜黄色大片| 俄罗斯白嫩BBwBBwBBw91| 国产传媒一区| 日日夜夜精选视频| 免费观看一区| 操极品少妇逼| 亚洲男女啪啪视频| 欧美AAA大片| 9999re| 日韩美女性爱| 在线观看亚洲无码视频| 久久久无码AV| 性欧美xxxx| 男人操女人网站| 亚欧在线视频| 欧美一区电影| 99在线精品视频在线观看| 求毛片网址| 水果派解说A∨无码区| 91大神免费在线观看| 日韩A人人| 成人做爰免费网站2023| 字幕一区二区久久人妻网站| 青草社区在线观看| 黄工厂精品视频在线播| 人妻性爱| 囯产精品久久久久久久久久久久久久| 伊人久久大综合中文无码| 中文字幕在线观看a| 无码av观看| 日韩中文字| AV天堂小说| 日韩免费在线观看一区入口| 吴梦梦一区二区三区| 天天想天天干| 精品国产乱子伦一区二区三区,小小扐 | 日本特级黄色毛片| 操逼麻豆| 亚洲一二区| 一本色道久久88综合无码| 中文av网站| 天天日天天干天天爽| 91丨国产丨白丝| 伊人色综合网| 久久av影院| 日韩成人AV毛片| www.91在线看| 蜜桃Av噜噜一区二区三区四区| 天堂网av2025| 91人妻人人澡人人爽人人爽| 大香蕉尹人视频| 99久久久精品| 特级西西人体WWWWW| 亚洲偷拍网| 亚人精品中文字幕在线观看| 日日夜夜拍| 国精产品秘成人一区二| 人妻无码电影推荐| 国产精品国产成人国产三级| 免费看一级无码成人片| 无码人妻丰满熟妇bbbb| 亚洲无码免费视频| 久久久久久国产免费A片| 无码视屏| 国产成人精品一区二区三区四区| 大屌在线| 一区二区经典| 日本69AV| 无码av一区二区| 午夜精品人妻无码| 男女国产网站| 亚洲无码AV一区二区三区| 黄骗免费网站| 91麻豆国产| 蜜桃av秘无码一区三区四| 91婷婷| 午夜无码鲁丝片午夜精品| 米奇电影777无码| 成人性生交大片免费看小芳| 91成人区| 一本色道综合久久欧美日韩精品| 神马午夜福利影院| 另类老妇奶BBBBwBB| 狠狠干狠狠色| 欧美成人久久| 青娱乐三级在线免| 蜜桃久久久久久久| 婷婷五月天免费视频| 亚洲视频在线观看网站| 久久午夜无码鲁丝片主演是谁| 手机看片1024国产| 亚欧久久| www.狠狠撸| 天天操综合网| 欧美老女人操逼群| 91国产免费视频| 在线观看亚洲中文字幕| 四川少妇bbbbbbbbb| 午夜性爱AV| 色婷婷AV国产精品| 操逼在线视频| 精品中文字幕在线播放| 欧美十区| 另类老妇奶性BBWBBwBBw| 伊人大香蕉视频在线观看| 国产美女精品视频| 久久婷婷综合网| 午夜成人免费视频| 99视频免费| 亚洲免费在线婷婷| 中文字幕AV免费观看| 伊人久久精品| 欧美成人三级精品| 极品少妇AV| 超碰大香蕉| 美国无码黄片| 亚洲无码色婷婷| 99草在线视频| 日日夜夜拍| 麻豆mdapp01.tⅴ| 操一操| 摸BBB槡BBBB搡BBB,,,,,| 精品国产AV无码一区二区三区| 青草无码| 日韩特级毛片| 中国老女人操逼| 亚洲无码A片在线观看APP| 爱爱欧美| 97干视频| 日韩成人三级| 三级片欧美| 三级电影久久麻豆| 99久久亚洲精品日本无码| 九九小视频| 欧美日本在线观看| 九九热在线视频| 婷婷黄色电影| 五月天综合久久| 在线观看操逼视频| 亚洲欧美日韩久久| 在线免费黄色视频| 亚洲色在线播放| 日韩一级免费观看| 国产美女AV| 亚洲中文娱乐| 一区二区高清无码| 能看的操逼网站| 日韩欧美成人片| 成人色色网站| 91乱子伦国产乱子伦| 少妇三区| 俺也要操| 亚洲中文字幕在线看| 免费一级a片| 脓肿是什么原因引起的,该怎么治疗 | 日韩色爱| 欧美在线大香蕉| 夜夜狠狠擅视频| 加勒比DVD手机在线播放观看视频| 超碰v| 河南熟妇搡BBBB搡BBBB| 国产主播福利| 欧美日韩午夜福利视频| 天天拍天天日| 韩国三级HD久久精品HD| 日皮视频免费观看| 国产无码在线影院| 国产在线观看你懂的| 国产a级视频| 亚色天堂| 亚洲AV无码国产精品二区| 色婷在线视频| 国产婷婷色一区二区三区| 婷婷综合| 91在线无码视频| 五月乱伦| 日韩一级电影在线观看| 欧美色成人免费在线视频| 色综合99久久久无码国产精品| 青青草在线免费视频| 波多野结衣视频在线| 国产精品无毛五区六区| 日韩午夜在线观看| 亚洲一区二区三区视频| 中文字幕亚洲有码| 97人妻一区二区精品免费视频| h片网站在线观看| 成人在线精品视频| 日本少妇黄色视频| 免费视频在线观看一区| A级毛片在线观看| 亚洲女人天堂| 久久99高清| 日韩成人三级| 婷婷五月天丁香| 久久精品性爱| AV无码免费一区二区三区不卡| 爱爱视频免费看| 西西人体大胆ww4444图片| www.199麻豆在线观看网站 | 国产精品五月天| 亚洲精品国产精品国自产在线| 99re热在线视频| AV香蕉| 狼友视频在线播放| 牛牛精品一区二区AV| 欧美熟妇BBB搡BBB| 国产精品6| a片在线电影网| 夜色88V精品国产亚洲| 麻豆成人无码精品视频| 无码中文字幕高清| 亚洲国产另类无码| 91精品导航| 免费做爱视频网站| 亚洲精品国产成人AV在线| 国产图区| AV天堂小说网| 五月婷婷婷婷| 无码-ThePorn| 国产最新AV| 三个黑人猛躁我一晚上| 在线高清无码| 在线观看欧美黄片| 欧洲成人在线视频| 另类老妇奶性BBWBBw| 亚洲国产精品精JIZZ老师| 99色色网| 黄色带亚州| 天堂av在线免费观看| 亚洲天堂网在线观看| 激情乱伦网站| 亚洲中文字幕在线看| 无码视频播放| 国产一级二级片| 一级成人A片| 亚洲AV三级片| 亚洲成人精品一区二区| 无码一区二区三区免费| 神马午夜激情| 国产中文在线观看| 亚洲性爱AV网站| 一级a免一级a做片免费| 成人AV天堂| 波多野结衣AV网站| 亚洲欧洲成人在线| 亚洲免费精品视频| 成人无码免费毛片| 国产免费无码一区二区| 亚洲性爱小说网址| 亚洲无码A片在线观看| 国产亚洲色情| 国产第56页| 日韩黄色视频| 日韩欧美黄色电影| 黄色三级在线观看| 在线视频播放| 欧美一二| 97色在线视频| 日韩有码在线观看| 亚洲av成人网| 中文字幕在线不卡视频| 亚洲无码中文字幕在线观看| 91蝌蚪91九色| 中文字幕在线观看视频www| 免费爱爱视频网站| 91人妻人人澡人人爽人人| 亚洲视频99| 欧美极品视频| 99热中文字幕在线观看| 99热3| 粉嫩AV蜜乳AV蜜臀AV蜂腰AV | 精品三级片| 国产在线看片| 成人无码中文字幕| 在线看v片| 精品国产三级| 欧美日韩性色无码免费| 亚洲成人av在线观看| 免费看黄色大全| 94久久| 少妇被躁到高潮无码| 日本免费在线视频| 亚洲免费视频在线观看| 校园春色av| 伊人成人在线观看| 亚洲无码高清在线视频| 欲色AV| 日本免费不卡视频| 99久久九九| 国产精品美女在线观看| 欧美性爱小说| 亚洲真人无码| 91精品人妻一区二区三区| 91精品视频在线免费观看| 久久99热这里只频精品6学生| 99热官网| 亚洲精品中文字幕无码| 久9久9久9久9久9久9| 人人干人人干| 美女被操面费网站| 麻豆mdapp01.tⅴ| 色噜噜狠狠一区二区三区| 亚洲国产精品久久久| 午夜久久福利| 日韩黄片视频| 成人午夜婬片A片| 久久久婷婷婷| 国产精品理论片| 欧美操逼逼| 亚洲AV成人无码一区二区三区| 久久国产精品波多野结衣AV| 日韩动态视频| 精品久| 狠狠干伊人| 51XX嘿嘿午夜| JLZZJLZZ亚洲女人| 精品精品视频| 亚洲久草| 亚洲无码在线资源| 成人国产在线| 日日操人人操| 福利二区| 无码日韩人妻精品久久蜜桃| 女孩自慰在线观看| 国产欧美综合在线| 黄色免费毛片| 影音先锋日韩资源| 国产精品一区二区在线播放| 亚洲在线视频观看| 日韩一区不卡| 懂色AV| 国产精品成人一区二区| 六月婷婷在线观看| 西西444www无码精品| 成人丁香五月天| 神马午夜精品96| 豆花视频在线看| 亚洲无码影院| 午夜福利aaa| 免费黄片视频大全| 在线观看禁无码精品| 日韩小视频+国产| 欧美视频免费| 国产一a毛一a免费观看| 久久无码影院| 91女人18片女毛片60分钟| 天天逼网| 日韩黄色电影在线观看| 麻豆传媒一区二区| 亚洲国产精品成人网站| 青青草伊人网| chinese高潮老女人| 国产午夜福利视频| 中文在线免费看视频| 天天操天天干麻豆| 91在线看片| 一级特黄A片| 国产aa| 97精品人妻一区二区三区在线| 西西444WWW无码视频软件| 亚洲人妻无码在线| 在线播放亚洲无码| 91水蜜桃| 成人无码区免费A片在线软件| 青青草社区视频| 亚洲色久| 91成人视频在线免费观看| 成人在线观看无码| 一区高清无码| jizz免费在线观看| 午夜无码鲁丝午夜免费| 日韩人妻精品无码| 69成人| www.91av| 超级碰碰| 日韩黄色片在线观看| 色猫AV| 美腿丝袜中文字幕精品| 亚洲精品另类| 五月婷婷婷| 三级片视频在线观看| 欧美日韩精品一区二区三区| 久久艹大香蕉| 美女久久久久| 超碰天天干天天摸| 欧美毛片A| 欧美乱伦内射| 亚洲AV无码久| 无码人妻一区二区三区免费n狂飙 性猛交AAAA片免费看蜜桃视频 | 国产又爽又黄视频| 91性爱视频| 欧美日逼网站| 亚洲成年人在线| 麻豆三级片| 91精品大屁股白浆自慰久久久 | 91视频熟女| 泄火熟妇2-ThePorn| 日本成人高清视频| 色哟哟一区二区三区四区| 日韩欧美国产高清91| 开心色情| 国产精品啪啪啪啪| 在线一区二区三区| 91久久| 大香蕉草久| 国产又爽又黄视频| 亚洲精品免费观看| 怡春院欧美| 国产青青操| 四虎在线观看| www.国产| 亚洲免费观看高清完| 91视频在线观看网| 大香蕉伊人av| 国产乱子伦一区二区三区在线观看 | h在线观看h| 熟女网址| 国产69页| yjizz国产| 综合色国产精品欧美在线| 俄罗斯熟妇搡BBBB搡BBBB| 五月丁香花视频| 丁香花在线高清完整版视频| 免费看一区二区三区A片| 一区二区入口| 日韩大吊| 天天精品| 一级a一级a爱片免费免免高潮| 日韩久久婷婷| 在线观看黄片网站| 日本a在线| 色婷婷亚洲婷婷| 欧美日韩一区在线观看| 亚洲人妻免费视频| 免费黄色毛片| 91麻豆精品传媒| 免费涩涩无遮挡18国产| 国产AV久| 九九偷拍视频| 日本欧美黄色| 国产91无码| 99视频在线免费| 国产精品123区| 青青AV| 成人无码免费一区二区中文| 精品秘一区性综合三区| 操逼AV无码| 久久亚洲成人| 翔田千里無碼破解| 亚洲精品在线视频观看| 精品乱子伦一区二区三区毛| 免费黄片在线看| 欧美A区| chinese搡老熟老妇人| 人人av在线| 欧美性爱在线| av不卡在线| 九九视频免费观看| 亚洲真人无码| 国产一级免费观看| 一区在线视频| 九九九久久久| 一插综合网| 日本黄色A片免费看| 欧美黄色免费| 97国产精品| 久久亚洲AV| 日本A在线观看| 特级西西西88大胆无码| 日本欧美一级片| 中文字幕免费在线观看| 香蕉婷婷| Chinese搡老女人| www.日韩一区| 97人妻人人澡人人| 看国产毛片| 一区二区三区在线看| 亚洲A级毛片| 一级Aa视频免费看| 日本黄色电影在线观看| 亚洲一区视频在线| 欧美久久国产精品| 中文字幕av在线播放| 18一20女一片毛片| 蜜桃av秘无码一区三| 国产在线拍揄自揄拍无码男男| 黄总av| www.99热| 欧美日韩小视频| 日韩综合另类| 五月天婷婷导航| 欧美熟妇搡BBBB搡BBBBB| 三级乱伦视频| 婷婷五月电影| 国产AV一区二区三区| 波多野结衣av无码| 久99| 欧美性爱xxxx| 亚洲黄色毛片| 国产黄片在线视频| 怡红院成人AV| 2025最新偷拍| 国产成人久久777777黄蓉| 成人91看片| 美女肏逼| 老婆被黑人杂交呻吟视频| 永久m3u8在线观看| 蜜臀av网站| 国产九九精品| 久久91久久久久麻豆精品| www.水蜜桃| 人人干人人操人人摸| 青草青在线视频| 亚洲免费黄| 丝瓜视频黄| 日日骚亚洲| 欧美在线国产| 蜜桃91精品秘入口| 久久精品一区二区三区四区| 色九九综合| 91蜜桃精品| 亚洲激情图| 国产无遮挡又黄又爽又色视频| 国产精品999999| 韩日成人| 最新久欠一区二区免费看| 麻豆av人人乐| 在线不欧美| 毛片毛片毛片毛片| 97成人人妻一区二区三区| 亚洲免费成人视频| jizz无码| 国产高清小视频| 69成人| 亚洲日韩在线视频播放| 久久久精品久久| 青娱乐三级在线免| 亚洲成人免费视频| 午夜福利码一区二区| 日本黄色大片| 91人妻网| 国产116页| 国产精品久久久久精| 无码秘蜜桃吴梦梦| 日韩免费不卡| 国产中文字幕第一页| 国产一级特黄大片| 超碰2021| 亚洲最新AV在线| 国产AV网| 男女怕怕网站| 青草视频精品| 国产97热人人| 亚洲18禁| 日韩无码毛片| 水蜜桃在线视频| 蜜桃精品视频| 日韩v| 亚洲色五月| 一级A黄色片| 久草免费电影| 2025AV天堂网| av天堂中文在线| 这里只有精品久久| 色色色亚洲| 久久久精品午夜人成欧洲亚洲韩国 | 国产亚洲精品久久久久久桃色| 欧美亚洲在线观看| 天天射天天日天天干| 少妇人妻一级A毛片| jizz在线观看免费视频| 艹逼视频免费观看| 人人妻人人做| 丁香五月婷婷视频| 99久久久久久久无码| 人妻人人干| 亚洲色色视频| 玖玖爱av| 国产成人片色情AAAA片| 波多野吉衣视频| 国产欧美高清在线| 91迷奸| 91人妻人人澡人人爽人人精品| 中文字幕无码在线观看| 亚洲综合在线视频| 三级无码| 黄色毛片,男人天堂| 亚洲美眉综合网| 浪潮在线观看完整版| 中文字幕浅井香舞被黑人俘虏| 日韩成人无码一区二区视频| 国产激情无码| 黑人av| 成人福利视频| 日本乱伦电影中文字幕| 欧美成人片免费看| 中国一级黄色A片| 国产日本在线视频| 国产青娱乐在线视频| 成人午夜A片免费看| 少妇熟女视频一区二区三区| 亚洲日本一区二区三区| 天天日天天干天天爽| 久草视频资源| 动漫人物插画动漫人物的视频软件 | 亚洲天堂无码| 亚洲性爱AV网站| 搞搞网日本9| 内射学生妹视频| 久久久久久久久久久亚洲| 国产精品国内自产拍| 操www| 人人操免费| 免费黄色av网址| 日本不卡一区| 成人伊人AV| 日韩无码免费电影| 日本一区二区视频在线观看| 高清的日逼| 国产91小视频| 99精品国产一区二区| 日逼高清无码| 视色AV| 国内精品久久久久久久久久| 成人黄网站免费视频| 日本在线一区二区| 日韩高清无码三级片| 久青草资源福利视频| 免费看成人A片无码照片88hⅤ| 婷婷伊人大香蕉| 日本A片视频| 欧美在线一区二区三区| 露脸丨91丨九色露脸| 天天看天天干| 蜜桃视频一区二区三区| 久久精品导航| 超碰一区二区三区| 天天综合在线观看| HEYZO少婦AV無碼精品| 丰满岳乱妇一区二区三区全文阅读| 97大香蕉视频| 青青青草视频| 永久免费一区二区三区| 视频一区在线观看| 九九精品12| 久艹久| 欧美成人在线免费| 福利导航视频| 成人无码观看| 99精品热视频| 国产无码Av| 69黄色视频| 色色婷婷五月天| 亚洲欧洲无码在线| 加勒比无码综合| 国产精品嫩草久久久久yw193 | 国产操屄网| 香蕉国产精品| av性爱在线| 无码视频久久| 91小视频在线| 日本黄色视频网址| 欧美亚洲黄片| 久久国产V一级毛多内射| 欧美欧美欧美| 夜色精品视频| 欧美污视频在线观看| 人人操人人干人人看| 东方a在线| 亚洲成人无码AV| 水果派AV解说| 韩日黄色| 欧美三级性爱视频| 地表最强网红八月未央道具大秀| 黄色成人视频免费看| 边吃边摸| av免费播放| 日韩黄色一级片| 国产成人无码区免费视频| 日本少妇中文字幕| 色情小电影免费网站观看网址在线播 | 久久久久无码精品国产91福利| www.尤物视频| 久久爆乳一区二区三区| 久久九九99| 人人干人| 亚洲中文无码av| 五月婷婷色色色| 国产一级A片久久久免费看快餐| 日韩黄色小说| 亚洲免费在线视频| 欧美成人中文字幕| 91无码精品国产AⅤ| 天天干在线观看| AV中文字幕网| 中文亚洲字幕| 国产操穴| 日韩少妇AV| 性爱视频久久| 色婷婷日韩精品一区二区三区| 欧美自拍视频在线观看| 亚洲中文字幕在线播放| 操一线天逼| 精品一区二区三区四区五区| 91亚洲精品在线观看| 色哟哟国产| 天天精品| 色色丁香五月天| 狠狠干2024| 高清无码二区| 2014天堂网| 大香蕉av一区二区三区在线观看| 亚洲Av在线观看| 免费作爱视频| 亚洲成人色色| 影音先锋成人资源站| 黄色视频一区二区| 久久久在线视频| 黑人巨大翔田千里AⅤ| 黄色成人网站在线观看免费| 无码精品ThePorn| 日韩99热| 在线观看无码高清视频| 这里只有精品久久| 欧美成人性爱网| а√天堂中文最新版8| 日本黄在线看| 懂色AV一区二区三区国产中文在线 | 亚洲精品在线观看视频| 超级碰碰碰碰碰碰碰碰碰| 丁香视频在线观看| 大香蕉这里只有精品| 亚洲精品一区二区三| 日韩免费在线| 大香蕉亚洲网| www高清无码| 欧美在线视频免费观看| 无码免费看| 99re热在线视频| 99免费热视频在线| 成人小视频18| 少妇大战28厘米黑人| 91丨九色丨熟女老版| 无码在线观看免费| 俺去草| 日本人妻中文字幕| www.99免费视频| 97国产精品手机| 欧美亚洲一区二区三区| 五月婷婷AV| 亚洲无码手机在线| 久久精品一二三| 国产成人av网站| 久久久久久91香蕉国产| 男人天堂亚洲| 国产精品AV在线观看| 亚洲精品视频无码| 91人妻无码一区二区久久| 超碰在线人人爱| 911精品国产一区二区在线| 人妻在线观看| 大香蕉在线视频观看| 各种BBwBBwBBwBBw| 国内成人精品| 国产操逼免费看| 无码电影在线播放| 视频一区二区三区在线观看| 一区二区不卡| 国产又粗又大又黄视频| 综合激情网站| 韩国高清无码视频| 影音先锋人妻资源| 国产无码高清在线| 亚洲欧洲成人在线| 婷婷涩嫩草鲁丝久久午夜精品| 成人免费无码激情AV片| 中文字幕精品在线视频| 成人免费观看视频| 大地8免费高清视频观看大全| 天天爱av| 一级黄色片视频| 美妇肥臀一区二区三区-久久99精品国| 成人H动漫精品一区二区无码 | 中文字幕国产在线| MAD033_后宫秘密陶子.| 中文字幕AV在线免费观看| aaa久久| 人人操人人射| 91人妻人人澡人人爽人人DVD| 91精品国产aⅴ一区二区| 国产精品揄拍一区二区| 人人妻人人澡人人DⅤD| 强伦轩人妻一区二区三区四区| 亚洲日韩精品中文字幕在线| 五月天在线电影| 亚洲天堂高清| 色情五月| 操B视频在线播放| 波多野结衣无码高清视频| 国产免费无码一区二区| 麻酥酥在线视频| 欧美高清无码视频| 中文字幕在线免费| AV大片免费看| 欧洲成人在线观看| 日韩免费在线视频| 色五月婷婷婷| 国产人妻精品| 日韩午夜欧美精品一二三区| 亚洲免费视频一区| 久久精品视频免费观看|