成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

驚爆!Spring AI 硬核拆解 MCP 客戶端服務器架構底層邏輯

開發 前端
各位 Javaer 們,今天咱們把 Spring AI 的 MCP 客戶端服務器架構從上到下拆了個遍,從客戶端的請求發起,到服務器端的處理,再到通信層的細節和性能優化,相信你對這個架構已經有了比較深入的理解。

兄弟們,今天咱們要干一票大的 —— 把 Spring AI 里那個神秘的 MCP 客戶端服務器架構從上到下拆個底朝天。放心,咱不玩虛的,全程大白話講解,就跟聊家常似的,保證讓你看得津津有味,還能實實在在學到干貨。咱先說好,看完覺得過癮的話,記得點擊收藏轉發,讓更多小伙伴一起圍觀這場技術拆解秀~

一、先搞懂 MCP 是個啥玩意兒

剛開始聽到 MCP 這個縮寫,是不是跟我第一次一樣,腦瓜子嗡嗡的?啥?MCP?是 "魔法客戶端協議"(Magic Client Protocol)嗎?哈哈,開個玩笑。其實啊,MCP 就是 Multi-Channel Processing Architecture 的縮寫,翻譯成咱們人話,就是多通道處理客戶端服務器架構。這玩意兒在 Spring AI 里可太重要了,就好比是整個系統的 "神經中樞",負責客戶端和服務器之間的通信、數據處理和業務邏輯協調。

你可以把 MCP 想象成一個超級大商場,客戶端就像是來商場購物的顧客,服務器則是商場里的各個店鋪。顧客(客戶端)帶著各種需求(請求)來到商場(MCP 架構),然后商場里的各個店鋪(服務器端的不同模塊)根據顧客的需求提供相應的服務(處理請求并返回結果)。而商場里的通道、指示牌、電梯等設施(MCP 的通信協議、數據傳輸機制等)就負責保證顧客能順利找到店鋪,店鋪也能及時把商品交給顧客。

(一)MCP 的核心設計目標

Spring AI 為啥要搞這么個 MCP 架構呢?主要是為了滿足這幾個核心需求:

  1. 高并發處理能力:現在的 AI 應用,尤其是那些面向大眾的,比如智能客服、AI 推薦系統等,每天都要面對海量的請求。MCP 得能像八爪魚一樣,同時處理成千上萬的請求,不能讓用戶等著。
  2. 靈活的擴展性:隨著業務的發展,功能越來越多,數據量越來越大,MCP 得像搭積木一樣,方便隨時添加新的模塊、新的服務器,而不會影響整個系統的運行。
  3. 可靠的通信機制:客戶端和服務器之間的通信得像打電話一樣穩定,不能說著說著就斷線了,也不能傳錯話。
  4. 高效的數據處理:AI 處理的數據往往都不小,比如圖像、語音數據,MCP 得能快速地傳輸和處理這些數據,不能讓數據在傳輸過程中 "堵車"。

(二)MCP 的整體架構概覽

咱們來看一張簡單的架構圖(雖然這里畫不了圖,但咱用文字描述得明明白白)。整個 MCP 架構分為客戶端層、通信層、服務器層和數據層四個主要部分。

客戶端層:就是咱們開發者調用的各種 API 接口,比如你在代碼里寫的AiClient.sendRequest(),它負責收集用戶的請求信息,轉換成 MCP 能識別的格式,然后交給通信層。

通信層:這是客戶端和服務器之間的 "信使",負責建立連接、傳輸數據、處理網絡異常等。它支持多種通信協議,比如 HTTP/2、gRPC、WebSocket 等,就像一個萬能的快遞員,不管你用啥方式寄包裹,它都能給你送到。

服務器層:是整個架構的核心處理部分,里面有多個處理模塊,比如請求解析模塊、業務邏輯處理模塊、結果生成模塊等。每個模塊各司其職,就像工廠里的流水線工人,一步步處理客戶端發來的請求。

數據層:負責存儲和管理數據,包括原始數據、中間處理數據和最終結果數據。它可能是數據庫、緩存、文件系統等,就像一個巨大的倉庫,隨時為服務器層提供數據支持。

二、客戶端那些事兒:從請求發起說起

