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

Redis源碼學習之事件驅動

運維 數(shù)據(jù)庫運維 Redis
Redis基于多路復用技術實現(xiàn)了一套簡單的事件驅動庫,代碼在ae.h、ae.c以及ae_epoll.c、ae_evport.c和ae_kqueue.c、ae_select.c這幾個文件中。其中ae表示的是antirez eventloop的意思。

Redis基于多路復用技術實現(xiàn)了一套簡單的事件驅動庫,代碼在ae.h、ae.c以及ae_epoll.c、ae_evport.c和ae_kqueue.c、ae_select.c這幾個文件中。其中ae表示的是antirez eventloop的意思。

Redis里面包含兩種事件類型:FileEvent和TimeEvent。

Redis采用IO多路復用技術,所有的事件都是在一個線程中進行處理。Redis的事件驅動模型可以以以下為代碼進行表示:

  1. int main(int argc,char **argv) 
  2.  
  3.  
  4.     while(true) { 
  5.  
  6.         // 等待事件到來:wait4Event(); 
  7.  
  8.         // 處理事件:processEvent() 
  9.  
  10.     } 
  11.  
  12.  

在一個死循環(huán)中等待事件的到來,然后對事件進行處理,以此往復。這就是一個最經(jīng)典的網(wǎng)絡編程模型。

1.基本數(shù)據(jù)結構

aeEventLoop 

 

aeEventLoop是Redis中事件驅動模型的核心,封裝了整個事件循環(huán),其中每個字段解釋如下:

  • maxfd:已經(jīng)接受的最大的文件描述符。
  • setsize:當前循環(huán)中所能容納的文件描述符的數(shù)量。
  • timeEventNextId:下一個時間事件的ID.
  • lastTime:上一次被訪問的時間,用來檢測系統(tǒng)時鐘是否被修改。
  • events:指針,指向保存所有注冊的事件的數(shù)組首地址。
  • fired:指針,保存所有已經(jīng)買被觸發(fā)的事件的數(shù)組首地址。
  • timeEventHead:Redis用一個鏈表來存儲所有的時間事件,timeEventHead是指向這個鏈表的首節(jié)點指針。
  • stop:停止整個事件循環(huán)。
  • apiData:指針,指向epoll結構。
  • beforeSleep:函數(shù)指針。每次實現(xiàn)循環(huán)的時候,在阻塞直到時間到來之前,會先調用這個函數(shù)。

aeFileEvent和aeTimeEvent

這兩個結構分別表示文件事件和時間事件,定義如下

  1. typedef struct aeFileEvent { 
  2.  
  3.     int mask; /* one of AE_(READABLE|WRITABLE) */ 
  4.  
  5.     aeFileProc *rfileProc; // 函數(shù)指針,寫事件處理 
  6.  
  7.     aeFileProc *wfileProc; // 函數(shù)指針,讀事件處理 
  8.  
  9.     void *clientData; // 具體的數(shù)據(jù) 
  10.  
  11. } aeFileEvent;  

其中mask表示文件事件類型掩碼,可以是AE_READABLE表示是可讀事件,AE_WRITABLE為可寫事件。aeFileProc是函數(shù)指針。

  1. /* Time event structure */ 
  2.  
  3. typedef struct aeTimeEvent { 
  4.  
  5.     long long id; // 事件ID 
  6.  
  7.     long when_sec; // 事件觸發(fā)的時間:s 
  8.  
  9.     long when_ms; // 事件觸發(fā)的時間:ms 
  10.  
  11.     aeTimeProc *timeProc; // 函數(shù)指針 
  12.  
  13.     aeEventFinalizerProc *finalizerProc; // 函數(shù)指針:在對應的aeTieEvent節(jié)點被刪除前調用,可以理解為aeTimeEvent的析構函數(shù) 
  14.  
  15.     void *clientData; // 指針,指向具體的數(shù)據(jù) 
  16.  
  17.     struct aeTimeEvent *next; // 指向下一個時間事件指針 
  18.  
  19. } aeTimeEvent;  

aeFiredEvent

aeFiredEvent結構表示一個已經(jīng)被觸發(fā)的事件,結果如下:

  1. /* A fired event */ 
  2.  
  3. typedef struct aeFiredEvent { 
  4.  
  5.     int fd; // 事件被觸發(fā)的文件描述符 
  6.  
  7.     int mask; // 被觸發(fā)事件的掩碼,表示被觸發(fā)事件的類型 
  8.  
  9. } aeFiredEvent;  

