亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB服務 > 正文

nginx HTTP處理流程的淺析

2020-03-22 16:24:53
字體:
來源:轉載
供稿:網友
本篇文章給大家帶來的內容是關于nginx HTTP處理流程的淺析,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

1.初始化服務器

server指令用于配置virtual server,我們通常會在一臺機器配置多個virtual server,監聽不同端口號,映射到不同文件目錄;nginx解析用戶配置,在所有端口創建socket并啟動監聽。

nginx解析配置文件是由各個模塊分擔處理的,每個模塊注冊并處理自己關心的配置,通過模塊結構體ngx_module_t的字段ngx_command_t *commands實現;

例如ngx_http_module是一個核心模塊,其commands字段定義如下:

struct ngx_command_s { ngx_str_t name; ngx_uint_t type; char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);html' target='_blank'>static ngx_command_t ngx_http_commands[] = { { ngx_string( http ), NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_http_block,};

name指令名稱,解析配置文件時按照名稱能匹配查找;

type指令類型,NGX_CONF_NOARGS該配置無參數,NGX_CONF_BLOCK該配置是一個配置塊,NGX_MAIN_CONF表示配置可以出現在哪些位(NGX_MAIN_CONF、NGX_HTTP_SRV_CONF、NGX_HTTP_LOC_CONF);

set指令處理函數指針;

可以看到解析http指令的處理函數為ngx_http_block,實現如下:

static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) //解析main配置 //解析server配置 //解析location配置 //初始化HTTP處理流程所需的handler //初始化listening if (ngx_http_optimize_servers(cf, cmcf, cmcf- ports) != NGX_OK) { return NGX_CONF_ERROR;}

ngx_http_optimize_servers方法循環所有配置端口,創建ngx_listening_t對象,并將其添加到conf- cycle- listening(后續操作會遍歷此數組,創建socket并監聽)。方法主要操作如下圖:

625472880-5bc55805f2035_articlex.png

注意到這里設置了ngx_listening_t的handler為ngx_http_init_connection,當接收到socket連接請求時,會調用此handler處理。

那么什么時候啟動監聽呢?全局搜索關鍵字cycle- listening可以找到。main方法會調用ngx_init_cycle,其完成了服務器初始化的大部分工作,其中就包括啟動監聽(ngx_open_listening_sockets)。

假設nginx使用epoll處理所有socket事件,什么時候將監聽事件添加到epoll呢?全局搜索關鍵字cycle- listening可以找到。ngx_event_core_module模塊是事件處理核心模塊,初始化此模塊時會執行ngx_event_process_init函數,其中將監聽事件添加到epoll。