客戶端在 MCP 架構里扮演著 "發起者" 的角色,它的主要任務就是把用戶的需求包裝成合適的請求,然后通過通信層發給服務器。別看這事兒聽起來簡單,里面的學問可不少呢。

(一)請求構建:把需求變成 "標準套餐"

用戶的需求是各種各樣的,比如有的要做圖像識別,有的要做自然語言處理,還有的要做數據預測。客戶端得把這些不同的需求轉換成 MCP 規定的 "標準請求格式"。這個過程就好比去快餐店點餐,你可以點漢堡、薯條、可樂,但快餐店得把你的點單轉換成廚房能識別的菜單,比如 "漢堡 1 個,中薯 1 份,可樂 1 杯(冰)"。

在 Spring AI 的客戶端里,每個請求都包含這些關鍵信息:

  • 請求 ID:每個請求都有一個唯一的 ID,就像你的快遞單號,方便后續追蹤和處理。
  • 請求類型:告訴服務器這是一個什么樣的請求,比如是圖像識別請求還是文本分類請求。
  • 數據內容:具體的輸入數據,比如要識別的圖像數據、要分類的文本內容等。
  • 參數配置:一些額外的配置參數,比如圖像識別的精度要求、文本分類的模型版本等。

咱們來看一段簡單的代碼示例(用 Java 寫的哈):

// 創建請求對象
AiRequest request = new AiRequest();
request.setRequestId(UUID.randomUUID().toString());
request.setRequestType("IMAGE_RECOGNITION");
request.setData(ImageUtils.readImageFile("path/to/image.jpg"));
request.addParameter("modelVersion", "v2.0");
request.addParameter("precision", "HIGH");
// 通過客戶端發送請求
AiClient client = new AiClient("server-address");
AiResponse response = client.sendRequest(request);

看到沒,客戶端就是這樣把用戶的需求包裝成一個完整的請求的。

(二)連接管理:和服務器保持 "熱線"

客戶端和服務器之間的連接可不是隨隨便便建立的,得有一套完善的連接管理機制。就像你和朋友打電話,得先撥號建立連接,打完電話再掛斷連接。不過在高并發場景下,頻繁地建立和斷開連接會很耗資源,所以 MCP 客戶端采用了連接池技術。

連接池就像是一個 "電話總機",里面預先建立好多個連接,當客戶端需要發送請求時,直接從連接池里拿一個可用的連接,用完之后再還回去,而不是每次都重新撥號。這樣可以大大提高連接的效率,減少資源消耗。

在 Spring AI 中,客戶端默認使用了 Netty 作為底層的網絡通信框架,Netty 的連接池管理非常強大,支持各種配置,比如最大連接數、連接超時時間、空閑連接檢測等。咱們可以通過配置文件或者代碼來設置這些參數,比如:

ClientConfig config = new ClientConfig();
config.setMaxConnections(100); // 最大連接數
config.setConnectTimeoutMillis(5000); // 連接超時時間5秒
config.setIdleTimeoutMillis(30000); // 空閑連接超時時間30秒
AiClient client = new AiClient("server-address", config);

這樣設置之后,客戶端就能更穩定、高效地和服務器保持通信啦。

(三)請求重試:不怕失敗,再來一次

網絡世界里,啥事兒都可能發生,比如突然斷網了、服務器暫時忙不過來、請求在傳輸過程中丟失了等等。這時候,客戶端得有重試機制,就像你網購時下單失敗,系統會提示你重試一樣。

MCP 客戶端的重試機制可不是簡單地重復發送請求,它有很多策略,比如固定重試次數、指數退避重試(每次重試間隔時間越來越長)、根據錯誤類型重試等。比如,如果是暫時性的網絡錯誤(像超時錯誤),就可以重試幾次;如果是服務器返回的永久性錯誤(像參數錯誤),就沒必要再重試了。

咱們來看一下 Spring AI 中是怎么實現重試機制的。客戶端里有一個RetryPolicy接口,里面定義了各種重試策略的方法,比如shouldRetry方法判斷是否需要重試,getNextDelay方法獲取下次重試的延遲時間。默認實現了FixedRetryPolicy(固定重試次數)和ExponentialBackoffRetryPolicy(指數退避重試)。

// 使用指數退避重試策略,最多重試3次,初始延遲1秒,每次延遲翻倍
RetryPolicy retryPolicy = new ExponentialBackoffRetryPolicy(3, 1000);
AiClient client = new AiClient("server-address");
client.setRetryPolicy(retryPolicy);