fd表示事件發(fā)生在哪個文件描述符上面,mask用來表示具體事件的類型。

aeApiState

Redis底層采用IO多路復用技術實現(xiàn)高并發(fā),具體實現(xiàn)可以采用kqueue、select、epoll等技術。對于Linux來說,epoll的性能要優(yōu)于select,所以以epoll為例來進行分析。

  1. typedef struct aeApiState { 
  2.  
  3.     int epfd; 
  4.  
  5.     struct epoll_event *events; 
  6.  
  7. } aeApiState;  

aeApiState封裝了跟epoll相關的數(shù)據(jù),epfd保存epoll_create()返回的文件描述符。

具體實現(xiàn)細節(jié)

事件循環(huán)啟動:aeMain()

事件驅動的啟動代碼位于ae.c的aeMain()函數(shù)中,代碼如下:

 

從aeMain()方法中可以看到,整個事件驅動是在一個while()循環(huán)中不停地執(zhí)行aeProcessEvents()方法,在這個方法中執(zhí)行從客戶端發(fā)送過來的請求。

初始化:aeCreateEventLoop()

aeEventLoop的初始化是在aeCreateEventLoop()方法中進行的,這個方法是在server.c中的initServer()中調用的。實現(xiàn)如下:

 

在這個方法中主要就是給aeEventLoop對象分配內存然后并進行初始化。其中關鍵的地方有:

1、調用aeApiCreate()初始化epoll相關的數(shù)據(jù)。aeApiCreate()實現(xiàn)如下:

 

在aeApiCreate()方法中主要完成以下三件事:

  1. 分配aeApiState結構需要的內存。
  2. 調用epoll_create()方法生成epoll的文件描述符,并保存在aeApiState.epfd字段中。
  3. 把第一步分配的aeApiState的內存地址保存在EventLoop->apidata字段中。

2、初始化events中的mask字段為為AE_NONE。

生成fileEvent:aeCreateFileEvent()

Redis使用aeCreateFileEvent()來生成fileEvent,代碼如下:

 

aeCreateFileEvent()方法主要做了以下三件事:

  1. 檢查新增的fd是否超過所能容納最大值。
  2. 調用aeApiAddEvent()方法把對應的fd以mask模式添加到epoll監(jiān)聽器中。
  3. 設置相應的字段值。

其中最關鍵的步驟是第二步,aeApiAddEvent()方法如下:

 

生成timeEvent:aeCreateTimeEvent()

aeCreateTimeEvent()方法主要是用來生成timeEvent節(jié)點,其實現(xiàn)比較簡單,代碼如下所示:

 

處理timeEevnt:processTimeEvents()

