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

接口從4秒到200毫秒-小小的日志竟能引發(fā)如此問題

開發(fā) 前端
我們的業(yè)務需對接不同渠道以完成線上回收業(yè)務,然而各渠道皆有其獨特的質(zhì)檢標準。為此,我們需對質(zhì)檢標準予以統(tǒng)一化處理,將外部標準轉化為內(nèi)部可識別的質(zhì)檢標準。

1 問題背景

我們的業(yè)務需對接不同渠道以完成線上回收業(yè)務,然而各渠道皆有其獨特的質(zhì)檢標準。為此,我們需對質(zhì)檢標準予以統(tǒng)一化處理,將外部標準轉化為內(nèi)部可識別的質(zhì)檢標準。在此場景下,我們提供了標準映射功能,將外部質(zhì)檢項與內(nèi)部質(zhì)檢項進行關聯(lián)。此次問題源于映射關系極為復雜,在導入映射關系后,發(fā)現(xiàn)映射邏輯耗時嚴重,最終定位至日志打印問題。接下來,讓我們一同探究如何定位到日志問題以及為何輸出大量日志會致使接口變慢。

2 問題驗證

在測試環(huán)境中維護某渠道質(zhì)檢項與內(nèi)部質(zhì)檢項映射關系15000+;

發(fā)現(xiàn)模版質(zhì)檢轉換接口耗時4s左右;

圖片圖片

圖片

將質(zhì)檢項的映射關系減少到100+時;

模版質(zhì)檢轉換接口耗時到了100毫秒左右。

圖片圖片

圖片圖片

發(fā)現(xiàn)模版映射接口時長確實與映射項多少有很強的關聯(lián)性。

3 問題初步定位

通過阿里的Arthas工具的trace命令可以分析方法的耗時。

圖片圖片

經(jīng)觀察,該方法的耗時主要集中于打印日志。查看代碼得知,在將外部質(zhì)檢項映射為內(nèi)部質(zhì)檢項的過程中會產(chǎn)生大量日志,且映射關系越多,日志數(shù)量越多。因項目急于上線,故先對打印日志的代碼進行注釋,隨后發(fā)現(xiàn)接口的響應速度明顯變快。

4 初步思考

4.1 有沒有可能日志打印配置的是同步打印?

首先考慮是否為同步打印日志,畢竟同步讀寫文件會涉及磁盤隨機讀寫,進而影響效率。經(jīng)查看 log4j 的配置,得知打印日志的配置為異步打印,而非同步打印。

4.2 既然是異步打印,有沒有可能是多線程爭搶資源導致打印日志過慢呢?

排除同步打印日志的原因后,由于起初并不了解異步日志打印的底層實現(xiàn)。但依據(jù)經(jīng)驗,因需異步打印日志,需有地方存儲需要打印的日志,故而可能涉及資源爭搶。基于此想法,創(chuàng)建一個測試方法,進行單線程循環(huán)打印日志2萬次操作。

@Test
private void test4(){
    long l = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
      log.info(i+"");
    }
    System.out.println("打印日志耗時:" + (System.currentTimeMillis() - l));
}

發(fā)現(xiàn)打印日志耗時為 600 多毫秒。這就感覺很奇怪,如果僅僅存儲 20000 個需要打印的日志任務需要這么長時間嗎?

于是,搞了一個線程池,提交20000個任務也查看一下耗時;

public static void main(String[] args) {
        long l = System.currentTimeMillis();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(20000));
        for (int i = 0; i < 20000; i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    
                }
            });
        }
        System.out.println("打印耗時:" + (System.currentTimeMillis() - l));
    }

發(fā)現(xiàn)只需要2,30毫秒。

在單線程的環(huán)境中,若打印大量日志,速度也極為緩慢,由此可見,并非是多線程的問題所致。

我們都清楚,線程池在提交任務時,若隊列已滿且達到最大線程數(shù),便會執(zhí)行拋棄策略,其中有一種是將任務交回給提交任務的線程執(zhí)行。那么在異步日志打印過程中,倘若需打印的日志過多,使得存儲需要異步打印日志的地方滿了,是否也存在相應的拋棄策略呢?比如將異步打印轉為同步打印。所以,我決定先去探究異步打印日志的原理。

5 異步日志打印原理

5.1 Disruptor原理

經(jīng)過查詢資料發(fā)現(xiàn),異步日志打印的底層采用的是Disruptor框架。

圖片圖片

