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

四個維度搞懂 Nacos 注冊中心

開發 項目管理
現如今市面上注冊中心的輪子很多,我實際使用過的就有三款:Eureka、Gsched、Nacos,由于當前參與 Nacos 集群的維護和開發工作,期間也參與了 Nacos 社區的一些開發和 Bug Fix 工作,過程中對 Nacos 原理有了一定的積累,今天給大家分享一下 Nacos 動態服務發現的原理。

大家好呀,我是樓仔。

現如今市面上注冊中心的輪子很多,我實際使用過的就有三款:Eureka、Gsched、Nacos,由于當前參與 Nacos 集群的維護和開發工作,期間也參與了 Nacos 社區的一些開發和 Bug Fix 工作,過程中對 Nacos 原理有了一定的積累,今天給大家分享一下 Nacos 動態服務發現的原理。

不 BB,上文章目錄:

圖片

1、什么是動態服務發現?

服務發現是指使用一個注冊中心來記錄分布式系統中的全部服務的信息,以便其他服務能夠快速的找到這些已注冊的服務。

在單體應用中,DNS+Nginx 可以滿足服務發現的要求,此時服務的IP列表配置在 nginx 上。在微服務架構中,由于服務粒度變的更細,服務的上下線更加頻繁,我們需要一款注冊中心來動態感知服務的上下線,并且推送IP列表變化給服務消費者,架構如下圖。

圖片

2、Nacos 實現動態服務發現的原理

Nacos實現動態服務發現的核心原理如下圖,我們接下來的內容將圍繞這個圖來進行。

圖片

2.1 通訊協議

整個服務注冊與發現過程,都離不開通訊協議,在1.x的 Nacos 版本中服務端只支持 http 協議,后來為了提升性能在2.x版本引入了谷歌的 grpc,grpc 是一款長連接協議,極大的減少了 http 請求頻繁的連接創建和銷毀過程,能大幅度提升性能,節約資源。

據官方測試,Nacos服務端 grpc 版本,相比 http 版本的性能提升了9倍以上。

2.2 Nacos 服務注冊

簡單來講,服務注冊的目的就是客戶端將自己的ip端口等信息上報給 Nacos 服務端,過程如下:

  • 創建長連接:Nacos SDK 通過Nacos服務端域名解析出服務端ip列表,選擇其中一個ip創建 grpc 連接,并定時檢查連接狀態,當連接斷開,則自動選擇服務端ip列表中的下一個ip進行重連。
  • 健康檢查請求:在正式發起注冊之前,Nacos SDK 向服務端發送一個空請求,服務端回應一個空請求,若Nacos SDK 未收到服務端回應,則認為服務端不健康,并進行一定次數重試,如果都未收到回應,則注冊失敗。
  • 發起注冊:當你查看Nacos java SDK的注冊方法時,你會發現沒有返回值,這是因為Nacos SDK做了補償機制,在真實給服務端上報數據之前,會先往緩存中插入一條記錄表示開始注冊,注冊成功之后再從緩存中標記這條記錄為注冊成功,當注冊失敗時,緩存中這條記錄是未注冊成功的狀態,Nacos SDK開啟了一個定時任務,定時查詢異常的緩存數據,重新發起注冊。

Nacos SDK注冊失敗時的自動補償機制時序圖。

圖片

相關源碼如下:

@Override
public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance {}", namespaceId, serviceName,
instance);
//添加redo日志
redoService.cacheInstanceForRedo(serviceName, groupName, instance);

doRegisterService(serviceName, groupName, instance);
}
public void doRegisterService(String serviceName, String groupName, Instance instance) throws NacosException {
//向服務端發起注冊
InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,
NamingRemoteConstants.REGISTER_INSTANCE, instance);
requestToServer(request, Response.class);
//標記注冊成功
redoService.instanceRegistered(serviceName, groupName);
}

執行補償定時任務RedoScheduledTask。