Redis在processTimeEvents()方法中來處理所有的timeEvent,實現(xiàn)如下:

  1. static int processTimeEvents(aeEventLoop *eventLoop) { 
  2.  
  3.     int processed = 0; 
  4.  
  5.     aeTimeEvent *te, *prev; 
  6.  
  7.     long long maxId; 
  8.  
  9.     time_t now = time(NULL); 
  10.  
  11.     /** 
  12.  
  13.      * 如果系統(tǒng)時間被調整到將來某段時間然后又被設置回正確的時間, 
  14.  
  15.      * 這種情況下鏈表中的timeEvent有可能會被隨機的延遲執(zhí)行,因 
  16.  
  17.      * 此在這個情況下把所有的timeEvent的觸發(fā)時間設置為0表示及執(zhí)行 
  18.  
  19.      */ 
  20.  
  21.     if (now < eventLoop->lastTime) { 
  22.  
  23.         te = eventLoop->timeEventHead; 
  24.  
  25.         while(te) { 
  26.  
  27.             te->when_sec = 0; 
  28.  
  29.             te = te->next
  30.  
  31.         } 
  32.  
  33.     } 
  34.  
  35.     eventLoop->lastTime = now; // 設置上次運行時間為now 
  36.  
  37.   
  38.  
  39.     prev = NULL
  40.  
  41.     te = eventLoop->timeEventHead; 
  42.  
  43.     maxId = eventLoop->timeEventNextId-1; 
  44.  
  45.     while(te) { 
  46.  
  47.         long now_sec, now_ms; 
  48.  
  49.         long long id; 
  50.  
  51.         /** 
  52.  
  53.          * 刪除已經(jīng)被標志位 刪除 的時間事件 
  54.  
  55.          */ 
  56.  
  57.         if (te->id == AE_DELETED_EVENT_ID) { 
  58.  
  59.             aeTimeEvent *next = te->next
  60.  
  61.             if (prev == NULL
  62.  
  63.                 eventLoop->timeEventHead = te->next
  64.  
  65.             else 
  66.  
  67.                 prev->next = te->next
  68.  
  69.             if (te->finalizerProc) 
  70.  
  71.                 // 在時間事件節(jié)點被刪除前調用finlizerProce()方法 
  72.  
  73.                 te->finalizerProc(eventLoop, te->clientData); 
  74.  
  75.             zfree(te); 
  76.  
  77.             te = next
  78.  
  79.             continue
  80.  
  81.         } 
  82.  
  83.         if (te->id > maxId) { 
  84.  
  85.             /** 
  86.  
  87.              * te->id > maxId 表示當前te指向的timeEvent為當前循環(huán)中新添加的, 
  88.  
  89.              * 對于新添加的節(jié)點在本次循環(huán)中不作處理。 
  90.  
  91.              * PS:為什么會出現(xiàn)這種情況呢?有可能是在timeProc()里面會注冊新的timeEvent節(jié)點? 
  92.  
  93.              * 對于當前的Redis版本中不會出現(xiàn)te->id > maxId這種情況 
  94.  
  95.              */ 
  96.  
  97.             te = te->next
  98.  
  99.             continue
  100.  
  101.         } 
  102.  
  103.         aeGetTime(&now_sec, &now_ms); 
  104.  
  105.         if (now_sec > te->when_sec || 
  106.  
  107.             (now_sec == te->when_sec && now_ms >= te->when_ms)) 
  108.  
  109.         { 
  110.  
  111.             // 如果當前時間已經(jīng)超過了對應的timeEvent節(jié)點設置的觸發(fā)時間, 
  112.  
  113.             // 則調用timeProc()方法執(zhí)行對應的任務 
  114.  
  115.             int retval; 
  116.  
  117.   
  118.  
  119.             id = te->id; 
  120.  
  121.             retval = te->timeProc(eventLoop, id, te->clientData); 
  122.  
  123.             processed++; 
  124.  
  125.             if (retval != AE_NOMORE) { 
  126.  
  127.                 // 要執(zhí)行多次,則計算下次執(zhí)行時間 
  128.  
  129.                 aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms); 
  130.  
  131.             } else { 
  132.  
  133.                 // 如果只需要執(zhí)行一次,則把id設置為-1,再下次循環(huán)中刪除 
  134.  
  135.                 te->id = AE_DELETED_EVENT_ID; 
  136.  
  137.             } 
  138.  
  139.         } 
  140.  
  141.         prev = te; 
  142.  
  143.         te = te->next
  144.  
  145.     } 
  146.  
  147.     return processed; 
  148.  
  149.  

在這個方法中會

  1. 判斷系統(tǒng)時間有沒有調整過,如果調整過,則會把timeEvent鏈表中的所有的timeEvent的觸發(fā)時間設置為0,表示立即執(zhí)行。
  2. 對timeEvent鏈表進行遍歷,對于每個timeEvent節(jié)點,如果有:
    • 返回為AE_NOMORE,表示當前timeEvent節(jié)點屬于一次性事件,標記該節(jié)點ID為AE_DELETED_EVENT_ID,表示刪除節(jié)點,該節(jié)點將會在下一輪的循環(huán)中被刪除。
    • 返回不是AE_NOMORE,表示當前timeEvent節(jié)點屬于周期性事件,需要多次執(zhí)行,調用aeAddMillisecondsToNow()方法設置下次被執(zhí)行時間。
    • 如果已經(jīng)被標記為刪除(AE_DELETED_EVENT_ID),則立即釋放對應節(jié)點內存,遍歷下個節(jié)點。
      • 如果id大于maxId,則表示當前節(jié)點為本次循環(huán)中新增節(jié)點,咋本次循環(huán)中不錯處理,繼續(xù)下個節(jié)點。
      • 如果當前節(jié)點的觸發(fā)時間大于當前時間,則調用對應節(jié)點的timeProc()方法執(zhí)行任務。根據(jù)timeProc()方法的返回,又分為兩種情況:

處理所有事件:aeProcessEvents()

Redis中所有的事件,包括timeEvent和fileEvent都是在aeProcessEvents()方法中進行處理的,剛方法實現(xiàn)如下:

  1. /* Process every pending time event, then every pending file event 
  2.  
  3. * (that may be registered by time event callbacks just processed). 
  4.  
  5. * Without special flags the function sleeps until some file event 
  6.  
  7. * fires, or when the next time event occurs (if any). 
  8.  
  9.  
  10. * If flags is 0, the function does nothing and returns
  11.  
  12. * if flags has AE_ALL_EVENTS setall the kind of events are processed. 
  13.  
  14. * if flags has AE_FILE_EVENTS set, file events are processed. 
  15.  
  16. * if flags has AE_TIME_EVENTS settime events are processed. 
  17.  
  18. * if flags has AE_DONT_WAIT set the function returns ASAP until all 
  19.  
  20. * the events that's possible to process without to wait are processed. 
  21.  
  22.  
  23. * The function returns the number of events processed. */ 
  24.  
  25. int aeProcessEvents(aeEventLoop *eventLoop, int flags) 
  26.  
  27.  
  28.     int processed = 0, numevents; 
  29.  
  30.     /** 
  31.  
  32.      * 既沒有時間事件也沒有文件事件,則直接返回 
  33.  
  34.      */ 
  35.  
  36.     if (!(flags & AE_TIME_EVENTS) && !(flags & AE_FILE_EVENTS)) return 0; 
  37.  
  38.     /** 
  39.  
  40.      * -1 == eventloop->maxfd 表示還么有任何aeFileEvent被添加到epoll     
  41.  
  42.      * 事件循環(huán)中進行監(jiān)聽 
  43.  
  44.      */ 
  45.  
  46.     if (eventLoop->maxfd != -1 || 
  47.  
  48.         ((flags & AE_TIME_EVENTS) && !(flags & AE_DONT_WAIT))) { 
  49.  
  50.         int j; 
  51.  
  52.         aeTimeEvent *shortest = NULL
  53.  
  54.         struct timeval tv, *tvp; 
  55.  
  56.   
  57.  
  58.         /** 
  59.  
  60.          * 如果有aeFileEvent需要處理,就先要從所有待處理的 
  61.  
  62.          * aeTimeEvent事件中找到最近的將要被執(zhí)行的aeTimeEvent節(jié)點 
  63.  
  64.          * 并結算該節(jié)點觸發(fā)時間 
  65.  
  66.          */ 
  67.  
  68.         if (flags & AE_TIME_EVENTS && !(flags & AE_DONT_WAIT)) 
  69.  
  70.             shortest = aeSearchNearestTimer(eventLoop); 
  71.  
  72.         if (shortest) { 
  73.  
  74.             long now_sec, now_ms; 
  75.  
  76.   
  77.  
  78.             aeGetTime(&now_sec, &now_ms); 
  79.  
  80.             tvp = &tv; 
  81.  
  82.   
  83.  
  84.             /* How many milliseconds we need to wait for the next 
  85.  
  86.              * time event to fire? */ 
  87.  
  88.             // 計算epoll_wait()需要等待的時間 
  89.  
  90.             long long ms = 
  91.  
  92.                 (shortest->when_sec - now_sec)*1000 + 
  93.  
  94.                 shortest->when_ms - now_ms; 
  95.  
  96.   
  97.  
  98.             if (ms > 0) { 
  99.  
  100.                 tvp->tv_sec = ms/1000; 
  101.  
  102.                 tvp->tv_usec = (ms % 1000)*1000; 
  103.  
  104.             } else { 
  105.  
  106.                 tvp->tv_sec = 0; 
  107.  
  108.                 tvp->tv_usec = 0; 
  109.  
  110.             } 
  111.  
  112.         } else { 
  113.  
  114.             // 如果flags設置了AE_DONT_WAIT,則設置epoll_wait()等待時間為0, 
  115.  
  116.             // 即立刻從epoll中返回 
  117.  
  118.             if (flags & AE_DONT_WAIT) { 
  119.  
  120.                 tv.tv_sec = tv.tv_usec = 0; 
  121.  
  122.                 tvp = &tv; 
  123.  
  124.             } else { 
  125.  
  126.                 /* Otherwise we can block */ 
  127.  
  128.                 tvp = NULL; /* wait forever */ 
  129.  
  130.             } 
  131.  
  132.         } 
  133.  
  134.   
  135.  
  136.         // 調用aeApiPoll()進行阻塞等待事件的到來,等待時間為tvp 
  137.  
  138.         numevents = aeApiPoll(eventLoop, tvp); 
  139.  
  140.         for (j = 0; j < numevents; j++) { 
  141.  
  142.             aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd]; 
  143.  
  144.             int mask = eventLoop->fired[j].mask; 
  145.  
  146.             int fd = eventLoop->fired[j].fd; 
  147.  
  148.             int rfired = 0; 
  149.  
  150.             /* note the fe->mask & mask & ... code: maybe an already processed 
  151.  
  152.              * event removed an element that fired and we still didn't 
  153.  
  154.              * processed, so we check if the event is still valid. */ 
  155.  
  156.             // fe->mask && mask 的目的是確保對應事件時候還有效 
  157.  
  158.             if (fe->mask & mask & AE_READABLE) { 
  159.  
  160.                 rfired = 1; 
  161.  
  162.                 fe->rfileProc(eventLoop,fd,fe->clientData,mask); 
  163.  
  164.             } 
  165.  
  166.             if (fe->mask & mask & AE_WRITABLE) { 
  167.  
  168.                 if (!rfired || fe->wfileProc != fe->rfileProc) 
  169.  
  170.                     fe->wfileProc(eventLoop,fd,fe->clientData,mask); 
  171.  
  172.             } 
  173.  
  174.             processed++; 
  175.  
  176.         } 
  177.  
  178.     } 
  179.  
  180.     /* Check time events */ 
  181.  
  182.     if (flags & AE_TIME_EVENTS) 
  183.  
  184.         // 處理aeTimeEvent 
  185.  
  186.         processed += processTimeEvents(eventLoop); 
  187.  
  188.   
  189.  
  190.     return processed; /* return the number of processed file/time events */ 
  191.  
  192.  

