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

使用DaemonSet實現heapdump文件自動化管理

開發 前端
當前功能已經初步實現,但仍有許多可以優化和擴展的方向。可以考慮擴展支持更多類型的云存儲,如騰訊云 COS、AWS S3 等,以滿足不同用戶的需求。這樣一來,用戶可以根據自己的實際情況和偏好,選擇最適合自己的云存儲服務,提高方案的通用性和靈活性。

一、引言

1、為什么要獲取heapdump文件

heapdump文件是Java應用遭遇OOM后的診斷報告,記錄了某一時刻 JVM 堆中對象的詳細使用情況,是 JVM 堆內存的一個快照。通過分析 heapdump 文件,我們可以深入了解到內存中究竟存在哪些對象,它們占用了多少內存空間,以及對象之間的引用關系如何。這對于定位內存泄漏問題至關重要。

2、為什么使用DaemonSet實現

之前在SRE運維筆記公眾號中看到一篇文章《運維救星!一鍵開啟k8s微服務OOM heapdump自動化之旅》,其實現思路通過在應用容器中增加dump腳本,然后通過java參數-XX:OnOutOfMemoryError配置腳本,它的作用是當內存溢出的時候,會調用這個參數配置的腳本做一些后續處理,比如文章中的dump腳本,也可以是重啟應用的腳本等。

上述方法對應用有一定的侵入性,另外,如果文件太大,會出現容器退出導致上傳失敗的情況。結合實際情況,準備使用DaemonSet部署一個heapdump-watcher應用,通過它來監聽heapdump.prof文件實現自動化管理。

Tips:該方法僅適合將heapdump.prof持久化到K8s節點的場景。但是具有一定的參考意義。

3、實施前提

該方案需要以下前提:

  • heapdump.prof文件持久化到K8s節點。
  • 持久化的目錄具備相同規則,比如:/mnt/logs/<APP_NAME>/logs/heapdump.prof,如果需要避免沖突,目錄可以改造成/mnt/logs/<APP_NAME>/logs/<POD_NAME>heapdump.prof。
  • 具備阿里云OSS操作權限。
  • 具備一個可用的企業微信機器人。

二、整體思路

圖片圖片

OOM事件觸發通過Java啟動參數配置,增加-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/mnt/logs/heapdump.hprof,當應用觸發OOM,則會在/mnt/logs目錄下自動生成heapdump.prof文件。

我們通過fsnotify來監聽文件的變化,當heapdump.prof生成完后,fsnotify就會迅速捕捉到這個事件,我們通過阿里云OSS的SDK實現文件上傳,將heapdump.prof文件壓縮后上傳到阿里云OSS。為了節約節點磁盤空間,當heapdump.prof文件上傳完成后清理本地文件。

為了讓相關開發人員了解到新的heapdump.prof文件已經生成,我們通過企業微信機器人通知到對應的開發群。

三、具體實現

(1)初始化部分

func init() {  
    // 獲取環境  
    env = getEnv("ENV", "prod")  
    var err error  
    watcher, err = fsnotify.NewWatcher()  
    if err != nil {  
       log.Fatalf("Failed to create fsnotify watcher: %v", err)  
    }  
  
    // 加載配置文件  
    config, err = loadConfig(configPath)  
    if err != nil {  
       log.Fatalf("Failed to load config: %v", err)  
    }  
  
    // 初始化OSS客戶端  
    ossClient, err := oss.New(config.OSS.Endpoint, config.OSS.AccessID, config.OSS.AccessKey)  
    if err != nil {  
       log.Fatalf("Failed to create OSS client: %v", err)  
    }  
    client, _ = ossClient.Bucket(config.OSS.Bucket)  
  
    if config.WatchPods {  
       // 初始化Kubernetes客戶端  
       kubeClient, err = createKubeClient()  
       if err != nil {  
          log.Fatalf("Failed to create Kubernetes client: %v", err)  
       }  
  
       // 獲取當前節點的IP  
       nodeIP, err = getNodeIP()  
       if err != nil {  
          log.Fatalf("Failed to get node IP: %v", err)  
       }  
    }  
  
    // 初始化信號通道  
    signalChan = make(chan os.Signal, 1)  
    stopChan = make(chan struct{})  
    signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)  
}

