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

基于開源方案構建統一的文件在線預覽與office協同編輯平臺的架構與實現歷程

開發 架構
對于人力不是特別充裕、或者項目投入預期規劃不是特別大的公司或者項目而言,通常會選擇基于一些開源方案來實現,但是開源組件選擇之后,如何將其無縫對接融入到自己的業務系統中并完全支持自身訴求的實現,不僅要能用、而且要好用,其實也是一個需要好好思量的問題。

大家好,又見面了。

在構建業務系統的時候,經常會涉及到對附件的支持,繼而又會引申出對附件在線預覽、在線編輯、多人協同編輯等種種能力的訴求。

圖片

對于人力不是特別充裕、或者項目投入預期規劃不是特別大的公司或者項目而言,通常會選擇基于一些開源方案來實現,但是開源組件選擇之后,如何將其無縫對接融入到自己的業務系統中并完全支持自身訴求的實現,不僅要能用、而且要好用,其實也是一個需要好好思量的問題。

此前在項目中就曾遇到過這么個場景,下面一起分享下具體的架構設計調整演進與最終方案落地策略,以及過程中遇到的一些問題。

開源組件的選擇

在正式開始構建在線的文件管理服務前,首先是分析下需要支持的功能訴求:

  • 需要支持office文檔的在線預覽、在線協同編輯能力
  • 需要支持常見的主流文件的在線預覽,比如圖片、視頻、文本文檔、PDF、壓縮包之類的
  • 需要支持文件的存儲管理能力

圖片

對于文件的存儲管理,直接采用了公司內部私有云的OSS文件托管服務進行實現,實現起來比較簡單。文件在線預覽與Office文件在線編輯的能力,則選用相關的開源方案來實現。經過一番對比分析,最終選定了兩個開源組件:

  • OnlyOffice用于支持office文檔的在線協同編輯、預覽等能力。
  • kkFileView用于支持常規文檔的在線預覽能力

選型確定之后,就是如何與現有業務系統進行整合了。因為開源組件往往都是通用邏輯設計的,而業務系統的邏輯又各不相同,所以如何去整合并方便擴展出自己需要的定制化能力,成了下一步擺在眼前需要處理的問題。

整體適配對接策略

為了保證業務系統的穩定,避免業務系統中強耦合文件預覽相關的開源模塊,同時也為了方便業務層的調用,所以規劃構建一個統一的入口代理轉接服務,統一由此服務對業務系統提供預覽與在線編輯相關能力,對業務層屏蔽掉底層具體的開源方案整合邏輯。這樣的好處是,不管預覽與編輯服務這邊如何調整,甚至后面更換實現方案,都不會影響到業務層的調用邏輯。

圖片

系統邊界劃定,對業務系統整體的接入配合而言就簡單了:

  • 業務系統只需要與預覽編輯服務之間進行接口與實現層面的約定對接即可,其實也是系統內部的模塊間規范定義
  • 預覽編輯服務負責完整的業務系統請求的鑒權、與開源組件之間的適配轉換、業務定制化的預覽與編輯能力擴展等等。

預覽編輯服務,作為業務系統的邊緣代理適配器模塊,需要保證提供給左側業務系統的接口的穩定,而右側具體對接的開源方案、內部處理邏輯等,則可以隨意調整。

整合OnlyOffice實現Office文檔在線預覽與編輯

讓業務代碼無耦合的方式使用預覽能力

OnlyOffice作為一個負責office在線預覽的功能組件,其提供了一個JS API方法。具體使用的時候,需要在HTML頁面中引用其提供的JS文件并調用對應API方法將請求參數傳遞給OnlyOffice進行處理。這些請求參數里面,既含有對文檔在線顯示相關的一些屬性約定,還包含一個重要的參數,也即需要操作的目標Office文件的獲取地址url。在OnlyOffice收到請求之后,需要去給定的地址下載目標Office文件,然后內部解析處理之后,按照請求參數的指定信息,渲染展示到界面上。

圖片

在實際的系統規劃中,為了便于后續版本升級維護,以及避免OnlyOffice強耦合到各個業務系統中,所以不太傾向于讓前端界面直接去集成與調用OnlyOffice相關的JS文件。

所以在實施的時候,在服務端的文件預覽編輯服務中進行了封裝,對外提供服務端API接口,服務端自帶一個簡單HTML界面(基于SpringBoot + Thymeleaf實現),業務請求對應服務端提供的獨立html界面,并在界面中完成使用OnlyOffice的JS api請求的操作。

具體步驟說明如下:

  • 對外提供服務端HttpGet?接口,借助Thymeleaf?框架,界面跳轉出現對應html界面

圖片

  • 提供簡單的HTML界面,用于引入OnlyOffice JS文件,作為最終顯示界面外殼:

圖片

  • 在獨立的JS?文件中,接收從JAVA?邏輯中傳入的參數信息,然后轉換封裝為OnlyOffice?需要的格式,然后調用OnlyOffice的API接口發送請求

圖片

這樣就實現整體的交互封裝,業務可以代碼無耦合的方式來直接使用預覽能力。具體的office文檔在線預覽與編輯的能力實現,由開源的OnlyOffice來提供。

圖片

具體使用的時候,交互邏輯如下:

  • 向文件預覽服務發送請求,指定要操作某個文檔;
  • 文件預覽服務經過對請求的鑒權以及其他處理邏輯之后,瀏覽器會跳轉出OnlyOffice在線文檔預覽編輯界面,此步驟也會攜帶上具體的文檔操作屬性數據(比如文件下載地址、文件更新保存回調地址等)、以及操作的用戶信息、允許當前用戶執行的具體操作權限等等信息;
  • 在打開的界面上,用戶可以執行查看或者編輯等操作;
  • OnlyOffice?會通過指定的接口地址,獲取要操作的文件的數據,以及編輯之后調用指定的回調接口,將更新后的內容保存。

看似很復雜的邏輯,但是經過封裝之后,對于業務使用而言其實很簡單,只要在發送給文件預覽服務的請求中,給定一個文件下載地址與文件保存回調地址即可。

協同在線編輯能力的關注點

前面有提過,采用OnlyOffice來實現office文檔的在線協同編輯,關于OnlyOffice在線編輯的原理,其官網給出的介紹如下:

圖片

對上述步驟解釋如下:

圖片

也即當用戶關閉文檔編輯界面之后,會觸發文檔的保存事件,回調callback接口,將保存事件推送給服務端,并告知服務端變更后的文檔地址,這樣服務端可以從給定的地址下載變更后的文檔,然后更新到自己的存儲中。

結合到我們具體的項目使用中,其具體的交互過程展開闡述下,就是下圖的過程:

圖片

這里,一個在線編輯操作的回調請求內容示例如下:

{
"actions": [{"type": 0, "userid": "78e1e841"}],
"changesurl": "https://documentserver/url-to-changes.zip",
"history": {
"changes": changes,
"serverVersion": serverVersion
},
"filetype": "docx",
"key": "Khirz6zTPdfd7",
"status": 2,
"url": "https://documentserver/url-to-edited-document.docx",
"users": ["6d5a81d0"]
}

關于回調請求的各個參數的具體含義,可以參見官網介紹,需要特別關注的幾個字段梳理如下:

字段

字段類型

含義說明

actions

??List<Object>??

每個用戶加入或者退出此文檔的編輯的動作信息。其中具體type的取值0表示斷開連接,1表示建立連接

key

??String??

目標文檔在OnlyOffice中處理的唯一標識ID,注意這里的key與業務系統中目標文件實際的唯一ID并非一個概念,不能混為一談,因為業務系統中某個文件的ID需要保持不變,但是在OnlyOffice中編輯的時候,這個key需要不停的變。

status

??Integer??

文檔當前的操作狀態類型,取值說明:

1: 文檔正在被編輯

2:文件已準備好保存

3:文檔保存發生錯誤

4:文件關閉,沒有變化

6:文檔正在被編輯,但是當前狀態已經被保存

7:強制保存文檔時發生錯誤

url

??String??

改動后的文檔的下載地址,可以從這個地址下載到變更后的文件,然后存儲更新業務系統中實際的文檔

實際測試的時候發現,此處的回調接口被調用的情況非常的頻繁,務必要注意當且僅當actions中所有的對象的type都等于0的時候,也即所有用戶均已經退出編輯且文檔已經準備好保存的時候,回調接口被調用的時候才需要去更新key值。

圖片

這里是在實際構建的時候踩坑較久的一個地方,下面章節中展開詳細說下踩坑過程。

OnlyOffice協同編輯踩坑記

在借助OnlyOffice構建在線協同編輯能力的時候,遇到一個很奇怪的問題,打開一篇文檔,在線對其內容進行編輯,然后編輯完成后關閉窗口,過了一段時間嘗試再次打開文檔編輯的時候,卻會報錯:

圖片

看了下官網的問題原因解釋,就是因為文檔編輯之后,原來的key對應的文檔已經被編輯過,已經不能被打開了(可以把key理解為不同的version,文檔被編輯之后,version變更了,原來老的version就不允許操作了)。最后官網還很貼心的提示:別忘了每次編輯之后要重新生成一個新的key!

圖片