該方法的入?yún)lag表示要處理哪些事件,可以取以下幾個值 :

  • AE_ALL_EVENTS:timeEvent和fileEvent都會處理。
  • AE_FILE_EVENTS:只處理fileEvent。
  • AE_TIME_EVENTS:只處理timeEvent。
  • AE_DONT_WAIT:要么立馬返回,要么處理完那些不需要等待的事件之后再立馬返回。

aeProcessEvents()方法會做下面幾件事:

  1. 判斷傳入的flag的值,如果既不包含AE_TIME_EVENTS也不包含AE_FILE_EVENTS則直接返回。
  2. 計算如果有aeFileEvent事件需要進行處理,則先計算epoll_wait()方法需要阻塞等待的時間,計算方式如下:
    • 先從aeTimeEvent事件鏈表中找到最近的需要被觸發(fā)的aeTimeEvent節(jié)點并計算需要被觸發(fā)的時間,該被觸發(fā)時間則為epoll_wait()需要等待的時間。
    • 如果沒有找到最近的aeTimeEvent節(jié)點,表示沒有aeTimeEvent節(jié)點被加入鏈表,則判斷傳入的flags是否包含AE_DONT_WAIT選項,則設置epoll_wait()需要等待時間為0,表示立即返回。
    • 如果沒有設置AE_DONT_WAIT,則設置需要等待時間為NULL,表示epoll_wait()一直阻塞等待知道有fileEvent事件到來。
  3. 調用aeApiPoll()方法阻塞等待事件的到來,阻塞時間為第二步中計算的時間。aeApiPoll()實現(xiàn)見文末:
    • aeApiPoll()會做下面幾件事:
      • 根據(jù)傳入的tvp計算需要阻塞的時間,然后調用epoll_wait()進行阻塞等待。
      • 有事件到來之后先計算對應事件的類型。
      • 把事件發(fā)生的fd以及對應的類型mask拷貝到fired數(shù)組中。
  4. 從aeApiPoll()方法返回之后,所有事件已經(jīng)就緒了的fd以及對應事件的類型mask已經(jīng)保存在eventLoop->fired[]數(shù)組中。依次遍歷fired數(shù)組,根據(jù)mask類型,執(zhí)行對應的frileProc()或者wfileProce()方法。
  5. 如果傳入的flags中有AE_TIME_EVENTS,則調用processTimeEvents()執(zhí)行所有已經(jīng)到時間了的timeEvent。

 