其基本原理為生產(chǎn)者向環(huán)形數(shù)組中存入數(shù)據(jù),消費者則消費環(huán)形數(shù)組中的數(shù)據(jù)。sequence 用于限制生產(chǎn)者的生產(chǎn)以及消費者的消費。通過閱讀代碼得知,本質(zhì)上生產(chǎn)者會保存所有消費者以及自身的 sequence 以限制生產(chǎn),消費者保存生產(chǎn)者來限制消費。

//org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor#start
public synchronized void start() {
  //....
  //
  disruptor.handleEventsWith(handlers);
  //....
}

//com.lmax.disruptor.dsl.Disruptor#handleEventsWith(com.lmax.disruptor.EventHandler<? super T>...)
//添加事件處理(消費者)
public final EventHandlerGroup<T> handleEventsWith(final EventHandler<? super T>... handlers) {
  return createEventProcessors(new Sequence[0], handlers);
}

//com.lmax.disruptor.dsl.Disruptor#createEventProcessors(com.lmax.disruptor.Sequence[], com.lmax.disruptor.EventHandler<? super T>[])
//創(chuàng)建事件處理(消費對象)
EventHandlerGroup<T> createEventProcessors(
  final Sequence[] barrierSequences,
  final EventHandler<? super T>[] eventHandlers) {
  //....
  //所有消費者的Sequence
  final Sequence[] processorSequences = new Sequence[eventHandlers.length];
  //將生產(chǎn)者包裝成為SequenceBarrier
  final SequenceBarrier barrier = ringBuffer.newBarrier(barrierSequences);
  //遍歷事件處理
  for (int i = 0, eventHandlersLength = eventHandlers.length; i < eventHandlersLength; i++) {
    final EventHandler<? super T> eventHandler = eventHandlers[i];
    //創(chuàng)建事件處理(消費者)
    final BatchEventProcessor<T> batchEventProcessor =
      new BatchEventProcessor<>(ringBuffer, barrier, eventHandler);
    //....
    //將消費者的Sequence放入gatingSequences中
    processorSequences[i] = batchEventProcessor.getSequence();
  }
  //更新生產(chǎn)者的processorSequences
  updateGatingSequencesForNextInChain(barrierSequences, processorSequences);
  //....
}

5.2 異步日志放入Disruptor環(huán)形數(shù)組的過程

圖片圖片

代碼

  • 將數(shù)據(jù)放入Disruptor環(huán)形數(shù)組中
//org.apache.logging.log4j.core.async.AsyncLoggerConfig#logToAsyncDelegate
private void logToAsyncDelegate(final LogEvent event) {
  if (!isFiltered(event)) {
    // Passes on the event to a separate thread that will call
    // asyncCallAppenders(LogEvent).
    populateLazilyInitializedFields(event);
  //嘗試將logevnet對象發(fā)布到環(huán)形數(shù)組中
    if (!delegate.tryEnqueue(event, this)) {
      //如果沒有放進去,說明隊列滿了,執(zhí)行隊列滿的處理方法,本質(zhì)上類似于線程池隊列滿丟棄策略
      //ENQUEUE:將日志放入環(huán)形數(shù)組(放入不進去就循環(huán)等待,一直到放進去)
      //SYNCHRONOUS:當前線程打印日志
      //DISCARD:直接丟棄,忽略日志
      handleQueueFull(event);
    }
  }
}
  • 放入環(huán)形數(shù)組的過程