static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) ls = cycle- listening.elts; for (i = 0; i cycle- listening.nelts; i++) { //設置讀事件處理handler rev- handler = ngx_event_accept; ngx_add_event(rev, NGX_READ_EVENT, 0);}

注意到接收到客戶端socket連接請求事件的處理函數是ngx_event_accept。

2.HTTP請求解析

2.1 基礎結構體

結構體ngx_connection_t存儲socket連接相關信息;nginx預先創建若干個ngx_connection_t對象,存儲在全局變量ngx_cycle- free_connections,稱之為連接池;當新生成socket時,會嘗試從連接池中獲取空閑connection連接,如果獲取失敗,則會直接關閉此socket。

指令worker_connections用于配置連接池最大連接數目,配置在events指令塊中,由ngx_event_core_module解析。

vents { use epoll; worker_connections 60000;}

當nginx作為HTTP服務器時,最大客戶端數目maxClient=worker_processesworker_connections/2;當nginx作為反向代理服務器時,最大客戶端數目maxClient=worker_processesworker_connections/4。其worker_processes為用戶配置的worker進程數目。

結構體ngx_connection_t定義如下:

struct ngx_connection_s { //空閑連接池中,data指向下一個連接,形成鏈表;取出來使用時,data指向請求結構體ngx_http_request_s void *data; //讀寫事件結構體,兩個關鍵字段:handler處理函數、timer定時器 ngx_event_t *read; ngx_event_t *write; ngx_socket_t fd; //socket fd ngx_recv_pt recv; //socket接收數據函數指針 ngx_send_pt send; //socket發送數據函數指針 ngx_buf_t *buffer; //輸入緩沖區 struct sockaddr *sockaddr; //客戶端地址 socklen_t socklen; ngx_listening_t *listening; //監聽的ngx_listening_t對象 struct sockaddr *local_sockaddr; //本地地址 socklen_t local_socklen; …………}

結構體ngx_http_request_t存儲整個HTTP請求處理流程所需的所有信息,字段非常多,這里只進行簡要說明:

struct ngx_http_request_s { ngx_connection_t *connection; //讀寫事件處理handler ngx_http_event_handler_pt read_event_handler; ngx_http_event_handler_pt write_event_handler; //請求頭緩沖區 ngx_buf_t *header_in; //解析后的請求頭 ngx_http_headers_in_t headers_in; //請求體結構體 ngx_http_request_body_t *request_body; //請求行 ngx_str_t request_line; //解析后請求行若干字段 ngx_uint_t method; ngx_uint_t http_version; ngx_str_t uri; ngx_str_t args; …………}

請求行與請求體解析相對比較簡單,這里重點講述請求頭的解析,解析后的請求頭信息都存儲在ngx_http_headers_in_t結構體中。

ngx_http_request.c文件中定義了所有的HTTP頭部,存儲在ngx_http_headers_in數組,數組的每個元素是一個ngx_http_header_t結構體,主要包含三個字段,頭部名稱、頭部解析后字段存儲在ngx_http_headers_in_t的偏移量,解析頭部的處理函數。

ngx_http_header_t ngx_http_headers_in[] = { { ngx_string( Host ), offsetof(ngx_http_headers_in_t, host), ngx_http_process_host }, { ngx_string( Connection ), offsetof(ngx_http_headers_in_t, connection), ngx_http_process_connection }, …………typedef struct { ngx_str_t name; ngx_uint_t offset; ngx_http_header_handler_pt handler;} ngx_http_header_t;

解析請求頭時,從ngx_http_headers_in數組中查找請求頭ngx_http_header_t對象,調用處理函數handler,存儲到r- headers_in對應字段。以解析Connection頭部為例,ngx_http_process_connection實現如下:

static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) if (ngx_strcasestrn(h- value.data, close , 5 - 1)) { r- headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; } else if (ngx_strcasestrn(h- value.data, keep-alive , 10 - 1)) { r- headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE; return NGX_OK;}

輸入參數offset在此處并沒有什么作用。注意到第二個輸入參數ngx_table_elt_t,存儲了當前請求頭的鍵值對信息:

typedef struct { ngx_uint_t hash; //請求頭key的hash值 ngx_str_t key; ngx_str_t value; u_char *lowcase_key; //請求頭key轉為小寫字符串(可以看到HTTP請求頭解析時key不區分大小寫)} ngx_table_elt_t;

再思考一個問題,從ngx_http_headers_in數組中查找請求頭對應ngx_http_header_t對象時,需要遍歷,每個元素都需要進行字符串比較,效率低下。因此nginx將ngx_http_headers_in數組轉換為哈希表,哈希表的鍵即為請求頭的key,方法ngx_http_init_headers_in_hash實現了數組到哈希表的轉換,轉換后的哈希表存儲在cmcf- headers_in_hash字段。

827829181-5bc5588653a0d_articlex.png

2.2 解析HTTP請求

第1節提到,在創建socket啟動監聽時,會添加可讀事件到epoll,事件處理函數為ngx_event_accept,用于接收socket連接,分配connection連接,并調用ngx_listening_t對象的處理函數(ngx_http_init_connection)。

void ngx_event_accept(ngx_event_t *ev) s = accept4(lc- fd, (struct sockaddr *) sa, socklen, SOCK_NONBLOCK); //客戶端socket連接成功時,都需要分配connection連接,如果分配失敗則會直接關閉此socket。 //而每個worker進程連接池的最大連接數目是固定的,當不存在空閑連接時,此worker進程accept的所有socket都會被拒絕; //多個worker進程通過競爭執行epoll_wait;而當ngx_accept_disabled大于0時,會直接放棄此次競爭,同時ngx_accept_disabled減1。 //以此實現,當worker進程的空閑連接過少時,減少其競爭epoll_wait次數 ngx_accept_disabled = ngx_cycle- connection_n / 8 - ngx_cycle- free_connection_n; c = ngx_get_connection(s, ev- log); ls- handler(c);}

socket連接成功后,nginx會等待客戶端發送HTTP請求,默認會有60秒的超時時間,即60秒內沒有接收到客戶端請求時,斷開此連接,打印錯誤日志。函數ngx_http_init_connection用于設置讀事件處理函數,以及超時定時器。

void ngx_http_init_connection(ngx_connection_t *c) c- read = ngx_http_wait_request_handler; c- write- handler = ngx_http_empty_handler; ngx_add_timer(rev, c- listening- post_accept_timeout);}

全局搜索post_accept_timeout字段,可以查找到設置此超時時間的配置指令,client_header_timeout,其可以在http、server指令塊中配置。

函數ngx_http_wait_request_handler為解析HTTP請求的入口函數,實現如下:

static void ngx_http_wait_request_handler(ngx_event_t *rev) //讀事件已經超時 if (rev- timedout) { ngx_log_error(NGX_LOG_INFO, c- log, NGX_ETIMEDOUT, client timed out  ngx_http_close_connection(c); return; size = cscf- client_header_buffer_size; //client_header_buffer_size指令用于配置接收請求頭緩沖區大小 b = c- buffer; n = c- recv(c, b- last, size); //創建請求對象ngx_http_request_t,HTTP請求整個處理過程都有用; c- data = ngx_http_create_request(c); rev- handler = ngx_http_process_request_line; //設置讀事件處理函數(此次請求行可能沒有讀取完) ngx_http_process_request_line(rev);}

函數ngx_http_create_request創建并初始化ngx_http_request_t對象,注意這賦值語句r- header_in =c- buffer。

解析請求行與請求頭的代碼較為繁瑣,終點在于讀取socket數據,解析字符串,這里不做詳述。HTTP請求解析過程主要函數調用如下圖所示:

3000860485-5bc55954dbd75_articlex.png

注意,解析完成請求行與請求頭,nginx就開始處理HTTP請求,并沒有等到解析完請求體再處理。處理請求入口為ngx_http_process_request。

3.處理HTTP請求

3.1 HTTP請求處理的11個階段

nginx將HTTP請求處理流程分為11個階段,絕大多數HTTP模塊都會將自己的handler添加到某個階段(將handler添加到全局唯一的數組phases中),注意其中有4個階段不能添加自定義handler,nginx處理HTTP請求時會挨個調用每個階段的handler;

typedef enum { NGX_HTTP_POST_READ_PHASE = 0, //第一個階段,目前只有realip模塊會注冊handler,但是該模塊默認不會運行(nginx作為代理服務器時有用,后端以此獲取客戶端原始ip) NGX_HTTP_SERVER_REWRITE_PHASE, //server塊中配置了rewrite指令,重寫url NGX_HTTP_FIND_CONFIG_PHASE, //查找匹配的location配置;不能自定義handler; NGX_HTTP_REWRITE_PHASE, //location塊中配置了rewrite指令,重寫url NGX_HTTP_POST_REWRITE_PHASE, //檢查是否發生了url重寫,如果有,重新回到FIND_CONFIG階段;不能自定義handler; NGX_HTTP_PREACCESS_PHASE, //訪問控制,比如限流模塊會注冊handler到此階段 NGX_HTTP_ACCESS_PHASE, //訪問權限控制,比如基于ip黑白名單的權限控制,基于用戶名密碼的權限控制等 NGX_HTTP_POST_ACCESS_PHASE, //根據訪問權限控制階段做相應處理;不能自定義handler; NGX_HTTP_TRY_FILES_PHASE, //只有配置了try_files指令,才會有此階段;不能自定義handler; NGX_HTTP_CONTENT_PHASE, //內容產生階段,返回響應給客戶端 NGX_HTTP_LOG_PHASE //日志記錄} ngx_http_phases;

nginx使用結構體ngx_module_s表示一個模塊,其中字段ctx,是一個指向模塊上下文結構體的指針(上下文結構體的字段都是一些函數指針);nginx的HTTP模塊上下文結構體大多都有字段postconfiguration,負責注冊本模塊的handler到某個處理階段。11個階段在解析完成http配置塊指令后初始化。

static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) //解析http配置塊 //初始化11個階段的phases數組,注意多個模塊可能注冊到同一個階段,因此phases是一個二維數組 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR; //遍歷索引HTTP模塊,注冊handler for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]- type != NGX_HTTP_MODULE) { continue; module = ngx_modules[m]-  if (module- postconfiguration) { if (module- postconfiguration(cf) != NGX_OK) { return NGX_CONF_ERROR; //將二維數組轉換為一維數組,從而遍歷執行數組所有handler if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) { return NGX_CONF_ERROR;}

以限流模塊ngx_http_limit_req_module模塊為例,postconfiguration方法簡單實現如下:

static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf) h = ngx_array_push( cmcf- phases[NGX_HTTP_PREACCESS_PHASE].handlers); *h = ngx_http_limit_req_handler; //ngx_http_limit_req_module模塊的限流方法;nginx處理HTTP請求時,都會調用此方法判斷應該繼續執行還是拒絕請求 return NGX_OK;}

GDB調試,斷點到ngx_http_block方法執行所有HTTP模塊注冊handler之后,打印phases數組

p cmcf- phases[*].handlersp *(ngx_http_handler_pt*)cmcf- phases[*].handlers.elts

11個階段注冊的handler如下圖所示:

1853153573-5bc559b613ab8_articlex.png

3.2 11個階段初始化

上面提到HTTP的11個處理階段handler存儲在phases數組,但由于多個模塊可能注冊handler到同一個階段,使得phases是一個二維數組,因此需要轉換為一維數組,轉換后存儲在cmcf- phase_engine字段,phase_engine的類型為ngx_http_phase_engine_t,定義如下:

typedef struct { ngx_http_phase_handler_t *handlers; //一維數組,存儲所有handler ngx_uint_t server_rewrite_index; //記錄NGX_HTTP_SERVER_REWRITE_PHASE階段handler的索引值 ngx_uint_t location_rewrite_index; //記錄NGX_HTTP_REWRITE_PHASE階段handler的索引值} ngx_http_phase_engine_t;struct ngx_http_phase_handler_t { ngx_http_phase_handler_pt checker; //執行handler之前的校驗函數 ngx_http_handler_pt handler; ngx_uint_t next; //下一個待執行handler的索引(通過next實現handler跳轉執行)//cheker函數指針類型定義typedef ngx_int_t (*ngx_http_phase_handler_pt)(ngx_http_request_t *r, ngx_http_phase_handler_t *ph);//handler函數指針類型定義typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);

數組轉換函數ngx_http_init_phase_handlers實現如下:

static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) use_rewrite = cmcf- phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; use_access = cmcf- phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0; n = use_rewrite + use_access + cmcf- try_files + 1 /* find config phase */; //至少有4個階段,這4個階段是上面說的不能注冊handler的4個階段 //計算handler數目,分配空間 for (i = 0; i NGX_HTTP_LOG_PHASE; i++) { n += cmcf- phases[i].handlers.nelts; ph = ngx_pcalloc(cf- pool, n * sizeof(ngx_http_phase_handler_t) + sizeof(void *)); //遍歷二維數組 for (i = 0; i NGX_HTTP_LOG_PHASE; i++) { h = cmcf- phases[i].handlers.elts; switch (i) { case NGX_HTTP_SERVER_REWRITE_PHASE: if (cmcf- phase_engine.server_rewrite_index == (ngx_uint_t) -1) { cmcf- phase_engine.server_rewrite_index = n; //記錄NGX_HTTP_SERVER_REWRITE_PHASE階段handler的索引值 checker = ngx_http_core_rewrite_phase; break; case NGX_HTTP_FIND_CONFIG_PHASE: find_config_index = n; //記錄NGX_HTTP_FIND_CONFIG_PHASE階段的索引,NGX_HTTP_POST_REWRITE_PHASE階段可能會跳轉回此階段 ph- checker = ngx_http_core_find_config_phase; n++; ph++; continue; //進入下一個階段NGX_HTTP_REWRITE_PHASE case NGX_HTTP_REWRITE_PHASE: if (cmcf- phase_engine.location_rewrite_index == (ngx_uint_t) -1) { cmcf- phase_engine.location_rewrite_index = n; //記錄NGX_HTTP_REWRITE_PHASE階段handler的索引值 checker = ngx_http_core_rewrite_phase;  break; case NGX_HTTP_POST_REWRITE_PHASE: if (use_rewrite) { ph- checker = ngx_http_core_post_rewrite_phase; ph- next = find_config_index; n++; ph++; continue; //進入下一個階段NGX_HTTP_ACCESS_PHASE case NGX_HTTP_ACCESS_PHASE: checker = ngx_http_core_access_phase; n++; break; case NGX_HTTP_POST_ACCESS_PHASE: if (use_access) { ph- checker = ngx_http_core_post_access_phase; ph- next = n; ph++; continue; //進入下一個階段 case NGX_HTTP_TRY_FILES_PHASE: if (cmcf- try_files) { ph- checker = ngx_http_core_try_files_phase; n++; ph++; continue; case NGX_HTTP_CONTENT_PHASE: checker = ngx_http_core_content_phase; break; default: checker = ngx_http_core_generic_phase; //n為下一個階段第一個handler的索引 n += cmcf- phases[i].handlers.nelts; //遍歷當前階段的所有handler for (j = cmcf- phases[i].handlers.nelts - 1; j j--) { ph- checker = checker; ph- handler = h[j]; ph- next = n; ph++;}

GDB打印出轉換后的數組如下圖所示,第一列是cheker字段,第二列是handler字段,箭頭表示next跳轉;圖中有個返回的箭頭,即NGX_HTTP_POST_REWRITE_PHASE階段可能返回到NGX_HTTP_FIND_CONFIG_PHASE;原因在于只要NGX_HTTP_REWRITE_PHASE階段產生了url重寫,就需要重新查找匹配location。

2115972663-5bc55a0499017_articlex.png

3.3 處理HTTP請求

2.2節提到HTTP請求的處理入口函數是ngx_http_process_request,其主要調用ngx_http_core_run_phases實現11個階段的執行流程;

ngx_http_core_run_phases遍歷預先設置好的cmcf- phase_engine.handlers數組,調用其checker函數,邏輯如下:

void ngx_http_core_run_phases(ngx_http_request_t *r) ph = cmcf- phase_engine.handlers; //phase_handler初始為0,表示待處理handler的索引;cheker內部會根據ph- next字段修改phase_handler while (ph[r- phase_handler].checker) { rc = ph[r- phase_handler].checker(r, ph[r- phase_handler]); if (rc == NGX_OK) { return;}

checker內部就是調用handler,并設置下一步要執行handler的索引;比如說ngx_http_core_generic_phase實現如下:

ngx_int_t ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r- connection- log, 0, rewrite phase: %ui , r- phase_handler); rc = ph- handler(r); if (rc == NGX_OK) { r- phase_handler = ph- next; return NGX_AGAIN;}

3.4 內容產生階段

內容產生階段NGX_HTTP_CONTENT_PHASE是HTTP請求處理的第10個階段,一般情況有3個模塊注冊handler到此階段:ngx_http_static_module、ngx_http_autoindex_module和ngx_http_index_module。

但是當我們配置了proxy_pass和fastcgi_pass時,情況會有所不同;

使用proxy_pass配置上游時,ngx_http_proxy_module模塊會設置其處理函數到配置類conf;使用fastcgi_pass配置時,ngx_http_fastcgi_module會設置其處理函數到配置類conf。例如:

static char * ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf- handler = ngx_http_fastcgi_handler;}