本系列

責任編輯:龐桂玉 來源: 數(shù)據(jù)庫開發(fā)
相關推薦

2015-11-06 13:59:01

JavaScript事件處理

2011-04-25 09:22:44

C#事件

2023-05-31 08:39:04

redis事件驅動

2011-08-11 13:53:45

JavaScript

2011-04-26 08:56:31

C#

2017-04-10 13:30:47

Redis數(shù)據(jù)庫命令

2011-08-02 17:58:09

iPhone開發(fā) 事件

2021-08-16 07:26:42

服務訂閱機制

2017-06-07 14:58:39

Redis源碼學習Redis事務

2020-12-23 07:37:17

瀏覽器HTML DOM0

2009-08-06 13:08:23

ASP.NET控件開發(fā)

2009-08-10 15:26:46

ASP.NET組件編程

2023-02-07 07:25:36

Spring事件驅動

2019-04-19 21:06:23

事件驅動架構VANTIQ

2009-06-22 09:23:18

事件監(jiān)聽器

2025-06-05 08:00:00

Go事件驅動系統(tǒng)編程

2009-06-25 14:05:08

Ajax JSF

2023-07-12 08:30:52

服務架構事件驅動架構

2025-07-09 00:37:30

2009-08-14 18:00:22

C#Windows應用
點贊
收藏