@Override
public void run() {
if (!redoService.isConnected()) {
LogUtils.NAMING_LOGGER.warn("Grpc Connection is disconnect, skip current redo task");
return;
}
try {
redoForInstances();
redoForSubscribes();
} catch (Exception e) {
LogUtils.NAMING_LOGGER.warn("Redo task run with unexpected exception: ", e);
}
}
private void redoForInstances() {
for (InstanceRedoData each : redoService.findInstanceRedoData()) {
try {
redoForInstance(each);
} catch (NacosException e) {
LogUtils.NAMING_LOGGER.error("Redo instance operation {} for {}@@{} failed. ", each.getRedoType(),
each.getGroupName(), each.getServiceName(), e);
}
}
}
  • 服務端數據同步(Distro協議):Nacos SDK只會與服務端某個節點建立長連接,當服務端接受到客戶端注冊的實例數據后,還需要將實例數據同步給其他節點。Nacos自己實現了一個一致性協議名為Distro,服務注冊的時候會觸發Distro一次同步,每個Nacos節點之間會定時互相發送Distro數據,以此保證數據最終一致。
  • 服務實例上線推送:Nacos服務端收到服務實例數據后會將服務的最新實例列表通過grpc推送給該服務的所有訂閱者。
  • 服務注冊過程源碼時序圖:整理了一下服務注冊過程整體時序圖,對源碼實現感興趣的可以按照根據這個時序圖view一下源碼。

圖片

2.3 Nacos 心跳機制

目前主流的注冊中心,比如Consul、Eureka、Zk包括我們公司自研的Gsched,都是通過心跳機制來感知服務的下線。Nacos也是通過心跳機制來實現的。

Nacos目前SDK維護了兩個分支的版本(1.x、2.x),這兩個版本心跳機制的實現不一樣。其中1.x版本的SDK通過http協議來定時向服務端發送心跳維持自己的健康狀態,2.x版本的SDK則通過grpc自身的心跳機制來保活,當Nacos服務端接受不到服務實例的心跳,會認為實例下線。如下圖:

圖片

grpc監測到連接斷開事件,發送ClientDisconnectEvent。

public class ConnectionBasedClientManager extends ClientConnectionEventListener implements ClientManager {
//連接斷開,發送連接斷開事件
public boolean clientDisconnected(String clientId) {
Loggers.SRV_LOG.info("Client connection {} disconnect, remove instances and subscribers", clientId);
ConnectionBasedClient client = clients.remove(clientId);
if (null == client) {
return true;
}
client.release();
NotifyCenter.publishEvent(new ClientEvent.ClientDisconnectEvent(client));
return true;
}
}

移除客戶端注冊的服務實例

public class ClientServiceIndexesManager extends SmartSubscriber {

@Override
public void onEvent(Event event) {
//接收失去連接事件
if (event instanceof ClientEvent.ClientDisconnectEvent) {
handleClientDisconnect((ClientEvent.ClientDisconnectEvent) event);
} else if (event instanceof ClientOperationEvent) {
handleClientOperation((ClientOperationEvent) event);
}
}
private void handleClientDisconnect(ClientEvent.ClientDisconnectEvent event) {
Client client = event.getClient();
for (Service each : client.getAllSubscribeService()) {
removeSubscriberIndexes(each, client.getClientId());
}
//移除客戶端注冊的服務實例
for (Service each : client.getAllPublishedService()) {
removePublisherIndexes(each, client.getClientId());
}
}

//移除客戶端注冊的服務實例
private void removePublisherIndexes(Service service, String clientId) {
if (!publisherIndexes.containsKey(service)) {
return;
}
publisherIndexes.get(service).remove(clientId);
NotifyCenter.publishEvent(new ServiceEvent.ServiceChangedEvent(service, true));
}
}

2.4 Nacos 服務訂閱

當一個服務發生上下線,Nacos如何知道要推送給哪些客戶端?

Nacos SDK 提供了訂閱和取消訂閱方法,當客戶端向服務端發起訂閱請求,服務端會記錄發起調用的客戶端為該服務的訂閱者,同時將服務的最新實例列表返回。當客戶端發起了取消訂閱,服務端就會從該服務的訂閱者列表中把當前客戶端移除。