階段NGX_HTTP_FIND_CONFIG_PHASE查找匹配的location,并獲取此ngx_http_core_loc_conf_t對象,將其handler賦值給ngx_http_request_t對象的content_handler字段(內容產生處理函數)。

而在執行內容產生階段的checker函數時,會執行content_handler指向的函數;查看ngx_http_core_content_phase函數實現(內容產生階段的checker函數):

ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) if (r- content_handler) { //如果請求對象的content_handler字段不為空,則調用 r- write_event_handler = ngx_http_request_empty_handler; ngx_http_finalize_request(r, r- content_handler(r)); return NGX_OK; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r- connection- log, 0, content phase: %ui , r- phase_handler); rc = ph- handler(r); //否則執行內容產生階段handler}

總結

nginx處理HTTP請求的流程較為復雜,因此本文只是簡單提供了一條線索:分析了nginx服務器啟動監聽的過程,HTTP請求的解析過程,11個階段的初始化與調用過程。至于HTTP解析處理的詳細流程,還需要讀者去探索。

以上就是nginx HTTP處理流程的淺析的詳細內容,PHP教程

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩最新在线视频| 性欧美长视频免费观看不卡| 国产精品久久不能| 日韩精品视频在线播放| 国产成人自拍视频在线观看| 国产精品稀缺呦系列在线| 精品视频9999| 日韩成人av网址| 欧美日韩色婷婷| 色偷偷av一区二区三区乱| 91精品久久久久久久久久另类| 青青久久aⅴ北条麻妃| 91精品在线播放| 欧美华人在线视频| 久久视频这里只有精品| 深夜福利亚洲导航| 国产精品久久一区主播| 欧美日本中文字幕| 欧美在线视频a| 国产精品麻豆va在线播放| 伊人精品在线观看| 欧美在线观看网址综合| 国产成人精品电影久久久| 亚洲综合中文字幕在线观看| 色无极亚洲影院| 俺去啦;欧美日韩| 91久久综合亚洲鲁鲁五月天| 日韩成人在线观看| 中文欧美在线视频| 日韩在线观看网站| 欧美视频中文在线看| 九色精品美女在线| 国产福利精品av综合导导航| 日韩一区二区三区国产| 91探花福利精品国产自产在线| 欧美在线日韩在线| 久久精品中文字幕一区| 黄色成人在线播放| 成人黄色av播放免费| www.99久久热国产日韩欧美.com| 日韩久久免费电影| 欧美成人高清视频| 国产精品mp4| 日韩中文字幕在线免费观看| 91wwwcom在线观看| 国产一区欧美二区三区| 国产精品欧美日韩| 亚洲福利视频网| 亚洲最大在线视频| 成人精品在线视频| 国产精品福利观看| 久久久精品国产一区二区| 国产在线观看一区二区三区| 午夜精品久久久久久久男人的天堂| 亚洲а∨天堂久久精品9966| 成人h片在线播放免费网站| 亚洲成**性毛茸茸| 成人久久久久久久| 在线看欧美日韩| 亚洲视频电影图片偷拍一区| 国产精品直播网红| 最近2019中文字幕mv免费看| 国产精品精品久久久| 国产精品视频一区二区三区四| 亚洲夜晚福利在线观看| 欧美一级在线亚洲天堂| 中文字幕在线视频日韩| 色噜噜狠狠色综合网图区| 91香蕉亚洲精品| 国产精品久久77777| 欧美一区三区三区高中清蜜桃| 韩国三级电影久久久久久| 亚洲福利视频专区| 久99九色视频在线观看| 亚洲人成五月天| 亚洲美女精品成人在线视频| 久久综合网hezyo| 国产成人jvid在线播放| 久热精品视频在线| 成人激情春色网| 亚洲高清不卡av| 久久人人爽人人爽人人片亚洲| 国产视频观看一区| 久久久久久香蕉网| 国产99久久久欧美黑人| 欧美三级xxx| 最近中文字幕mv在线一区二区三区四区| 久久天天躁日日躁| 欧美又大粗又爽又黄大片视频| 日本高清视频一区| 亚洲iv一区二区三区| 亚洲欧美一区二区激情| 欧洲亚洲免费视频| 97精品国产97久久久久久免费| 日韩精品中文字幕在线观看| 国产精品最新在线观看| 国产男人精品视频| 成人免费视频在线观看超级碰| 九九久久国产精品| 国产精品激情av电影在线观看| 国产精品久久久亚洲| 欧美在线视频网站| 国产精品久久综合av爱欲tv| 日韩美女毛茸茸| 欧美激情精品久久久久久大尺度| 久久免费视频网| 亚洲成人激情图| 成人有码视频在线播放| 色综久久综合桃花网| 国产精品久久久久久搜索| 亚洲精品欧美一区二区三区| 成人免费福利在线| 欧美做受高潮1| 日韩电影网在线| 久久精品国产99国产精品澳门| 中文字幕最新精品| 国产精品高潮呻吟久久av野狼| 亚洲综合精品伊人久久| 亚洲欧美日韩综合| 欧美激情精品久久久久| 日韩中文字幕视频在线观看| 亚洲成人精品视频| 久久久久久91香蕉国产| 日韩av有码在线| 久久婷婷国产麻豆91天堂| 欧美激情第6页| 日韩激情在线视频| 国模视频一区二区| 国内外成人免费激情在线视频| 丰满岳妇乱一区二区三区| 久久久久五月天| 日韩大片在线观看视频| 亚洲福利视频网站| 欧美综合国产精品久久丁香| 伊人久久男人天堂| 欧美在线免费观看| 国产mv免费观看入口亚洲| 国产精品视频精品视频| 亚洲人成亚洲人成在线观看| 人人澡人人澡人人看欧美| 久久久久久久久久久久久久久久久久av| 欧美成人精品影院| 欧美日韩国产中文字幕| 91精品久久久久久久久久久久久久| 91精品国产综合久久男男| 亚洲欧美国产精品| 亚洲精品成人久久| 日本一区二三区好的精华液| 国产亚洲激情视频在线| 日本一欧美一欧美一亚洲视频| 成人在线国产精品| 精品中文字幕视频| 欧美成人黑人xx视频免费观看| 午夜免费久久久久| 成人久久久久久| 国产999在线观看| 欧美激情a在线| 岛国av一区二区| 性欧美暴力猛交69hd| 国产亚洲精品一区二区| 日韩欧美亚洲一二三区| 亚洲伊人久久大香线蕉av| 国产婷婷色综合av蜜臀av| 国产精品激情av电影在线观看|