//org.apache.logging.log4j.core.async.AsyncLoggerConfigDisruptor#tryEnqueue
public boolean tryEnqueue(final LogEvent event, final AsyncLoggerConfig asyncLoggerConfig) {
    final LogEvent logEvent = prepareEvent(event);
    //獲取環(huán)形數(shù)組
    return disruptor.getRingBuffer().
      //放入環(huán)形數(shù)組中
      tryPublishEvent(translator, logEvent, asyncLoggerConfig);
}
//com.lmax.disruptor.RingBuffer#tryPublishEvent(com.lmax.disruptor.EventTranslatorTwoArg<E,A,B>, A, B)
//嘗試放入環(huán)形數(shù)組中
public <A, B> boolean tryPublishEvent(EventTranslatorTwoArg<E, A, B> translator, A arg0, B arg1){
    try
    {
      //嘗試獲取生產(chǎn)者下一個要存放到環(huán)形數(shù)組中的位置
      final long sequence = sequencer.tryNext();
      //將其放入指定的位置中
      translateAndPublish(translator, sequence, arg0, arg1);
      return true;
    }
    catch (InsufficientCapacityException e)
    {
      //容量不足,就返回fals,執(zhí)行環(huán)形數(shù)組滿的處理方法
      return false;
    }
}
//com.lmax.disruptor.MultiProducerSequencer#tryNext(int)
//獲取生產(chǎn)者下一個位置,n表示當前位置+1,tryNext()就是tryNext(1)
public long tryNext(int n) throws InsufficientCapacityException {
    if (n < 1) {
      throw new IllegalArgumentException("n must be > 0");
    }

    long current;
    long next;

    do {
      //獲取當前位置
      current = cursor.get();
      //想要獲取的位置
      next = current + n;
      //判斷是否有可用容量
      //實現(xiàn)原理大概就是比較Sequence(消費者消費到哪里了)和current中的較小值,與next差值是否大于環(huán)形數(shù)組的大小
      if (!hasAvailableCapacity(gatingSequences, n, current)) {
        throw InsufficientCapacityException.INSTANCE;
      }
    }
    while (!cursor.compareAndSet(current, next));
    return next;
}

發(fā)現(xiàn)確實有類似于線程池的拋棄策略。

5.3 復用4.2中打印日志的測試代碼進行打斷點

經(jīng)過調(diào)試發(fā)現(xiàn),在日志打印的過程中消費者消費快,沒有出現(xiàn)handleQueueFull的調(diào)用。

所以并不會經(jīng)過ENQUEUE、SYNCHRONOUS、DISCARD的三種策略的處理。

那么現(xiàn)在問題就變得十分離譜,并非上述原因所致。因此,決定采用暴力破解之法,即逐行注釋代碼的方式,以查看究竟是哪一行代碼引發(fā)了日志打印緩慢的問題。

6 將日志打印過程中的代碼進行逐行注釋,找到那一行導致日志輸出慢

6.1 定位原因發(fā)現(xiàn)是getLocation方法

經(jīng)過逐行注釋后,確定是由于getLocation方法所致。那么這行代碼究竟有何作用呢?

查詢資料得知getLocation 是用來獲取內(nèi)容匹配日志輸出格式中的%C、%F、%l、%L、%M 。

以下是該方法的調(diào)用之處以及其內(nèi)部代碼。

//org.apache.logging.log4j.spi.AbstractLogger#logMessageTrackRecursion
private void logMessageTrackRecursion(final String fqcn,
                                      final Level level,
                                      final Marker marker,
                                      final Message message,
                                      final Throwable throwable) {
  try {
    incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031
    tryLogMessage(fqcn, getLocation(fqcn), level, marker, message, throwable);
  } finally {
    decrementRecursionDepth();
  }
}
//org.apache.logging.log4j.spi.AbstractLogger#getLocation
//獲取日志是哪個類,哪個方法,哪一行打印的
//舉例[11-05 00:03:39 596 INFO ] [] [] [] [main] [] c.z.h.p.r.r.c.ChannelCommonFacadeTest.main(383) - 111
//中的c.z.h.p.r.r.c.ChannelCommonFacadeTest.main(383)字符串
private StackTraceElement getLocation(String fqcn) {
  //requiresLocation 用于判斷是否需要Location,不需要直接返回null
  return requiresLocation() ? StackLocatorUtil.calcLocation(fqcn) : null;
}

繼續(xù)向下追蹤會到下方代碼:

//org.apache.logging.log4j.util.StackLocator#calcLocation
public StackTraceElement calcLocation(final String fqcnOfLogger) {
    //....
   //fqcnOfLogger=org.apache.logging.slf4j.Log4jLogger
    //獲取當前方法調(diào)用鏈路上所有的調(diào)用鏈路
    final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    boolean found = false;
    for (int i = 0; i < stackTrace.length; i++) {
      final String className = stackTrace[i].getClassName();
      //判斷類名稱是否相同
      if (fqcnOfLogger.equals(className)) {

        found = true;
        continue;
      }
      //這樣就得到了誰調(diào)用的日志輸出了
      if (found && !fqcnOfLogger.equals(className)) {
        return stackTrace[i];
      }
    }
    return null;
}
//java.lang.Throwable#getStackTrace
public StackTraceElement[] getStackTrace() {
 return getOurStackTrace().clone();
}
//java.lang.Throwable#getOurStackTrace
private synchronized StackTraceElement[] getOurStackTrace() {
  // Initialize stack trace field with information from
  // backtrace if this is the first call to this method
  if (stackTrace == UNASSIGNED_STACK ||
      (stackTrace == null && backtrace != null) /* Out of protocol state */) {
    //獲取調(diào)用鏈路的長度
    int depth = getStackTraceDepth();
    stackTrace = new StackTraceElement[depth];
    for (int i=0; i < depth; i++)
      //獲取每一級調(diào)用鏈路
      stackTrace[i] = getStackTraceElement(i);
  } else if (stackTrace == null) {
    return UNASSIGNED_STACK;
  }
  return stackTrace;
}
//方法都是本地方法
native int getStackTraceDepth();
native StackTraceElement getStackTraceElement(int index);