按照官網的介紹,在callback接口被調用的時候,重新為文件生成一個key,后續新的用戶想要加入此文檔的編輯的時候,都是拿到新生成的一個key,這樣不就可以了嗎?

  • Step1: 文檔打開的時候,先嘗試獲取已存在的key值,如果不存在則新生成一個key并緩存起來
try {
// 如果redis里面有緩存此文檔對應的key值,則直接使用
fileUniqueKey = redisCacheOperateService.getFileUniqueKeyDetail(fileId);
} catch (Exception e) {
// 如果redis里面沒有緩存此文檔對應的key值,則生成對應的key并加入緩存中
fileUniqueKey = FileUniqueKey.builder().build();
redisCacheOperateService.saveOrUpdateFileUniqueKeyDetail(fileUniqueKey);
}
//獲取本次在線操作對應的key值
document.setKey(fileUniqueKey.generatekey());
  • Step2: 文件編輯保存回調處理中,重新生成新的key值并更新緩存的key值
// 編輯成功后,重新生成隨機碼,實現key值變化的目的
fileUniqueKey.updateRandomUniqueKey();
redisCacheOperateService.saveOrUpdateFileUniqueKeyDetail(fileUniqueKey);

按照上述思路改完后,再次嘗試,發現:

  • 當用戶A打開文檔未做任何改動的時候,用戶B也去打開文檔,然后兩個用戶A、B都可以加入到同一個文檔的協同編輯中,也可以進行協同編輯了;
  • 當用戶A或B做了改動之后,再有一個新的用戶C加入此文檔編輯的時候,卻沒有辦法和A、B加入到同一個協同編輯會話中,C的改動會覆蓋到A和B的改動,同理A或者B的改動也會覆蓋掉C的改動。

難道只有讓大家都約好了一起加入進去再開始編輯才行嗎?那這個在線編輯功能顯然就是個雞肋了 —— 顯然OnlyOffice也不太可能會是這種實現。再全面復盤了下測試的現象,分析了下可能原因:

因為A、B使用同一個key,所以A和B可以加入到同一個協同編輯會話中

  • A或者B修改了文檔之后,在callback觸發的邏輯中,將此文檔對應的key更新成了一個新的值
  • C嘗試進行同一篇文檔的在線編輯的時候,因為使用的key和A、B使用的key不相同,所以這個時候對于OnlyOffice而言,其實C是在編輯一篇與A、B完全獨立的文檔
  • 所以問題還是出在了key的處理策略上。在網上找了一圈的文檔沒找到答案,受限于時間約束,也沒有去看過OnlyOffice的源碼,只能根據現象分析OnlyOffice內部是基于本地緩存來處理的,而key是能否讓請求打到同一份本地緩存的關鍵,猜測了下OnlyOffice內部的大致處理思路是下面這個樣子:

圖片

基于上述分析:

  • 要想多人參與到同一個協作編輯會話中,必須要保證所有人操作的key都是相同的一個
  • 要想編輯后的文檔能夠下次再被打開,必須保證下次打開的時候key使用新的值
  • key不變更的情況下,用戶A打開編輯的時候,窗口未關閉的情況下,用戶B可以加入,但如果用戶A關閉,用戶B再用同一個key訪問的時候,就會報錯。

所以說,如果每次只要有用戶還在線的時候,這個文檔的key就不應該變,只有等某篇文檔的所有用戶都關閉編輯窗口的時候,再去處理文檔key的變更,這樣不就解決問題了嗎?

那問題就簡單了,按照這個思路修改了下callback的代碼邏輯,判斷下某篇文檔的所有用戶都退出編輯之后,再去重新生成新的key值。

代碼演示如下:

@PostMapping("/callback")
public DocumentEditCallbackResponse saveDocumentFile(@RequestBody DocumentEditCallback callback) throws IOException {
try {
// 當且僅當所有用戶都退出后,才需要將key重新生成一下,否則下次再打開的時候,就打不開了
if (callback.getStatus() == DocumentStatus.READY_FOR_SAVING.getCode()
|| callback.getStatus() == DocumentStatus.BEING_EDITED_STATE_SAVED.getCode()) {
// 保存文件內容
documentService.saveDocumentFile(callback.getKey(), callback.getUrl());
// 如果所有用戶都已退出,則更新此文件對應的預覽key值
boolean allUserExits = callback.getActions()
.stream().anyMatch(actionsBean -> actionsBean.getType() == 0);
if (allUserExits) {
fileUniqueKey.updateRandomUniqueKey();
redisCacheOperateService.saveOrUpdateFileUniqueKeyDetail(fileUniqueKey);
}
}
return DocumentEditCallbackResponse.success();
} catch (Exception e) {
return DocumentEditCallbackResponse.failue();
}
}

代碼改動完成后,再次測試,果然問題消失,在線預覽功能恢復正常。