當客戶端發起訂閱時,服務端除了會同步返回最新的服務實例列表,還會異步的通過grpc推送給該訂閱者最新的服務實例列表,這樣做的目的是為了異步更新客戶端本地緩存的服務數據。

當客戶端訂閱的服務上下線,該服務所有的訂閱者會立刻收到最新的服務列表并且將服務最新的實例數據更新到內存。

圖片

我們也看一下相關源碼,服務端接收到訂閱數據,首先保存到內存中。

@Override
public void subscribeService(Service service, Subscriber subscriber, String clientId) {
Service singleton = ServiceManager.getInstance().getSingletonIfExist(service).orElse(service);
Client client = clientManager.getClient(clientId);
//校驗長連接是否正常
if (!clientIsLegal(client, clientId)) {
return;
}
//保存訂閱數據
client.addServiceSubscriber(singleton, subscriber);
client.setLastUpdatedTime();
//發送訂閱事件
NotifyCenter.publishEvent(new ClientOperationEvent.ClientSubscribeServiceEvent(singleton, clientId));
}

private void handleClientOperation(ClientOperationEvent event) {
Service service = event.getService();
String clientId = event.getClientId();
if (event instanceof ClientOperationEvent.ClientRegisterServiceEvent) {
addPublisherIndexes(service, clientId);
} else if (event instanceof ClientOperationEvent.ClientDeregisterServiceEvent) {
removePublisherIndexes(service, clientId);
} else if (event instanceof ClientOperationEvent.ClientSubscribeServiceEvent) {
//處理訂閱操作
addSubscriberIndexes(service, clientId);
} else if (event instanceof ClientOperationEvent.ClientUnsubscribeServiceEvent) {
removeSubscriberIndexes(service, clientId);
}
}

然后發布訂閱事件。

private void addSubscriberIndexes(Service service, String clientId) {
//保存訂閱數據
subscriberIndexes.computeIfAbsent(service, (key) -> new ConcurrentHashSet<>());
// Fix #5404, Only first time add need notify event.
if (subscriberIndexes.get(service).add(clientId)) {
//發布訂閱事件
NotifyCenter.publishEvent(new ServiceEvent.ServiceSubscribedEvent(service, clientId));
}
}

服務端自己消費訂閱事件,并且推送給訂閱的客戶端最新的服務實例數據。

@Override
public void onEvent(Event event) {
if (!upgradeJudgement.isUseGrpcFeatures()) {
return;
}
if (event instanceof ServiceEvent.ServiceChangedEvent) {
// If service changed, push to all subscribers.
ServiceEvent.ServiceChangedEvent serviceChangedEvent = (ServiceEvent.ServiceChangedEvent) event;
Service service = serviceChangedEvent.getService();
delayTaskEngine.addTask(service, new PushDelayTask(service, PushConfig.getInstance().getPushTaskDelay()));
} else if (event instanceof ServiceEvent.ServiceSubscribedEvent) {
// If service is subscribed by one client, only push this client.
ServiceEvent.ServiceSubscribedEvent subscribedEvent = (ServiceEvent.ServiceSubscribedEvent) event;
Service service = subscribedEvent.getService();
delayTaskEngine.addTask(service, new PushDelayTask(service, PushConfig.getInstance().getPushTaskDelay(),
subscribedEvent.getClientId()));
}
}

2.5 Nacos 推送

推送方式

前面說了服務的注冊和訂閱都會發生推送(服務端->客戶端),那推送到底是如何實現的呢?

在早期的Nacos版本,當服務實例變化,服務端會通過udp協議將最新的數據發送給客戶端,后來發現udp推送有一定的丟包率,于是新版本的Nacos支持了grpc推送。Nacos服務端會自動判斷客戶端的版本來選擇哪種方式來進行推送,如果你使用1.4.2以前的SDK進行注冊,那Nacos服務端會使用udp協議來進行推送,反之則使用grpc。

