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

接口撥測 Plus 版本,你知道多少?

開發 后端
在結構體中,主要定義撥測相關字段,比如撥測地址,返回值,狀態碼,撥測頻率等,這些字段都通過前端頁面填寫。然后就是對撥測任務的增刪改查,這類接口比較通用,可以直接復制gin-vue-admin中的實例進行修改。

之前寫了一個《開發一個接口監控的Prometheus Exporter》,當時只是單純的實現了一個簡單的Exporter,但是基本能滿足要求,最近對接口監控的需求做了升級,主要有:

  • 接口的管理通過前端頁面實現,將數據存入數據庫
  • 接口的校驗除了可以校驗狀態碼,還增加了返回值校驗
  • 前端頁面可以顯示當前接口的可用性百分比
  • 撥測項可以靈活配置
  • 撥測頻率可以靈活調整
  • 撥測結果校驗可以靈活配置
  • 可以靈活開啟或關閉撥測

功能的實現方式比較簡單,梳理如下:

  • 用戶創建撥測任務,將任務存入數據庫
  • 后端為新的撥測起一個定時任務
  • 后端協程實時監聽更新或者刪除操作,更新定時任務
  • 撥測任務生成Prometheus指標,供Prometheus收集做監控告警使用

下面簡單總結后端的實現和前端的效果。

Tips: 整個項目是使用gin-vue-admin搭建,撥測只是其中一個小功能。

后端實現

(1)定義數據庫的結構體
// DialApi 撥測 結構體  
type DialApi struct {  
    global.GVA_MODEL  
    Name           string `json:"name" form:"name" gorm:"column:name;default:'';comment:接口名稱;size:32;"`                                       //接口名稱  
    Type           string `json:"type" form:"type" gorm:"column:type;default:'';comment:撥測類型 HTTP TCP PING DNS;size:8;"`                      // 撥測類型  
    HttpMethod     string `json:"httpMethod" form:"httpMethod" gorm:"column:http_method;default:GET;comment:HTTP請求方法;size:8;"`                //HTTP請求方法  
    Url            string `json:"url" form:"url" gorm:"column:url;comment:撥測地址;size:255;"binding:"required"`                                  //撥測地址  
    RequestBody    string `json:"requestBody" form:"requestBody" gorm:"column:request_body;comment:請求BODY;size:255;"`                         //撥測地址  
    Enabled        *bool  `json:"enabled" form:"enabled" gorm:"column:enabled;default:false;comment:是否啟用;"binding:"required"`                 //是否啟用  
    Application    string `json:"application" form:"application" gorm:"column:application;comment:所屬應用;size:32;"`                             //所屬應用  
    ExceptResponse string `json:"exceptResponse" form:"exceptResponse" gorm:"column:except_response;comment:預期返回值;size:32;"`                  //預期返回值  
    HttpStatus     int    `json:"httpStatus" form:"httpStatus" gorm:"column:http_status;type:smallint(5);default:200;comment:預期狀態碼;size:16;"` //預期狀態碼  
    Cron           string `json:"cron" form:"cron" gorm:"column:cron;comment:cron表達式;size:20;"`                                               //cron表達式  
    SuccessRate    string `json:"successRate" form:"successRate" gorm:"column:success_rate;comment:撥測成功率"`  
    CreatedBy      uint   `gorm:"column:created_by;comment:創建者"`  
    UpdatedBy      uint   `gorm:"column:updated_by;comment:更新者"`  
    DeletedBy      uint   `gorm:"column:deleted_by;comment:刪除者"`  
}

在結構體中,主要定義撥測相關字段,比如撥測地址,返回值,狀態碼,撥測頻率等,這些字段都通過前端頁面填寫。

然后就是對撥測任務的增刪改查,這類接口比較通用,可以直接復制gin-vue-admin中的實例進行修改。

(2)對于新創建的撥測任務,需要將其加入到定時任務中。在這里做了偷懶,直接使用gin-vue-admin的定時任務功能。因此,需要實現一個Run方法,如下:

type StartDialApi struct{}  
type StartSingleDialApiTask struct{}