有了重試機制,客戶端就能更可靠地和服務器通信啦,減少了因為偶然錯誤導致的請求失敗。

三、服務器端大揭秘:從接收請求到返回結果

服務器端在 MCP 架構里就是那個默默干活的 "幕后英雄",它接收客戶端發來的請求,經過一系列處理,再把結果返回給客戶端。這里面的流程可復雜了,咱們一步一步來拆解。

(一)請求接收:打開大門,迎接客人

服務器端首先得能接收客戶端發來的請求,這就需要監聽特定的端口,就像餐廳門口的迎賓員,時刻等著客人上門。在 MCP 服務器端,同樣基于 Netty 框架來實現網絡通信,Netty 的高性能 IO 處理能力讓它能夠輕松應對大量的并發請求。

服務器啟動的時候,會創建一個ServerBootstrap對象,綁定監聽端口,然后注冊各種處理器來處理不同的事件,比如連接建立事件、數據接收事件、連接斷開事件等。當客戶端發起連接請求時,服務器接受連接,建立通道,然后就可以通過這個通道接收客戶端發來的數據啦。

// 服務器啟動代碼示例
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
     .channel(NioServerSocketChannel.class)
     .option(ChannelOption.SO_BACKLOG, 128)
     .childOption(ChannelOption.SO_KEEPALIVE, true)
     .childHandler(new ChannelInitializer<SocketChannel>() {
         @Override
         public void initChannel(SocketChannel ch) throws Exception {
             ch.pipeline().addLast(new HttpRequestDecoder());
             ch.pipeline().addLast(new HttpResponseEncoder());
             ch.pipeline().addLast(new ServerHandler());
         }
     });
    ChannelFuture f = b.bind(8080).sync();
    System.out.println("服務器啟動,監聽端口8080");
    f.channel().closeFuture().sync();
} finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
}

這里的ServerHandler就是咱們自定義的處理器,負責處理接收到的請求數據。

(二)請求解析:把 "外賣" 拆開看看是啥

服務器接收到的請求數據可能是二進制格式的,也可能是 JSON、Protobuf 等格式的,所以首先得把這些數據解析成服務器能理解的請求對象。這個過程就像你收到外賣后,得打開包裝看看里面是不是你點的漢堡和可樂。

MCP 服務器端支持多種數據序列化和反序列化方式,比如 JSON 序列化(用 Jackson 庫)、Protobuf 序列化(高效的二進制序列化方式)、XML 序列化等。開發者可以根據自己的需求選擇合適的序列化方式。比如,當傳輸的數據量很大、對性能要求很高時,Protobuf 就是一個很好的選擇,因為它的序列化后的數據體積小,解析速度快。

在請求解析過程中,還需要做一些校驗工作,比如檢查請求 ID 是否合法、請求類型是否支持、數據內容是否完整等。如果校驗不通過,就會返回一個錯誤響應給客戶端,就像餐廳服務員發現你的訂單有問題,會及時跟你溝通一樣。

(三)業務邏輯處理:真正的 "炒菜" 環節

解析完請求之后,就該進入真正的業務邏輯處理環節了,這可是服務器端的核心任務。不同的請求類型對應不同的業務處理模塊,比如圖像識別請求會交給圖像識別模塊,文本分類請求會交給自然語言處理模塊。

這些業務處理模塊可能會涉及到復雜的算法、模型推理、數據查詢等操作。比如,在圖像識別模塊中,可能需要加載預訓練好的深度學習模型,對輸入的圖像數據進行預處理、特征提取、模型推理,最后得到識別結果。這個過程就像廚師炒菜,需要準備食材(數據預處理)、使用各種廚具和調料(算法和模型),最后做出美味的菜肴(處理結果)。

在 Spring AI 中,業務處理模塊通常是基于 Spring Boot 的注解來實現的,比如@Service注解標識一個業務服務類,@Autowired注解自動注入依賴的組件。這樣可以讓代碼結構更清晰,易于維護和擴展。

