<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      手把手教你改造 Sentinel Dashboard 實現配置持久化

      一. 概述

      Sentinel客戶端默認情況下接收到 Dashboard 推送的規則配置后,可以實時生效。但是有一個致命缺陷,Dashboard和業務服務并沒有持久化這些配置,當業務服務重啟后,這些規則配置將全部丟失。

      Sentinel 提供兩種方式修改規則:

      • 通過 API 直接修改 (loadRules)
      • 通過 DataSource 適配不同數據源修改

      通過 API 修改比較直觀,可以通過以下幾個 API 修改不同的規則:

      FlowRuleManager.loadRules(List<FlowRule> rules); // 修改流控規則
      DegradeRuleManager.loadRules(List<DegradeRule> rules); // 修改降級規則
      

      手動修改規則(硬編碼方式)一般僅用于測試和演示,生產上一般通過動態規則源的方式來動態管理規則。

      上述 loadRules() 方法只接受內存態的規則對象,但更多時候規則存儲在文件、數據庫或者配置中心當中。DataSource 接口給我們提供了對接任意配置源的能力。相比直接通過 API 修改規則,實現 DataSource 接口是更加可靠的做法。

      我們推薦通過控制臺設置規則后將規則推送到統一的規則中心,客戶端實現 ReadableDataSource 接口端監聽規則中心實時獲取變更,流程如下:

      DataSource 擴展常見的實現方式有:

      • 拉模式:客戶端主動向某個規則管理中心定期輪詢拉取規則,這個規則中心可以是 RDBMS、文件,甚至是 VCS 等。這樣做的方式是簡單,缺點是無法及時獲取變更;
      • 推模式:規則中心統一推送,客戶端通過注冊監聽器的方式時刻監聽變化,比如使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。

      Sentinel 目前支持以下數據源擴展:

      Sentinel開源版在Push模式下只實現了 路徑2,也就是Nacos到業務服務之間的規則同步;路徑1 Dashboard配置修改寫入Nacos并沒有實現,在后文中我們會介紹如何修改 Dashboard 源碼完成配置的寫入。

      二. 從 Nacos 加載規則配置

      首先,我們先來看看如何使用Sentinel官方提供的 sentinel-datasource-nacos 從Nacos加載規則配置。

      第一步:引入依賴

      <dependency>
          <groupId>com.alibaba.csp</groupId>
          <artifactId>sentinel-datasource-nacos</artifactId>
          <version>1.8.6</version>
      </dependency>
      

      第二步:配置規則自動加載

      package cn.bigcoder.demo.sentinel.sentineldemo.demos.config;
      
      import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
      import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
      import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
      import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
      import com.alibaba.fastjson.JSON;
      import com.alibaba.fastjson.TypeReference;
      import com.alibaba.nacos.api.PropertyKeyConst;
      import java.util.List;
      import java.util.Properties;
      import org.springframework.context.ApplicationListener;
      import org.springframework.context.event.ContextRefreshedEvent;
      import org.springframework.stereotype.Component;
      
      @Component
      public class SentinelRuleConfiguration implements ApplicationListener<ContextRefreshedEvent> {
      
          private static final String remoteAddress = "10.10.10.12:8848";
          // nacos group
          private static final String groupId = "SENTINEL_GROUP";
          // nacos dataId
          private static final String dataId = "sentinel-demo";
      
          private static final String NACOS_NAMESPACE_ID = "SENTINEL";
      
          @Override
          public void onApplicationEvent(ContextRefreshedEvent event) {
              Properties properties = new Properties();
              properties.put(PropertyKeyConst.SERVER_ADDR, remoteAddress);
      //        properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE_ID);
      
              ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId,
                      dataId,
                      source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                      }));
              FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
          }
      }
      

      第三步:往Nacos中寫入配置

      import com.alibaba.nacos.api.NacosFactory;
      import com.alibaba.nacos.api.PropertyKeyConst;
      import com.alibaba.nacos.api.config.ConfigService;
      import java.util.Properties;
      
      
      public class NacosConfigSender {
      
          public static void main(String[] args) throws Exception {
              final String groupId = "SENTINEL_GROUP";
              final String dataId = "sentinel-demo-flow-rules";
              // 創建ConfigService實例
              Properties properties = new Properties();
              properties.put(PropertyKeyConst.SERVER_ADDR, "10.10.10.12:8848");
              // 指定namespace
              properties.put(PropertyKeyConst.NAMESPACE, "SENTINEL");
              final String rule = "[\n"
                  + "  {\n"
                  + "    \"resource\": \"GET:/user/getById\",\n"
                  + "    \"controlBehavior\": 0,\n"
                  + "    \"count\": 1,\n"
                  + "    \"grade\": 1,\n"
                  + "    \"limitApp\": \"default\",\n"
                  + "    \"strategy\": 0\n"
                  + "  }\n"
                  + "]";
              ConfigService configService = NacosFactory.createConfigService(properties);
              System.out.println(configService.publishConfig(dataId, groupId, rule));
          }
      }
      
      

      執行完后,Nacos中就會出現對應的配置:

      第四步:啟動項目,驗證規則配置是否生效

      訪問 http://127.0.0.1:8719/getParamRules?type=flow 即可看到業務服務內存中加載到的規則配置

      并發執行 /user/getById 接口,可以發現接口被成功限流,1s內的10次請求,只有一次成功。

      三. Dashboard存在的問題

      使用此方案雖然解決了配置規則配置持久化的問題,但是在Dashboard上修改配置仍然是通過業務服務暴露的接口進行的配置同步。業務服務既可以接收 Nacos 配置變更,又可以接收Dashboard的配置變更,控制臺的變更的配置并沒有同步到Nacos,應用重啟后Sentinel控制臺修改的配置仍然會全部丟失:

      一個理想的情況是Sentinel控制臺規則配置讀取至 Nacos 而不是內存,在控制臺修改/新增的配置寫入Nacos,當Nacos配置發生變更時,配置進而自動同步至業務服務:

      當然存儲媒介可以根據情況選用別的組件:ZooKeeper, Redis, Apollo, etcd

      很可惜的是,阿里官方開源的Sentinel控制臺并沒有實現將規則配置寫入其他中間件的能力。它默認只支持將配置實時推送至業務服務,所以我們在生產環境中想要使用 Sentinel Dashboard 需要自行修改其源碼,將其配置同步邏輯改為寫入我們所需要的中間件中。

      四. 修改Sentinel Dashboard源碼

      4.1 準備工作

      首先通過git拉取下載源碼,導入idea工程:

      https://github.com/alibaba/Sentinel

      本文源碼修改基于 Sentinel 1.8.8 版本,所有修改的源碼可參考:

      https://github.com/bigcoder84/Sentinel

      4.1.1 流控規則接口

      Sentinel Dashboard的流控規則下的所有操作,都會調用Sentinel-Dashboard源碼中的FlowControllerV1類,這個類中包含流控規則本地化的CRUD操作:

      在com.alibaba.csp.sentinel.dashboard.controller.v2包下存在一個FlowControllerV2;類,這個類同樣提供流控規則的CURD,與V1不同的是,它可以實現指定數據源的規則拉取和發布

      @RestController
      @RequestMapping(value = "/v2/flow")
      public class FlowControllerV2 {
      
          private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
      
          @Autowired
          private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
      
          @Autowired
          @Qualifier("flowRuleNacosProvider")
          private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
          @Autowired
          @Qualifier("flowRuleNacosPublisher")
          private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
          
          //....
      }
      

      官方說明:從 Sentinel 1.4.0 開始,我們抽取出了接口用于向遠程配置中心推送規則以及拉取規則。

      • DynamicRuleProvider<T>: 拉取規則
      • DynamicRulePublisher<T>: 推送規則

      以 Nacos 為例,若希望使用 Nacos 作為動態規則配置中心,用戶可以提取出相關的類,然后只需在 FlowControllerV2 中指定對應的 bean 即可開啟 Nacos 適配

      FlowControllerV2依賴兩個非常重要的類

      • DynamicRuleProvider:動態規則的拉取,從指定數據源中獲取控制后在Sentinel Dashboard中展示。
      • DynamicRulePublisher:動態規則發布,將在Sentinel Dashboard中修改的規則同步到指定數據源中。

      只需要擴展這兩個類,然后集成Nacos來實現Sentinel Dashboard規則同步

      4.1.2 需要改造的頁面入口

      簇點鏈路:

      由于該頁面的“流控”配置是對單節點進行配置的,所以理論上該頁面的URL是不用改的

      流控規則:

      上述位置我們都需要改造對應前端代碼,使之調用的接口更改為我們新的V2接口上。

      4.2 源碼改造

      4.2.1 在pom.xml文件中去掉test scope注釋

      這是因為官方提供的Nacos持久化用例都是在test目錄下,所以scope需要去除test,需要sentinel-datasource-nacos包的支持。之后將修改好的源碼放在源碼主目錄下,而不是繼續在test目錄下。

      <dependency>
          <groupId>com.alibaba.csp</groupId>
          <artifactId>sentinel-datasource-nacos</artifactId>
          <!--<scope>test</scope>-->
      </dependency>
      

      4.2.2 創建Nacos配置

      我們采用官方的約束,即默認 Nacos 適配的 dataId 和 groupId 約定如下:

      • groupId: SENTINEL_GROUP
      • 流控規則 dataId: {appName}-flow-rules,比如應用名為 appA,則 dataId 為 appA-flow-rules

      所以不需要修改NacosConfigUtil.java了,但這是展示是為了步驟的完整性。

      package com.alibaba.csp.sentinel.dashboard.rule.nacos;
      
      import org.springframework.boot.context.properties.ConfigurationProperties;
      
      @ConfigurationProperties(prefix = "sentinel.nacos")
      public class NacosPropertiesConfiguration {
          private String serverAddr;
          private String groupId = "SENTINEL_GROUP"; // 默認分組
          private String namespace;
         // 省略 getter/setter  
      }
      

      然后配置sentinel-dashboar/resources/application.properties中配置nacos配置,以為sentinel.nacos為前綴:

      # nacos config server
      sentinel.nacos.serverAddr=127.0.0.1:8848
      sentinel.nacos.namespace=
      sentinel.nacos.group-id=SENTINEL-GROUP
      

      4.2.3 改造NacosConfig,創建NacosConfigService

      package com.alibaba.csp.sentinel.dashboard.config;
      
      import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
      import com.alibaba.csp.sentinel.datasource.Converter;
      import com.alibaba.fastjson.JSON;
      import com.alibaba.nacos.api.PropertyKeyConst;
      import com.alibaba.nacos.api.config.ConfigFactory;
      import com.alibaba.nacos.api.config.ConfigService;
      import java.util.List;
      import java.util.Properties;
      import org.springframework.boot.context.properties.EnableConfigurationProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      @EnableConfigurationProperties(NacosPropertiesConfiguration.class)
      @Configuration
      public class NacosConfig {
      
          @Bean
          public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
              return JSON::toJSONString;
          }
      
          @Bean
          public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
              return s -> JSON.parseArray(s, FlowRuleEntity.class);
          }
      
          @Bean
          public ConfigService nacosConfigService(NacosPropertiesConfiguration nacosPropertiesConfiguration)
                  throws Exception {
              Properties properties = new Properties();
              properties.put(PropertyKeyConst.SERVER_ADDR, nacosPropertiesConfiguration.getServerAddr());
              properties.put(PropertyKeyConst.NAMESPACE, nacosPropertiesConfiguration.getNamespace());
              return ConfigFactory.createConfigService(properties);
          }
      }
      

      NacosConfig主要做兩件事:

      1) 注入Convert轉換器,將 FlowRuleEntity 使用序列化為JSON字符串,以及將JSON字符串反序列化為 FlowRuleEntity

      2) 注入Nacos配置服務ConfigService

      4.2.4 實現 DynamicRulePublisher 和 DynamicRuleProvider 接口完成配置的持久化和遠程加載

      在 test 包下,已經有Sentinel官方的實現了,我們只需要將其拷貝至 src 目錄下即可:

      FlowRuleNacosProvider:用于從Nacos中拉取規則配置。

      package com.alibaba.csp.sentinel.dashboard.rule;
      
      import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
      import com.alibaba.csp.sentinel.dashboard.util.NacosConfigUtil;
      import com.alibaba.csp.sentinel.datasource.Converter;
      import com.alibaba.csp.sentinel.util.StringUtil;
      import com.alibaba.nacos.api.config.ConfigService;
      import java.util.ArrayList;
      import java.util.List;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      
      /**
       * @author Eric Zhao
       * @since 1.4.0
       */
      @Component("flowRuleNacosProvider")
      public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
      
          @Autowired
          private ConfigService configService;
          @Autowired
          private Converter<String, List<FlowRuleEntity>> converter;
      
          @Override
          public List<FlowRuleEntity> getRules(String appName) throws Exception {
              String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
                  NacosConfigUtil.GROUP_ID, 3000);
              if (StringUtil.isEmpty(rules)) {
                  return new ArrayList<>();
              }
              return converter.convert(rules);
          }
      }
      
      

      FlowRuleNacosPublisher:用于將配置保存至Nacos中

      package com.alibaba.csp.sentinel.dashboard.rule;
      
      import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
      import com.alibaba.csp.sentinel.dashboard.util.NacosConfigUtil;
      import com.alibaba.csp.sentinel.datasource.Converter;
      import com.alibaba.csp.sentinel.util.AssertUtil;
      import com.alibaba.nacos.api.config.ConfigService;
      import java.util.List;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Component;
      
      /**
       * @author Eric Zhao
       * @since 1.4.0
       */
      @Component("flowRuleNacosPublisher")
      public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
      
          @Autowired
          private ConfigService configService;
          @Autowired
          private Converter<List<FlowRuleEntity>, String> converter;
      
          @Override
          public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
              AssertUtil.notEmpty(app, "app name cannot be empty");
              if (rules == null) {
                  return;
              }
              configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,
                  NacosConfigUtil.GROUP_ID, converter.convert(rules));
          }
      }
      

      4.2.5 修改FlowControllerV2類將Nacos實現類注入進去

      @RestController
      @RequestMapping(value = "/v2/flow")
      public class FlowControllerV2 {
      
          private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class);
      
          @Autowired
          private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository;
      
          @Autowired
          @Qualifier("flowRuleNacosProvider")
          private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
          @Autowired
          @Qualifier("flowRuleNacosPublisher")
          private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
      
          // 省略      
      }
      

      到這里所有流控規則相關的后端接口都已經改造完畢,我們需要接著改造前端頁面,將頁面請求的接口全部換成V2新接口。

      4.2.6 修改前端“流控規則”路由配置(sidebar.html)

      找到 resources/app/scripts/directives/sidebar/sidebar.html 文件,該文件是用來渲染左側路由的:

      我們需要將 “流控規則” 路由跳轉的頁面由 app/views/flow_v1.html 更換為 app/views/flow_v2.html,因為 flow_v2.html 頁面中調用的后端接口全部都是 v2接口。

      修改flowV1為flow,去掉V1,這樣的話會調用FlowControllerV2接口

      <!--<li ui-sref-active="active" ng-if="!entry.isGateway">
        <a ui-sref="dashboard.flowV1({app: entry.app})">
          <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控規則</a>
      </li>-->
      <!-- 修改為flow,直接調用FlowControllerV2 -->
      <li ui-sref-active="active" ng-if="!entry.isGateway">
        <a ui-sref="dashboard.flow({app: entry.app})">
          <i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控規則</a>
      </li>
      

      這樣就可以通過js跳轉至FlowControllerV2了

            .state('dashboard.flow', {
                templateUrl: 'app/views/flow_v2.html',
                url: '/v2/flow/:app',
                controller: 'FlowControllerV2',
                resolve: {
                    loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
                        return $ocLazyLoad.load({
                            name: 'sentinelDashboardApp',
                            files: [
                                'app/scripts/controllers/flow_v2.js',
                            ]
                        });
                    }]
                }
            })
      

      4.2.7 修改前端“簇點鏈路”中流控配置的接口

      根據 app/scripts/directives/sidebar/sidebar.html 觸點鏈路路由調用js方法可知,最終路由轉發到了 app/views/identity.html 頁面:

      <!-- app/scripts/directives/sidebar/sidebar.html -->
      <li ui-sref-active="active" ng-if="!entry.isGateway">
        <a ui-sref="dashboard.identity({app: entry.app})">
          <i class="glyphicon glyphicon-list-alt"></i>&nbsp;&nbsp;簇點鏈路</a>
      </li>
      
      // app/scripts/app.js
      .state('dashboard.identity', {
        templateUrl: 'app/views/identity.html',
        url: '/identity/:app',
        controller: 'IdentityCtl',
        resolve: {
          loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
            return $ocLazyLoad.load({
              name: 'sentinelDashboardApp',
              files: [
                'app/scripts/controllers/identity.js',
              ]
            });
          }]
        }
      })
      

      app/views/identity.html 頁面中,我們需要將“流控”彈窗的保存按鈕調用的接口換成V2版本,

      addNewFlowRule 方法在 app/scripts/controllers/identity.js 文件中:

          $scope.addNewFlowRule = function (resource) {
            if (!$scope.macInputModel) {
              return;
            }
            var mac = $scope.macInputModel.split(':');
            flowRuleDialogScope = $scope.$new(true);
            flowRuleDialogScope.currentRule = {
              enable: false,
              strategy: 0,
              grade: 1,
              controlBehavior: 0,
              resource: resource,
              limitApp: 'default',
              clusterMode: false,
              clusterConfig: {
                  thresholdType: 0
              },
              app: $scope.app,
              ip: mac[0],
              port: mac[1]
            };
      
            flowRuleDialogScope.flowRuleDialog = {
              title: '新增流控規則',
              type: 'add',
              confirmBtnText: '新增',
              saveAndContinueBtnText: '新增并繼續添加',
              showAdvanceButton: true
            };
            // $scope.flowRuleDialog = {
            //     showAdvanceButton : true
            // };
            flowRuleDialogScope.saveRule = saveFlowRule;
            flowRuleDialogScope.saveRuleAndContinue = saveFlowRuleAndContinue;
            flowRuleDialogScope.onOpenAdvanceClick = function () {
              flowRuleDialogScope.flowRuleDialog.showAdvanceButton = false;
            };
            flowRuleDialogScope.onCloseAdvanceClick = function () {
              flowRuleDialogScope.flowRuleDialog.showAdvanceButton = true;
            };
      
            flowRuleDialog = ngDialog.open({
              template: '/app/views/dialog/flow-rule-dialog.html',
              width: 680,
              overlay: true,
              scope: flowRuleDialogScope
            });
          };
      

      在這個方法中,會調用 saveFlowRule 方法保存流控規則:

          function saveFlowRule() {
            if (!FlowService.checkRuleValid(flowRuleDialogScope.currentRule)) {
              return;
            }
            FlowService.newRule(flowRuleDialogScope.currentRule).success(function (data) {
              if (data.code === 0) {
                flowRuleDialog.close();
                let url = '/dashboard/flow/' + $scope.app;
                $location.path(url);
              } else {
                alert('失敗:' + data.msg);
              }
            }).error((data, header, config, status) => {
                alert('未知錯誤');
            });
          }
      

      在這個方法中,會調用 FlowService.newRule 方法發送HTTP請求新建規則,成功后會將頁面重定向至 '/dashboard/flow/' + $scope.app,所以我們需要改兩個地方:

      1. 將FlowService改成V2版本

      2. 將重定向頁面跳轉至 '/dashboard/v2/flow/' + $scope.app

      4.3.8 重新打包項目

      進入 sentinel-dashboard 目錄,執行下列命令重新打包:

      mvn clean package -Dmaven.test.skip
      

      4.3 測試

      可以看到修改后的Dashboard成功將配置寫入Nacos中,Nacos配置發生變更,也同時通知了訂閱這些配置的客戶端,使得業務服務能實時更新流控配置,即使業務服務重啟,之前仍能正常從Nacos中拉取配置。

      五. 總結

      本文詳細介紹了如何利用Nacos實現Sentinel Dashboard配置的持久化,解決了業務服務重啟后配置丟失的問題。通過以下幾個步驟,我們成功實現了配置的動態管理和持久化存儲:

      1. 引入Nacos依賴:在項目中添加了sentinel-datasource-nacos依賴,為后續集成打下基礎。
      2. 配置自動加載:通過實現ReadableDataSource接口,配置了規則自動從Nacos加載到Sentinel的流程。
      3. Nacos配置寫入:通過編寫NacosConfigSender類,實現了向Nacos寫入配置的功能。
      4. Dashboard源碼改造:針對Dashboard存在的問題,通過修改前后端源碼,實現了配置的持久化存儲和同步更新。

      通過這一系列的改造,我們不僅提高了Sentinel Dashboard的可用性和穩定性,還增強了其在生產環境中的實用性。現在,即使在業務服務重啟的情況下,配置也不會丟失,確保了服務的連續性和一致性。

      本文只是講解了“流控規則”持久化的源碼修改過程,如果其它模塊也有持久化的需求,也可以參考此過程進行相應的源碼修改。

      本文參考至:

      dynamic-rule-configuration | Sentinel (sentinelguard.io)

      Sentinel Dashboard(基于1.8.1)流控規則持久化到Nacos——涉及部分Sentinel Dashboard源碼改造 - JJian - 博客園 (cnblogs.com)

      posted @ 2024-06-16 13:51  聽到微笑  閱讀(335)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99精品国产一区在线看| 精品国产乱码久久久人妻| 亚洲国产精品久久综合网| 老太脱裤让老头玩ⅹxxxx| 精品国产一区av天美传媒| 超碰成人人人做人人爽| 性欧美VIDEOFREE高清大喷水| 婷婷色综合成人成人网小说| 精品一区二区久久久久久久网站 | 天天做天天爱夜夜夜爽毛片| 亚洲无人区视频在线观看| 国产精品沙发午睡系列990531| 男女啪啪免费观看网站| 国产乱子伦视频在线播放| 97久久精品无码一区二区天美| 亚洲精品三区四区成人少| 另类 专区 欧美 制服| 国产福利一区二区三区在线观看| 乱色欧美激惰| 92精品国产自产在线观看481页| 久久av无码精品人妻出轨| 国产成人精品性色av麻豆| 人妻中文字幕精品系列| 体育| 中文字幕第一页亚洲精品| 国产97人人超碰CAO蜜芽PROM| 国模雨珍浓密毛大尺度150p| 午夜福利影院不卡影院| 亚洲精品第一国产综合精品| 4hu44四虎www在线影院麻豆| 韩国无码av片在线观看| 免费网站看av片| 欧美激情 亚洲 在线| 蜜臀av一区二区三区在线| 色哟哟www网站入口成人学校| 色99久久久久高潮综合影院| 深田えいみ禁欲后被隔壁人妻 | 青青青爽在线视频观看| 亚洲熟妇色xxxxx欧美老妇| 亚洲天堂伊人久久a成人| 国产绿帽在线视频看|