OnlyOffice集群化部署

為了保障預覽服務的可靠,在生產環境上規劃實施集群化部署。從上一章的闡述中,我們知道OnlyOffice的功能實現嚴重依賴單機本地的緩存數據信息,在集群部署的場景下,過度依賴本地緩存的弊端就顯現出來了。

集群化部署,本以為會很簡單,直接部署多個docker節點,然后使用Nginx做一下反向代理以及負載均衡不就可以了嘛?但是實際實施的時候卻發現在協同編輯場景下出現了預期之外的問題。因為多人在線協同編輯的能力要求所有人對某篇文檔的編輯請求都在同一個OnlyOffice服務節點上才行,而Nginx隨機負載分發,會導致同一篇文檔的編輯請求分發到不同節點上,這樣就會導致編輯的內容相互覆蓋。

圖片

因為用戶的請求并不是直接打到OnlyOffice地址上的,而是先打到文件預覽服務中,然后由文件預覽服務經過某種策略處理后,再將請求重定向到OnlyOffice服務上進行文檔操作的,所以這里我們可以通過增加一個簡單的分發策略,保證對同一個文檔的所有的請求操作,都被分發到固定的一個OnlyOffice服務上處理即可。

這里的分發策略,考慮有2種方案:

  • 根據每個文檔的唯一ID計算hashcode?值,然后與OnlyOffice節點數取余,決定每個文檔分別有哪個OnlyOffice服務處理。此方案實現起來最為簡單,但是存在的問題也不少(比如節點新增或者刪除的時候存在問題,需要上一致性hash算法)。
  • 通過隨機分發+Redis記住文檔與節點映射的方式,先隨機選擇一個節點,然后記錄下此文件與OnlyOffice節點之間的映射關系,然后后面對此文件的請求始終分發到該OnlyOffice節點上。

圖片

這里我們實現的時候采用了第2種方案,借助redis緩存來實現,整體策略如上圖示意。具體實現的時候對緩存數據增加了一定的過期與續期策略,既保證同一文檔請求分發到同一節點,又保證一定時間之后文檔分發緩存消失,可以重新分配空閑的OnlyOffice服務器(因為開源版本OnlyOffice只支持最大20并發量,所以可以在此層級進行分配調整)。

具體代碼邏輯如下:

public NodeServerInfo getOnlyOfficeServer(String fileUniqueId) {
// 從redis中先看下是否有分配過,如果有,繼續使用
NodeServerInfo existServer = redisCacheOperateService.getExistOnlyOfficeServerByFileId(fileUniqueId);
if (existServer != null) {
if (serverAvailable(existServer)) {
// 延長有效期
redisCacheOperateService.renewalOnlyOfficeMapExpireDays(fileUniqueId, onlyOfficeServerCacheDays);
return existServer;
} else {
// 刪除無效的緩存
redisCacheOperateService.deleteExistOnlyOfficeServerMapping(fileUniqueId);
}
}
// 重新選擇一個可用的server
NodeServerInfo nodeServerInfo = chooseAvaliableServer();
// 將文件與服務器之間映射關系存儲redis中
redisCacheOperateService.saveFileAndOnlyOfficeServerMapping(fileUniqueId, nodeServerInfo,
onlyOfficeServerCacheDays);
return nodeServerInfo;
}

至此呢,集群化部署的問題解決,可用性上得到的有效保證。并且通過定期探測機制,及時將不可用的OnlyOffice節點從候選列表中剔除掉,保證了請求始終在可用節點上,有效避免了單點問題的出現,也一定程度上緩解單個節點的壓力(社區版本同時僅支持20并發數、通過一定策略可以分散不同文件的請求到不同節點上)。

圖片

整合kkFileView實現其他文件的在線預覽

kkFileView作為一個基于JAVA構建的可獨立集成部署的文件預覽開源組件,其在各種文件的預覽上表現非常的優異,集成起來也非常的簡單,直接提供下文件下載的地址就可以了。支持Office文檔、圖片、視頻、音頻、壓縮包等各種文檔的預覽。

對于kkFileView的集成,我們采用了與OnlyOffice集成截然不同的處理策略,因為kkFileView基于JAVA SpringBoot技術棧構建,與我們業務系統技術棧一致,所以我們基于kkFileView的源碼進行了深度的定制整改。主要包括幾方面:

  • 已經采用了OnlyOffice來提供Office文檔的預覽與編輯能力,這樣kkFileView就不需要此部分能力,去掉此部分能力之后,整個kkFileView部署包體積縮小300M左右
  • kkFileView打包的時候是打成了zip包,然后通過start.sh?腳本來進行啟動的,我們適配了下公司內CI構建工具的特點,改為了經典的SpringBoot的部署形態,即1個jar搞定
  • 由于我們的文件獲取接口涉及到權限校驗,我們定制了下此部分的邏輯,對接了下統一的鑒權中心。