@Service
public class ImageRecognitionService {
    @Autowired
    private ModelLoader modelLoader;
    public RecognitionResult process(ImageData imageData) {
        // 數據預處理
        PreprocessedImage preImage = preprocess(imageData);
        // 加載模型
        DeepLearningModel model = modelLoader.loadModel("image_recognition_model");
        // 模型推理
        InferenceResult inferenceResult = model.infer(preImage);
        // 結果處理
        RecognitionResult result = convertToRecognitionResult(inferenceResult);
        return result;
    }
    private PreprocessedImage preprocess(ImageData imageData) {
        // 預處理邏輯,比如縮放、歸一化等
        return new PreprocessedImage();
    }
    private RecognitionResult convertToRecognitionResult(InferenceResult inferenceResult) {
        // 轉換邏輯
        return new RecognitionResult();
    }
}

(四)結果生成與返回:把 "菜" 端給客人

業務邏輯處理完之后,會得到一個處理結果,服務器需要把這個結果包裝成 MCP 規定的響應格式,然后通過通信層返回給客戶端。響應格式和請求格式類似,也包含響應 ID(和請求 ID 對應)、響應類型、結果數據、狀態碼等信息。

在生成結果時,需要注意數據的序列化方式要和客戶端保持一致,比如客戶端用 Protobuf 發送請求,服務器返回結果時也應該用 Protobuf 序列化,這樣客戶端才能正確解析。另外,還要處理可能出現的異常情況,比如業務處理過程中發生了錯誤,需要返回一個包含錯誤信息的響應,而不是讓客戶端干等著。

返回結果的過程和接收請求的過程類似,通過 Netty 的通道將數據發送出去。服務器端會維護每個客戶端連接的通道信息,確保結果能準確無誤地發送回對應的客戶端。

四、通信層:客戶端和服務器的 "溝通橋梁"

前面咱們說了客戶端和服務器各自的工作,那它們之間是怎么溝通的呢?這就離不開通信層了。通信層就像一條高速公路,讓客戶端和服務器的數據能夠在上面快速、穩定地傳輸。

(一)支持的通信協議

MCP 架構支持多種通信協議,每種協議都有自己的特點和適用場景:

  1. HTTP/2:現在比較流行的協議,支持多路復用(一個連接可以同時處理多個請求和響應)、頭部壓縮(減少數據傳輸量)、服務器推送等功能,適合 RESTful 風格的 API 調用。
  2. gRPC:Google 開發的高性能 RPC 框架,基于 HTTP/2 協議,支持強類型定義(通過 Protobuf 定義接口)、多種編程語言、流處理(支持客戶端流、服務器流和雙向流),適合微服務之間的通信。
  3. WebSocket:全雙工通信協議,允許客戶端和服務器在單個連接上進行雙向通信,適合需要實時交互的場景,比如實時聊天、實時數據推送等。

開發者可以根據自己的業務需求選擇合適的協議,Spring AI 對這些協議都有很好的支持,只需要在配置中簡單設置即可。

(二)數據傳輸安全

在數據傳輸過程中,安全是非常重要的。MCP 通信層支持 SSL/TLS 加密,就像給數據傳輸加上一個 "密碼鎖",確保數據在傳輸過程中不會被竊取或篡改。客戶端和服務器在建立連接時,會進行 SSL 握手,協商加密算法和密鑰,然后用加密后的通道進行數據傳輸。

另外,還可以對數據進行簽名和校驗,比如在請求中添加一個簽名參數,服務器收到請求后驗證簽名是否正確,防止數據被篡改。

(三)網絡異常處理

網絡環境是復雜多變的,可能會出現連接中斷、超時、數據包丟失等異常情況。通信層需要有完善的異常處理機制,比如:

  • 連接中斷重連:當檢測到連接中斷時,自動嘗試重新建立連接,就像你手機斷網后會自動重新連接 Wi-Fi 一樣。
  • 超時處理:設置請求的超時時間,如果服務器在規定時間內沒有返回結果,客戶端就會觸發超時回調,進行重試或者給用戶提示。
  • 流量控制:當網絡流量過大時,進行流量控制,防止網絡堵塞,就像十字路口的紅綠燈,控制車輛的通行速度。

五、性能優化:讓 MCP 跑起來像 "閃電"

對于一個高并發的客戶端服務器架構來說,性能優化是永遠繞不開的話題。MCP 架構在性能優化方面做了很多工作,咱們來看看幾個關鍵的優化點。

(一)線程池管理