51CTO技術棧公眾號

色哟哟入口国产精品| 一本久久a久久免费精品不卡| 2019国产精品视频| 国产第一页在线播放| 国产成人精品三级高清久久91| 欧美日韩中文一区| 日本五级黄色片| 国产精品久久久久一区二区国产| 国产在线播放一区二区三区| 97涩涩爰在线观看亚洲| 四虎国产成人精品免费一女五男| 日本一区精品视频| 色av成人天堂桃色av| 大片在线观看网站免费收看| 欧美xxx.com| 国产精品资源网| 国产成人福利视频| 国产午夜精品无码一区二区| 日韩久久综合| 精品一区电影国产| 国产成人精品一区二区三区在线观看 | 免费在线观看国产精品| 精品日韩在线| 亚洲精品国产电影| 国产人妖在线观看| 婷婷久久免费视频| 在线视频你懂得一区| 成人在线播放网址| 黄色一级片在线观看| 久久久久久毛片| 国产三区精品| 精品人妻久久久久一区二区三区| 日韩av一级片| 欧美一区二三区| 国内免费精品视频| 欧美午夜一区| 久久国产视频网站| 国产精品视频看看| 色综合蜜月久久综合网| 亚洲免费视频网站| 青青草视频网站| 亚洲视频一起| 欧美va亚洲va在线观看蝴蝶网| 羞羞的视频在线| 国内欧美日韩| 欧美日韩在线电影| 亚洲少妇久久久| 欧美日韩视频免费观看| 色综合久久久久网| 成人小视频在线看| 欧美成人黑人| 色婷婷综合久久久| 日韩无套无码精品| 日韩制服一区| 欧美网站一区二区| 天天干天天操天天玩| 国产成人毛片| 欧美精品久久99久久在免费线| 91欧美视频在线| 日韩有码欧美| 日韩欧美国产成人一区二区| 久久黄色一级视频| 九色丨蝌蚪丨成人| 亚洲精品中文字| 欧美激情aaa| 精品美女久久| 日韩最新免费不卡| 欧美老熟妇一区二区三区| 午夜精品婷婷| 97精品视频在线| 久久久久久久久久久影院| 老司机精品视频网站| 国产成人精品电影| 在线观看免费视频a| 国产麻豆精品视频| 国产精品一区二区三区四区五区| 婷婷在线免费视频| 久久毛片高清国产| 在线国产伦理一区| 日皮视频在线观看| 精品日韩中文字幕| 国产wwwxx| 日韩一区二区三区在线看| 亚洲爱爱爱爱爱| 国产aⅴ激情无码久久久无码| 欧美色图激情小说| 欧美猛交ⅹxxx乱大交视频| 国产 欧美 日韩 在线| 久久精品道一区二区三区| 成人福利网站在线观看| 黑人精品一区二区三区| 国产亚洲欧洲一区高清在线观看| 亚洲综合网中心| 黄色污污视频在线观看| 在线观看视频91| 又黄又爽又色的视频| 亚洲丁香日韩| 欧美xxxx综合视频| 中文字幕在线欧美| 国产一区二区三区久久久| 欧美日韩一区二区三| 超碰免费在线播放| 欧美日韩综合视频网址| 黄色片免费网址| 妖精一区二区三区精品视频| 久久亚洲国产精品| 国产高潮久久久| 国产乱色国产精品免费视频| 日本不卡高清视频一区| 亚洲h片在线看| 欧洲一区在线电影| 亚洲天堂av网站| 91精品国产91久久久久久密臀| 69视频在线播放| 国产视频一区二区三| 国产午夜精品福利| 欧美久久久久久久久久久久久 | 色欧美88888久久久久久影院| 一级做a爱视频| 欧美裸体在线版观看完整版| 97人人做人人爱| 亚洲成人中文字幕在线| 国产精品福利一区二区三区| 少妇性饥渴无码a区免费| 日韩中文字幕无砖| yellow中文字幕久久| 黄色污污网站在线观看| 成人丝袜18视频在线观看| 天天综合五月天| 精品九九久久| 一本一本久久a久久精品牛牛影视| 四虎永久在线精品| 国产电影精品久久禁18| 久久av喷吹av高潮av| 日韩av黄色| 亚洲日本成人网| 亚洲av中文无码乱人伦在线视色| 不卡av在线网| 日韩伦理在线免费观看| 成人三级毛片| 久久久久久久国产| 国产 欧美 自拍| 亚洲影院久久精品| 丰满少妇xbxb毛片日本| 激情丁香综合| 国产精品我不卡| 9765激情中文在线| 亚洲国产精品成人一区二区| 五月天婷婷网站| kk眼镜猥琐国模调教系列一区二区 | 在线看黄色的网站| 亚洲三级免费| 久久亚洲一区二区| 全亚洲第一av番号网站| 亚洲香蕉成人av网站在线观看| 精品人妻无码一区二区性色 | 青青草自拍偷拍| 免费看黄色91| 中国人体摄影一区二区三区| 亚洲欧美一级| 欧美黄色片免费观看| 欧美 日韩 国产 在线| 五月婷婷久久丁香| 性欧美13一14内谢| 日本视频在线一区| 一区二区三区不卡在线| 国产视频一区二| 欧美激情一区二区三区在线视频观看 | 精品网站999| 欧美激情免费在线| 日本五码在线| 欧美性猛片aaaaaaa做受| 国产人与禽zoz0性伦| 国产成人精品免费| 116极品美女午夜一级| 成人高清电影网站| 91久久国产精品91久久性色| 欧美bbbxxxxx| 亚洲午夜av久久乱码| av加勒比在线| 欧美日韩综合视频| 91香蕉视频在线播放| 不卡一区二区三区四区| 看欧美ab黄色大片视频免费| 影音先锋成人在线电影| 精品一区二区不卡| 2019中文亚洲字幕| 97视频在线观看网址| porn亚洲| 亚洲第一精品夜夜躁人人躁| 日韩 国产 欧美| 亚洲免费观看高清完整版在线 | 亚洲黄色小说网| 色视频成人在线观看免| 69xx绿帽三人行| 久久久久国产精品麻豆| www.四虎精品| 九一九一国产精品| 成年人观看网站| 欧美成人中文| 婷婷精品国产一区二区三区日韩| 国产午夜亚洲精品一级在线| 国产suv精品一区二区| 最新国产在线拍揄自揄视频| 亚洲深夜福利网站| 狠狠综合久久av一区二区| 欧美日韩在线三区| 91在线视频在线观看| 亚洲综合色成人| 日韩一区二区三区四区视频| 91色|porny| 国产精品99精品无码视亚| 麻豆中文一区二区| 国产日韩一区二区在线| 在线成人国产| 蜜臀av性久久久久蜜臀av| 精品国产乱码久久久久久蜜坠欲下| 成人免费视频观看视频| 91麻豆精品国产综合久久久| 国产精品9999| gay欧美网站| 国产69精品久久久久99| av网址在线看| 久久精品电影网| 成年人在线观看| 亚洲人成网在线播放| 水莓100在线视频| 亚洲第一在线视频| 蜜臀久久99精品久久久| 欧美不卡视频一区| 99国产揄拍国产精品| 欧美欧美午夜aⅴ在线观看| 99精品人妻国产毛片| 欧美视频在线看| 久久精品一二区| 精品美女永久免费视频| 日本熟妇乱子伦xxxx| 亚洲亚洲人成综合网络| 国产亚洲第一页| 洋洋成人永久网站入口| 国产精品30p| 午夜精品福利视频网站| www.av麻豆| 狠狠干狠狠久久| 亚洲国产成人精品女人久久| 色综合久久综合网欧美综合网| 五月天激情国产综合婷婷婷| 福利一区福利二区微拍刺激| 激情视频网站在线观看| 在线一区二区三区四区五区 | 欧美精品一区在线发布| 一区二区美女| 日韩高清专区| 色琪琪久久se色| japanese在线视频| 正在播放日韩欧美一页| 六月婷婷激情综合| 99精品视频免费| 久久精品午夜福利| 麻豆一区二区99久久久久| 亚洲天堂国产视频| 国产成人在线视频网址| 国产白袜脚足j棉袜在线观看| 9i在线看片成人免费| 精品久久久久久中文字幕人妻最新| 91麻豆swag| 欧美激情视频二区| 亚洲乱码国产乱码精品精的特点| 久久精品黄色片| 天天综合天天做天天综合| 欧美男人亚洲天堂| 欧美精品在线观看播放| 亚洲成人一二三区| 国产午夜精品视频免费不卡69堂| 在线观看国产原创自拍视频| 欧美另类老女人| 爱啪啪综合导航| 国产mv久久久| 欧美影院在线| 欧美日韩综合另类| 一本精品一区二区三区| 免费无码不卡视频在线观看| 秋霞电影网一区二区| 国偷自产av一区二区三区麻豆| 99国产精品视频免费观看| 亚洲色图日韩精品| 天天色 色综合| 国产精品乱码一区二区| 日韩视频一区二区| 国产三区四区在线观看| 欧美黑人性猛交| 99久久伊人| 国产精品国产精品国产专区蜜臀ah| 久久不见久久见中文字幕免费| 自拍另类欧美| 每日更新成人在线视频| 手机在线播放av| 国产无遮挡一区二区三区毛片日本| 欧美成人精品一区二区免费看片| 狠狠久久亚洲欧美专区| 国产成人精品白浆久久69| 国产香蕉一区二区三区在线视频 | 精品视频二区| 欧美大片在线看| 青草综合视频| 欧美日韩在线精品| 激情久久久久久久| 亚洲第一天堂久久| 国产婷婷色一区二区三区四区| 国产精品日日夜夜| 制服.丝袜.亚洲.另类.中文| 国产在线观看网站| 97碰碰碰免费色视频| 欧美成人精品午夜一区二区| 日韩欧美三级电影| 夜夜嗨网站十八久久| 少妇性l交大片7724com| 国产精品三级电影| 中文字幕精品视频在线观看| 亚洲精品一区二区精华| 最新超碰在线| 95av在线视频| 97在线精品| 亚欧激情乱码久久久久久久久| 久久一区二区三区四区| 国产一卡二卡在线| 欧美成人一区二区三区片免费| 免费观看成人高潮| 国产一区私人高清影院| 精品国产91| 国内外免费激情视频| 91免费观看视频| 黄色一级片免费看| 亚洲国产成人精品电影| 超碰在线公开| 久久精品99| 日韩视频免费| 精品无码国产一区二区三区51安| 亚洲高清在线精品| 色呦呦中文字幕| 韩剧1988在线观看免费完整版| 99re热精品视频| 国产玉足脚交久久欧美| 成人免费毛片app| 日本一区二区不卡在线| 亚洲国语精品自产拍在线观看| 国产污视频在线播放| 精品视频高清无人区区二区三区| 日韩亚洲在线| 亚洲永久无码7777kkk| 日韩欧美成人网| 国产高清自拍视频在线观看| 国产精品热视频| 久久久国产精品| 国产精品久久久久野外| 亚洲国产精品久久人人爱蜜臀| 免费看黄网站在线观看| 欧美一区二三区| 俺要去色综合狠狠| 国产美女视频免费看| 亚洲美女少妇撒尿| 日韩永久免费视频| 国产成人精品在线| 久久社区一区| 日本少妇激三级做爰在线| 亚洲国产精品尤物yw在线观看| 无码精品在线观看| 国产精品69av| 五月天综合网站| 国产a级黄色片| 色妹子一区二区| v片在线观看| 极品尤物一区二区三区| 视频一区在线视频| 欧美手机在线观看| 亚洲国产精品字幕| 欧美色片在线观看| 久久免费一级片| www.精品在线| 国产精品影视在线观看| 日韩一本精品| 亚洲视频三区| 91干在线观看| а√中文在线资源库| 97se亚洲国产综合在线| 视频一区视频二区视频三区高| 最近在线中文字幕| 亚洲午夜精品久久久久久性色 | 在线日韩欧美| 中文字幕日韩专区| 亚洲国产第一区| 性xxxx欧美老肥妇牲乱| 日韩亚洲精品电影| 极品久久久久久| 爽好久久久欧美精品| 国产精欧美一区二区三区| 97成人免费视频| 极品美女销魂一区二区三区| 91欧美精品成人综合在线观看| 日本黄视频在线观看|