在這段初始化代碼中,首先通過getEnv函數獲取環境變量ENV的值,如果未設置則默認為prod。接著創建一個fsnotify.Watcher,用于監聽文件系統的變化。然后從指定路徑configPath加載配置文件,配置文件中包含了 OSS、企業微信 Webhook 以及白名單等相關配置信息。

隨后,利用配置信息初始化阿里云 OSS 客戶端,通過提供的Endpoint、AccessID和AccessKey創建ossClient,并獲取指定的Bucket,以便后續進行文件上傳操作。

如果配置中WatchPods字段為true,表示會監聽Pod的變化(因為Pod會重建,如果日志目錄包含POD_NAME,重建后就不應該再監聽原來Pod目錄),則會初始化 Kubernetes 客戶端。通過createKubeClient函數創建kubeClient,用于與 Kubernetes 集群進行交互。還會獲取當前節點的 IP 地址,以便后續監聽該節點上的 Pod 變化。

最后,初始化兩個通道signalChan和stopChan。signalChan用于接收操作系統發送的信號,如SIGINT(中斷信號,通常由用戶按下 Ctrl+C 觸發)和SIGTERM(終止信號,用于正常終止進程),以便程序能夠在接收到這些信號時進行優雅退出;stopChan則用于停止 Informer,當程序接收到終止信號時,通過關閉stopChan來通知 Informer 停止工作。

(2)文件監聽

func watchFiles() {  
    for {  
       select {  
       case event, ok := <-watcher.Events:  
          if !ok {  
             return  
          }  
          if event.Op&fsnotify.Create == fsnotify.Create {  
             // 檢測到新文件創建  
             if strings.HasSuffix(event.Name, "heapdump.prof") {  
                log.Printf("New heapdump file detected: %s", event.Name)  
                // 等待文件寫入完成  
                if err := waitForFileCompletion(event.Name); err != nil {  
                   log.Printf("Failed to wait for file completion: %v", err)  
                   continue  
                }  
                // 上傳文件到OSS  
                appName := filepath.Base(filepath.Dir(filepath.Dir(event.Name)))  
                err := uploadFileToOSS(event.Name, appName)  
                if err != nil {  
                   log.Printf("Failed to upload file to OSS: %v", err)  
                } else {  
                   log.Printf("File uploaded to OSS successfully: %s", event.Name)  
                   // 發送企業微信告警通知  
                   err = sendWechatAlert(appName)  
                   if err != nil {  
                      log.Printf("Failed to send WeChat alert: %v", err)  
                   }  
                }  
             }  
          }  
       case err, ok := <-watcher.Errors:  
          if !ok {  
             return  
          }  
          log.Printf("Error: %v", err)  
       }  
    }  
}

watchFiles函數是實現文件監聽的核心部分。它通過一個無限循環for { }和select語句來監聽watcher.Events通道和watcher.Errors通道。

當watcher.Events通道有事件發生時,會檢查事件類型是否為文件創建(event.Op&fsnotify.Create == fsnotify.Create)。如果是新文件創建,且文件后綴為heapdump.prof,則表示檢測到了新的 heapdump 文件。

此時,會調用waitForFileCompletion函數等待文件寫入完成。該函數通過不斷檢查文件大小是否變化來判斷文件是否寫入完成,設置了最大檢查時長為 30 秒,檢查間隔為 2 秒。如果文件在規定時間內大小不再變化,則認為文件寫入完成;否則,返回錯誤并繼續監聽下一個事件。

文件寫入完成后,獲取文件所在目錄的應用名稱,然后調用uploadFileToOSS函數將文件上傳到 OSS。上傳成功后,會調用sendWechatAlert函數發送企業微信告警通知,告知相關人員新的 heapdump 文件已生成并上傳。

(3)Pod狀態監聽

該方法主要是針對heapdump.prof所存放的目錄有POD_NAME變量,希望實現的是當原Pod銷毀會取消監聽原Pod目錄,當新Pod創建會監聽新Pod目錄。