無論是客戶端還是服務器端,都大量使用了線程池來管理線程。線程池可以避免頻繁地創建和銷毀線程,減少線程創建的開銷,提高資源利用率。在 Spring AI 中,默認使用了 Java 的ExecutorService來創建線程池,并且可以通過配置參數來設置線程池的大小、隊列類型、拒絕策略等。

比如,服務器端的業務處理模塊可以使用一個獨立的線程池,專門處理請求的業務邏輯,這樣不會阻塞網絡 IO 線程,提高系統的吞吐量。

(二)異步非阻塞 IO

MCP 架構基于 Netty 的異步非阻塞 IO 模型,這是高性能網絡通信的關鍵。異步非阻塞 IO 允許程序在等待 IO 操作完成時,不阻塞當前線程,而是去處理其他任務,就像你在等燒水的時候,可以去做其他事情,而不是傻站在那里等著。

在 Netty 中,每個 IO 操作都會返回一個ChannelFuture對象,通過添加監聽器(FutureListener)來處理 IO 操作的結果,這樣就實現了異步處理。這種方式大大提高了系統的并發處理能力,能夠同時處理成千上萬的連接。

(三)負載均衡

當服務器端有多個實例(比如部署在多個服務器上)時,需要用到負載均衡技術,把客戶端的請求均勻地分配到各個服務器實例上,避免某個服務器過載,就像餐廳里的多個服務員,均勻地接待客人,提高整體服務效率。

MCP 架構支持多種負載均衡策略,比如輪詢策略(Round-Robin)、隨機策略(Random)、最少連接數策略(Least Connections)、權重策略(Weighted)等。開發者可以根據實際情況選擇合適的策略,Spring AI 中默認實現了輪詢策略和最少連接數策略。

(四)緩存機制

對于一些頻繁訪問的數據或結果,可以使用緩存機制,把數據存儲在內存中,避免每次都去數據庫或文件系統中查詢,提高響應速度。比如,服務器端處理完一個請求后,可以把結果緩存起來,當相同的請求再次到來時,直接從緩存中獲取結果,而不需要重新處理。

Spring AI 集成了多種緩存框架,比如 Caffeine、Ehcache、Redis 等,開發者可以根據需求選擇合適的緩存方案。

六、實戰案例:用 MCP 架構實現一個智能客服系統

說了這么多理論知識,咱們來結合一個實戰案例,看看 MCP 架構在實際項目中是怎么應用的。咱們就以一個智能客服系統為例,看看客戶端和服務器端是怎么配合工作的。

(一)客戶端實現

智能客服的客戶端需要收集用戶的輸入信息(比如文本消息),然后發送給服務器端的智能客服處理模塊。客戶端的代碼大致是這樣的:

// 用戶輸入消息
String userMessage = "你好,請問怎么修改密碼?";
// 創建請求
AiRequest request = new AiRequest();
request.setRequestId(UUID.randomUUID().toString());
request.setRequestType("CUSTOMER_SERVICE");
request.setData(userMessage.getBytes());
request.addParameter("language", "zh_CN");
// 發送請求并獲取響應
AiClient client = new AiClient("客服服務器地址");
AiResponse response = client.sendRequest(request);
// 處理響應結果
String serverReply = new String(response.getData());
System.out.println("客服回復:" + serverReply);

(二)服務器端實現

服務器端接收到用戶的消息后,需要進行自然語言理解(NLU),識別用戶的意圖(比如 "修改密碼"),然后根據意圖調用相應的處理邏輯(比如返回修改密碼的步驟),最后把結果返回給客戶端。服務器端的處理流程大致如下:

  1. 請求接收與解析:通過 Netty 監聽端口,接收客戶端發來的請求,解析出用戶消息和參數。
  2. 意圖識別:使用自然語言處理模型(比如 Rasa、Dialogflow)對用戶消息進行意圖識別,確定用戶想做什么。
  3. 對話管理:維護對話的上下文,比如用戶之前問了什么,現在的問題和之前的對話有沒有關聯。
  4. 響應生成:根據意圖和對話上下文,生成合適的回復內容,可以是文本、圖片、鏈接等。
  5. 結果返回:把回復內容包裝成響應對象,通過 Netty 返回給客戶端。

(三)性能優化實踐