推送失敗重試

當發送推送時,客戶端可能正在重啟,或者連接不穩定導致推送失敗,這個時候Nacos會進行重試。Nacos將每個推送都封裝成一個任務對象,放入到隊列中,再開啟一個線程不停的從隊列取出任務執行,執行之前會先刪除該任務,如果執行失敗則將任務重新添加到隊列,該線程會記錄任務執行的時間,如果超過1秒,則會記錄到日志。

推送部分源碼

添加推送任務到執行隊列中。

private static class PushDelayTaskProcessor implements NacosTaskProcessor {

private final PushDelayTaskExecuteEngine executeEngine;

public PushDelayTaskProcessor(PushDelayTaskExecuteEngine executeEngine) {
this.executeEngine = executeEngine;
}

@Override
public boolean process(NacosTask task) {
PushDelayTask pushDelayTask = (PushDelayTask) task;
Service service = pushDelayTask.getService();
NamingExecuteTaskDispatcher.getInstance()
.dispatchAndExecuteTask(service, new PushExecuteTask(service, executeEngine, pushDelayTask));
return true;
}
}

推送任務PushExecuteTask 的執行。

public class PushExecuteTask extends AbstractExecuteTask {

//..省略

@Override
public void run() {
try {
//封裝要推送的服務實例數據
PushDataWrapper wrapper = generatePushData();
ClientManager clientManager = delayTaskEngine.getClientManager();
//如果是服務上下線導致的推送,獲取所有訂閱者
//如果是訂閱導致的推送,獲取訂閱者
for (String each : getTargetClientIds()) {
Client client = clientManager.getClient(each);
if (null == client) {
// means this client has disconnect
continue;
}
Subscriber subscriber = clientManager.getClient(each).getSubscriber(service);
//推送給訂閱者
delayTaskEngine.getPushExecutor().doPushWithCallback(each, subscriber, wrapper,
new NamingPushCallback(each, subscriber, wrapper.getOriginalData(), delayTask.isPushToAll()));
}
} catch (Exception e) {
Loggers.PUSH.error("Push task for service" + service.getGroupedServiceName() + " execute failed ", e);
//當推送發生異常,重新將推送任務放入執行隊列
delayTaskEngine.addTask(service, new PushDelayTask(service, 1000L));
}
}

//如果是服務上下線導致的推送,獲取所有訂閱者
//如果是訂閱導致的推送,獲取訂閱者
private Collection<String> getTargetClientIds() {
return delayTask.isPushToAll() ? delayTaskEngine.getIndexesManager().getAllClientsSubscribeService(service)
: delayTask.getTargetClients();
}

執行推送任務線程InnerWorker 的執行。

/**
* Inner execute worker.
*/
private class InnerWorker extends Thread {

InnerWorker(String name) {
setDaemon(false);
setName(name);
}

@Override
public void run() {
while (!closed.get()) {
try {
//從隊列中取出任務PushExecuteTask
Runnable task = queue.take();
long begin = System.currentTimeMillis();
//執行PushExecuteTask
task.run();
long duration = System.currentTimeMillis() - begin;
if (duration > 1000L) {
log.warn("task {} takes {}ms", task, duration);
}
} catch (Throwable e) {
log.error("[TASK-FAILED] " + e.toString(), e);
}
}
}
}

2.6 Nacos SDK 查詢服務實例

服務消費者首先需要調用Nacos SDK的接口來獲取最新的服務實例,然后才能從獲取到的實例列表中以加權輪詢的方式選擇出一個實例(包含ip,port等信息),最后再發起調用。

前面已經提到Nacos服務發生上下線、訂閱的時候都會推送最新的服務實例列表到當客戶端,客戶端再更新本地內存中的緩沖數據,所以調用Nacos SDK提供的查詢實例列表的接口時,不會直接請求服務端獲取數據,而是會優先使用內存中的服務數據,只有內存中查不到的情況下才會發起訂閱請求服務端數據。

Nacos SDK內存中的數據除了接受來自服務端的推送更新之外,自己本地也會有一個定時任務定時去獲取服務端數據來進行兜底。Nacos SDK在查詢的時候也了容災機制,即從磁盤獲取服務數據,而這個磁盤的數據其實也是來自于內存,有一個定時任務定時從內存緩存中獲取然后加載到磁盤。Nacos SDK的容災機制默認關閉,可通過設置環境變量failover-mode=true來開啟。

架構圖

用戶查詢流程

查詢服務實例部分源碼

private final ConcurrentMap<String, ServiceInfo> serviceInfoMap;
@Override
public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters,
boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
String clusterString = StringUtils.join(clusters, ",");
//這里默認傳過來是true
if (subscribe) {
//從本地內存獲取服務數據,如果獲取不到則從磁盤獲取
serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, clusterString);
if (null == serviceInfo || !clientProxy.isSubscribed(serviceName, groupName, clusterString)) {
//如果從本地獲取不到數據,則調用訂閱方法
serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString);
}
} else {
//適用于不走訂閱,直接從服務端獲取數據的情況
serviceInfo = clientProxy.queryInstancesOfService(serviceName, groupName, clusterString, 0, false);
}
List<Instance> list;
if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {
return new ArrayList<Instance>();
}
return list;
}
}
//從本地內存獲取服務數據,如果開啟了故障轉移則直接從磁盤獲取,因為當服務端掛了,本地啟動時內存中也沒有數據
public ServiceInfo getServiceInfo(final String serviceName, final String groupName, final String clusters) {
NAMING_LOGGER.debug("failover-mode: {}", failoverReactor.isFailoverSwitch());
String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
String key = ServiceInfo.getKey(groupedServiceName, clusters);
//故障轉移則直接從磁盤獲取
if (failoverReactor.isFailoverSwitch()) {
return failoverReactor.getService(key);
}
//返回內存中數據
return serviceInfoMap.get(key);
}