func (j *StartDialApi) Run() {  
    var dialService = service.ServiceGroupApp.DialApiServiceGroup.DialApiService  
    // 獲取狀態為打開的定時任務  
    pageInfo := dialApiReq.DialApiSearch{}  
    dialApiInfoList, _, err := dialService.GetDialApiInfoList(pageInfo)  
    if err == nil {  
       var option []cron.Option  
       option = append(option, cron.WithSeconds())  
       for _, dialApi := range dialApiInfoList {  
          // 將cron的值變成表達式  
          c := utils.ConvertToCronExpression(dialApi.Cron)  
          dialApi.Cron = c  
          dialService.AddSingleDialApiTimerTask(dialApi)  
       }  
    } else {  
       global.GVA_LOG.Error("獲取撥測任務列表失敗")  
    }  
}

然后會調用dialService.AddSingleDialApiTimerTask實現定時任務的真正操作。

func (dialService *DialApiService) AddSingleDialApiTimerTask(dialApiEntity dialApi.DialApi) {  
    var option []cron.Option  
    option = append(option, cron.WithSeconds())  
    idStr := strconv.Itoa(int(dialApiEntity.ID))  
    cronName := global.DIAL_API + idStr  
    taskName := global.DIAL_API + idStr  
    task, found := global.GVA_Timer.FindTask(cronName, taskName)  
    if !found {  
       if *dialApiEntity.Enabled {  
          _, err := global.GVA_Timer.AddTaskByFunc(cronName, dialApiEntity.Cron, func() {  
             global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "success").Add(0)  
             global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "failed").Add(0)  
             switch dialApiEntity.Type {  
             case "HTTP":  
                ok := checkHTTP(dialApiEntity)  
                if ok {  
                   global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "success").Add(1)  
                } else {  
                   global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "failed").Add(1)  
                }  
  
                // 記錄日志  
                logHealthCheckResult(ok, nil, dialApiEntity, "HTTP")  
  
                // 獲取Prometheus指標并存入數據庫  
                getSuccessRateFromPrometheus(dialApiEntity)  
  
             case "TCP", "DNS", "ICMP":  
                var ok bool  
                var err error  
                switch dialApiEntity.Type {  
                case "TCP":  
                   ok, err = checkTCP(dialApiEntity)  
                case "DNS":  
                   ok, err = checkDNS(dialApiEntity)  
                case "ICMP":  
                   ok, err = checkICMP(dialApiEntity)  
                }  
                if ok {  
                   global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "success").Add(1)  
                } else {  
                   global.HealthCheckResults.WithLabelValues(dialApiEntity.Name, dialApiEntity.Type, "failed").Add(1)  
                }  
  
                // 記錄日志  
                logHealthCheckResult(ok, err, dialApiEntity, dialApiEntity.Type)  
  
                // 獲取Prometheus指標并存入數據庫  
                getSuccessRateFromPrometheus(dialApiEntity)  
             default:  
                global.GVA_LOG.Error("未知的檢測類型",  
                   zap.String("DetectType", dialApiEntity.Type),  
                )  
             }  
          }, global.DIAL_API+idStr, option...)  
          if err != nil {  
             global.GVA_LOG.Error(fmt.Sprintf("添加撥測定時任務失敗: %s : %s , 原因是: %s", idStr, dialApiEntity.Name, err.Error()))  
          }  
       }  
    } else {  
       if task.Spec != dialApiEntity.Cron {  
          global.GVA_LOG.Info(fmt.Sprintf("修改定時任務時間: %s", dialApiEntity.Name))  
          global.GVA_Timer.Clear(global.DIAL_API + idStr)  
          dialService.AddSingleDialApiTimerTask(dialApiEntity)  
       } else if !*dialApiEntity.Enabled || dialApiEntity.DeletedAt.Valid {  
          global.GVA_LOG.Info(fmt.Sprintf("停止撥測任務: %s", dialApiEntity.Name))  
          global.GVA_Timer.RemoveTaskByName(cronName, taskName)  
       }  
    }  
}

在該方法中,先判斷定時任務是否已經存在,只有不存在且開啟撥測的任務才會加入定時任務。否則,就會執行修改或者刪除邏輯。

另外,為了方便前端顯示撥測成功率,每次執行任務的時候會計算一次成功率,這里采用的是直接計算Prometheus指標,使用getSuccessRateFromPrometheus方法實現,如下:

func getSuccessRateFromPrometheus(dialApiEntity dialApi.DialApi) {  
    // 查詢prometheus獲取過去1小時的成功率  
    successQuery := fmt.Sprintf(`sum(rate(health_check_results{name="%s", type="%s", status="success"}[1h]))`, dialApiEntity.Name, dialApiEntity.Type)  
    totalQuery := fmt.Sprintf(`sum(rate(health_check_results{name="%s", type="%s"}[1h]))`, dialApiEntity.Name, dialApiEntity.Type)  
    successResponse, err := utils.QueryPrometheus(successQuery, global.GVA_CONFIG.Prometheus.Address)  
    if err != nil {  
       global.GVA_LOG.Error("Failed to query success rate from Prometheus", zap.Error(err))  
       return  
    }  
    totalResponse, err := utils.QueryPrometheus(totalQuery, global.GVA_CONFIG.Prometheus.Address)  
    if err != nil {  
       global.GVA_LOG.Error("Failed to query total rate from Prometheus", zap.Error(err))  
       return  
    }  
  
    // 解析 Prometheus 響應并計算成功率  
    var successValue float64  
    var totalValue float64  
    if len(successResponse.Data.Result) > 0 {  
       for _, result := range successResponse.Data.Result {  
          if value, ok := result.Value[1].(string); ok {  
             if value, err := strconv.ParseFloat(value, 64); err == nil {  
                successValue = value  
             }  
          }  
       }  
    }  
    if len(totalResponse.Data.Result) > 0 {  
       for _, result := range totalResponse.Data.Result {  
          if value, ok := result.Value[1].(string); ok {  
             if value, err := strconv.ParseFloat(value, 64); err == nil {  
                totalValue = value  
             }  
          }  
       }  
    }  
  
    if totalValue > 0 {  
       successRate := CalculateSuccessRate(successValue, totalValue)  
  
       // 獲取數據庫中最新的值  
       var dialService = DialApiService{}  
       dial, err := dialService.GetDialApi(strconv.Itoa(int(dialApiEntity.ID)))  
       if err != nil {  
          global.GVA_LOG.Error("獲取任務失敗", zap.String("err", err.Error()))  
       }  
       successRateStr := fmt.Sprintf("%.2f", successRate)  
       if dial.SuccessRate != successRateStr {  
          dial.SuccessRate = successRateStr  
          err := dialService.UpdateDialApi(dial)  
          if err != nil {  
             global.GVA_LOG.Error("更新任務成功率失敗", zap.String("err", err.Error()))  
             return  
          }  
       }  
  
    }  
}  
  
// CalculateSuccessRate 計算成功率  
func CalculateSuccessRate(success, total float64) float64 {  
    if total == 0 {  
       return 0  
    }  
    return (success / total) * 100 // 返回百分比形式的成功率  
}

另外,撥測任務支持HTTP、TCP、DNS以及ICMP(ICMP功能未完善),代碼如下:

func checkHTTP(dialApiEntity dialApi.DialApi) bool {  
    idStr := strconv.Itoa(int(dialApiEntity.ID))  
    var response *http.Response = nil  
    var httpErr error = nil  
    switch dialApiEntity.HttpMethod {  
    case "GET":  
       response, httpErr = http.Get(dialApiEntity.Url)  
       break  
    case "POST":  
       response, httpErr = http.Post(dialApiEntity.Url, "application/json", strings.NewReader(dialApiEntity.RequestBody))  
       break  
    default:  
    }  
    if response != nil {  
       dialApiRecrod := new(dialApi.DialApiRecrod)  
       dialApiRecrod.DialApiId = dialApiEntity.ID  
       dialApiRecrod.CreatedAt = time.Now()  
       dialApiRecrod.UpdatedAt = time.Now()  
  
       if httpErr == nil {  
          if response.StatusCode == dialApiEntity.HttpStatus {  
             // 如果定義了返回值判斷  
             if dialApiEntity.ExceptResponse != "" {  
                bodyBytes, err := io.ReadAll(response.Body)  
                if err != nil {  
                   return false  
                }  
                if strings.Contains(string(bodyBytes), dialApiEntity.ExceptResponse) {  
                   return true  
                } else {  
                   return false  
                }  
             } else {  
                return true  
             }  
          } else {  
             global.GVA_LOG.Info(idStr + ":" + dialApiEntity.Name + "撥測結果與預期不一致")  
             return false  
          }  
       } else {  
          global.GVA_LOG.Error("撥測失敗: " + dialApiEntity.Url)  
          dialApiRecrod.FailReason = httpErr.Error()  
          return false  
       }  
    }  
    return false  
}  
  