func watchPods() {  
    // 獲取當前節點上的Pod列表  
    for _, appName := range config.Whitelist {  
       pods, err := kubeClient.CoreV1().Pods(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{  
          LabelSelector: fmt.Sprintf("app=%s", appName),  
          FieldSelector: fmt.Sprintf("spec.nodeName=%s", nodeIP),  
       })  
       if err != nil {  
          log.Printf("Failed to list pods for app %s: %v", appName, err)  
          continue  
       }  
  
       for _, pod := range pods.Items {  
          addPodWatch(appName, pod.Name)  
       }  
    }  
  
    // 監聽Pod變化  
    _, controller := cache.NewInformer(  
       &cache.ListWatch{  
          ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {  
             options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeIP)  
             return kubeClient.CoreV1().Pods(metav1.NamespaceAll).List(context.TODO(), options)  
          },  
          WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {  
             options.FieldSelector = fmt.Sprintf("spec.nodeName=%s", nodeIP)  
             return kubeClient.CoreV1().Pods(metav1.NamespaceAll).Watch(context.TODO(), options)  
          },  
       },  
       &corev1.Pod{},  
       0,  
       cache.ResourceEventHandlerFuncs{  
          AddFunc: func(obj interface{}) {  
             pod := obj.(*corev1.Pod)  
             appName := pod.Labels["app"]  
             if isWhitelisted(appName) {  
                log.Printf("Pod added: %s/%s", pod.Namespace, pod.Name)  
                addPodWatch(appName, pod.Name)  
             }  
          },  
          DeleteFunc: func(obj interface{}) {  
             pod := obj.(*corev1.Pod)  
             appName := pod.Labels["app"]  
             if isWhitelisted(appName) {  
                log.Printf("Pod deleted: %s/%s", pod.Namespace, pod.Name)  
                removePodWatch(appName, pod.Name)  
             }  
          },  
       },  
    )  
    controller.Run(stopChan) // 使用 stopChan 來停止 Informer}

watchPods函數負責監聽 Pod 的變化。首先,遍歷配置中的白名單應用名稱,通過 Kubernetes 客戶端kubeClient獲取當前節點上屬于這些應用的 Pod 列表。使用LabelSelector來篩選出特定應用的 Pod,FieldSelector來指定只獲取當前節點上的 Pod。

對于獲取到的每個 Pod,調用addPodWatch函數為其添加文件監聽。addPodWatch函數會根據應用名稱和 Pod 名稱構建日志目錄路徑,并使用watcher.Add方法將該目錄添加到文件監聽列表中,以便后續能及時監聽到該 Pod 生成的 heapdump 文件。

然后,通過cache.NewInformer創建一個 Informer,用于監聽 Pod 的變化。Informer是 Kubernetes 客戶端中的一個重要組件,它通過ListWatch機制定期從 Kubernetes API Server 獲取 Pod 列表,并監聽 Pod 的變化事件。

ListFunc和WatchFunc分別定義了獲取 Pod 列表和監聽 Pod 變化的方法,都通過kubeClient.CoreV1().Pods(metav1.NamespaceAll)來操作所有命名空間下的 Pod,并根據當前節點 IP 進行篩選。

ResourceEventHandlerFuncs定義了 Informer 在接收到 Pod 添加和刪除事件時的處理邏輯。當有新 Pod 添加時,如果該 Pod 的應用名稱在白名單中,會調用addPodWatch函數為其添加文件監聽;當有 Pod 被刪除時,如果應用名稱在白名單中,會調用removePodWatch函數移除對該 Pod 的文件監聽。

最后,啟動 Informer 并傳入stopChan,當stopChan被關閉時,Informer 會停止運行,實現了優雅停止的功能。

(4)文件上傳