通過上述跟蹤源碼,懷疑是Java調(diào)用C++代碼或者需要遍歷StackTraceElement數(shù)組導致異步日志打印過慢。

所以先將getOurStackTrace方法進行修改,不調(diào)用C++方法,直接創(chuàng)建對象,來排除不是因為遍歷數(shù)組導致的原因。

//org.apache.logging.log4j.util.StackLocator#calcLocation
public StackTraceElement calcLocation(final String fqcnOfLogger) {
    //....
   //fqcnOfLogger=org.apache.logging.slf4j.Log4jLogger
    //將這里改為自己的寫的方法調(diào)用,構建方法調(diào)用鏈路
    final StackTraceElement[] stackTrace = stackTraceElements(fqcnOfLogger);
    boolean found = false;
    for (int i = 0; i < stackTrace.length; i++) {
      final String className = stackTrace[i].getClassName();
      //判斷類名稱是否相同
      if (fqcnOfLogger.equals(className)) {

        found = true;
        continue;
      }
      //這樣就得到了誰調(diào)用的日志輸出了
      if (found && !fqcnOfLogger.equals(className)) {
        return stackTrace[i];
      }
    }
    return null;
}
/**
* 構建stackTraceElement數(shù)組
* @param fqcnOfLogger
* @return
*/
private StackTraceElement[] stackTraceElements(String fqcnOfLogger) {
    //構建一個42長度的,保持測試代碼獲取相同長度的方法調(diào)用鏈路
    int size = 42;
    StackTraceElement[] stackTraceElement = new StackTraceElement[size];
    for (int i = 0; i < size - 2; i++) {
      stackTraceElement[i] = new StackTraceElement("1", "1", "1", 1);
    }
    stackTraceElement[size - 2] = new StackTraceElement(fqcnOfLogger, "1", "1", 1);
    stackTraceElement[size - 1] = new StackTraceElement("1", "1", "1", 1);
    return stackTraceElement;
}

//然后再執(zhí)行代碼測試代碼
@Test
private void test4(){
    long l = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
      log.info(i+"");
    }
    System.out.println("打印日志耗時:" + (System.currentTimeMillis() - l));
}

發(fā)現(xiàn)耗時只需要50毫秒,所以由此懷疑是Java調(diào)用C++代碼導致異步日志打印過慢。Java調(diào)用C++代碼用的框架叫JNI。

6.2 官方資料

圖片圖片

這段文字說明使用堆棧跟蹤比不實用堆棧跟蹤慢30-100倍。

圖片圖片

這張圖用來說明單線程異步日志記錄時需要記錄調(diào)用位置信息與不需要記錄調(diào)用位置信息的對比。

6.3 JNI原理

JNI調(diào)用Java代碼是一種類似反射的原理,先找到jclass、再找到jmethodId,然后調(diào)用,這樣一步步地來;

Java調(diào)用C/C++代碼創(chuàng)建對象是需要保存對象指針,然后各種操作是要將指針傳入到jni層,然后強轉到具體對象再進行操作的。

6.3.1 JNI 架構

JNI 的基本架構可以分為以下幾個部分:

  • Java 代碼:調(diào)用 native 方法的 Java 類。
  • JNI 頭文件:由 Java 編譯器生成的 C/C++ 頭文件,定義了 Java 類中的 native 方法。
  • 本地實現(xiàn):C/C++ 代碼實現(xiàn) native 方法的具體邏輯。
  • Java 虛擬機:提供 JNI 支持的運行環(huán)境,負責加載和執(zhí)行 Java 字節(jié)碼。

6.3.2 數(shù)據(jù)類型轉換