func checkTCP(dialApiEntity dialApi.DialApi) (bool, error) {  
    conn, err := net.DialTimeout("tcp", dialApiEntity.Url, 5*time.Second)  
    if err != nil {  
       return false, err  
    }  
    defer conn.Close()  
    return true, nil  
}  
  
func checkDNS(dialApiEntity dialApi.DialApi) (bool, error) {  
    _, err := net.LookupHost(dialApiEntity.Url)  
    if err != nil {  
       return false, err  
    }  
    return true, nil  
}  
  
func checkICMP(dialApiEntity dialApi.DialApi) (bool, error) {  
    pinger, err := ping.NewPinger(dialApiEntity.Url)  
    if err != nil {  
       return false, err  
    }  
    pinger.Count = 2  
    err = pinger.Run() // Blocks until finished.  
    if err != nil {  
       return false, err  
    }  
    return true, nil  
}

其中HTTP撥測是比較常用的,相比之前的Prometheus Exporter,這里豐富了對結果的校驗,使撥測的結果值更準確。

(3)如果遇到撥測任務的更新或者刪除,有一個定時的協程去處理。如下:

func startUpdateDialCron() {  
    var dialService = service.ServiceGroupApp.DialApiServiceGroup.DialApiService  
    for {  
       select {  
       case updateId := <-global.UpdateDialAPIChannel:  
          // 獲取數據  
          if updateId != "" {  
             dial, err := dialService.GetDialApi(updateId)  
             if err != nil {  
                global.GVA_LOG.Error("獲取任務失敗", zap.String("err", err.Error()))  
                continue  
             } else {  
                // 先刪除舊的定時任務  
                global.GVA_LOG.Info("更新定時任務", zap.String("updateId", updateId))  
                cronName := global.DIAL_API + updateId  
                taskName := global.DIAL_API + updateId  
                if _, found := global.GVA_Timer.FindTask(cronName, taskName); found {  
                   global.GVA_Timer.Clear(cronName)  
                   // 啟動新的定時任務  
                   // 將cron的值變成表達式  
                   c := utils.ConvertToCronExpression(dial.Cron)  
                   dial.Cron = c  
                   dialService.AddSingleDialApiTimerTask(dial)  
                }  
             }  
          }  
       case deleteId := <-global.DeleteDialAPIChannel:  
          if deleteId != "" {  
             cronName := global.DIAL_API + deleteId  
             taskName := global.DIAL_API + deleteId  
             if _, found := global.GVA_Timer.FindTask(cronName, taskName); found {  
                global.GVA_LOG.Info("刪除定時任務", zap.String("updateId", deleteId))  
                global.GVA_Timer.RemoveTaskByName(cronName, taskName)  
             }  
          }  
       }  
    }  
}

該協程監聽global.UpdateDialAPIChannel和global.DeleteDialAPIChannel這兩個channel,然后再調用dialService.AddSingleDialApiTimerTask對定時任務進行操作。

上面就是簡單的接口撥測的功能實現,因能力有限,所以代碼比較混亂。

前端展示

為了便于日常的維護,所以開發一個前端界面,主要支持撥測任務的增刪改查。

新增撥測任務,可以靈活選擇撥測類型以及定義返回值和狀態碼。

然后可以查看撥測任務的具體情況,也可以靈活開啟或者關閉或者任務。

監控告警

在前端頁面只是展示了成功率,實際告警還是通過Prometheus實現,該平臺暫未實現直接配置告警。

所以,只需要創建一個Prometheus收集的Job,就可以查看對應的指標,指標名是health_check_results,如下:

然后再配置一個告警規則,在使用率低于100%的時候發送告警通知,如下:

至此,整個功能就實現了,足夠滿足日常使用。在公有云上,是有成熟的撥測產品,不過有的收費比較貴,好處是可以實現不同地區的撥測,覆蓋面比較廣。另外,也可以使用Black Exporter實現撥測,其也支持上面的所有功能,只是沒有前端的維護界面,不過功能強大很多。

責任編輯:姜華 來源: 運維開發故事
相關推薦

2022-08-11 08:46:23

索引數據結構

2024-05-06 00:30:00

MVCC數據庫

2022-03-23 15:36:13

數字化轉型數據治理企業

2023-08-02 08:14:33

監控MTS性能

2019-05-08 16:00:48

人工智能人臉識別刷臉

2018-01-02 09:31:12

大數據數據互聯網

2024-09-26 14:48:35

SpringAOP范式

2023-09-18 08:56:57

StringJava

2025-04-01 08:45:00