func uploadFileToOSS(filePath string, appName string) error {  
    file, err := os.Open(filePath)  
    if err != nil {  
       return err  
    }  
    defer file.Close()  
  
    // 創建臨時文件用于存儲壓縮后的文件  
    tempFile, err := os.CreateTemp("", "heapdump-*.zip")  
    if err != nil {  
       return err  
    }  
    defer tempFile.Close()  
    defer os.Remove(tempFile.Name()) // 刪除臨時文件  
  
    // 創建 zip.Writer    
    zipWriter := zip.NewWriter(tempFile)  
    defer zipWriter.Close()  
  
    // 添加文件到 zip    
    zipFileWriter, err := zipWriter.Create(filepath.Base(filePath))  
    if err != nil {  
       return err  
    }  
    _, err = io.Copy(zipFileWriter, file)  
    if err != nil {  
       return err  
    }  
  
    // 確保 zip 文件寫入完成  
    err = zipWriter.Close()  
    if err != nil {  
       return err  
    }  
  
    // 重新打開臨時文件用于上傳  
    tempFile.Seek(0, 0)  
    tempFileReader := io.Reader(tempFile)  
  
    // 構建上傳路徑  
    timestamp := time.Now().Format("20060102150405")  
    objectName := fmt.Sprintf("heapdump/%s/heapdump_%s.zip", appName, timestamp)  
  
    // 設置文件元數據
    expires := time.Now().Add(24 * time.Hour) // 設置過期時間為24小時后  
    options := []oss.Option{  
       oss.Expires(expires),  
    }  
  
    err = client.PutObject(objectName, tempFileReader, options...)  
    if err != nil {  
       return err  
    }  
  
    // 生成預簽名URL  
    ossURL, err = client.SignURL(objectName, oss.HTTPGet, expires.Unix()-time.Now().Unix())  
    if err != nil {  
       log.Fatalf("Failed to generate presigned URL: %v", err)  
    }  
  
    // 文件上傳成功后,刪除本地文件  
    log.Printf("Deleting local file: %s", filePath)  
    if err := os.Remove(filePath); err != nil {  
       log.Printf("Failed to delete local file: %v", err)  
    }  
    return nil  
}

這一步先將heapdump.prof進行zip壓縮,然后再將其上傳到OSS,上傳成功后刪除本地文件。

(5)發送通知

func sendWechatAlert(appName string) error {  
    // 構建 Markdown 格式的消息  
    markdownContent := fmt.Sprintf(`# JAVA OOM DUMP 文件生成  
> 應用:%s  
> 環境:%s  
> 文件:[下載地址](%s)  
> *Tips*: 文件只保留1天,請及時下載`, appName, env, ossURL)  
  
    payload := map[string]interface{}{  
       "msgtype": "markdown",  
       "markdown": map[string]string{  
          "content": markdownContent,  
       },  
    }  
  
    _, body, errs := gorequest.New().Post(config.Wechat.WebhookURL).Send(payload).End()  
    if errs != nil {  
       return fmt.Errorf("failed to send WeChat alert: %v", errs)  
    }  
    log.Printf("WeChat alert response: %s", body)  
    return nil  
}

該步驟將產生heapdump的信息發送到對應的告警群。

四、部署驗證

(1)制作鏡像

將應用打包成Docker鏡像。

FROM golang:1.21-alpine AS builder  
WORKDIR /app  
COPY go.mod go.sum ./  
RUN go mod download  
COPY . .  
RUN CGO_ENABLED=0 GOOS=linux go build -o /heapdump-watcher  
  
FROM alpine:3.18  
RUN apk add --no-cache ca-certificates  
WORKDIR /app  
COPY --from=builder /heapdump-watcher ./heapdump-watcher  
CMD ["/heapdump-watcher"]

(2)在K8s中部署應用

apiVersion: v1  
kind: ServiceAccount  
metadata:  
  name: heapdump-watcher  
  namespace: default  
---  
apiVersion: rbac.authorization.k8s.io/v1  
kind: Role  
metadata:  
  namespace: default  
  name: heapdump-watcher-role  
rules:  
  - apiGroups: [""]  
    resources: ["pods"]  
    verbs: ["get", "list", "watch"]  
---  
apiVersion: v1  
kind: ConfigMap  
metadata:  
  name: heapdump-config  
  namespace: default  