JNI 負責在 Java 數(shù)據(jù)類型和 C/C++ 數(shù)據(jù)類型之間進行轉換。常見的數(shù)據(jù)轉換方法包括:

  • Java 字符串:使用 GetStringUTFChars 和 NewStringUTF 方法進行轉換。
  • Java 數(shù)組:使用 GetIntArrayElements、SetIntArrayRegion 等方法處理數(shù)組。
  • Java 對象:使用 GetObjectField、CallObjectMethod 等方法訪問對象的字段和方法。

6.3.3 異常處理

JNI 提供異常處理機制,允許本地代碼檢測和拋出 Java 異常。通過 env->ExceptionCheck() 和 env->Throw 方法,可以在本地代碼中檢查異常狀態(tài)并拋出異常。

6.3.4 線程管理

JNI 允許多線程訪問 JVM,提供了與線程相關的 API,如 AttachCurrentThread 和 DetachCurrentThread,用于在本地代碼中管理 Java 線程。

6.3.5 性能考慮

  • 開銷:JNI 方法調(diào)用相對 Java 方法調(diào)用來說有更高的開銷,因為涉及到上下文切換和數(shù)據(jù)轉換。
  • 效率:盡管 JNI 可以提供更高的性能,特別是在需要大量計算或系統(tǒng)級操作時,過多的 JNI 調(diào)用可能導致性能下降。

6.4 編寫本地方法測試

public class Hello {
    public native int helloFromCpp(int i);

    static {
       //加載動態(tài)鏈接
        System.load(System.getProperty("user.dir") +"/libnative.dylib");
    }
}

下面是如何能進行本地方法調(diào)用的過程:

  1. javac Hello.java -h . 將Java文件編譯為.class并產(chǎn)生頭文件。
  2. 產(chǎn)生的頭文件的展示
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class test_Hello */

#ifndef _Included_test_Hello
#define _Included_test_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     test_Hello
 * Method:    helloFromCpp
 * Signature: (I)I
 */
//jni產(chǎn)生的方法名稱是有規(guī)則的 Java開頭 test表示包 Hello表示類 helloFromCpp表示方法
JNIEXPORT jint JNICALL Java_test_Hello_helloFromCpp
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif
  • 編寫頭文件對應的cpp文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include "test_Hello.h"
/* Header for class test_Hello */