3. 結語

本篇文章向大家介紹 Nacos 服務發現的基本概念和核心能力以及實現的原理,旨在讓大家對 Nacos 的服務注冊與發現功能有更多的了解,做到心中有數。

責任編輯:武曉燕 來源: 樓仔
相關推薦

2025-05-08 09:31:06

2018-12-05 20:58:53

2021-10-26 00:07:35

TCP連接python

2023-11-13 10:00:09

數據中心服務器

2019-07-15 09:09:29

RedisJava操作系統

2021-08-04 11:54:25

Nacos注冊中心設計

2020-01-15 11:30:59

編碼優化性能

2023-03-01 08:15:10

NginxNacos

2011-11-02 10:59:03

陳旭東聯想云計算

2022-02-23 15:09:18

數字化轉型國有企業數據

2023-10-30 09:35:01

注冊中心微服務

2024-12-27 00:37:46

2023-04-04 09:44:52

數據中心能源安全

2018-12-24 10:04:35

SAP Concur智慧費用管理

2022-08-30 22:12:19

Nacos組件服務注冊

2024-06-25 12:45:05

2013-03-18 13:31:28

2010-09-01 11:17:24

數據中心搬遷

2018-08-15 08:33:33

編程Go語言開發

2024-04-10 12:22:19

DubboNacos微服務
點贊
收藏

51CTO技術棧公眾號