data:  
  config.yaml: |  
    oss:  
      endpoint: your-oss-endpoint  
      bucket: your-oss-bucket  
      accessID: your-oss-access-id  
      accessKey: your-oss-access-key  
  
    wechat:  
      webhookURL: your-wechat-webhook-url  
  
    whitelist:  
      - app1  
      - app2  
      - app3  
    
    watchPods: false  # 控制是否監聽 Pod 變化
---  
apiVersion: apps/v1  
kind: DaemonSet  
metadata:  
  name: heapdump-watcher  
  namespace: default  
spec:  
  selector:  
    matchLabels:  
      app: heapdump-watcher  
  template:  
    metadata:  
      labels:  
        app: heapdump-watcher  
    spec:  
      serviceAccountName: heapdump-watcher  
      containers:  
        - name: heapdump-watcher  
          image: your-docker-image:latest  
          volumeMounts:  
            - name: logs  
              mountPath: /mnt/logs  
              readOnly: false  
            - name: config  
              mountPath: /app/config.yaml  
              subPath: config.yaml  
              readOnly: true  
          env:  
            - name: NODE_NAME  
              valueFrom:  
                fieldRef:  
                  fieldPath: spec.nodeName  
            - name: ENV  
              value: prod  
      volumes:  
        - name: logs  
          hostPath:  
            path: /mnt/logs  
            type: Directory  
        - name: config  
          configMap:  
            name: heapdump-config  
            items:  
              - key: config.yaml  
                path: config.yaml

(3)驗證

當應用產生告警后會通知到對應的企業微信,如下:

圖片圖片

五、最后

當前功能已經初步實現,但仍有許多可以優化和擴展的方向。可以考慮擴展支持更多類型的云存儲,如騰訊云 COS、AWS S3 等,以滿足不同用戶的需求。這樣一來,用戶可以根據自己的實際情況和偏好,選擇最適合自己的云存儲服務,提高方案的通用性和靈活性。

另外在通知內容和方式上,可以進一步豐富通知內容,不僅包含應用名稱、環境和文件下載鏈接,還可以增加更多關于內存問題的詳細信息,如內存使用峰值、OOM 發生的時間點等。在通知方式上,可以增加對其他通信工具的支持,如釘釘、飛書等,讓用戶能夠根據自己團隊的使用習慣選擇合適的通知方式,確保通知能夠及時、準確地傳達給相關人員。

還可以引入更智能的分析功能,在上傳 heapdump 文件后,自動對文件進行初步分析,提取關鍵信息,如內存泄漏的疑似對象、內存占用過高的類等,并將分析結果一并通知給相關人員。這樣可以幫助開發人員更快地定位問題,提高問題解決的效率,為 Java 應用的穩定運行提供更強大的支持。

責任編輯:武曉燕 來源: 運維開發故事
相關推薦

2015-10-21 15:08:25

電纜自動化

2021-04-19 14:00:03

ExchangelibPython郵箱自動化管理

2022-11-15 17:07:40

開發自動化前端

2010-12-24 14:46:31

Perl腳本

2015-06-26 15:12:20

2011-05-10 14:35:07

TivoliIT服務管理整合

2010-12-06 09:59:58

2013-12-17 17:43:45

DevOps自動化云管理

2018-07-16 10:49:53

自動化

2021-10-14 09:55:28

AnsibleanacronLinux

2023-10-25 08:00:00

人工智能游戲開發

2021-09-08 16:03:12

Kubernetes 安全開源

2015-08-12 15:10:46

Ubuntucronlinux

2011-09-29 10:58:51

rBuilderLinux

2013-03-22 15:15:28

自動化管理部署虛擬化

2017-12-17 21:58:18

2024-06-11 10:41:14

2022-03-30 09:43:19

jscodeshif自動化重構開發

2021-09-17 15:56:14

數據平臺自動化

2021-11-19 10:55:03

GitOps運維自動化
點贊
收藏

51CTO技術棧公眾號