/*
 * Class:     test_Hello
 * Method:    helloFromCpp
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_test_Hello_helloFromCpp
  (JNIEnv * env, jobject o , jint j1){
    return j1;
  }
  • 產(chǎn)生動態(tài)鏈接g++ -dynamiclib  -o libnative.dylib -I "/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/include/darwin" -I "/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/include" test_Hello.cpp
  • 執(zhí)行代碼測試
public static void test() {
  long l = System.currentTimeMillis();
  for (int i = 0; i < 20000*32; i++) {
  Hello h = new Hello();
  h.helloFromCpp(i);
  }
  System.out.println("耗時時間" + (System.currentTimeMillis() - l));
}

注意:蘋果電腦要是arm架構的,一定要注意執(zhí)行Java程序的JDK版本要是arm架構的。

發(fā)現(xiàn)耗時很少,所以并不是因為Java通過JNI執(zhí)行C語言代碼的問題。

所以最終結論應該是底層執(zhí)行C++代碼慢的緣故。

7 結論

  • 避免打印過多無用日志,將測試過程中需要觀察的日志輸出為為 DEBUG 級別。
  • 生產(chǎn)環(huán)境打印日志的級別設置為INFO。
  • 如果不需要關注日志打印的位置信息,可以將日志輸出格式中的%C、%F、%l、%L、%M去掉。

8 擴展(想了解C底層實現(xiàn))

可以查看一下下面三個類:

  • jdk/src/share/native/java/lang/Throwable.c
  • hotspot/src/share/vm/prims/jvm.cpp
  • hotspot/src/share/vm/classfile/javaClasses.cpp
責任編輯:武曉燕 來源: 轉轉技術
相關推薦

2013-11-11 11:17:45

AngularJS性能優(yōu)化

2025-06-27 09:05:47

2025-08-18 03:00:22

Spring樹形結構分類樹

2021-04-27 06:20:25

MySQL集群優(yōu)化

2021-04-22 07:29:46

數(shù)據(jù)展現(xiàn)方式

2012-03-11 15:27:57

微軟

2017-05-31 13:58:05

戴爾宕機服務器

2023-09-27 07:35:27

2025-06-25 09:30:14

2019-01-30 09:34:56

ElasticSearLogstashKibana

2014-08-04 15:13:27

光纖

2024-04-12 09:02:15

JavaCPU執(zhí)行時間線程

2019-08-21 14:35:18

壓縮文件優(yōu)化過程Java

2022-09-26 09:41:25

MySQL數(shù)據(jù)庫

2020-11-12 18:51:43

Java編程語言

2025-03-24 08:51:16

2025-04-03 09:45:51

2017-10-31 15:28:27

RUDP傳輸優(yōu)化實踐

2017-12-25 11:15:06

JavaArray數(shù)組
點贊
收藏

51CTO技術棧公眾號

中文字幕一区二区日韩精品绯色| 午夜免费一区| 91搞黄在线观看| 亚洲高清在线观看一区| jlzzjlzz亚洲女人18| 99热精品在线| 日韩在线观看视频免费| 亚洲天堂av网站| 欧美日韩视频免费看| 亚洲高清视频的网址| 偷拍视频一区二区| 好吊色在线观看| 免费观看在线综合| 97久久精品人搡人人玩| 日韩一卡二卡在线观看| 极品尤物一区| 制服丝袜中文字幕亚洲| 国产91对白刺激露脸在线观看| 日韩精品黄色| 91丨porny丨首页| 91丝袜美腿美女视频网站| 天堂在线免费观看视频| 国语精品一区| 久久视频免费观看| 我不卡一区二区| 久久影视三级福利片| 337p亚洲精品色噜噜狠狠| 青青在线视频免费| av在线最新| 亚洲午夜一区二区| 欧美性视频在线播放| 久蕉在线视频| 26uuu另类欧美亚洲曰本| 91九色在线观看| 一级黄色免费片| 首页亚洲欧美制服丝腿| 26uuu久久噜噜噜噜| 精品无码免费视频| 亚洲五月综合| zzjj国产精品一区二区| 手机看片福利视频| 久草成人在线| 亚洲美女精品久久| 熟女丰满老熟女熟妇| 成人av地址| 亚洲成人av在线播放| 又黄又爽又色的视频| 国产精品xnxxcom| 欧美人与禽zozo性伦| www.com操| 国产激情久久| 欧美日本在线播放| 成年人三级黄色片| 亚洲ww精品| 5858s免费视频成人| 色播五月激情五月| 日韩福利影视| 欧美一级一级性生活免费录像| 国产三级生活片| 亚洲一区二区小说| 欧美一区二区三区视频免费| 永久免费黄色片| 视频国产精品| 亚洲成人网久久久| 少妇一级淫片免费放播放| 日韩mv欧美mv国产网站| 日韩电影第一页| 能直接看的av| 亚洲欧洲中文字幕| 欧美高清在线播放| 一区二区三区视频免费看| 香蕉久久国产| 国产精品日韩一区| 国产乱子伦精品无码码专区| 国产a区久久久| 精品日韩电影| 成年人在线观看| 亚洲欧洲精品天堂一级| 日本福利视频在线观看| 嗯啊主人调教在线播放视频 | 亚洲女人天堂成人av在线| 亚洲午夜久久久久久久久红桃| 国产精品密蕾丝视频下载| 深夜福利亚洲导航| 国产在线一二区| 久久九九99| 91免费人成网站在线观看18| 欧美视频xxx| 国产人妖乱国产精品人妖| 日日噜噜噜夜夜爽爽| 白浆视频在线观看| 欧美色电影在线| 久久久久久久久久久久国产精品| 天天躁日日躁成人字幕aⅴ| 尤物九九久久国产精品的特点| 日本黄色免费片| 在线观看亚洲| 国产欧美精品日韩| 狠狠综合久久av一区二区| 国产亚洲精品免费| 欧美一级特黄aaaaaa在线看片| av今日在线| 欧美美女一区二区三区| 99久久免费看精品国产一区 | 成人免费精品视频| 日韩欧美国产二区| 操喷在线视频| 欧美老女人第四色| 中文字幕日韩三级片| 天天操综合网| 日韩av高清不卡| 性欧美一区二区三区| 久久精品一区二区三区四区| 国产乱子伦精品视频| 国产精品久久久久av电视剧| 精品免费99久久| 欧美日韩国产一二三区| 国产精品一级| 成人一区二区三区四区| 欧美人xxx| 欧美综合在线视频| 国产又黄又粗又猛又爽的视频| 五月天激情综合网| 国产精品极品美女在线观看免费| 人妻无码中文字幕| 亚洲另类中文字| 久久久久久久久久一区二区| 精品国产乱码久久久久久果冻传媒 | 精品在线视频一区二区| 最爽无遮挡行房视频在线| 欧美三级乱人伦电影| 扒开jk护士狂揉免费| 日韩午夜激情| 国产日韩欧美一区二区三区四区 | 91国偷自产一区二区三区的观看方式 | 亚洲经典在线| 粉嫩精品一区二区三区在线观看| 欧美69xxx| 欧美日本在线一区| 黄色一级片一级片| 欧美aaaaa成人免费观看视频| 蜜桃传媒视频麻豆第一区免费观看 | 啪啪亚洲精品| 日韩av电影中文字幕| 九色视频在线播放| 色天天综合色天天久久| 好吊日免费视频| 在线欧美亚洲| 精品国产乱码久久久久久郑州公司| 黑人精品视频| 亚洲第一二三四五区| 豆国产97在线 | 亚洲| 成人丝袜视频网| 国产特级淫片高清视频| 欧美电影在线观看免费| 欧美一区二区视频97| 邻居大乳一区二区三区| 欧洲在线/亚洲| 992在线观看| 国产伦精品一区二区三区视频青涩 | 免费激情视频在线观看| 中文精品一区二区| 国产精品电影观看| av播放在线| 6080午夜不卡| 中文字幕一区二区三区手机版 | 男女视频在线| 亚洲国内精品视频| 日韩免费观看一区二区| 91啪亚洲精品| 久久国产这里只有精品| 欧美777四色影| 国产精品一 二 三| 欧美大片免费| 久久精品视频亚洲| 国模私拍视频在线| 色94色欧美sute亚洲13| 久久久久人妻一区精品色| 国产精品一区二区无线| 人人干视频在线| 免费成人高清在线视频theav| 国产精品美女在线| 人交獸av完整版在线观看| 精品中文字幕久久久久久| 最新国产中文字幕| 一区二区三区在线观看动漫 | 丰满人妻熟女aⅴ一区| 欧美日韩精品国产| 久久久久久久久久97| gogogo免费视频观看亚洲一| 国产黄色特级片| 欧美 亚欧 日韩视频在线| 欧美1o一11sex性hdhd| 久久69成人| 欧美亚洲国产另类| 免费网站看v片在线a| 亚洲国产成人一区| 中文字幕制服诱惑| 午夜精品福利久久久| 天天操天天摸天天舔| 91最新地址在线播放| 久久精品亚洲天堂| 日韩成人一级片| 婷婷无套内射影院| 国产精品成人av| 欧美成人在线免费观看| 日韩精品三级| 国产精品激情自拍| 午夜久久中文| 国内精品久久久久久久| 麻豆网站在线免费观看| 亚洲欧美中文另类| 日韩在线一区二区三区四区| 在线播放91灌醉迷j高跟美女| 欧美a视频在线观看| 亚洲综合在线第一页| 麻豆明星ai换脸视频| 国产色产综合产在线视频| 成年女人免费视频| 国产一区二区三区久久久| 天堂在线资源视频| 亚洲一区二区免费看| 成人性生活视频免费看| 你懂的国产精品| 一卡二卡3卡四卡高清精品视频| 天堂网av成人| 国产一区免费观看| silk一区二区三区精品视频| 91日韩在线视频| 日韩黄色三级在线观看| 国产成人一区三区| 国产精品扒开腿做爽爽爽视频软件| 欧美—级高清免费播放| 爆操欧美美女| 久久视频在线免费观看| 男人资源在线播放| 色偷偷9999www| 91ph在线| 综合网中文字幕| 超碰国产在线| 中文字幕亚洲在线| 在线视频91p| 日韩视频免费观看| 黄网站在线免费| 久久综合电影一区| 国产欧美黑人| 九九九久久久久久| 黄色美女视频在线观看| 久久久欧美一区二区| 爱啪啪综合导航| 国产69久久精品成人| 亚洲精品**中文毛片| 日本成熟性欧美| 免费成人美女女| 国产精品女视频| 日韩综合久久| 亚洲japanese制服美女| 一区二区三区视频播放| 国产欧美精品一区二区三区| 欧洲亚洲成人| 秋霞在线观看一区二区三区| 欧美色蜜桃97| 日韩最新中文字幕| 怡红院精品视频在线观看极品| 免费看黄在线看| 三级欧美在线一区| 天天影视色综合| 国产99久久久久| 亚洲欧美日本一区| 国产日韩成人精品| 中文字幕另类日韩欧美亚洲嫩草| 夜夜爽夜夜爽精品视频| 日韩成年人视频| 在线观看区一区二| 99在线精品视频免费观看20| 亚洲国产天堂网精品网站| 男人天堂综合| 另类视频在线观看| 蜜桃视频m3u8在线观看| 国产精品国产三级国产aⅴ9色| 亚洲欧美一级| 精品高清视频| 国产精品久久久久蜜臀| www.日本少妇| 美女脱光内衣内裤视频久久网站 | 亚洲欧美日本伦理| 在线综合视频网站| 亚洲高清成人| 成年网站免费在线观看| 99精品久久只有精品| 亚洲欧美卡通动漫| 欧美日韩国产区| 国产肥老妇视频| 亚洲男人7777| 色呦呦在线播放| 国产福利精品av综合导导航| 日本精品视频| 先锋影音网一区| 夜夜嗨网站十八久久| 一区二区三区四区毛片| 337p粉嫩大胆色噜噜噜噜亚洲| 91精品国产闺蜜国产在线闺蜜| 精品久久香蕉国产线看观看gif| 国产一区二区自拍视频| 亚洲乱亚洲乱妇无码| 伊人福利在线| 国产欧美日韩中文| 女人丝袜激情亚洲| 久久国产午夜精品理论片最新版本| 久久精品国产一区二区| 青青草视频成人| 亚洲国产人成综合网站| 国产女人18毛片水真多| 亚洲日本欧美日韩高观看| 成人bbav| 翡翠波斯猫1977年美国| 91综合视频| 午夜免费精品视频| 99久久99久久久精品齐齐| 人妻少妇精品一区二区三区| 在线观看不卡一区| 经典三级在线| 日本国产高清不卡| 国产在线播放精品| 欧美交换配乱吟粗大25p| 久久av老司机精品网站导航| 亚洲一区二区自偷自拍 | 天堂综合网久久| 久久久久久www| 国产成人欧美日韩在线电影| 性生交大片免费全黄| 欧美精品免费视频| 在线观看精品一区二区三区| 国产福利精品在线| 精品大片一区二区| 午夜在线观看av| 国产精品剧情在线亚洲| 在线视频播放大全| 国产一区二区三区视频在线观看| 欧美第一视频| 欧美一区二区三区在线免费观看| 国产一区二区精品| 双性尿奴穿贞c带憋尿| 精品国产鲁一鲁一区二区张丽| 少妇喷水在线观看| 亚洲 日韩 国产第一| 欧美交a欧美精品喷水| 日本在线xxx| 91看片淫黄大片一级| 成人h动漫精品一区二区下载| 亚洲精选在线观看| 日本少妇一区| 亚洲最新免费视频| 国产精品亚洲第一 | 91成人免费在线| 国产精品一区在线看| 国产精品xxx视频| 日韩在线视频精品| 天天色天天干天天色| 亚洲国产一二三| 欧美美女色图| 国产精品欧美日韩久久| 我不卡神马影院| 欧美一级片在线免费观看| 亚洲成a人片在线观看中文| 天天干天天干天天干| 国产ts人妖一区二区三区| 青青草国产免费一区二区下载| 亚洲日本黄色片| 亚洲自拍偷拍九九九| 青草久久伊人| 国产在线高清精品| 欧美日韩三级| 中文字幕一区二区三区人妻电影| 欧美影院一区二区| 国产激情在线观看| 国模一区二区三区私拍视频| 日韩影院免费视频| 精品99在线观看| 亚洲女同精品视频| 国产激情精品一区二区三区| 拔插拔插海外华人免费| 中文字幕不卡三区| 亚洲免费黄色片| 国产精品偷伦免费视频观看的| 欧美一区在线看| 亚洲人成人无码网www国产| 7777精品伊人久久久大香线蕉完整版 | 欧美日韩一区二区三区在线免费观看 | 69视频免费看| 九九久久精品一区| 国产精品三级| 97中文字幕在线观看| 欧美在线不卡视频| 欧美a级在线观看| 最新视频 - x88av| 久久精品视频在线免费观看| 国产ts变态重口人妖hd| 国产大片精品免费永久看nba| 合欧美一区二区三区|