2021-07-26 23:57:48

Vuex模塊項目

2024-10-28 12:46:22

2023-08-28 07:39:49

線程調度基本單位

2023-09-07 10:26:50

接口測試自動化測試

2024-03-20 00:04:46

TypeScriptas const類型斷言

2024-12-26 09:05:18

HTTP狀態碼數據

2019-07-04 05:22:02

物聯網設備物聯網IOT

2018-08-24 06:56:17

2024-06-17 11:02:47

2011-06-24 17:30:34

網站權重

2015-11-02 09:50:48

電腦1秒鐘事情
點贊
收藏

51CTO技術棧公眾號

性久久久久久久久久| 日韩伦理在线免费观看| 亚洲中文字幕一区二区| 中文字幕乱码亚洲无线精品一区| 精品成人一区二区三区四区| 91av俱乐部| 怡红院av在线| 国产三级精品视频| 成人av播放| 免费观看日批视频| 亚洲视屏一区| 色噜噜亚洲精品中文字幕| 国产伦精品一区二区三区88av| 欧美成人精品三级网站| 亚洲综合男人的天堂| 欧美日韩在线一二三| 亚洲AV无码乱码国产精品牛牛| 丝袜美腿亚洲色图| 久久99久久久久久久噜噜| 97伦伦午夜电影理伦片| 欧美高清一级片| 在线观看亚洲成人| 国产av天堂无码一区二区三区| h网站视频在线观看| 成人av网站大全| 91精品在线一区| 久久久久久亚洲av无码专区| 亚洲国产片色| 欧美成人三级视频网站| 手机av在线不卡| 要久久电视剧全集免费| 亚洲高清免费观看高清完整版| 91网址在线观看精品| 成人涩涩视频| 色综合激情五月| 国产午夜伦鲁鲁| caoporn视频在线| 亚洲精品国产无套在线观 | 久久久久久毛片免费看| 在线电影院国产精品| 在线免费av播放| 欧美日韩五区| 在线精品视频一区二区三四| 男人天堂网视频| 日韩深夜视频| 亚洲成a人片在线观看中文| 无码人妻精品一区二区蜜桃网站| 国产人成网在线播放va免费| 中文字幕一区在线观看| 视频一区二区在线观看| 国产高清在线观看| 国产欧美日本一区二区三区| 日韩欧美三级一区二区| 九九在线视频| 欧美国产成人在线| 亚洲欧洲一区二区| 免费av在线播放| 亚洲欧洲另类国产综合| 亚洲av综合色区| 在线午夜影院| 午夜婷婷国产麻豆精品| 日本久久久精品视频| 韩日成人影院| 在线亚洲一区二区| 五月激情五月婷婷| 经典三级久久| 亚洲精品wwww| 亚洲午夜福利在线观看| 日本在线电影一区二区三区| 久久精品国产2020观看福利| 国产这里有精品| 最新日韩在线| 欧洲美女免费图片一区| 中文字幕 自拍偷拍| 久草热8精品视频在线观看| 91av免费看| 五月婷婷六月丁香综合| 国产日韩欧美一区二区三区乱码| 亚洲欧美综合一区| 在线视频国产区| 偷拍亚洲欧洲综合| 国产野外作爱视频播放| 国产一区一区| 亚洲黄色www网站| 日韩一级av毛片| 亚欧美无遮挡hd高清在线视频| 欧美国产日韩xxxxx| 久久久久久91亚洲精品中文字幕| 美女视频一区二区| 国产精品久久精品国产| 九色在线播放| 亚洲综合丝袜美腿| 韩国日本美国免费毛片| 日韩中文字幕| 亚洲系列中文字幕| 欧美黑人一级片| 久久免费黄色| 91黄色精品| 第一页在线观看| 亚洲一区在线免费观看| 91最新在线观看| 亚洲天堂av资源在线观看| 日韩精品视频中文在线观看| 小向美奈子av| 亚洲一区一卡| 91免费在线观看网站| 天堂91在线| 国产精品的网站| 亚洲欧洲日产国码无码久久99| 99er精品视频| 一道本无吗dⅴd在线播放一区| 激情小说中文字幕| 久久精品99久久久| 日本高清一区| 国产福利电影在线播放| 91精品黄色片免费大全| 天堂久久精品忘忧草| 亚洲精品影院在线观看| 亚洲a成v人在线观看| 国产女主播在线写真| 午夜欧美一区二区三区在线播放| 中文字幕在线视频一区二区| 成人直播大秀| 日本高清不卡的在线| 亚洲av无码片一区二区三区| 国产精品久久久久aaaa| 黑鬼大战白妞高潮喷白浆| 精品亚洲自拍| 性欧美激情精品| 亚洲高清精品视频| 亚洲欧美激情一区二区| 亚洲 激情 在线| 狠狠操综合网| 茄子视频成人在线| 亚洲色图欧美视频| 午夜久久久久久久久| 成人午夜精品无码区| 女主播福利一区| 97超碰人人模人人爽人人看| 超碰个人在线| 67194成人在线观看| 老司机深夜福利网站| 日韩高清在线一区| 亚洲女人毛片| 亚洲电影二区| 久久在线免费观看视频| 国产美女主播在线观看| 1024精品合集| 图片区乱熟图片区亚洲| 亚洲女同另类| 亚洲xxx视频| 欧美aaaaaaa| 亚洲国产欧美自拍| 国产又爽又黄的视频| 久久婷婷国产综合精品青草| 国产性xxxx18免费观看视频| 久久最新网址| 国产精品亚发布| 久久久免费高清电视剧观看| 欧美日韩精品在线播放| 国产精品 日韩| 亚洲资源一区| 日韩免费性生活视频播放| 久久一级黄色片| zzijzzij亚洲日本少妇熟睡| 国产精品久久中文字幕| 亚洲人成网www| 国产精品入口免费视| 日本a在线播放| 日韩精品一区二区三区蜜臀| 日本一级淫片免费放| 91色九色蝌蚪| 日本中文字幕高清| 亚洲一级毛片| 国产嫩草一区二区三区在线观看| 欧美xxx视频| 久久久国产精品视频| 亚洲av永久纯肉无码精品动漫| 午夜精品福利一区二区三区av | www.亚洲在线| 手机看片福利盒子久久| **女人18毛片一区二区| 国产麻豆日韩| 九九热这里有精品| 九九精品视频在线| 国产在线观看精品一区| 欧美一区二区性放荡片| 久久久久99精品成人片我成大片| 亚洲欧美综合在线精品| 中文字幕一区二区人妻电影丶| 日韩av在线播放中文字幕| 国产一二三四区在线观看| 午夜欧洲一区| 91在线观看免费观看 | 精品视频站长推荐| 美国三级日本三级久久99| 免费在线黄网站| 成人直播大秀| 九色91视频| 成人污版视频| 国产精品看片资源| 国产在线xxx| 色妞在线综合亚洲欧美| 亚洲欧美色视频| 在线不卡a资源高清| 成人精品免费在线观看| 最近中文字幕一区二区三区| 玖玖爱在线观看| 国产成人精品三级麻豆| 男女男精品视频站| 久久亚洲风情| 国产免费黄色小视频| 亚洲一区二区三区| 欧美一区三区二区在线观看| 久久成人福利| 亚洲淫片在线视频| 国产精品高潮久久| 日韩av毛片网| 黑人巨大亚洲一区二区久| 久久久爽爽爽美女图片| 午夜在线激情影院| 久久手机免费视频| 国产经典自拍视频在线观看| 日韩成人在线观看| 免费看国产片在线观看| 91精品欧美福利在线观看| 欧美性受xxx黑人xyx性爽| 欧美视频第一页| 国产午夜福利精品| 亚洲曰韩产成在线| 国产大学生自拍| 中文字幕在线一区免费| 国产激情av在线| 国产日产欧美一区二区三区| 欧美日韩高清丝袜| 久久综合av免费| 美国黄色a级片| av一本久道久久综合久久鬼色| 扒开伸进免费视频| 成人美女在线观看| 超碰男人的天堂| 成人免费视频播放| yy1111111| 99久久精品国产毛片| 国产又黄又粗又猛又爽的视频| 99这里都是精品| 黄色短视频在线观看| 99久久精品免费看国产免费软件| 欧美日韩人妻精品一区在线| 成人精品高清在线| 超碰97在线资源站| 2023国产一二三区日本精品2022| 日韩网站在线播放| 久久久久高清精品| 日韩黄色中文字幕| 亚洲欧洲三级电影| 老女人性淫交视频| 性做久久久久久久免费看| 全部毛片永久免费看| 一本大道久久a久久综合婷婷| 波多野结衣电车痴汉| 欧美日韩中文精品| 国产美女裸体无遮挡免费视频| 欧美一级日韩一级| 神马午夜精品95| 亚洲人成电影在线观看天堂色| av中文在线| 久久精品亚洲国产| 日本动漫理论片在线观看网站 | 免费视频成人| 97影院在线午夜| 婷婷综合一区| 亚洲欧美国产精品桃花| 欧美一区二区三区另类| 日韩av高清在线看片| 日韩精品成人一区二区在线| 欧美成人手机在线视频| av不卡免费在线观看| 成年人在线免费看片| 亚洲精品欧美专区| 天堂在线免费观看视频| 欧美男女性生活在线直播观看| 亚洲乱色熟女一区二区三区| 日韩精品中文字幕在线| 麻豆视频在线观看免费网站| 久久男人资源视频| 国产伊人久久| 精品日本一区二区三区在线观看| 欧美日韩性在线观看| 久久久久久久久久伊人| 快she精品国产999| 欧洲成人午夜精品无码区久久| 国产日韩欧美不卡在线| 久久一级黄色片| 欧美日本一区二区| 在线观看xxx| 操人视频在线观看欧美| 成人免费影院| 91久久精品国产91久久性色tv| 精品国产视频| 亚洲熟妇无码一区二区三区| 老司机精品视频导航| 3d动漫精品啪啪一区二区下载 | 91综合久久爱com| 视频二区一区| 国产精品亚洲欧美| 亚洲精品久久久久久| 国产精品毛片大码女人| 国产成人在线免费视频| 日韩美女视频在线| 8888四色奇米在线观看| 日韩av电影在线播放| 精品视频高潮| 国产精品久久久久9999爆乳| 久久国产人妖系列| 波多野结衣办公室33分钟| 一区二区三区欧美在线观看| 亚洲一区二区三区高清视频| 亚洲午夜未满十八勿入免费观看全集| 黄色在线看片| 444亚洲人体| 亚洲精品网址| 中日韩av在线播放| 欧美激情资源网| 色老头一区二区| 亚洲精品一区二区三区不| av电影免费在线看| 国产精品大全| 黄色在线一区| 粗大的内捧猛烈进出视频| 亚洲欧美日韩在线不卡| 亚洲一线在线观看| 伊人青青综合网站| 欧美色999| 特级西西444www大精品视频| 狂野欧美一区| 亚洲一区二区自偷自拍| 欧美最猛黑人xxxxx猛交| 韩国三级av在线免费观看| 日本成人黄色片| 精品大片一区二区| 不卡av免费在线| 国产精品久久久久久久久免费樱桃 | 精品久久久久久亚洲精品| 四虎影视2018在线播放alocalhost| 久久久久日韩精品久久久男男| 国产成人一二片| 成 年 人 黄 色 大 片大 全| 99久久久久久99| 亚洲欧美自拍视频| 一区二区三区www| 高清在线一区| 国产精品h视频| 国产麻豆视频精品| 伊人国产在线观看| 日韩电影大全免费观看2023年上| 在线天堂资源| 日本在线播放一区| 激情综合网av| 青娱乐国产精品| 亚洲激情在线视频| 欧美大胆性生话| 亚洲最新免费视频| 国产suv精品一区二区三区| 日本熟妇成熟毛茸茸| 亚洲色图偷窥自拍| 电影91久久久| 蜜臀av色欲a片无码精品一区| 97精品超碰一区二区三区| 国产精品视频一区在线观看| 色妞欧美日韩在线| 成人三级av在线| 国产精品免费成人| 亚洲免费视频成人| 亚洲a视频在线| 国产成+人+综合+亚洲欧美丁香花| 99精品视频在线观看免费播放| 9191在线视频| 色噜噜狠狠一区二区三区果冻| 黄色片网站在线观看| 国模一区二区三区私拍视频| 日本视频中文字幕一区二区三区| 一区二区国产精品精华液| 亚洲精品国产欧美| 亚洲欧洲二区| 黄色免费福利视频| 亚洲欧洲美洲综合色网| 五月婷婷丁香花| 成人免费福利在线| 午夜在线视频观看日韩17c| 永久免费看mv网站入口| 亚洲精品久久久久中文字幕欢迎你 | 天堂地址在线www| 国产三区精品| 国内精品免费在线观看| 少妇高潮av久久久久久| 久久99久久久久久久噜噜| 欧美日韩伦理在线免费| 国产黑丝一区二区| 91精品国产91久久综合桃花|