日韩大片免费观看视频播放| 国产精品入口麻豆九色| 久久久久久久91| 三级视频网站在线观看| 欧美无毛视频| 亚洲同性gay激情无套| 国产一区二区三区免费不卡| 中文字幕 自拍偷拍| 亚洲调教视频在线观看| 亚洲欧美另类国产| 欧美老女人bb| 日韩在线观看不卡| 亚洲一区在线观看免费| 日韩免费一区二区三区| 国产黄色片免费观看| 久久激情婷婷| 久久久久久久久久久免费精品| 一本加勒比北条麻妃| 精品中文在线| 日韩欧美一区二区三区久久| 超碰在线免费观看97| 视频三区在线观看| 国产一级精品在线| 欧美在线视频免费| 欧美交换国产一区内射| 操欧美老女人| 日韩av在线精品| 自拍一级黄色片| 99只有精品| 日韩欧美国产免费播放| 水蜜桃在线免费观看| 成人p站proumb入口| 91视频免费观看| 999在线观看免费大全电视剧| 曰批又黄又爽免费视频| 国产午夜精品一区二区三区欧美 | 国产成人精品最新| 欧美日韩免费做爰视频| 五月天综合网站| 中文综合在线观看| 国产一二三四五区| 99国产精品久久一区二区三区| 欧美日韩黄视频| 丰满少妇在线观看| 亚洲一二三四| 精品人伦一区二区三区蜜桃免费| 免费看日b视频| 黄色大片在线播放| 国产精品区一区二区三| 欧美日韩无遮挡| 欧美美乳在线| 国产日韩欧美综合一区| 欧美久久在线| 国产视频在线看| 久久久久青草大香线综合精品| 翡翠波斯猫1977年美国| 性猛交富婆╳xxx乱大交天津| 免费人成精品欧美精品| 欧美诱惑福利视频| av网站中文字幕| 麻豆成人精品| 国产国语videosex另类| 天天天天天天天干| 日韩电影免费在线看| 日韩免费观看网站| 久久久久久av无码免费看大片| 日韩电影在线免费观看| 国产日韩欧美在线| 国产精品自偷自拍| 国产乱妇无码大片在线观看| 成人久久18免费网站漫画| 亚洲第一精品网站| 99久久综合99久久综合网站| 免费亚洲精品视频| 成人性爱视频在线观看| 亚洲欧美怡红院| 激情六月天婷婷| 美女搞黄视频在线观看| 日本高清无吗v一区| 91极品尤物在线播放国产| 99久久久成人国产精品| 日韩一级大片在线观看| 黄色录像a级片| 中文字幕伦av一区二区邻居| 色偷偷噜噜噜亚洲男人的天堂| 免费三级在线观看| 亚洲区国产区| 国产精品国模在线| 国产福利免费视频| 99免费精品在线| 在线观看欧美一区| sm在线播放| 精品视频在线视频| 国产大尺度视频| 精品国产成人| 欧美激情一区二区三区久久久 | 亚洲综合精品| 国产日韩欧美中文在线播放| 人妻中文字幕一区| 中文字幕不卡在线播放| 久无码久无码av无码| 日韩影片中文字幕| 日韩美一区二区三区| 日韩在线免费观看av| 欧美国产专区| 国产精品爱久久久久久久| 国产99999| 久久网站热最新地址| 91免费视频黄| 国模一区二区| 日韩精品一区二区三区在线观看| 干b视频在线观看| 亚洲精品日本| 91在线免费视频| 国产在线自天天| 亚洲地区一二三色| 一区二区三区四区毛片| 亚洲精品进入| 国模gogo一区二区大胆私拍| 在线不卡免费视频| 久久综合久久综合久久综合| 日韩精品福利片午夜免费观看| 日韩三区在线| 亚洲免费福利视频| 国产在线精品观看| 国产精品亚洲第一| 在线视频精品一区| 欧美影视资讯| 日韩成人av网址| 国产真人真事毛片| 国产精品一区二区你懂的| 日韩免费一区二区三区| 综合另类专区| 日韩精品视频免费专区在线播放 | 懂色av一区二区三区| 91福利视频免费观看| 久久香蕉国产| 国产精品三级久久久久久电影| 三级av在线播放| 黄色一区二区三区| 韩国av中国字幕| 欧美三级午夜理伦三级中文幕| 成人免费视频在线观看超级碰| yw视频在线观看| 欧美又粗又大又爽| 中文字幕av久久爽一区| 久久综合九色综合欧美狠狠| 欧美精品亚洲| 97欧美成人| 丝袜情趣国产精品| 在线观看日韩一区二区| 日本一区二区三区视频视频| 国产高潮免费视频| 国产精品成人一区二区不卡| 国产欧美精品在线播放| 欧美午夜电影一区二区三区| 91精品国产色综合久久ai换脸| 中文字幕91视频| 精品一区二区av| 欧美大片免费播放| 国产精品传媒| 国产91在线播放| 在线看av的网址| 91精品国产综合久久久久久| 青青操视频在线播放| 成人午夜看片网址| 国产精品50p| 精品国产乱码| 亚洲xxxxx电影| av小说在线播放| 亚洲深夜福利视频| 国产又粗又猛又爽又黄的| 亚洲精品乱码久久久久久| 天天躁日日躁狠狠躁av| 久久xxxx精品视频| 亚洲在线视频一区二区| 婷婷久久综合九色综合99蜜桃| 九九热99久久久国产盗摄| 人妻精品无码一区二区| 91福利在线导航| 欧美丰满艳妇bbwbbw| 久久综合一区二区| 色综合色综合色综合色综合| 欧美黄色免费| 欧美第一黄网| 精品视频91| 欧美自拍视频在线| 精品孕妇一区二区三区| 亚洲国产精彩中文乱码av在线播放| 中文字幕精品无码一区二区| 中文字幕日本乱码精品影院| 日本性生活一级片| 蜜臀久久99精品久久久久久9| 狠狠精品干练久久久无码中文字幕| 午夜精品福利影院| 成人a在线视频| 在线中文字幕播放| 欧美成人精品一区二区| 久青青在线观看视频国产| 欧美另类变人与禽xxxxx| 亚洲综合一二三| 亚洲欧洲性图库| 超碰97在线资源站| 国模无码大尺度一区二区三区| 无码人妻丰满熟妇区96| 99成人在线视频| 久久久久国产精品视频| 国产日本亚洲| 国产成人在线精品| 超免费在线视频| 色一区av在线| 日本人妖在线| 亚洲成色999久久网站| 91成年人视频| 在线免费视频一区二区| 国产精品成人国产乱| 亚洲色图20p| 国产成人一区二区在线观看| 99国产精品久久久久久久久久| 69久久精品无码一区二区| 日本不卡视频在线观看| 国内精品在线观看视频| 午夜日本精品| 中文字幕日韩一区二区三区不卡| 自拍偷拍精品| 麻豆成人小视频| 成人直播在线观看| 亚洲一区制服诱惑| 成人精品国产亚洲| 国产suv精品一区二区| 国产欧洲在线| 午夜精品久久17c| 岛国毛片av在线| 欧美日韩成人网| 成人在线免费看片| 久久精品亚洲精品| 免费黄网在线观看| 最近2019中文字幕在线高清 | 欧美另类交人妖| 永久av在线| 久久精品视频中文字幕| 国产黄a三级三级三级av在线看| 最近2019中文字幕在线高清| 色欧美激情视频在线| 精品国产一区久久久| 免费黄网站在线播放| 日韩在线小视频| 日本在线观看网站| 久久伊人精品视频| av网址在线播放| 欧美激情视频一区| 91jq激情在线观看| 97在线免费视频| 最近高清中文在线字幕在线观看1| 777精品视频| 色综合桃花网| 国产成人短视频| 欧美少妇激情| 99国产视频在线| 精品网站aaa| 日本不卡二区| 色狮一区二区三区四区视频| 亚洲在线视频一区二区| 欧美黄色aaaa| 久久网站免费视频| 肉色丝袜一区二区| 污污的视频免费| 国产精品一区2区| 亚洲色图欧美日韩| 久久久久久亚洲综合| 色婷婷国产精品免| 亚洲精品乱码久久久久久日本蜜臀| 久久丫精品久久丫| 欧美日韩亚洲激情| 中文字幕人成人乱码亚洲电影| 欧美老肥妇做.爰bbww| 亚洲精品一区二区三区四区| 亚洲激情小视频| www免费网站在线观看| 久久香蕉国产线看观看av| hd国产人妖ts另类视频| 国产91在线视频| 日韩视频在线直播| 久久er99热精品一区二区三区| 精品日产免费二区日产免费二区| 日本xxxxx18| 午夜亚洲视频| 五月天婷婷在线观看视频| av在线一区二区| 国产中文字幕久久| 午夜精品福利一区二区蜜股av| 黄色片视频免费| 日韩欧美精品在线| 成人在线二区| 992tv成人免费视频| 日韩欧美专区| 久久久久久九九九九| 91精品观看| 男人天堂成人在线| 国产成人av网站| 亚洲aaa视频| 日韩欧美中文免费| 性一交一乱一色一视频麻豆| 中文字幕视频一区二区在线有码| 草草视频在线| 91久久久亚洲精品| 黑人操亚洲人| 亚洲美免无码中文字幕在线| 韩国视频一区二区| 免费看91的网站| 欧美日韩国产精品一区二区不卡中文| 11024精品一区二区三区日韩| 亚洲色无码播放| 欧美男人天堂| 成人看片在线| 中文字幕免费一区二区| 亚洲精品自拍网| 国产午夜精品久久久久久免费视| 中文字幕第28页| 欧美福利一区二区| 国产黄色在线| 日本在线观看天堂男亚洲| 超碰一区二区三区| 99久re热视频精品98| 久久精品99国产精品| 色一情一交一乱一区二区三区| 午夜成人免费电影| 亚洲国产www| 久久91亚洲人成电影网站| 亚洲欧美在线人成swag| 视频一区视频二区视频三区视频四区国产 | 国产成人综合欧美精品久久| 欧美精品一区二区高清在线观看 | 日韩av电影在线免费播放| 久久a级毛片毛片免费观看| 精品视频在线观看一区二区| 国产在线国偷精品产拍免费yy| 国产精品免费在线视频| 欧美色欧美亚洲另类二区| 国产精品秘入口| 国产精品免费在线免费| 精品理论电影| 国产三级三级看三级| 欧美国产一区二区| 老熟妇一区二区三区啪啪| 中文字幕一区电影| 成人国产在线| 亚洲最大免费| 国产中文一区二区三区| 中文字幕电影av| 日韩亚洲欧美高清| 欧美人与动牲性行为| 国产区二精品视| 母乳一区在线观看| 男生草女生视频| 欧美视频一区二区在线观看| 色开心亚洲综合| 成人在线小视频| 欧美日本亚洲韩国国产| 逼特逼视频在线观看| 精品国产999| 精品影院一区| 国产精品尤物福利片在线观看| 婷婷色综合网| 无人码人妻一区二区三区免费| 午夜精品在线看| 免费在线超碰| 国产精品自产拍在线观看| 亚洲先锋影音| 极品粉嫩小仙女高潮喷水久久 | 国产精品久久久久7777按摩| 国产精品久久久久久免费免熟| 欧美极品少妇xxxxx| 亚洲大片精品免费| 亚洲视频第二页| 亚洲国产精品视频| 色播色播色播色播色播在线| 国产精品男人爽免费视频1| 欧美另类女人| 亚洲av片不卡无码久久| 欧美日韩国产一级| 久久www人成免费看片中文| 欧美男人的天堂| 国产麻豆一精品一av一免费 | 欧美日韩成人一区二区三区| 六月丁香婷婷久久| 久久久久久久伊人| 亚洲图片制服诱惑| 午夜日韩影院| 最新中文字幕免费视频| 亚洲在线观看免费视频| 免费黄网站在线观看| 亚洲va欧美va国产综合剧情| 蜜桃视频一区| 国产亚洲精品成人| 国产一区二区三区18| 精品少妇一区| 无套内谢丰满少妇中文字幕| 91黄色小视频| 51av在线|