兩者融合:緩解OnlyOffice加載慢問題

基于前面整體的規劃策略,Office文檔使用OnlyOffice進行預覽操作,非Office文檔則由kkFileView實現預覽操作(業務調用方無感知,都是統一一個url地址)。開發完成部署上線之后,功能也都一切正常。

但是自從上線之后,用戶普遍吐槽在線Office文檔預覽的加載速度太慢,難以忍受。因為首次使用的時候OnlyOffice會在瀏覽器本地加載一個30M左右的緩存數據,而我們的服務部署在公司內網機房里面,通過多層代理開放到公網中,用戶在公司辦公網絡中訪問的時候,相當于繞了多層網絡代理,且由于公司辦公網絡對客戶端單機下行速率有限制,導致這個第一次加載緩存數據的時間需要10-15s左右才能加載出文件。

圖片

雖然僅僅是第一次的打開速度比較慢(如果清理了瀏覽器緩存之后,首次加載還是會慢),但是等待的時間確實也有點久,所以考慮進行優化,提升下用戶的體驗感知。

異步Office轉PDF進行預覽

雖然系統支持了Office文檔的在線預覽與編輯能力,但是統計了下,其實近乎95%的Office文檔操作都是預覽操作,考慮到kkFileView預覽PDF的速度非常的快,因此決定通過kkFileView來支持Office文檔的預覽操作,而OnlyOffice只用來做Office文檔的在線協同編輯,或者用于某些kkFileView預覽效果不夠好的Office文檔的兜底預覽場景。

因為kkFileView預覽Office文檔的策略是先將Office文檔轉換為PDF,然后采用預覽PDF的策略來實現的,為了進一步的提升速度,避免每次都實時去進行Office文檔轉PDF的操作,所以設計采用異步事件的方式進行預處理轉換,異步轉化Office文檔為PDF,然后對于Office文檔只讀場景直接使用PDF預覽即可。

圖片

當業務系統中的文件內容有新增或者變更的時候,具體的異步轉換處理的時序操作邏輯如下:

圖片

在線協同編輯的時候,需要監聽下每個文件的變更,如果編輯后的話,需要異步重新轉換下文檔緩存內容。

預留禁用緩存預覽的接口

到這里呢,對于快速預覽office文檔的邏輯,就算基本完成了。按照當前的策略,對于office文檔預覽的場景,默認都會使用轉換后的緩存PDF文檔進行預覽。在實際驗證的時候,偶爾會遇到一些轉換后PDF預覽效果不佳的情況, 所以為了解決此類問題,又對處理流程的邏輯進行了一點優化,請求參數中,預留了個字段,可以用于調用方設定是否禁用本地轉換緩存結果文件進行預覽:

@ApiModelProperty(value = "是否禁止使用轉換后的格式來預覽文件以提升速度,默認false", required = false)
private boolean notUseConvertedResultForPreview;

這樣呢,在預覽界面上可以提供個切換按鈕。如果預覽效果不滿意,可以直接切換到原始文檔采用OnlyOffice服務進行預覽,雖然速度慢些、但是可以解決預覽效果的問題。

圖片

整體實現全貌

到此呢,整個文檔的在線預覽與編輯能力的構建,就算完成了。在處理具體的文檔的預覽或者在線編輯請求的時候,對應的處理判斷總體邏輯如下:

圖片

回顧下構建之初規劃的功能訴求,也已經全部支持:

功能點

支持情況

常規文檔在線預覽

?

office文檔在線預覽

?

office文檔協同編輯

?

集群部署

?

業務解耦

?

整體系統層面的網元模塊架構情況如下圖所示,整個預覽服務中,所有內部邏輯均封裝在內部,統一由預覽編輯服務對外提供API接口,供業務服務進行調用與交互。后續如果需要對預覽服務的實現策略進行調整,也無需變更外部業務側的邏輯,實現與業務邏輯解耦的效果。

圖片

總結

好啦,關于基于開源方案構建統一的文件在線預覽與Office協同編輯平臺的架構考量與實現過程關鍵點,這里就給大家分享到這里咯。看到這里,不知道你是否也有過此方面的經歷呢?針對文中的實現策略,是否還有什么更好的見解呢?歡迎多多留言切磋交流。

需要補充一下:

  • 因為對OnlyOffice的源碼實現或者框架具體實現了解也不是很深入,所以本文闡述的相關方案,主要是基于其社區版本,在使用層面進行額外的封裝,來達到自身訴求。
  • 如有足夠的精力或者能力,也可以考慮直接基于其源碼進行二次開發定制來實現目的 —— 這塊受限于業務交付的急迫性,沒有嘗試。