在這個智能客服系統中,為了提高性能,我們可以做這些優化:

  1. 使用 gRPC 協議:因為客服系統需要實時交互,gRPC 的高性能和流處理能力非常適合。
  2. 緩存常用回復:對于一些常見問題(比如 "怎么注冊"、"怎么登錄")的回復,緩存起來,減少重復處理。
  3. 多線程處理:使用線程池處理多個用戶的請求,避免阻塞。
  4. 負載均衡:當用戶量增大時,部署多個客服服務器實例,使用最少連接數策略進行負載均衡。

七、總結:MCP 架構的優勢與適用場景

說了這么多,咱們來總結一下 MCP 客戶端服務器架構的優勢:

  1. 高性能:基于 Netty 的異步非阻塞 IO 模型和各種性能優化手段,能夠處理高并發請求。
  2. 高擴展性:模塊化設計,方便添加新的功能模塊和服務器實例。
  3. 靈活性:支持多種通信協議、序列化方式和負載均衡策略,適應不同的業務需求。
  4. 可靠性:完善的連接管理、重試機制和異常處理,保證系統穩定運行。

那 MCP 架構適合哪些場景呢?

  • AI 服務平臺:比如提供圖像識別、語音識別、自然語言處理等 AI 服務的平臺,需要處理大量的并發請求。
  • 實時交互系統:比如在線教育平臺的實時互動課堂、金融實時數據推送系統等。
  • 微服務架構:在微服務架構中,各個服務之間的通信可以使用 MCP 的 gRPC 協議,提高服務間的通信效率。

好了,各位 Javaer 們,今天咱們把 Spring AI 的 MCP 客戶端服務器架構從上到下拆了個遍,從客戶端的請求發起,到服務器端的處理,再到通信層的細節和性能優化,相信你對這個架構已經有了比較深入的理解。希望這篇文章能讓你在開發 AI 相關的客戶端服務器應用時少走彎路,也希望你能把學到的知識應用到實際項目中去。

責任編輯:武曉燕 來源: 石杉的架構筆記
相關推薦

2025-06-19 02:30:00

Spring服務器MCP

2011-06-09 10:51:26

Qt 服務器 客戶端

2009-08-18 12:51:19

服務器+客戶端

2018-07-17 09:59:10

PythonUDP服務器

2018-12-18 10:47:37

2009-12-25 10:47:17

DNS服務器

2009-09-16 16:09:41

NIS服務器客戶端NIS

2018-12-19 10:31:32

客戶端IP服務器

2019-08-28 15:19:15

PythonTCP服務器

2010-10-26 13:54:45

連接Oracle服務器

2014-01-17 15:23:55

Nagios

2010-06-09 14:39:58

2009-06-27 20:32:00

LinuxNFS客戶端

2010-08-27 10:18:24

DHCP服務

2014-06-01 11:03:13

VDI零客戶端

2024-02-22 13:47:40

2014-07-17 15:47:52

2012-05-29 09:38:04

Linux客戶端服務器

2010-10-11 17:46:01

mysql客戶端

2018-12-20 08:50:53

TCPIP服務器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜精品一区二区三区在线 | 国产伦一区二区三区四区 | 成人不卡视频 | 欧美区在线 | 精品日本久久久久久久久久 | 亚洲美乳中文字幕 | 欧美五月婷婷 | 美女天天操 | 日韩亚洲视频 | 久久久久久亚洲精品 | 欧美一区二区久久 | 在线精品一区二区三区 | 日韩在线精品 | 日本高清不卡视频 | 午夜久久久久久久久久一区二区 | 国产精品久久久久久久久久久久午夜片 | 色伊人久久 | 久久精品国产久精国产 | 亚洲一区二区欧美 | 国产成人精品一区 | 澳门永久av免费网站 | 国产精品视频免费观看 | 日韩欧美在线观看视频 | 中文字幕av亚洲精品一部二部 | 草久久久| 国产精品免费一区二区三区四区 | 久久99精品久久久久久琪琪 | 日韩中文视频 | 99热在线播放 | 久久婷婷麻豆国产91天堂 | 日韩在线播放视频 | 国产精品综合色区在线观看 | 日韩欧美国产精品 | 国产高清视频在线观看 | 全免一级毛片 | 成人精品一区 | 亚洲精品日本 | 亚洲免费毛片 | 欧美一级久久 | 欧美一区二区免费 | 亚洲精品国产第一综合99久久 |