<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          騰訊游戲業(yè)務(wù)竟然是這樣利用低代碼平臺(tái)的 | ArchSummit

          共 7195字,需瀏覽 15分鐘

           ·

          2022-03-19 05:00

          點(diǎn)擊上方“服務(wù)端思維”,選擇“設(shè)為星標(biāo)

          回復(fù)”669“獲取獨(dú)家整理的精選資料集

          回復(fù)”加群“加入全國(guó)服務(wù)端高端社群「后端圈」


          作者 | 李忠良
          出品 | InfoQ
          騰訊游戲業(yè)務(wù)需要應(yīng)對(duì)大量運(yùn)營(yíng)安全場(chǎng)景,為此他們研發(fā)團(tuán)隊(duì)設(shè)計(jì)了一套覆蓋數(shù)據(jù)、后端、前端的開(kāi)發(fā)配置化低代碼平臺(tái)。
          在 2020年11月13-14日落地的 ArchSummit 全球架構(gòu)師峰會(huì) 2021(深圳)上,我們邀請(qǐng)到了騰訊 IEG 數(shù)據(jù)產(chǎn)品開(kāi)發(fā)組負(fù)責(zé)人葉鑫林來(lái)分享他們的低代碼實(shí)踐。此次分享中他著重介紹了低代碼平臺(tái)的設(shè)計(jì)理念,如接口元數(shù)據(jù)自動(dòng)注冊(cè)、SQL 賦能、基于 Mock 的前端快捷配置等,希望對(duì)你有所啟發(fā)。  

          當(dāng)大家談到低代碼的時(shí)候,常常只會(huì)想到邏輯可視化的平臺(tái)、UI 可視化的平臺(tái),但是低代碼還有更多的可能,我們還可以引入很多其他模塊,例如,數(shù)據(jù)處理、接口、測(cè)試、人工智能等等。今天我將基于數(shù)據(jù)處理、接口、邏輯可視化,以及 UI 可視化這四方面來(lái)展開(kāi)分享,并闡述我們案例中低代碼平臺(tái)中所有子平臺(tái)之間是如何協(xié)作的。

          低代碼可以解決哪些業(yè)務(wù)問(wèn)題?

          假設(shè)有這樣一個(gè)場(chǎng)景,當(dāng)我們需要統(tǒng)計(jì)騰訊某游戲業(yè)務(wù)的城市登錄人數(shù),并且需要提供可以運(yùn)營(yíng)或可以檢索的頁(yè)面。

          一般的開(kāi)發(fā)流程是這樣的,首先將任務(wù)派發(fā)給數(shù)據(jù)開(kāi)發(fā),基于大數(shù)據(jù)的方案統(tǒng)計(jì)登錄人數(shù),接著找到后臺(tái)開(kāi)發(fā)進(jìn)行數(shù)據(jù)接口開(kāi)發(fā),然后尋找前端人員進(jìn)行 Web 頁(yè)面開(kāi)發(fā)。

          如果基于低代碼的方案來(lái)實(shí)現(xiàn),我們希望這些任務(wù)可以由一個(gè)非開(kāi)發(fā)人員來(lái)獨(dú)立完成。他可以在數(shù)據(jù)平臺(tái)進(jìn)行數(shù)據(jù)統(tǒng)計(jì),在邏輯可視化平臺(tái)完成接口開(kāi)發(fā),然后在 UI 可視化平臺(tái)配置界面,最后整體交付這個(gè)需求。當(dāng)然,要實(shí)現(xiàn)上述過(guò)程,我們還有很多問(wèn)題要解決。

          例如,當(dāng)統(tǒng)計(jì)每個(gè)城市的登錄人數(shù)的時(shí)候,登錄信息日志一般只有 IP,并不會(huì)顯示城市,這使得產(chǎn)品人員不得不將 IP 轉(zhuǎn)換成城市,但這有很大的難度;其次,當(dāng)數(shù)據(jù)平臺(tái)輸出數(shù)據(jù)之后,如何將它轉(zhuǎn)換成接口?最后,即使有了接口,非開(kāi)發(fā)人員還需要知道前端調(diào)用的接口參數(shù)、輸出以及對(duì)應(yīng)到的 UI 等等。

          上面的這一切,對(duì)于一個(gè)非技術(shù)人員來(lái)講比較困難。

          1低代碼三大問(wèn)題  

          這里一共有三個(gè)問(wèn)題需要解決。

          首先,是否存在強(qiáng)大的 SQL 可以提供給用戶,這個(gè) SQL 可以直接將 IP 轉(zhuǎn)換成城市?

          其次,當(dāng)有了原數(shù)據(jù)之后,是否可以直接給到接口?是否可以針對(duì)傳統(tǒng)的 CURD 的方法直接生成接口?

          最后,當(dāng)有了接口之后,UI 平臺(tái)是否可以簡(jiǎn)化,不需要進(jìn)行復(fù)制粘貼。

          那么針對(duì)這三個(gè)問(wèn)題,我們采用了以下這套方案。

          這套方案的整體架構(gòu),包含四個(gè)部分,第一層是微服務(wù)底座,中間是邏輯可視化,再向上是數(shù)據(jù)平臺(tái),最上層是 UI 平臺(tái)。所有的基底都是微服務(wù)。

          這里我們首先引入本方案中兩個(gè)比較重要的概念——元數(shù)據(jù)和 Mock。

          元數(shù)據(jù)包含了數(shù)據(jù)的存儲(chǔ)、表、字段等元信息,大家都比較熟悉,這里不深入闡述,但是本方案中的 Mock 與業(yè)界稍微有些不同,業(yè)界通常使用 Mock 來(lái)做開(kāi)發(fā)聯(lián)調(diào)和單測(cè)。

          比如,當(dāng)后端的接口沒(méi)有開(kāi)發(fā)完成的時(shí)候,它可以通過(guò) Mock 將請(qǐng)求打到 Mock CGI,然后將返回接口傳遞過(guò)來(lái);或者是當(dāng)我們并不希望觸發(fā)真實(shí)的請(qǐng)求,可以在 CI/CD 里進(jìn)行單測(cè)(如下圖所示)

          不過(guò)這將帶來(lái)另外一個(gè)問(wèn)題,那就是 Mock 如何進(jìn)行收集,我們都知道,很多接口不可能都依靠人力輸出。

          騰訊的方案是:首先用戶的請(qǐng)求作為輸入,接著經(jīng)過(guò)網(wǎng)關(guān),網(wǎng)關(guān)將 Input 傳遞到整個(gè)微服務(wù),然后網(wǎng)關(guān)拿到返回結(jié)果,接著網(wǎng)關(guān)會(huì)把結(jié)果傳遞到客戶端,這個(gè)時(shí)候請(qǐng)求已經(jīng)完成了。

          接下來(lái)將 Input、Output 以及微服務(wù)的接口注釋,推薦給 Mocks server,Mocks server 會(huì)進(jìn)行清洗,得到標(biāo)準(zhǔn)的 Mock 的數(shù)據(jù)(標(biāo)準(zhǔn) Mock 數(shù)據(jù)包含用戶的請(qǐng)求方式、地址、輸入以及輸出)。

          這里會(huì)有一些性能相關(guān)的難點(diǎn),采集任務(wù)不能影響微服務(wù)的性能,一些常見(jiàn)的解決方案已貼在上圖 Tips 中,比如,在這個(gè)網(wǎng)關(guān)里面需要進(jìn)行抽樣上報(bào)、增量上報(bào)以及異步上報(bào)等。

          假設(shè)我們需要拉取一份數(shù)據(jù),目前開(kāi)發(fā)人員已經(jīng)開(kāi)發(fā)了拉取數(shù)據(jù)源的接口(接口已經(jīng)部署在微服務(wù)),這時(shí)候如何生成 Mock?

          首先我們通過(guò)反射拿到接口的注釋,接著拿到參數(shù),然后通過(guò)注釋匹配。當(dāng)然我們會(huì)先對(duì)這一份注釋進(jìn)行清洗,然后得到字段對(duì)應(yīng)中文名的 TV 對(duì),接著嘗試匹配。如果匹配不上,它會(huì)有一個(gè)單詞庫(kù),再次嘗試匹配,直到拿到中文名為止,最后我們會(huì)得到一個(gè)標(biāo)準(zhǔn)的 Mock 自動(dòng)化的方案流程。

          經(jīng)過(guò)這樣一套流程,所有接口一旦經(jīng)過(guò)調(diào)用,我們馬上經(jīng)過(guò)自動(dòng)化采集,得到了所有接口 Mock。接口的請(qǐng)求,參數(shù)的上傳,以及返回的結(jié)果我們都了如指掌。

          那我們?cè)撊绾问褂眠@些自動(dòng)采集的 Mock 數(shù)據(jù)呢?接下來(lái)一起看看低代碼的第三個(gè)問(wèn)題。

          是否存在極其強(qiáng)大的 SQL  

          首先,我們需要更強(qiáng)大的 SQL。

          一般來(lái)講,當(dāng) SQL 無(wú)法滿足計(jì)算邏輯的時(shí)候,我們就需要找開(kāi)發(fā)人員開(kāi)發(fā)一個(gè) UDF,比如一個(gè)"IP 轉(zhuǎn)城市"的函數(shù),它會(huì)注冊(cè)到 SQL 的執(zhí)行引擎,你便可以使用這個(gè)函數(shù)了。但這樣的方案是需要開(kāi)發(fā)人員進(jìn)行開(kāi)發(fā)支持的。

          低代碼的方案應(yīng)該怎么設(shè)計(jì)呢?我們提供 SQL 的方案是將微服務(wù)注冊(cè)進(jìn)執(zhí)行引擎,整個(gè)引擎是 Spark SQL 的引擎,它會(huì)代替開(kāi)發(fā)人員發(fā)起微服務(wù)的調(diào)用,會(huì)上傳參數(shù),然后再調(diào)度到微服務(wù)里面。Mock 幫助人工進(jìn)行了最快速的 UDF 的注冊(cè),無(wú)需要任何成本,馬上便可以通過(guò) SQL 調(diào)用微服務(wù),

          例如,當(dāng)我們使用 SQL 調(diào)取微服務(wù)的時(shí)候,首先需要知道地址、輸入?yún)?shù)、以及返回值。這個(gè)接口返回 data 和 count,為什么你接口返回城市一定是 data?這些都是一些我們?cè)谶M(jìn)行注冊(cè)的時(shí)候需要做的工作。

          這里有個(gè)視頻,大家可以看一下。



          00:30

          例如選擇一個(gè)獲取黑名單的任務(wù),它馬上注冊(cè)微服務(wù),這個(gè) UDF 是一個(gè)微服務(wù),它就可以被 SQL 使用,大家可以判斷他是不是黑名單了。

          整個(gè)過(guò)程中,用戶只需要非常簡(jiǎn)單的四個(gè)步驟,SQL 馬上就可以具備微服務(wù)的調(diào)度能力。

          此處也會(huì)有一些性能上的挑戰(zhàn),當(dāng)使用 Spark 調(diào)用微服務(wù)的時(shí)候,性能會(huì)出現(xiàn)一些問(wèn)題。因?yàn)槿绻褂梅浅鹘y(tǒng)的調(diào)動(dòng)方法,它是一個(gè)串行的過(guò)程,那么我們這里提了可以供大家參考的方案。

          UDF 注冊(cè)之后,我們會(huì)直接執(zhí)行 SQL,但不會(huì)馬上調(diào)用 UDF,將它標(biāo)記起來(lái),呈現(xiàn)出來(lái)是一個(gè)偽執(zhí)行的狀態(tài),SQL(無(wú) UDF)產(chǎn)生一個(gè)中間結(jié)果,我們會(huì)將這個(gè)中間結(jié)果重新分區(qū),把它打得更散更平均,這樣后續(xù)每個(gè)分區(qū)執(zhí)行分派到的 UDF 任務(wù)個(gè)數(shù)將會(huì)更近平均,避免一些數(shù)據(jù)傾斜的情況。最后在我們偽標(biāo)記的 UDF 的基礎(chǔ)上,我們會(huì)啟用整個(gè)的異步調(diào)度方案,使用異步 HTTP 完成微服務(wù)調(diào)用,并配套相應(yīng)的緩存以及限流的策略,整體提升請(qǐng)求效率和成功率。

          截至到這里,我們通過(guò) SQL+ 微服務(wù)提供了更強(qiáng)大的 SQL,通過(guò)了 UDF 的快速注冊(cè),提供給產(chǎn)品人員非常簡(jiǎn)潔的操作。這個(gè)時(shí)候,第一個(gè)問(wèn)題就被完美地解決了。

          接下來(lái)分享第二個(gè)問(wèn)題的解決方案,CURD 是否還需要開(kāi)發(fā)接口?

          CURD 是否需要開(kāi)發(fā)接口  

          我們通過(guò)數(shù)據(jù)平臺(tái)產(chǎn)生的數(shù)據(jù)之后,接著需要 CURD 接口。業(yè)界有很多生產(chǎn) CURD 接口的方案,騰訊的 APIJSON 開(kāi)源方案,它可以做到零代碼生成接口和文檔,并且整個(gè)生成過(guò)程是自動(dòng)化。

          當(dāng)企業(yè)有元數(shù)據(jù)的時(shí)候,馬上就可以獲得接口,不過(guò)這個(gè)接口暫時(shí)不能滿足運(yùn)營(yíng)系統(tǒng)的需要。這時(shí)候需要引入規(guī)則引擎。

          我們可以將接口進(jìn)行簡(jiǎn)單地編排,采用了 BPMN2.0 協(xié)議實(shí)現(xiàn)了同步和異步雙引擎,因此整個(gè)規(guī)則引擎可以做任務(wù)流的事情。

          Mock 可以幫助整個(gè)組件的快速注冊(cè),因?yàn)槊恳粋€(gè)節(jié)點(diǎn)都是微服務(wù),這種 Mock 節(jié)點(diǎn)就可以快速注冊(cè),同時(shí)整個(gè)微服務(wù)在調(diào)試的過(guò)程中,我們生成了任務(wù)工作流,當(dāng)邏輯執(zhí)行完之后,它也會(huì)馬上去進(jìn)行 Mock 注冊(cè)。

          當(dāng)然,當(dāng)我們有了簡(jiǎn)單的 CURD 過(guò)程,我們可以選擇編排一些參數(shù)校驗(yàn)。比如,對(duì)時(shí)間做要求、對(duì)權(quán)限做要求,當(dāng)然也可以做一些錯(cuò)誤返回等的編排工作,最終通過(guò)規(guī)則引擎生成完整的查詢接口。

          那么經(jīng)過(guò)了這一步驟,我們就具備了 SQL 和接口,這時(shí)候可以將接口放到頁(yè)面呈現(xiàn)。

          配置前端是否只能依靠 Ctrl c+v  

          上圖是我們UI平臺(tái)的架構(gòu),跟常規(guī)的低代碼平臺(tái)大同小異,這里介紹兩個(gè)點(diǎn):通信邏輯模型和Mock加速前端配置

          首先是通信邏輯模型,這個(gè)模型解決了組件與組件的通信與行為相應(yīng),當(dāng)一個(gè)組件拖出來(lái)到頁(yè)面后,會(huì)馬上分配一個(gè)唯一實(shí)例 ID,每個(gè)實(shí)例都會(huì)有屬性,會(huì)有系統(tǒng)事件或自定義事件。

          比如我們現(xiàn)在要實(shí)現(xiàn)點(diǎn)擊搜索按鈕后表格組件自動(dòng)從后端重新獲取最新數(shù)據(jù)并呈現(xiàn)。

          那么,我們配置的邏輯大概是這樣的:按鈕實(shí)例的 OnClick 事件可以配置觸發(fā)表格實(shí)例的 HTTP 時(shí)事件。Table 實(shí)例的 HTTP 的事件實(shí)現(xiàn)拉取數(shù)據(jù)以后,將它寫(xiě)進(jìn) Value 里面,實(shí)現(xiàn)了整個(gè) Table 的數(shù)據(jù)刷新輸出。

          其次是 Mock 加速前端配置,有了 Mock 之后,在配置前端的時(shí)候可以省去了很多復(fù)制粘貼的工作。當(dāng)我拉取一個(gè)表格,可能有很多字段,復(fù)制粘貼將會(huì)非常崩潰,這里有 Mock server 的快捷配置以及預(yù)覽,當(dāng)用戶配置完之后,便可以馬上預(yù)覽,來(lái)檢查你的配置是否和你的預(yù)期。

          我們是如何通過(guò) Mock 快速地配置?

          例如,當(dāng)我們配置表格的時(shí)候,地址、請(qǐng)求方式、上報(bào)參數(shù)、表格輸出等均需要配置。這對(duì)于一個(gè)配置人員來(lái)講,其實(shí)成本非常高的,尤其是當(dāng)碰到非常極端的案例的時(shí)候,例如,當(dāng)你碰到具備 20 多個(gè)字段的時(shí)候,它的配置工作將會(huì)非常令人崩潰。



          00:33


          我們的方案是這樣的,一起來(lái)看一下這個(gè)視頻。

          首先拉取一個(gè)表格,然后選擇一個(gè)微服務(wù)地址,然后自動(dòng)地獲取參數(shù)。

          所有的上報(bào)參數(shù),其返回都會(huì)全部自動(dòng)填上,以及基于 Mock 的實(shí)時(shí)預(yù)覽,馬上就可以擁有。

          通過(guò)使用 Mock,平臺(tái)也可以透過(guò) Mock 平臺(tái)進(jìn)行真實(shí)的預(yù)發(fā)布環(huán)境的預(yù)覽。

          今天的主要三個(gè)挑戰(zhàn)都已經(jīng)解決了,有了這樣方案之后,其實(shí)對(duì)于產(chǎn)品人員來(lái)講,可以搞定很多內(nèi)容。

          2騰訊游戲低代碼落地實(shí)踐及未來(lái)展望  

          騰訊游戲低代碼的整個(gè)數(shù)據(jù)平臺(tái)大概支撐了 3000 個(gè)任務(wù),后端沉淀的原子接口有 1000 個(gè),整個(gè)邏輯可視化模板有 200 個(gè),頁(yè)面 600 個(gè)等等。

          在我們的平臺(tái)上層,支撐著很多的應(yīng)用。比如客服系統(tǒng),大家知道王者榮耀的客服系統(tǒng)往往非常復(fù)雜,它會(huì)有郵件贈(zèng)送福利。假設(shè)用戶 30 天沒(méi)有領(lǐng)取,這個(gè)郵件就會(huì)頂替掉,但是有些人會(huì)打電話投訴要求補(bǔ)發(fā)福利,這個(gè)時(shí)候客服需要檢查日志去檢查是否已經(jīng)領(lǐng)???

          這一系列流程之前都是依賴人工,但是現(xiàn)在當(dāng)我們將平臺(tái)傳遞給客服的時(shí)候,他們利用這套平臺(tái)配置邏輯就可以輕松搞定。

          當(dāng)然,在平臺(tái)的上層,我們也支持運(yùn)維安全 SOAR 以及安全監(jiān)控的一些事情。

          說(shuō)完我們的實(shí)踐,談?wù)勎覀兊恼雇?/p>

          今天我分享的兩個(gè)關(guān)鍵點(diǎn)是元數(shù)據(jù)和 Mock,我們經(jīng)過(guò)這兩個(gè)元素的頻繁交互,達(dá)成了整個(gè)平臺(tái)的融合。

          回顧整個(gè)平臺(tái)架構(gòu),我們發(fā)現(xiàn)平臺(tái)的所有東西都是微服務(wù),并且所有的微服務(wù)都可以變成 API 使用,整個(gè) SQL 也變得非常的強(qiáng)大。整個(gè)數(shù)據(jù)平臺(tái)輸出的數(shù)據(jù)都有 CURD,也貢獻(xiàn)回了微服務(wù),微服務(wù)里面的 CURD 同樣貢獻(xiàn)給規(guī)則引擎。這是一種相輔相成的關(guān)系。

          最后一部分是關(guān)于我對(duì)低代碼未來(lái)趨勢(shì)的一些思考。現(xiàn)在低代碼百花齊放,有非常多的低代碼平臺(tái),業(yè)界需要一些規(guī)范,以及如何保證低代碼平臺(tái)的質(zhì)量。

          上圖是我們整個(gè)的騰訊的低代碼架構(gòu)圖。

          首先,我們整個(gè)騰訊提出了一些方案——騰訊有 UI 可視化邏輯,還有 DSL 整個(gè)語(yǔ)言,生產(chǎn)環(huán)境、開(kāi)發(fā)環(huán)境以后,便會(huì)有配套的前端以及后端的 SARS 的能力。整個(gè)的低代碼可以用來(lái)配置 Web 和 App,可以通過(guò)提供一些 Pass 的服務(wù),也可以通過(guò) Open API 或者鉤子做很多事情。

          當(dāng)然這里介紹兩個(gè)執(zhí)行引擎。作為低代碼,我們有一個(gè)基于 Schema 的解析引擎和編譯引擎。解釋引擎可以用 Schema 直接執(zhí)行,編譯引擎更多是從性能角度考慮。編輯引擎可以根據(jù) Schema 轉(zhuǎn)成可運(yùn)行的代碼,希望大家可以了解一下。

          其次,再談一下 Schema 與 DSL 的這樣關(guān)系,DSL 可以通過(guò) Pass 模塊轉(zhuǎn)換成 Schema,Schema 是可以被解釋引擎和編譯引擎識(shí)別的。在面向用戶的使用方式上,我們支持整個(gè)可視化編輯,也就是說(shuō),大家可以在頁(yè)面進(jìn)行拖拉拽。當(dāng)然如果你不喜歡,也可以無(wú)風(fēng)險(xiǎn)、無(wú)損失地切換到 DSL。

          最后,對(duì)于一些中小企業(yè)來(lái)說(shuō),當(dāng)企業(yè)選擇了低碼平臺(tái)時(shí)候,便馬上會(huì)被這個(gè)平臺(tái)綁架。因?yàn)槠髽I(yè)的所有邏輯全部配置在了低代碼平臺(tái),由于其他平臺(tái)無(wú)法識(shí)別 Schema,所以根本無(wú)法遷移。

          目前騰訊低代碼提出了一個(gè)思想——Schema 可以不一樣,因?yàn)椴煌膱?zhí)行引擎或編譯引擎是不同的,它們的 schema 規(guī)范必然也不一樣。但是 DSL 是更上層的語(yǔ)言,就是大部分?jǐn)?shù)據(jù)都支持標(biāo)準(zhǔn)的 SQL 一樣,我們可以抽象 DSL,站在整個(gè)低代碼的行業(yè)的角度與立場(chǎng)去抽象 DSL。在我的平臺(tái)里面剛才我們講了,其實(shí) Schema 是可以轉(zhuǎn) DSL 的,當(dāng)他真正地想從平臺(tái)導(dǎo)出的時(shí)候,它其實(shí)就可以把 Schema 轉(zhuǎn)成 DSL 打包帶走,然后在另外一個(gè)平臺(tái)里面導(dǎo)入。

          我相信如果大家都這樣做,低代碼綁架業(yè)務(wù)的問(wèn)題就迎刃而解,整個(gè)低代碼的生態(tài)會(huì)變得更加健康。

          這是我今天的分享,謝謝大家。



          — 本文結(jié)束 —


          ● 漫談設(shè)計(jì)模式在 Spring 框架中的良好實(shí)踐

          ● 顛覆微服務(wù)認(rèn)知:深入思考微服務(wù)的七個(gè)主流觀點(diǎn)

          ● 人人都是 API 設(shè)計(jì)者

          ● 一文講透微服務(wù)下如何保證事務(wù)的一致性

          ● 要黑盒測(cè)試微服務(wù)內(nèi)部服務(wù)間調(diào)用,我該如何實(shí)現(xiàn)?



          關(guān)注我,回復(fù) 「加群」 加入各種主題討論群。



          對(duì)「服務(wù)端思維」有期待,請(qǐng)?jiān)谖哪c(diǎn)個(gè)在看

          喜歡這篇文章,歡迎轉(zhuǎn)發(fā)、分享朋友圈


          在看點(diǎn)這里
          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产逼网 | 在线中文av | 爱草逼爱草逼爱草逼爱草逼爱草逼爱草逼 | 丁香五月天视频 | 大鸡吧在线视频 |