責任編輯:武曉燕 來源: 架構悟道
相關推薦

2021-06-29 07:14:19

NEXTCLOUDONLYOFFICE協同編輯平臺

2011-10-20 14:02:11

虛擬化基礎架構服務器

2021-12-14 15:35:33

Flink數據分析數據集成平臺

2025-01-10 14:35:23

2018-04-23 12:41:21

云計算政務云平臺架構

2025-01-26 13:27:23

2010-05-21 12:02:07

統一通信解決方案

2010-08-11 18:13:26

SOAIT架構開發管理

2025-08-15 07:10:00

2010-05-13 23:31:54

統一通信平臺

2021-06-01 06:59:58

運維Jira設計

2020-03-06 19:28:23

UOS瀏覽器WPS Office

2025-04-30 08:10:00

Vue文件預覽預覽編輯

2020-09-18 06:00:51

開源Markdown編輯器

2011-06-28 16:40:17

Qt Widget 圖片

2013-12-10 23:06:58

開源云平臺云計算

2012-10-09 09:25:57

2019-12-26 15:37:33

操作系統WindowsUOS

2024-06-06 08:43:44

2012-10-11 10:51:39

開源IaaS云
點贊
收藏

51CTO技術棧公眾號

欧美三区视频| 成人激情综合| 99久久综合精品| 日韩男女性生活视频| 中文字幕资源站| 国产suv精品一区| 色狠狠综合天天综合综合| 综合久久国产| 天堂v视频永久在线播放| 蜜桃精品在线观看| 久久久欧美精品| 69xxx免费| 欧美a级网站| 欧美电影一区二区| 国产第一页视频| 日本精品600av| 国产精品入口麻豆九色| 国产免费一区二区三区| 一区二区三区精彩视频| 亚洲另类视频| 久青草国产97香蕉在线视频| 97超碰在线免费观看| 深夜福利一区二区三区| 欧美色男人天堂| 国产黄色一级网站| 另类视频在线| 中文字幕一区二区在线观看| 蜜桃臀一区二区三区| 国产 欧美 精品| 激情伊人五月天久久综合| 日韩av免费看网站| 中日韩精品视频在线观看| 欧美日本一区二区高清播放视频| 中文字幕亚洲一区二区三区五十路| 免费看黄色片的网站| 精品国产麻豆| 欧美剧在线免费观看网站| 日本黄网站免费| 夜鲁夜鲁夜鲁视频在线播放| 亚洲无人区一区| 日本xxxxx18| 欧美成人精品一区二区男人看| 久久久久青草大香线综合精品| 国产日韩亚洲精品| 亚洲精选一区二区三区| 国产精品夜夜嗨| 91亚洲精品一区| 国产精品一品二区三区的使用体验| 日韩国产在线观看一区| 日本亚洲欧洲色α| 国产婷婷色一区二区在线观看| 一区二区三区四区五区在线| 欧美激情精品久久久久久| 欧美性猛交xxxxx少妇| 永久亚洲成a人片777777| 日韩在线观看免费| 爱爱视频免费在线观看| 中文字幕乱码亚洲无线精品一区| 久久韩剧网电视剧| 日日噜噜夜夜狠狠久久波多野| 日韩免费久久| 久久久精品久久久| 美国黄色小视频| 国产精品va| 欧美精品videossex88| 国产精品suv一区二区| 亚洲免费激情| 国产成人精彩在线视频九色| 日本黄色中文字幕| 免费成人在线视频观看| 国产有码一区二区| 精品久久久中文字幕人妻| 国产99久久久国产精品免费看| 国产精品久久精品视| 天天色综合av| 久久九九全国免费| 伊人久久av导航| 在线黄色网页| 欧美日韩激情视频| 亚洲欧美久久久久| 亚洲成人黄色| 国产视频久久网| 国产精品av久久久久久无| 亚洲国产一成人久久精品| 欧美激情综合色| 日韩欧美成人一区二区三区| 日韩国产精品大片| 国产精品美女久久久免费| 国产视频手机在线观看| 北条麻妃一区二区三区| 欧美日本亚洲| 91中文在线| 日韩欧美精品免费在线| 国产免费中文字幕| 视频小说一区二区| 中文字幕亚洲一区在线观看| 久久久久久久国产精品毛片| 久久久久99| 99精品在线直播| 国产毛片av在线| 悠悠色在线精品| 无遮挡又爽又刺激的视频| 经典三级久久| 亚洲日韩欧美视频| 国产一级二级三级视频| 日韩高清不卡在线| 国产精品theporn88| h视频在线免费| 亚洲第一主播视频| 三区视频在线观看| 沈樵精品国产成av片| 久久久久久国产三级电影| 久草视频在线免费| thepron国产精品| 三年中国中文在线观看免费播放| 女人高潮被爽到呻吟在线观看 | 日韩精品丝袜在线| 91香蕉一区二区三区在线观看| 国产精品入口66mio| 99re在线视频观看| 男人影院在线观看| 在线日韩一区二区| 国产伦精品一区二区三区妓女 | 国产女人18毛片水真多成人如厕| 99国产精品白浆在线观看免费| 欧美另类激情| 亚洲午夜精品久久久久久性色| 日韩成人av毛片| 国产成人小视频| 国产系列第一页| 成人亚洲网站| 国产香蕉精品视频一区二区三区| 午夜影院在线看| 成人av免费观看| 免费人成在线观看视频播放| 蜜桃精品视频| 美日韩精品视频免费看| 91无套直看片红桃| 国产精品理论片在线观看| 国产天堂在线播放| 视频精品在线观看| 国产精品精品一区二区三区午夜版 | 青青操国产视频| 国产真实乱偷精品视频免| 亚洲午夜精品国产| 欧美性aaa| 色偷偷888欧美精品久久久| 亚洲精品无码久久久久| 中文字幕av一区 二区| 亚洲成人天堂网| 色爱综合网欧美| 成人午夜黄色影院| 国产高清一区二区三区视频| 欧美女孩性生活视频| 最新av电影网站| 狠狠色综合日日| 中文字幕の友人北条麻妃| 精品一区二区三区免费看| 欧美猛少妇色xxxxx| 国产激情视频在线播放| 亚洲自拍偷拍av| 国产精品入口麻豆| 久久电影一区| 亚欧洲精品在线视频免费观看| jizz欧美| 久青草国产97香蕉在线视频| 亚洲经典一区二区| 好吊成人免视频| 国产一区二区三区精品在线| 日韩国产精品久久久| eeuss中文| av毛片精品| 2019中文字幕全在线观看| 欧美日韩国产中文字幕在线| 欧美午夜不卡在线观看免费| 亚洲精品电影院| 成人免费毛片a| 人妻熟女一二三区夜夜爱| 日本久久黄色| 成人在线观看91| 成人福利视频| 久久色免费在线视频| 蜜桃av中文字幕| 91传媒视频在线播放| 北条麻妃在线观看视频| 成人激情av网| 999精品视频在线| 自拍偷拍欧美| 欧美专区一二三| 亚洲国产欧美在线观看| 欧美中文字幕视频在线观看| 欧美一级二级三级区| 亚洲成人精品久久久| 免费在线观看av的网站| 亚洲综合免费观看高清完整版| 西西444www无码大胆| 国产一区二区三区免费看| 国产aaa一级片| 久久久久久久久久久妇女| 久久青青草原一区二区| 精品视频一区二区三区在线观看| 欧美最顶级丰满的aⅴ艳星| 国产一二区在线| 亚洲系列中文字幕| 日韩中文字幕综合| 69久久99精品久久久久婷婷 | 国产三级aaa| 91麻豆高清视频| 无码人妻一区二区三区在线视频| 久久精品人人做人人爽电影蜜月| 一道本在线观看视频| 国产中文精品久高清在线不| 国产精品夜夜夜一区二区三区尤| 久久91视频| 欧美在线性视频| bl在线肉h视频大尺度| zzjj国产精品一区二区| 飘雪影院手机免费高清版在线观看 | 那种视频在线观看| 在线免费观看欧美| 992tv成人免费观看| 全球成人免费直播| 欧美日韩精品不卡| 精品国产午夜肉伦伦影院| 亚洲在线视频观看| 伊人久久一区| 国产欧美一区二区白浆黑人| 黄瓜视频成人app免费| 91黄色8090| 888av在线视频| 欧美激情久久久久| 99视频免费在线观看| www.欧美三级电影.com| 999国产在线视频| 伊人久久免费视频| 黄色美女网站在线观看| 亚洲毛片在线看| 香蕉视频911| 日韩风俗一区 二区| 色婷婷中文字幕| 亚洲国产精品小视频| 欧美熟妇交换久久久久久分类| 精品卡一卡二卡三卡四在线| 精品人妻一区二区三区三区四区| 7777精品伊人久久久大香线蕉超级流畅 | 欧美日韩色视频| 成人免费一区二区三区视频| 日韩一区二区三区四区视频| 国产精品每日更新在线播放网址| 日韩一级片在线免费观看| 国产清纯白嫩初高生在线观看91 | 亚洲一区二区三区小说| 久久黄色免费网站| 午夜一区二区三区在线观看| 国产精彩视频在线观看| 亚洲成人免费电影| 草久视频在线观看| 91久久精品一区二区二区| 成人免费视频国产免费| 欧美日韩黄色影视| 国产视频手机在线| 亚洲成人av中文字幕| 午夜性色福利视频| 亚洲欧洲日产国产网站| 91社区在线观看播放| 久久国产一区二区三区| 精品精品导航| 热久久免费国产视频| 国产情侣一区二区三区| 91中文字幕在线观看| 丁香婷婷成人| 欧美日韩电影一区二区三区| 久久社区一区| 人妻激情另类乱人伦人妻| 国产欧美欧美| 高清av免费看| 丁香激情综合五月| 亚洲综合色一区| 亚洲视频一区二区在线| 国产午夜精品无码| 欧美伊人久久久久久久久影院 | 国产嫩bbwbbw高潮| 欧美亚洲免费在线一区| www.久久综合| 亚洲乱码av中文一区二区| 97超碰人人在线| 欧美激情一区二区三区久久久| japanese23hdxxxx日韩| 91精品免费视频| 天天躁日日躁成人字幕aⅴ| 一区二区不卡在线视频 午夜欧美不卡' | 国产一区二区黑人欧美xxxx| 成人av免费| 欧美一区三区三区高中清蜜桃| 欧美一级免费| 欧美二区在线| 欧美另类视频| 日韩av片网站| 99精品国产视频| 日韩在线视频网址| 一本大道久久a久久精二百| 精品人妻少妇AV无码专区| 亚洲视频欧洲视频| 91福利在线尤物| 成人av番号网| 久久97视频| 黄页网站在线观看视频| 精品一区二区三区久久| 蜜桃无码一区二区三区| 亚洲一区二区三区三| 国产又粗又大又黄| 亚洲男子天堂网| 91禁在线看| 超碰97国产在线| 91成人精品视频| www.涩涩涩| 久久男人中文字幕资源站| 18精品爽视频在线观看| 欧美疯狂做受xxxx富婆| 国产综合在线观看| 性色av一区二区咪爱| 欧美影院视频| 一区二区三区国产福利| 丝袜诱惑制服诱惑色一区在线观看 | 欧美电影在线观看网站| 日韩精品最新在线观看| 性xx色xx综合久久久xx| 精品影片一区二区入口| 亚洲综合激情网| 国产高清免费观看| 欧美成人免费在线视频| 日本亚洲欧洲无免费码在线| 欧美日韩亚洲综合一区二区三区激情在线| 精品福利av| 日本中文字幕有码| 亚洲一区精品在线| 亚洲av无码一区二区三区dv | 69av视频在线| 日韩欧美国产1| 中文在线免费| 99久热re在线精品视频| 欧美日韩亚洲国产精品| 婷婷激情5月天| 曰韩精品一区二区| 亚洲精品97久久中文字幕| 欧美老女人xx| av不卡一区| www.日本在线播放| 99久久精品免费观看| 国产一级片毛片| 亚洲性无码av在线| 精品九九久久| 黄瓜视频免费观看在线观看www| 久久精品av麻豆的观看方式| 日韩在线不卡av| 欧美成人三级电影在线| 超免费在线视频| 久久精品日韩| 天堂久久久久va久久久久| 五月婷婷欧美激情| 欧美二区三区91| 国产精品国精产品一二| 久久精品久久精品国产大片| 鲁大师影院一区二区三区| 公肉吊粗大爽色翁浪妇视频| 欧美日韩免费不卡视频一区二区三区 | 欧美国产综合在线| 99精品视频一区二区| 亚洲天堂五月天| 久久精品久久久久久国产 免费| 久久国产精品免费一区二区三区| 欧美人与动牲交xxxxbbbb| 99久久精品费精品国产一区二区| 99久久久久久久久| 按摩亚洲人久久| 国产精品流白浆在线观看| 欧美牲交a欧美牲交aⅴ免费真 | 色一情一区二区三区四区| 黑人巨大精品欧美黑白配亚洲| 久草国产在线视频| 亚洲欧美日韩天堂一区二区| 日韩一区二区三区四区五区 | 四虎永久在线精品免费一区二区| 久久精品国产99国产| 久久久一二三区| 国产午夜精品全部视频播放| 精品国产亚洲一区二区三区大结局| 波多野结衣乳巨码无在线| 欧美国产精品v| 亚洲第一成人av| 国产精品黄视频| 极品中文字幕一区| 黄色av片三级三级三级免费看| 欧美成人aa大片| 91亚洲视频| 国产素人在线观看| 亚洲欧美激情小说另类| 黄视频在线播放| 粉嫩av免费一区二区三区| 蜜桃av一区二区三区|