91资源在线播放| 91九色丨porny丨国产jk| 在线播放国产一区| 一本精品一区二区三区| 亚洲国产精品一区二区三区| 国产精品无码一区二区在线| 福利成人在线观看| 极品尤物av久久免费看| 国内外成人免费激情在线视频网站 | 国产日本精品| 久久这里有精品视频| 国产白嫩美女无套久久| 亚洲在线资源| 色一区在线观看| 天天做天天躁天天躁| 九色在线播放| 成人免费视频app| 91精品久久久久久久久不口人| 日韩三级视频在线播放| 久久久久久免费视频| 国产偷亚洲偷欧美偷精品| 夜夜爽久久精品91| 91国拍精品国产粉嫩亚洲一区| 亚洲午夜久久久久| 国产又大又长又粗又黄| 浮生影视网在线观看免费| 97精品超碰一区二区三区| 亚洲影影院av| 91精品国产乱码久久久久| 免费看的黄色欧美网站| 久久久久免费精品国产| 国产成人自拍网站| 91综合视频| 中文字幕亚洲欧美在线| 亚洲精品乱码久久久久久久久久久久| 狠狠久久伊人| 亚洲精品在线免费观看视频| 992kp免费看片| 日本免费成人| 精品视频123区在线观看| 亚洲国产精品久久久久爰色欲| heyzo在线播放| 一区二区三区资源| 女女同性女同一区二区三区按摩| 1769在线观看| 国产视频在线观看一区二区三区| 久久精品成人一区二区三区蜜臀| 日韩中文字幕免费在线观看| 粉嫩av一区二区三区在线播放| 444亚洲人体| 99久久久国产精品无码免费| 狠狠色丁香久久婷婷综| 成人国产精品一区二区| 国产精品永久久久久久久久久| 免播放器亚洲一区| 国产精品视频久久久| 国产精品51麻豆cm传媒| 美女网站色91| 91精品中文在线| 99久久精品国产成人一区二区| 国产精品一区二区视频| 91久久爱成人| 日韩有码第一页| 久久综合九色综合97_久久久| 免费看成人午夜电影| 精品av中文字幕在线毛片| 欧美激情中文字幕一区二区| 亚洲天堂电影网| fc2ppv国产精品久久| 亚洲一区二区在线播放相泽| 国产资源在线视频| se01亚洲视频| 欧美久久久久久蜜桃| 日本在线视频播放| 精品国产乱子伦一区二区| 日韩国产中文字幕| 国产一区二区三区四区在线| 香蕉国产精品| 午夜精品久久久久久久白皮肤 | 欧美日韩一区三区| 激情文学亚洲色图| 哺乳挤奶一区二区三区免费看 | 高清国产一区| 丝袜+亚洲+另类+欧美+变态| 99re这里只有精品视频首页| 视频在线99| 日本大胆在线观看| 欧美日韩精品国产| 国产乱码一区二区三区四区| 成人爽a毛片| 中文字幕av一区中文字幕天堂| 男人操女人的视频网站| 国产精品三上| 亚洲一区二区在线| 免费福利在线观看| 亚洲欧美另类小说| 成人羞羞国产免费网站| 国产精品一区免费在线| 日韩激情第一页| 中文字幕无码日韩专区免费 | 国产精品久久久久久麻豆一区软件| 欧美老女人性视频| 69av视频在线观看| 成人爱爱电影网址| 在线综合视频网站| 成人直播视频| 日韩精品一区二区三区视频播放 | 四虎影院在线播放| 亚洲精品菠萝久久久久久久| 老司机午夜av| 精品三级av| 欧美成人精品xxx| 亚洲精品91天天久久人人| 成人午夜精品在线| 中文字幕一区综合| 欧美成a人片在线观看久| 精品国产一区久久| 成人高潮免费视频| 蜜臀久久久久久久| 日韩成人av网站| 黄色aa久久| 欧美r级电影在线观看| 美国黄色片视频| 日韩**一区毛片| 久久久精彩视频| 丁香花视频在线观看| 日韩一区二区三| 日本中文在线视频| 日本欧美韩国一区三区| 欧美日韩精品不卡| 在线看片福利| 亚洲国产一区二区三区在线观看| 老妇女50岁三级| 国产一区二区三区av电影| 亚洲欧洲日韩精品| 国产福利91精品一区二区| 亚洲欧美中文字幕在线一区| 全部毛片永久免费看| 成人国产视频在线观看| 国产一区二区三区在线免费| 欧美在线在线| 欧美另类69精品久久久久9999| 91在线你懂的| 亚洲视频综合在线| 午夜一级免费视频| 91精品秘密在线观看| 成人精品一区二区三区| 成人看av片| 日韩欧美区一区二| 久久香蕉精品视频| 成人avav影音| 免费在线观看毛片网站| 免费一区二区三区视频导航| 国产精品 欧美在线| eeuss影院在线观看| 欧美日韩一区不卡| 久久免费看少妇高潮v片特黄| 国产在线不卡一卡二卡三卡四卡| 影音先锋成人资源网站| 澳门成人av| 欧美在线视频一区| 国产系列在线观看| 欧美福利一区二区| 久久av高潮av无码av喷吹| 丁香婷婷综合激情五月色| 国产av天堂无码一区二区三区| 亚洲8888| 国产日韩中文字幕在线| 中文字幕伦理免费在线视频 | 欧美熟乱第一页| 永久免费看片直接| 成人晚上爱看视频| 欧在线一二三四区| 天天影视欧美综合在线观看| caoporen国产精品| 三上悠亚一区二区| 波霸ol色综合久久| 欧美天堂在线视频| 欧美在线综合视频| 四虎免费在线视频| 久久久亚洲欧洲日产国码αv| www.xxx亚洲| 亚洲欧美文学| 蜜桃av久久久亚洲精品| 日本电影久久久| 91成人福利在线| 黄视频网站在线| 亚洲国产精品字幕| 中文字幕在线一| 亚洲国产精品自拍| 极品蜜桃臀肥臀-x88av| 国产不卡在线一区| www.日本xxxx| 在线精品一区| 一区二区三区在线视频看| 久9re热视频这里只有精品| 国产精品无码专区在线观看| 另类视频在线| 最新国产成人av网站网址麻豆| 亚洲国产精品国自产拍久久| 在线观看免费一区| 男人天堂中文字幕| 国产精品美日韩| 日韩片在线观看| 国产毛片精品一区| 国产成人久久婷婷精品流白浆| 伊人久久大香线蕉综合四虎小说| 老牛影视免费一区二区| 日韩欧洲国产| 成人激情视频小说免费下载| 最近在线中文字幕| 久久久久久中文字幕| 麻豆最新免费在线视频| 亚洲午夜色婷婷在线| 色一情一乱一区二区三区| 欧美精品三级日韩久久| 蜜臀精品一区二区三区| 精品欧美一区二区三区| 欧美成人手机视频| 国产精品成人一区二区艾草| 免费看黄色的视频| 91亚洲资源网| 玖玖爱在线精品视频| 国产乱码精品一区二区三区av | 国产精品毛片av| 91手机在线播放| 国产电影一区| 91精品国产综合久久香蕉的用户体验 | 一本久久综合| 欧美精品卡一卡二| 欧美成人嫩草网站| 日本福利视频导航| 香蕉国产精品| 国产精品一区在线免费观看| 欧美国产一级| 永久域名在线精品| 999国产精品| 亚洲国产精品影视| 999精品一区| 欧美h视频在线观看| 国产精品久久久久久| 在线观看成人av| 天天影视综合| 亚洲国产精品影视| 欧美ab在线视频| 日韩极品视频在线观看 | 日韩免费高清在线| 亚洲影院免费| 日韩中文字幕免费在线| 日韩精品一卡二卡三卡四卡无卡| 日韩视频在线免费看| 日韩精品五月天| 999精彩视频| 精品无人区卡一卡二卡三乱码免费卡| 欧美美女一级片| 国产在线观看一区二区| 91成人在线观看喷潮蘑菇| 成人福利视频网站| 在哪里可以看毛片| 国产精品久久久久久久裸模| 国产激情无码一区二区三区| 亚洲一二三四区不卡| 日韩人妻无码一区二区三区99| 欧美性猛交xxxx黑人猛交| 久久久久久无码精品大片| 欧美日韩精品免费| 99久久久国产精品无码网爆| 亚洲精品一区二区精华| 黄色小视频在线观看| 日韩中文在线中文网在线观看| 黄色免费在线观看| 午夜精品久久久久久久99热浪潮 | 51蜜桃传媒精品一区二区| 伊人久久大香线蕉av超碰| 久久99精品久久久久久久青青日本| 国产精品视频一区二区三区四蜜臂| 亚洲国产成人不卡| 欧美激情麻豆| 久久久久狠狠高潮亚洲精品| 美女任你摸久久| 人妻互换一二三区激情视频| 久久久久久亚洲综合影院红桃| 色偷偷男人天堂| 亚洲制服丝袜av| 国产一区二区视频免费| 欧美一区二区三区免费大片| 四虎影院在线域名免费观看| 日韩色av导航| 自拍在线观看| 99影视tv| 日韩综合一区| 人妻夜夜添夜夜无码av| 久久电影网站中文字幕| 亚洲男人在线天堂| 最新日韩av在线| 国产精品熟女视频| 欧美成人bangbros| 成年人在线观看网站| 午夜精品久久久久久久白皮肤| 看片一区二区| 蜜桃网站成人| 好看的日韩av电影| 鲁一鲁一鲁一鲁一av| 91网页版在线| 免费一级肉体全黄毛片| 欧美色视频一区| 天堂a√在线| 久久久久久久久久久av| av在线亚洲一区| 热舞福利精品大尺度视频| 在线观看日韩av电影| 91亚洲精品久久久蜜桃借种| 久久精品在这里| 在线看成人av| 欧美变态tickling挠脚心| 69视频在线观看| 国产精品福利网站| 日韩美女毛片| 秋霞无码一区二区| 国产精品 日产精品 欧美精品| 老熟妇一区二区| 图片区小说区国产精品视频| 国产福利小视频| 久久精品视频播放| 亚洲成人高清| 综合久久国产| 久久精品二区亚洲w码| 在线视频第一页| 日韩欧美aaa| 欧美男男激情freegay| 4438全国成人免费| 激情av综合| 欧美综合在线播放| av电影天堂一区二区在线观看| 久久久久久久久久久网 | 91精品国产自产在线观看永久| 日本不卡二三区| 中文字幕永久视频| 欧美激情一区二区三区全黄| 中文字幕人妻丝袜乱一区三区| 国产午夜精品一区二区三区| 韩国女主播一区二区| 日本在线观看不卡| 奇米精品一区二区三区四区| 国产黄色录像视频| 欧美日韩中文精品| 91.xxx.高清在线| 亚洲r级在线观看| 欧美午夜电影在线观看 | 欧美a级片视频| 精品综合久久久久| 亚洲色大成网站www久久九九| 国产99久一区二区三区a片| 欧美成人久久久| 加勒比中文字幕精品| 男人操女人免费软件| 日本一区二区视频在线| 一级久久久久久久| 欧美高清视频在线| 欧美久久精品| 午夜视频在线瓜伦| 中文字幕日韩一区二区| 国产成人精品av在线观| 91国产中文字幕| 欧美一级本道电影免费专区| 国产精品自在自线| 亚洲一区二区美女| 欧美xxx.com| 成人网页在线免费观看| 欧美精品一卡| 毛片网站免费观看| 精品视频1区2区| 92久久精品| 日韩视频在线播放| 国产在线播精品第三| 国产精品美女久久久久av爽| 中文日韩电影网站| 涩爱av色老久久精品偷偷鲁| 欧美日韩激情视频在线观看| 中文字幕高清一区| 国内精品久久久久久久久久久| 2019中文字幕全在线观看| 日韩精品中文字幕第1页| 中文字幕一区二区三区人妻在线视频| 婷婷夜色潮精品综合在线| 91在线观看| 国精产品一区二区| 美女网站一区二区| 日本网站在线免费观看| 日韩在线视频导航| 国产精品一线| 亚洲一区二区三区四区五区| 亚洲va韩国va欧美va精品| 日韩免费啪啪| 久久久综合亚洲91久久98| 国产在线日韩欧美| 无码人妻久久一区二区三区| 欧美黑人巨大xxx极品| 不卡中文字幕| 人妻在线日韩免费视频|