国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

探索 Serverless 中的前端開發(fā)模式(多場景)

共 13557字,需瀏覽 28分鐘

 ·

2020-12-06 09:59

在 QCon 北京 2019 大會上,蔣航講師做了《探索 Serverless 中的前端開發(fā)模式》主題演講,主要內(nèi)容如下。


前言

最近關(guān)于 Serverless 的討論越來越多。看似與前端關(guān)系不大的 Serverless,其實早已和前端有了淵源,并且將對前端開發(fā)模式產(chǎn)生變革性的影響。本文主要就根據(jù)個人理解和總結(jié),從前端開發(fā)模式的演進、基于 Serverless 的前端開發(fā)案例以及 Serverless 開發(fā)最佳實踐等方面,與大家探討 Serverless 中的前端開發(fā)模式。本人也有幸在 QCon2019 分享了這一主題。

前端開發(fā)模式的演進

首先回顧一下前端開發(fā)模式的演進,我覺得主要有四個階段。

  • 基于模板渲染的動態(tài)頁面

  • 基于 AJAX 的前后端分離

  • 基于 Node.js 的前端工程化

  • 基于 Node.js 的全棧開發(fā)

基于模板渲染的動態(tài)頁面

在早起的互聯(lián)網(wǎng)時代,我們的網(wǎng)頁很簡單,就是一些靜態(tài)或動態(tài)的頁面,主要目的是用來做信息的展示和傳播。這個時候開發(fā)一個網(wǎng)頁也很容易,主要就是通過 JSP、PHP 等技術(shù)寫一些動態(tài)模板,然后通過 Web Server 將模板解析成一個個 HTML 文件,瀏覽器只負責(zé)渲染這些 HTML 文件。這個階段還沒有前后端的分工,通常是后端工程師順便寫了前端頁面。

基于 AJAX 的前后端分離

2005 年 AJAX 技術(shù)的正式提出,翻開了 Web 開發(fā)的新篇章?;?AJAX,我們可以把 Web 分為前端和后端,前端負責(zé)界面和交互,后端負責(zé)業(yè)務(wù)邏輯的處理。前后端通過接口進行數(shù)據(jù)交互。我們也不再需要在各個后端語言里面寫著難以維護的 HTML。網(wǎng)頁的復(fù)雜度也由后端的 Web Server 轉(zhuǎn)向了瀏覽器端的 JavaScript。也正因如此,開始有了前端工程師這個職位。

基于 Node.js 的前端工程化

2009年 Node.js 的出現(xiàn),對于前端工程師來說,也是一個歷史性的時刻。隨著 Node.js 一同出現(xiàn)的還有 CommonJS 規(guī)范和 npm 包管理機制。隨后也出現(xiàn)了 Grunt、Gulp、Webpack 等一系列基于 Node.js 的前端開發(fā)構(gòu)建工具。

在 2013 年前后,前端三大框架 React.js/Angular/Vue.js 相繼發(fā)布第一個版本。我們可以從以往基于一個個頁面的開發(fā),變?yōu)榛谝粋€個組件進行開發(fā)。開發(fā)完成后使用 webpack 等工具進行打包構(gòu)建,并通過基于 Node.js 實現(xiàn)的命令行工具將構(gòu)建結(jié)果發(fā)布上線。前端開發(fā)開始變得規(guī)范化、標準化、工程化。

基于 Node.js 的全棧開發(fā)

Node.js 對前端的重要意義還有,以往只能運行在瀏覽器中的 JavaScript 也可以運行在服務(wù)器上,前端工程師可以用自己最熟悉的語言來寫服務(wù)端的代碼。于是前端工程師開始使用 Node.js 做全棧開發(fā),開始由前端工程師向全棧工程師的方向轉(zhuǎn)變。這是前端主動突破自己的邊界。

另一方面,前端在發(fā)展,后端也在發(fā)展。也差不多在 Node.js 誕生那個時代,后端普遍開始由巨石應(yīng)用模式由微服務(wù)架構(gòu)轉(zhuǎn)變。這也就導(dǎo)致以往的前后端分工出現(xiàn)了分歧。隨著微服務(wù)架構(gòu)的興起,后端的接口漸漸變得原子性,微服務(wù)的接口也不再直接面向頁面,前端的調(diào)用變得復(fù)雜了。于是 BFF(Backend For Frontend)架構(gòu)應(yīng)運而生,在微服務(wù)和前端中間,加了一個 BFF 層,由 BFF 對接口進行聚合、裁剪后,再輸出給前端。而 BFF 這層不是后端本質(zhì)工作,且距離前端最近和前端關(guān)系最大,所以前端工程師自然而然選擇了 Node.js 來實現(xiàn)。這也是當前 Node.js 在服務(wù)端較為廣泛的應(yīng)用。

下一代前端開發(fā)模式

可以看到,每一次前端開發(fā)模式的變化,都因某個變革性的技術(shù)而起。先是 AJAX,而后是 Node.js。那么下一個變革性的技術(shù)是什么?不言而喻,就是 Serverless。

Serverless 服務(wù)中的前端解決方案

Serverless 簡介

根據(jù) CNCF 的定義,Serverless 是指構(gòu)建和運行不需要服務(wù)器管理的應(yīng)用程序的概念。(serverless-overview)

Serverless computing refers to the concept of building and running applications that do not require server management. —- CNCF

其實 Serverless 早已和前端產(chǎn)生了聯(lián)系,只是我們可能沒有感知。比如 CDN,我們把靜態(tài)資源發(fā)布到 CDN 之后,就不需要關(guān)心 CDN 有多少個節(jié)點、節(jié)點如何分布,也不需要關(guān)心它如何做負載均衡、如何實現(xiàn)網(wǎng)絡(luò)加速,所以 CDN 對前端來說是 Serverless。再比如對象存儲,和 CDN 一樣,我們只需要將文件上傳到對象存儲,就可以直接使用了,不需要關(guān)心它如何存取文件、如何進行權(quán)限控制,所以對象存儲對前端工程師來說是 Serverless。甚至一些第三方的 API 服務(wù),也是 Serverless,因為我們使用的時候,不需要去關(guān)心服務(wù)器。

當然,有了體感還不夠,我們還是需要一個更精確的定義。從技術(shù)角度來說,Serverless 就是 FaaS 和 BaaS 的結(jié)合。

Serverless = FaaS + BaaS。

簡單來講,F(xiàn)aaS(Function as a Service) 就是一些運行函數(shù)的平臺,比如阿里云的函數(shù)計算、AWS 的 Lambda 等。

BaaS(Backend as a Service)則是一些后端云服務(wù),比如云數(shù)據(jù)庫、對象存儲、消息隊列等。利用 BaaS,可以極大簡化我們的應(yīng)用開發(fā)難度。

Serverless 則可以理解為運行在 FaaS 中的,使用了 BaaS 的函數(shù)。

Serverless 的主要特點有:

  • 事件驅(qū)動

  • 函數(shù)在 FaaS 平臺中,需要通過一系列的事件來驅(qū)動函數(shù)執(zhí)行。

  • 無狀態(tài)

  • 因為每次函數(shù)執(zhí)行,可能使用的都是不同的容器,無法進行內(nèi)存或數(shù)據(jù)共享。如果要共享數(shù)據(jù),則只能通過第三方服務(wù),比如 Redis 等。

  • 無運維

  • 使用 Serverless 我們不需要關(guān)心服務(wù)器,不需要關(guān)心運維。這也是 Serverless 思想的核心。

  • 低成本

  • 使用 Serverless 成本很低,因為我們只需要為每次函數(shù)的運行付費。函數(shù)不運行,則不花錢,也不會浪費服務(wù)器資源

Serverless 服務(wù)中的前端解決方案架構(gòu)圖

上圖是當前主要的一些 Serverless 服務(wù),以及對應(yīng)的前端解決方案。

從下往上,分別是基礎(chǔ)設(shè)施和開發(fā)工具。

基礎(chǔ)設(shè)施主要是一些云計算廠商提供,包括云計算平臺和各種 BaaS 服務(wù),以及運行函數(shù)的 FaaS 平臺。

前端主要是 Serverless 的使用者,所以對前端來說,最重要的開發(fā)工具這一層,我們需要依賴開發(fā)工具進行 Serverless 開發(fā)、調(diào)試和部署。

框架(Framework)

如今還沒有一個統(tǒng)一的 Serverless 標準,不同云計算平臺提供的 Serverless 服務(wù)很可能是不一樣的,這就導(dǎo)致我們的代碼,無法平滑遷移。Serverless 框架一個主要功能是簡化 Serverless 開發(fā)、部署流程,另一主要功能則是屏蔽不同 Serverless 服務(wù)中的差異,讓我們的函數(shù)能夠在不改動或者只改動很小一部分的情況下,在其他 Serverless 服務(wù)中也能運行。

常見的 Serverless 框架有 Serverless Framework、ZEIT Now、Apex 等。不過這些基本都是國外公司做的,國內(nèi)還沒有這樣的平臺。

Web IDE

和 Serverless 緊密相關(guān)的 Web IDE 主要也是各個云計算平臺的 Web IDE。利用 Web IDE,我們可以很方便地在云端開發(fā)、調(diào)試函數(shù),并且可以直接部署到對應(yīng)的 FaaS 平臺。這樣的好處是避免了在本地安裝各種開發(fā)工具、配置各種環(huán)境。常見的 Web IDE 有 AWS 的 Cloud9、阿里云的函數(shù)計算 Web IDE、騰訊云的 Cloud Studio。從體驗上來說,AWS Cloud9 最好。

命令行工具

當然,目前最主要的開發(fā)方式還是在本地進行開發(fā)。所以在本地開發(fā) Serverless 的命令行工具也必不可少。

命令行工具主要有兩類,一類是云計算平臺提供的,如 AWS 的 aws、 Azure 的 az、阿里云的 fun;還有一類是 Serverless 框架提供的,如 serverless、now。

大部分工具如 serverless、fun 等,都是用 Node.js 實現(xiàn)的。

下面是幾個命令行工具的例子。

創(chuàng)建
# serverless
$ serverless create --template aws-nodejs --path myService
# fun
$ fun init -n qcondemo helloworld-nodejs8
部署
# serverless
$ serverless deploy
# fun
$ fun deploy
調(diào)試
# serverless
$ serverless invoke [local] --function functionName
# fun
$ fun local invoke functionName
應(yīng)用場景

在開發(fā)工具上面一層,則是 Serverless 的一些垂直應(yīng)用場景。除了使用傳統(tǒng)的服務(wù)端開發(fā),目前使用 Serverless 技術(shù)的還有小程序開發(fā),未來可能還會設(shè)計物聯(lián)網(wǎng)領(lǐng)域(IoT)。

不同 Serverless 服務(wù)的對比

上圖從支持語言、觸發(fā)器、價格等多個方面對不同 Serverless 服務(wù)進行了對比,可以發(fā)現(xiàn)有差異,也有共性。

比如幾乎所有 Serverless 服務(wù)都支持 Node.js/Python/Java 等語言。

從支持的觸發(fā)器來看,幾乎所有服務(wù)也都支持 HTTP、對象存儲、定時任務(wù)、消息隊列等觸發(fā)器。當然,這些觸發(fā)器也與平臺自己的后端服務(wù)相關(guān),比如阿里云的對象存儲觸發(fā)器,是基于阿里云的 OSS 產(chǎn)品的存取等事件觸發(fā)的;而 AWS 的對象存儲觸發(fā)器,則是基于 AWS 的 S3 的事件觸發(fā)的,兩個平臺并不通用。這也是當前 Serverless 面臨的一個問題,就是標準不統(tǒng)一。

從計費的角度來看,各個平臺的費用基本一致。在前面也提到,Serverless 的計費是按調(diào)用次數(shù)計費。對于各個 Serverless,每個月都有 100 萬次的免費調(diào)用次數(shù),之后差不多 ¥1.3/百萬次;以及 400,000 GB-s 的免費執(zhí)行時間,之后 ¥0.0001108/GB-s。所以在應(yīng)用體量較小的時候,使用 Serverless 是非常劃算的。

基于 Serverless 的前端開發(fā)模式

在本章節(jié),主要以幾個案例來說明基于 Serverless 的前端開發(fā)模式,以及它和以往的前端開發(fā)有什么不一樣。

在開始具體的案例之前,先看一下傳統(tǒng)開發(fā)流程。

在傳統(tǒng)開發(fā)流程中,我們需要前端工程師寫頁面,后端工程師寫接口。后端寫完接口之后,把接口部署了,再進行前后端聯(lián)調(diào)。聯(lián)調(diào)完畢后再測試、上線。上線之后,還需要運維工程師對系統(tǒng)進行維護。整個過程涉及多個不同角色,鏈路較長,溝通協(xié)調(diào)也是一個問題。

而基于 Serverless,后端變得非常簡單了,以往的后端應(yīng)用被拆分為一個個函數(shù),只需要寫完函數(shù)并部署到 Serverless 服務(wù)即可,后續(xù)也不用關(guān)心任何服務(wù)器的運維操作。后端開發(fā)的門檻大幅度降低了。因此,只需要一個前端工程師就可以完成所有的開發(fā)工作。

當然,前端工程師基于 Serverless 去寫后端,最好也需要具備一定的后端知識。涉及復(fù)雜的后端系統(tǒng)或者 Serverless 不適用的場景,還是需要后端開發(fā),后端變得更靠后了。

基于 Serverless 的 BFF

一方面,對不同的設(shè)備需要使用不同的 API,另一方面,由于微服務(wù)導(dǎo)致前端接口調(diào)用的復(fù)雜,所以前端工程師開始使用 BFF 的方式,對接口進行聚合裁剪,以得到適用于前端的接口。
下面是一個通用的 BFF 架構(gòu)。

最底層的就是各種后端微服務(wù),最上層就是各種前端應(yīng)用。在微服務(wù)和應(yīng)用之前,就是通常由前端工程師開發(fā)的 BFF。

這樣的架構(gòu)解決了接口協(xié)調(diào)的問題,但也帶來了一些新的問題。

比如針對每個設(shè)備開發(fā)一個 BFF 應(yīng)用,也會面臨一些重復(fù)開發(fā)的問題。而且以往前端只需要開發(fā)頁面,關(guān)注于瀏覽器端的渲染即可,現(xiàn)在卻需要維護各種 BFF 應(yīng)用。以往前端也不需要關(guān)心并發(fā),現(xiàn)在并發(fā)壓力卻集中到了 BFF 上??偟膩碚f運維成本非常高,通常前端并不擅長運維。

Serverless 則可以幫我們很好的解決這些問題?;?Serverless,我們可以使用一個個函數(shù)來實各個接口的聚合裁剪。前端向 BFF 發(fā)起的請求,就相當于是 FaaS 的一個 HTTP 觸發(fā)器,觸發(fā)一個函數(shù)的執(zhí)行,這個函數(shù)中來實現(xiàn)針對該請求的業(yè)務(wù)邏輯,比如調(diào)用多個微服務(wù)獲取數(shù)據(jù),然后再將處理結(jié)果返回給前端。這樣運維的壓力,就由以往的 BFF Server 轉(zhuǎn)向了 FaaS 服務(wù),前端再也不用關(guān)心服務(wù)器了。

上圖則是基于 Serverless 的 BFF 架構(gòu)。為了更好的管理各種 API,我們還可以添加網(wǎng)關(guān)層,通過網(wǎng)關(guān)來管理所有 API(比如阿里云的網(wǎng)關(guān)),比如對 API 進行分組、分環(huán)境?;?API 網(wǎng)關(guān),前端就不直接通過 HTTP 觸發(fā)器來執(zhí)行函數(shù),而是將請求發(fā)送至網(wǎng)關(guān),再由網(wǎng)關(guān)去觸發(fā)具體的函數(shù)來執(zhí)行。

基于 Serverless 的服務(wù)端渲染

基于當下最流行的三大前端框架(React.js/Anguler/Vue.js),現(xiàn)在的渲染方式大部分都是客戶端渲染。頁面初始化的時候,只加載一個簡單 HTML 以及對應(yīng)的 JS 文件,再由 JS 來渲染出一個個頁面。這種方式最主要的問題就是白屏?xí)r間和 SEO。

為了解決這個問題,前端又開始嘗試服務(wù)端渲染。本質(zhì)思想其實和最早的模板渲染是一樣的。都是前端發(fā)起一個請求,后端 Server 解析出一個 HTML 文檔,然后再返回給瀏覽器。只不過以往是 JSP、PHP 等服務(wù)端語言的模板,現(xiàn)在是基于 React、Vue 等實現(xiàn)的同構(gòu)應(yīng)用,這也是如今的服務(wù)端渲染方案的優(yōu)勢。

但服務(wù)端渲染又為前端帶來了一些額外的問題:運維成本,前端需要維護用于渲染的服務(wù)器。

Serverless 最大的優(yōu)點就是可以幫我們減少運維,那 Serverless 能不能用于服務(wù)端渲染呢?當然也是可以的。

傳統(tǒng)的服務(wù)端渲染,每個請求的 path 都對應(yīng)著服務(wù)端的每個路由,由該路由實現(xiàn)對應(yīng) path 的 HTML 文檔渲染。用于渲染的服務(wù)端程序,就是這些集成了這些路由的應(yīng)用。

使用 Serverless 來做服務(wù)端渲染,就是將以往的每個路由,都拆分為一個個函數(shù),再在 FaaS 上部署對應(yīng)的函數(shù)。這樣用戶請求的 path,對應(yīng)的就是每個單獨的函數(shù)。通過這種方式,就將運維操作轉(zhuǎn)移到了 FaaS 平臺,前端做服務(wù)端渲染,就不用再關(guān)心服務(wù)端程序的運維部署了。

ZEIT 的 Next.js 就對基于 Serverless 的服務(wù)端渲染做了很好的實現(xiàn)。下面就是一個簡單的例子。

代碼結(jié)構(gòu)如下:

.
├── next.config.js
├── now.json
├── package.json
└── pages
├── about.js
└── index.js
// next.config.js
module.exports = {
target: 'serverless'
}

其中 pages/about.js 和 pages/index.js 就是兩個頁面,在 next.config.js 配置了使用 Zeit 提供的 Serverless 服務(wù)。

然后使用 now 這個命令,就可以將代碼以 Serverless 的方式部署。部署過程中,pages/about.js 和 pages/index.js 就分別轉(zhuǎn)換為兩個函數(shù),負責(zé)渲染對應(yīng)的頁面。

基于 Serverless 的小程序開發(fā)

目前國內(nèi)使用 Serverless 較多的場景可能就是小程開發(fā)了。具體的實現(xiàn)就是小程序云開發(fā),支付寶小程序和微信小程序都提供了云開發(fā)功能。

在傳統(tǒng)的小程序開發(fā)中,我們需要前端工程師進行小程序端的開發(fā);后端工程師進行服務(wù)端的開發(fā)。小程序的后端開發(fā)和其他的后端應(yīng)用開發(fā),本質(zhì)是是一樣的,需要關(guān)心應(yīng)用的負載均衡、備份冗災(zāi)、監(jiān)控報警等一些列部署運維操作。如果開發(fā)團隊人很少,可能還需要前端工程師去實現(xiàn)服務(wù)端。

但基于云開發(fā),就只需要讓開發(fā)者關(guān)注于業(yè)務(wù)的實現(xiàn),由一個前端工程師就能夠完成整個應(yīng)用的前后端開發(fā)。因為云開發(fā)將后端封裝為了 BaaS 服務(wù),并提供了對應(yīng)的 SDK 給開發(fā)者,開發(fā)者可以像調(diào)用函數(shù)一樣使用各種后端服務(wù)。應(yīng)用的運維也轉(zhuǎn)移到了提供云開發(fā)的服務(wù)商。

下面分別是使用支付寶云開發(fā)(Basement)的一些例子,函數(shù)就是定義在 FaaS 服務(wù)中的函數(shù)。

操作數(shù)據(jù)庫

// `basement` 是一個全局變量
// 操作數(shù)據(jù)庫
basement.db.collection('users')
.insertOne({
name: 'node',
age: 18,
})
.then(() => {
resolve({ success: true });
})
.catch(err => {
reject({ success: false });
});

上傳圖片

// 上傳圖片
basement.file
.uploadFile(options)
.then((image) => {
this.setData({
iconUrl: image.fileUrl,
});
})
.catch(console.error);

調(diào)用函數(shù)

// 調(diào)用函數(shù)
basement.function
.invoke('getUserInfo')
.then((res) => {
this.setData({
user: res.result
});
})
.catch(console.error}
通用 Serverless 架構(gòu)

基于上述幾個 Serverless 開發(fā)的例子,就可以總結(jié)出一個通用的 Serverless 架構(gòu)。

其中最底層就是實現(xiàn)復(fù)雜業(yè)務(wù)的后端微服務(wù)(Backend)。然后 FaaS 層通過一系列函數(shù)實現(xiàn)業(yè)務(wù)邏輯,并為前端直接提供服務(wù)。對于前端開發(fā)者來說,前端可以通過編寫函數(shù)的方式來實現(xiàn)服務(wù)端的邏輯。對于后端開發(fā)者來說,后端變得更靠后了。如果業(yè)務(wù)比較較淡,F(xiàn)aaS 層能夠?qū)崿F(xiàn),甚至也不需要微服務(wù)這一層了。

同時不管是在后端、FaaS 還是前端,我們都可以去調(diào)用云計算平臺提供的 BaaS 服務(wù),大大降低開發(fā)難度、減少開發(fā)成本。小程序云開發(fā),就是直接在前端調(diào)用 BaaS 服務(wù)的例子。

Serverless 開發(fā)最佳實踐

基于 Serverless 開發(fā)模式和傳統(tǒng)開發(fā)模式最大的不同,就是傳統(tǒng)開發(fā)中,我們是基于應(yīng)用的開發(fā)。開發(fā)完成后,我們需要對應(yīng)用進行單元測試和集成測試。而基于 Serverless,開發(fā)的是一個個函數(shù),那么我們應(yīng)該如
何對 Serverless 函數(shù)進行測試?Serverless 函數(shù)的測試和普通的單元測試又有什么區(qū)別?

還有一個很重要的點是,基于 Serverless 開發(fā)的應(yīng)用性能如何?應(yīng)該怎么去提高 Serverless 應(yīng)用的性能?

本章主要就介紹一下,基于 Serverless 的函數(shù)的測試和函數(shù)的性能兩個方面的最佳實踐。

函數(shù)的測試

雖然使用 Serverless 我們可以簡單地進行業(yè)務(wù)的開發(fā),但它的特性也給我們的測試帶來了一些挑戰(zhàn)。主要有以下幾個方面。

Serverless 函數(shù)是分布式的,我們不知道也無需知道函數(shù)是部署或運行在哪臺機器上,所以我們需要對每個函數(shù)進行單元測試。Serverless 應(yīng)用是由一組函數(shù)組成的,函數(shù)內(nèi)部可能依賴了一些別的后端服務(wù)(BaaS),所以我們也需要對 Serverless 應(yīng)用進行集成測試。

運行函數(shù)的 FaaS 和 BaaS 在本地也難以模擬。除此之外,不同平臺提供的 FaaS 環(huán)境可能不一致,不平臺提供的 BaaS 服務(wù)的 SDK 或接口也可能不一致,這不僅給我們的測試帶來了一些問題,也增加了應(yīng)用遷移成本。

函數(shù)的執(zhí)行是由事件驅(qū)動的,驅(qū)動函數(shù)執(zhí)行的事件,在本地也難以模擬。

那么如何解決這些問題呢?

根據(jù) Mike Cohn 提出的測試金字塔,單元測試的成本最低,效率最高;UI 測試(集成)測試的成本最高,效率最低,所以我們要盡可能多的進行單元測試,從而減少集成測試。這對 Serverless 的函數(shù)測試同樣適用。

為了能更簡單對函數(shù)進行單元測試,我們需要做的就是將業(yè)務(wù)邏輯和函數(shù)依賴的 FaaS(如函數(shù)計算) 和 BaaS (如云數(shù)據(jù)庫)分離。當 FaaS 和 BaaS 分離出去之后,我們就可以像編寫傳統(tǒng)的單元測試一樣,對函數(shù)的業(yè)務(wù)邏輯進行測試。然后再編寫集成測試,驗證函數(shù)和其他服務(wù)的集成是否正常工作。

一個糟糕的例子

下面是一個使用 Node.js 實現(xiàn)的函數(shù)的例子。該函數(shù)做的事情就是,首先將用戶信息存儲到數(shù)據(jù)庫中,然后給用戶發(fā)送郵件。

const db = require('db').connect();
const mailer = require('mailer');

module.exports.saveUser = (event, context, callback) => {
const user = {
email: event.email,
created_at: Date.now()
}

db.saveUser(user, function (err) {
if (err) {
callback(err);
} else {
mailer.sendWelcomeEmail(event.email);
callback();
}
});
};

這個例子主要存在兩個問題:

  • 業(yè)務(wù)邏輯和 FaaS 耦合在一起。主要就是業(yè)務(wù)邏輯都在 saveUser 這個函數(shù)里,而 saveUser 參數(shù)的 event 和 conent 對象,是 FaaS 平臺提供的。

  • 業(yè)務(wù)邏輯和 BaaS 耦合在一起。具體來說,就是函數(shù)內(nèi)使用了 db 和 mailer 這兩個后端服務(wù),測試函數(shù)必須依賴于 db 和 mailer。

編寫可測試的函數(shù)

基于將業(yè)務(wù)邏輯和函數(shù)依賴的 FaaS 和 BaaS 分離的原則,對上面的代碼進行重構(gòu)。

class Users {
constructor(db, mailer) {
this.db = db;
this.mailer = mailer;
}

save(email, callback) {
const user = {
email: email,
created_at: Date.now()
}

this.db.saveUser(user, function (err) {
if (err) {
callback(err);
} else {
this.mailer.sendWelcomeEmail(email);
callback();
}
});
}
}

module.exports = Users;
const db = require('db').connect();
const mailer = require('mailer');
const Users = require('users');

let users = new Users(db, mailer);

module.exports.saveUser = (event, context, callback) => {
users.save(event.email, callback);
};

在重構(gòu)后的代碼中,我們將業(yè)務(wù)邏輯全都放在了 Users 這個類里面,Users 不依賴任何外部服務(wù)。測試的時候,我們也可以不傳入真實的 db 或 mailer,而是傳入模擬的服務(wù)。

下面是一個模擬 mailer 的例子。

// 模擬 mailer
const mailer = {
sendWelcomeEmail: (email) => {
console.log(`Send email to ${email} success!`);
},
};

這樣只要對 Users 進行充分的單元測試,就能確保業(yè)務(wù)代碼如期運行。
然后再傳入真實的 db 和 mailer,進行簡單的集成測試,就能知道整個函數(shù)是否能夠正常工作。
重構(gòu)后的代碼還有一個好處是方便函數(shù)的遷移。當我們想要把函數(shù)從一個平臺遷移到另一個平臺的時候,只需要根據(jù)不同平臺提供的參數(shù),修改一下 Users 的調(diào)用方式就可以了,而不用再去修改業(yè)務(wù)邏輯。

小結(jié)

綜上所述,對函數(shù)進行測試,就需要牢記金字塔原則,并遵循以下原則:

  • 將業(yè)務(wù)邏輯和函數(shù)依賴的 FaaS 和 BaaS 分離

  • 對業(yè)務(wù)邏輯進行充分的單元測試

  • 將函數(shù)進行集成測試驗證代碼是否正常工作

函數(shù)的性能

使用 Serverless 進行開發(fā),還有一個大家都關(guān)心的問題就是函數(shù)的性能怎么樣。

對于傳統(tǒng)的應(yīng)用,我們的程序啟動起來之后,就常駐在內(nèi)存中;而 Serverless 函數(shù)則不是這樣。

當驅(qū)動函數(shù)執(zhí)行的事件到來的時候,首先需要下載代碼,然后啟動一個容器,在容器里面再啟動一個運行環(huán)境,最后才是執(zhí)行代碼。前幾步統(tǒng)稱為冷啟動(Cold Start)。傳統(tǒng)的應(yīng)用沒有冷啟動的過程。

下面是函數(shù)生命周期的示意圖:

冷啟動時間的長短,就是函數(shù)性能的關(guān)鍵因素。優(yōu)化函數(shù)的性能,也就需要從函數(shù)生命周期的各個階段去優(yōu)化。

不同編程語言對冷啟動時間的影響

在此之前,已經(jīng)有很多人測試過不同編程語言對冷啟動時間的影響,比如:

  • Compare coldstart time with different languages, memory and code sizes -by Yan Cui

  • Cold start / Warm start with AWS Lambda - by Erwan Alliaume

  • Serverless: Cold Start War - by Mikhail Shilkov

從這些測試中能夠得到一些統(tǒng)一的結(jié)論:

  • 增加函數(shù)的內(nèi)存可以減少冷啟動時間

  • C#、Java 等編程語言的能啟動時間大約是 Node.js、Python 的 100 倍

基于上述結(jié)論,如果想要 Java 的冷啟動時間達到 Node.js 那么小,可以為 Java 分配更大的內(nèi)存。但更大的內(nèi)存意味著更多的成本。

函數(shù)冷啟動的時機

剛開始接觸 Serverless 的開發(fā)者可能有一個誤區(qū),就是每次函數(shù)執(zhí)行,都需要冷啟動。其實并不是這樣。
當?shù)谝淮握埱螅?qū)動函數(shù)執(zhí)行的事件)來臨,成功啟動運行環(huán)境并執(zhí)行函數(shù)之后,運行環(huán)境會保留一段時間,以便用于下一次函數(shù)執(zhí)行。這樣就能減少冷啟動的次數(shù),從而縮短函數(shù)運行時間。當請求達到一個運行環(huán)境的限制時,F(xiàn)aaS 平臺會自動擴展下一個運行環(huán)境。

以 AWS Lambda 為例,在執(zhí)行函數(shù)之后,Lambda 會保持執(zhí)行上下文一段時間,預(yù)期用于另一次 Lambda 函數(shù)調(diào)用。其效果是,服務(wù)在 Lambda 函數(shù)完成后凍結(jié)執(zhí)行上下文,如果再次調(diào)用 Lambda 函數(shù)時 AWS Lambda 選擇重用上下文,則解凍上下文供重用。

下面以兩個小測試來說明上述內(nèi)容。

我使用阿里云的函數(shù)計算實現(xiàn)了一個 Serverless 函數(shù),并通過 HTTP 事件來驅(qū)動。然后使用不同并發(fā)數(shù)向函數(shù)發(fā)起 100 個請求。

首先是一個并發(fā)的情況:

可以看到第一個請求時間為 302ms,其他請求時間基本都在 50ms 左右?;揪湍艽_定,第一個請求對應(yīng)的函數(shù)是冷啟動,剩余 99 個請求,都是熱啟動,直接重復(fù)利用了第一個請求的運行環(huán)境。

接下來是并發(fā)數(shù)為 10 的情況:

可以發(fā)現(xiàn),前 10 個請求,耗時基本在 200ms-300ms,其余請求耗時在 50ms 左右。于是可以得出結(jié)論,前 10 個并發(fā)請求都是冷啟動,同時啟動了 10 個運行環(huán)境;后面 90 個請求都是熱啟動。
這也就印證了之前的結(jié)論,函數(shù)不是每次都冷啟動,而是會在一定時間內(nèi)復(fù)用之前的運行環(huán)境。

執(zhí)行上下文重用

上面的結(jié)論對我們提高函數(shù)性能有什么幫助呢?當然是有的。既然運行環(huán)境能夠保留,那就意味著我們能對運行環(huán)境中的執(zhí)行上下文進行重復(fù)利用。
來看一個例子:

const mysql = require('mysql');

module.exports.saveUser = (event, context, callback) => {

// 初始化數(shù)據(jù)庫連接
const connection = mysql.createConnection({ /* ... */ });
connection.connect();

connection.query('...');

};

上面例子實現(xiàn)的功能就是在 saveUser 函數(shù)中初始化一個數(shù)據(jù)庫連接。這樣的問題就是,每次函數(shù)執(zhí)行的時候,都會重新初始化數(shù)據(jù)庫連接,而連接數(shù)據(jù)庫又是一個比較耗時的操作。顯然這樣對函數(shù)的性能是沒有好處的。

既然在短時間內(nèi),函數(shù)的執(zhí)行上下文可以重復(fù)利用,那么我們就可以將數(shù)據(jù)庫連接放在函數(shù)之外:

const mysql = require('mysql');

// 初始化數(shù)據(jù)庫連接
const connection = mysql.createConnection({ /* ... */ });
connection.connect();


module.exports.saveUser = (event, context, callback) => {

connection.query('...');

};

這樣就只有第一次運行環(huán)境啟動的時候,才會初始化數(shù)據(jù)庫連接。后續(xù)請求來臨、執(zhí)行函數(shù)的時候,就可以直接利用執(zhí)行上下文中的 connection,從而提后續(xù)高函數(shù)的性能。
大部分情況下,通過犧牲一個請求的性能,換取大部分請求的性能,是完全可以夠接受的。

給函數(shù)預(yù)熱

既然函數(shù)的運行環(huán)境會保留一段時間,那么我們也可以通過主動調(diào)用函數(shù)的方式,隔一段時間就冷啟動一個運行
環(huán)境,這樣就能使得其他正常的請求都是熱啟動,從而避免冷啟動時間對函數(shù)性能的影響。
這是目前比較有效的方式,但也需要有一些注意的地方:

  • 不要過于頻繁調(diào)用函數(shù),至少頻率要大于 5 分鐘

  • 直接調(diào)用函數(shù),而不是通過網(wǎng)關(guān)等間接調(diào)用

  • 創(chuàng)建專門處理這種預(yù)熱調(diào)用的函數(shù),而不是正常業(yè)務(wù)函數(shù)

這種方案只是目前行之有效且比較黑科技的方案,可以使用,但如果你的業(yè)務(wù)允許“犧牲第一個請求的性能換取大部分性能”,那也完全不必使用該方案,

小結(jié)

總體而言,優(yōu)化函數(shù)的性能就是優(yōu)化冷啟動時間。上述方案都是開發(fā)者方面的優(yōu)化,當然還一方面主要是 FaaS 平臺的性能優(yōu)化。

總結(jié)一下上述方案,主要是以下幾點:

  • 選用 Node.js / Python 等冷啟動時間短的編程語言

  • 為函數(shù)分配合適的運行內(nèi)存

  • 執(zhí)行上下文重用

  • 為函數(shù)預(yù)熱

總結(jié)

作為前端工程師,我們一直在探討前端的邊界是什么?,F(xiàn)在的前端開發(fā)早已不是以往的前端開發(fā),前端不僅可以做網(wǎng)頁,還可以做小程序,做 APP,做桌面程序,甚至做服務(wù)端。而前端之所以在不斷拓展自己的邊界、不斷探索更多的領(lǐng)域,則是希望自己能夠產(chǎn)生更大的價值。最好是用我們熟悉的工具、熟悉的方式來創(chuàng)造價值。

而 Serverless 架構(gòu)的誕生,則可以最大程度幫助前端工程師去實現(xiàn)自己的理想。使用 Serverless,我們不需要再過多關(guān)注服務(wù)端的運維,不需要關(guān)心我們不熟悉的領(lǐng)域,我們只需要專注于業(yè)務(wù)的開發(fā)、專注于產(chǎn)品的實現(xiàn)。我們需要關(guān)心的事情變少了,但我們能做的事情更多了。

Serverless 也必將對前端的開發(fā)模式產(chǎn)生巨大的變革,前端工程師的職能也將再度回歸到應(yīng)用工程師的職能。

如果要用一句話來總結(jié) Serverless,那就是 Less is More。

關(guān)于本文
作者:蔣航
原文:https://zhuanlan.zhihu.com/p/65914436



最后


  • 歡迎加我微信(winty230),拉你進技術(shù)群,長期交流學(xué)習(xí)...

  • 歡迎關(guān)注「前端Q」,認真學(xué)前端,做個專業(yè)的技術(shù)人...

點個在看支持我吧
瀏覽 62
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點贊
評論
收藏
分享

手機掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 麻豆91精品91久久久| 国产欧美视频在线| 一区二区三区四区av| 三级在线观看视频| 欧美性爱在线| 欧美成人精品三级网站| 亚洲免费视频播放| 影音先锋无码AV| 不卡视频一区| 老熟女痒到不行-ThePorn | 激情六月婷婷| 91天天在线| 亚洲a网| 青娱乐AV| 精品久久大香蕉| 十八禁在线播放| 四虎国产精品成人久久| 五月婷婷六月婷婷| 3D动漫精品啪啪一区二区免费| 日本一区二区三区四区在线观看 | 久久无码高清视频| 亚洲欧美婷婷五月色综合| 四个熟妇搡BBBB搡BBBB| 成人无码视频| 国产中文自拍| 91狠狠综合久久久| 九九r在线精品观看视频| A片国产| 亚洲日韩久久| 欧美成人日韩| 人妻骚逼| 成年人免费公开视频| 亚洲中文字幕影院| 人人操成人| 91探花秘在线播放偷拍| 99久久99久国产黄毛片| 欧美性猛交XXXX乱大交HD| 午夜精品秘一区二区三区| 九热精品| 国产av影视| 日韩三级黄色| 精品自拍视频| 清清草在线视频| 91探花国产综合在线精品| 午夜福利免费在线观看| 国产一级a一级a免费视频| 成人在线看片| 日韩欧美精品在线观看| 久久久久国产精品视频| av资源站| 成人片网站在线观看| 国精产品一区一区三区四川| 国产欧美综合在线观看| 国产一卡二卡三卡| 青青草视频91| 91香蕉视频在线播放| 琪琪色五月天| 蝌蚪窝视频在线观看| 欧美成人电影在线观看| 人人色人人摸| 日韩精品视频一区二区三区| 91大神免费观看| 精东影业AV无码精品| 无码不卡视频在线观看| 射死你天天日| 久久99精品久久久久| 97在线国产| 亚洲va欧美va| 熟妇人妻中文字幕无码老熟妇| 亚洲AV女人18毛片水真多| 无码人妻一区二区三区| 亚洲成人av无码| 亚洲成人在线视频| 欧美午夜无码| 西西444WWW无码视频软件| 日日干天天射| 在线视频内射| 久久99精品国产| 小h片| 色综合网址| 精品午夜福利| 国产一级生活片| 奇米影视亚洲春色| 小h片| 成人在线看片| 久久婷婷国产| 亚洲精品一区二区三区无码电影| AV日逼网| 国产精品乱| 亚洲精品无码一区| 免费激情网站| 午夜福利爱爱视频| 中文字幕一区三区人妻视频| 国产一区二区三区免费| 北条麻妃一区二区三区在线播放 | 亚洲伦理一区二区| 人人爽人人爽人人爽| 日韩在线视频不卡| 先锋成人资源| 天天舔天天干| 国产成人片色情AAAA片| 99久久久久久| 国产麻豆精品成人免费视频| 国产成人精品无码片区在线观91 | 3D动漫精品一区二区在线播放免费| 亚洲天堂天天| 欧美精品三级| 天天精品视频| 天天搞天天色| 亚洲无码AV电影| 无码精品人妻| 吴梦梦无码| 免费a在线| 久久国产99| 黄色小说在线播放| 国产日韩欧美在线| 翔田AV无码秘三区| H网站在线观看| 俺来也俺去啦欧美www| 华女与黑人91A∨| 天天天天天天天干| 亚洲视频99| 国产www| 亚洲免费黄色视频| 国产超碰青青草| 黑人干亚洲| 亚洲成人性爱网| 日韩在线一| 国产欧美精品一区二区三区 | 色欲av伊人久久大香线蕉影院 | 韩国三级AV| 久久综合电影| 狠狠插狠狠操| 日韩激情一区二区| 少妇无码一区| 91av电影| 久久人人超碰| 在线观看中文字幕亚洲| 轻轻操内射无码| 国产av中文字幕| 少妇高潮喷水视频| 一区无码高清| 丁香激情视频| 九九色综合| 成人中文字幕在线| 日韩成年视频| 男女91视频| 国产香蕉视频免费| 亚洲av影院| 亚洲xxxxx| 国产无码AV在线| 日本在线观看www| 日韩激情无码视频精选| 精品国产乱子伦一区二区三区最新章| 91丨PORNY丨丰满人妻网站| 国产愉拍91九色国产愉拍| 在线看一区二区三区| 韩国深夜福利视频| 日产久久视频| 五月丁香婷婷在线| 日韩成年视频| 五月丁香婷婷啪啪| 成人网站一区二区| 任你爽在线视频| 一区二区无码视频| 大香蕉性爱视频| 亚洲AV无码成人精品区大猫| 久久精品秘一区二区三免费| 3D动漫操逼视频| 天天综合网站| 国产操逼免费| 国产无码内射| 一本大道东京热av无码| 一级黄色视频在线观看| 亚洲无码在线免费视频| 久草毛片| 北条麻妃AV在线播放| 高清无码视频免费看| 亚洲Av在线观看| 免费看毛片中文字幕| 无码高清在线播放| 手机看片久久| 亚洲欧美视频在线| 成人免费毛片蓝莓| 可以免费看AV的网站| 日韩操屄视频| 在线亚洲欧洲| 成人做爰100片免费视频| av色图| 日本a片| 免费看黃色AAAAAA片| 午夜福利资源| 日韩中文字幕高清| 一区二区日本| 黑人猛躁白人BBBBBBBBB| 麻豆91精品91久久久| 日本欧美一区二区三区| 狠狠色噜噜狠狠狠888| 天天夜夜狠狠| 成人亚洲性情网站www在线| 九九九在线观看视频| 青娱乐三级在线免| 国产视频久久| 第一页在线| 欧美精产国品一区二区区别| 人妻丰满精品一区二区| 影音先锋黄色资源| 少妇搡BBBB搡BBB搡18禁| 亚洲超级高清无码第一在线视频观看 | 啪啪视频免费观看| 国产无遮挡又黄又爽又色| 国产丝袜自拍| 精品国产va久久久久久久| 日韩成人大片| 无码9999| 亚欧一区二区| 777色色色| 竹菊传媒一区二区三区| 黄色A片免费视频| 精品成人影视| 北条麻妃一区二区三区在线播放| 亚洲AV无码久久寂寞少妇多毛| 中文字幕精品久久久久人妻红杏Ⅰ | 探花在线播放| 91国在线视频| 内射视频网| 亚洲国产中文字幕在线播放| 蝌蚪窝在线免费观看视频| 亚洲国产一区二区三区四区| 亚洲去干网| 第四色网站| 在线看片国产| 狠狠干老司机| 久久久久亚洲AV无码成人片| 婷婷色情网| 午夜AV在线播放| 手机在线一区| 欧美三级欧美一级| 一区免费在线观看| 中文字幕AV网| 国产午夜福利视频在线观看| 麻豆91精品91久久久停运原因| 精品AV无码一区二区三区| 在线综合国产欧美| 日韩在线免费观看视频| 无码视频免费在线观看| 91在线精品无码秘入口苹果 | 国精品无码人妻一区二区三区| 丁香视频在线观看| 国产波霸爆乳一区二区| 亚洲综合网在线观看| 激情婷婷六月| 亚洲va综合va国产va中文 | 翔田千里珍藏版无码| 国产激情无码视频| 黄色A级毛片| 永久免费一区二区三区| 亚洲精品秘一区二区三区蜜桃久| 中文字幕三区| 日韩日逼| 一区二区三区四区五区六区高清无吗视频 | 日韩中文字幕av在线| 丁香五月激情啪啪啪| 有码一区二区三区| 亚洲欧美在线观看视频| 超碰97免费| 私人玩物』黑絲OL尤物| 天天日穴| 欧美日韩字幕| 成年人视频免费看| 神马午夜精品| 欧美、日韩、中文、制服、人妻 | 亚洲精品久久久久久久蜜桃| 国产精品免费人成网站酒店| 操B视频在线免费观看| 亚洲高清无码视频大全| 久久艹久久| 操逼在线播放| 操逼大全| 大香蕉伊人9| 怡春院首页| 国产精品不卡在线| 丁香五月欧美激情| 泄火熟妇2-ThePorn| 欧美视频免费操逼图。| 一级a毛片| 亚洲无码AV在线观看| 亚洲天码中字| 国产AA| 无码日韩AV| 97免费视频在线观看| 人人摸天天| 日韩啊v| 操一操影院| 免费看黄片网站| 黄频在线免费观看| 91亚洲免费视频| 麻豆av在线观看| 中日韩欧美一级A片免费| 日韩无码高清免费视频| 国产精品成人3p一区二区三区 | 亚洲福利网站| 黄色在线网站| 91视频电影| 亚洲天堂av网| 亚洲精品日韩无码| 中文字幕人妻精品一区| 久久综合无码内射国产| 日韩精品一区二区在线观看| 精品在线免费观看| 亲子伦一区二区三区| 蜜桃久久| 日B视频在线观看| 日韩国产在线| 亚洲成人动漫在线| 国产成人自拍视频在线| 日本高清无码在线观看| 中文字幕国产| 操熟女视频| 韩日一区二区| 欧洲精品在线视频| 成人精品三级麻豆| 海滩AV黑人| 国产av播放| 亚洲热在线观看| 人人妻人人玩澡人人爽| 成人精品三级麻豆| 中文字幕免费在线看一区七区| 日韩三级在线播放| 日韩城人免费| 亚洲xxxxxx| A视频在线免费观看| 国产女人操逼视频| 五月婷婷婷婷| 久久伊人大香蕉| 好男人WWW社区在线视频夜恋| 99久久精品国产一区色| 玖玖国产精品| 久久久久亚洲AV成人网人人软件| 国产精品爽爽久久久| 围产精品久久久久久久| 国产操逼视频| 日韩一区不卡| 骚逼影院| 亚洲天堂在线观看免费视频 | 婷婷色综合| 91人妻一区二区三区无不码超满| 伊人大综合| 北条麻妃在线观看香蕉| 国产丝袜人妖TS系列| 毛片毛片毛片| 亚洲第一综合| 成人精品在线观看| www黄色在线观看| 爱搞搞就搞搞| 97伊人大香蕉| 99精品视频在线观看免费| 91青青视频| 欧美成人三区性价比| 日韩乱码| 中文字幕人妻互换av久久| 无码网站内射| 狠狠干2021| 高清毛片AAAAAAAAA片| 苍井空一区二区三区| 一级性生活视频| 欧美在线成人视频| 亚洲最新中文字幕| 插菊花综合网亚洲| 五月丁香性爱| 中文在线最新版天堂8| 午夜天堂网| 特特级毛片| 无码看片| 自拍一区在线观看| 五月婷亚洲精品AV天堂| JIZZJIZZ国产精品喷水| 久久久久久久久免费看无码| 一区二区三区小视频| 国产无码免费在线观看| 人人人人人妻| 国产黄色免费乱伦片| 91国产精品在线视频| 免费看一级A片| 国产欧美综合在线观看| 亚洲爱爱视频| 无码直播| 亚洲日韩成人| 天天干天天日| 欧美日韩免费| 一二区免费视频| 特级毛片在线观看| 黄色电影网站在线观看| 欧美操B在线| 亚洲久久久久久| 日韩bbbb| 高清无码三级| 69av网站| 中文人妻第9页| 大香蕉黄色片| 中文字幕浅井香舞被黑人俘虏| 激情人妻av| 91日日| 日韩国产一区二区| 玖热精品| 国产女人在线观看| 日韩逼逼| 免费中文字幕日韩欧美| 亚洲精品女人久久久| 日本无码区| 在线播放一区| sm视频网站| 久久久久成人片免费观看蜜芽| 欧美在线一级片| 日韩Av无码一区二区三区不卡| 成人毛片在线视频| 在线免费观看国产| 亚洲无码AV在线播放| 日韩美女在线视频| 九九精品热| 精品视频日韩| AⅤ中文字幕在线免费观看| 亚洲欧美日韩色图| 亚洲欧美另类图片| 加勒比综合| 欧美特黄一级视频| 国产性爱精品影片免费看| 日韩天天| 国产精品久久77777| 激情网五月天| 大香蕉75在线| 久久68| 人妻熟妇乱子伦精品无码专区毛片| 国产婬片一级A片AAA毛片AⅤ| 黄色片a| 国产午夜精品一区二区三区牛牛 | 午夜成人黄色电影| 日韩一区无码| 天干天干天夜夜| 黄色电影免费网站| 女人操逼| 精品在线播放视频| 免费爱爱视频| 天堂а√在线中文在线新版| 亚洲视频在线免费| 97资源在线| 国产精品黄色片| 久久久人妻无码精品蜜桃| 免费无码成人片在线播放| 看一级黄色视频| 狼人亚洲伊人| 99国产精品免费视频观看8| 大肉大捧一进一出免费阅读| 国产美女裸体网站| 亚洲精品成AV人片天堂无码| 拍拍拍免费视频| 91在线无码精品秘国产色多多| 成人福利在线观看| 五月天堂婷婷| 高清无码免费在线| 色综合加勒比| 边摸边插| 日韩国产一区| 26uuu亚洲| 国产欧美第一页| 草久久| 欧美成人精品欧美一级| 婷婷电影网| 国产午夜福利视频| 在线内射视频| 国产在线接入| 99国产精品| jizzjizz欧美| 狠狠91| 亚洲免费在线视频| 91青青草视频| 乱轮视频| 成人国产片女人爽到高潮| 操屄视频在线观看| 精品中文字幕在线| 国产成人毛片18女人18精品 | 色欲av伊人久久大香线蕉影院 | 高清无码二区| 高清无码视频免费版本在线观看| 久热久热| 亚洲欧美国产日韩字幕| 日本免费色视频| 激情日逼| 超碰首页| 日韩精品在线免费| 久久成人影音先锋| 青草网| 91欧美视频| 3d啪啪动漫| 欧美综合视频在线观看| 加勒比久久综合| 自拍偷拍精品| 一级AV在线| 成人女人18女人毛片| 熟女网址| 欧美性BBB槡BBB槡BBB| 极品久久久久| 午夜性爽视频男人的天堂| 亚洲免费成人网站| 第一页在线观看| 欧美日韩国产三级| 青青草原av| 亚洲精品国产精品国自产曰本| 日韩性爱av| 日韩小电影在线观看| 91精品国产综合久久久蜜臀酒店 | 悠悠色综合| 久久久久久久97| 在线观看国产一级片| 美女黄色视频永费在线观看网站 | 亚洲天堂在线观看视频| 日本不卡中文字幕| 欧美av| 无码人妻精品一区二区蜜桃网站| 亚洲日本黄色网址| 日韩艹| 99精品全国免费观看| 国产又粗又大又爽| 91大神免费在线观看| 69视频网| AⅤ在线| 一级黄色A片视频| 国产欧美在线观看不卡| 日韩人妻精品中文字幕| 国产91在线亚洲| 亚洲视频无码在线| AV婷婷在线| 亚洲国产高清在线观看视频| 欧美三级片网址| 亚洲国产无码在线| 综合精品7799| 成人亚洲精品一区二区三区| 狠狠久久| 人人干人人艹| 北条麻妃99精品| 夜夜骚av.一区二区三区四区| 性欧美丰满熟妇XXXX性久久久| 欧美视频一区| 成人91看片| 黄页网址在线观看| 免费在线观看AV网站| 中文字幕精品一区久久久久| 亚洲中文字幕在线播放| 91香蕉国产| 亚洲日韩免费观看| WWW.亚洲无码| 狼友免费视频| 亚洲成人69| 亚洲一二三| 小视频+福利| 俺来也在线视频| 53岁露大奶熟女偷情贴吧| 91人妻一区二区三区无不码超满| 精品网站999www| 国产精品一区二区在线| 国产一卡二卡在线| 精品视频在线观看免费| 久久免费视频网站| 亚洲aaa在线| 国产视频久久| 7799精品视频| 激情视频国产| 七六十路の高齢熟妇无码| 靠逼网站免费观看| 黄片网址在线观看| 黄色网址av| 欧美一区二区三区四区视频 | 亚洲成人中文字幕| 国产在线观看国产精品产拍| 久久国产黄色视频| 懂色AV一区二区三区国产中文在线 | 麻豆精品在线| 波多野结衣91| 2014av天堂网| 久久97人妻AⅤ无码一区| 一级无码在线| 周晓琳AV| 最新中文字幕| 韩国成人啪啪无码高潮| 天天操一操| 91干干干| 日本做爱视频| 精品丰满人妻一区二区三区免费观 | 日本99视频| 91国产视频网站| 国产欧美日韩综合| 精品视频一区二区| 三级网址在线观看| 香蕉视频在线看| 狠狠狠狠狠狠狠| 国产精品高潮呻吟久久| 亚洲在线成人| 国产精品乱伦片| 麻豆蜜桃91无码| 久久无码成人| 丁月婷婷五香天日五月天| 亚洲偷| 久久无码一区| 操逼观看| 欧美性猛交XXXX乱大交| 国产黄色视频在线观看免费| 国产一区在线看| 黄色A片免费| 熟女视频网| 波多野结衣Av在线| 佐山爱人妻无码蜜桃| 亚洲AV官方网站| 天天操天天操天天操| 一级A片免费观看| 亚洲69视频| 亚洲乱码日产精品BD在线观看 | 亚洲A片一区二区三区电影网| 五月天婷婷无码| 五月丁香婷婷在线观看| 吴梦梦无码| 中文字幕线观看| 欧洲三级片网站| 亚洲欧美美国产| 三级久久| 超碰97免费| 国内自拍偷拍| 日本不卡一区二区三区| 亚洲国产精品久久人人爱| 日韩性爱视频在线观看| 91精品国产aⅴ一区二区| 国产AV中文| 天天日,天天干,天天操| 操逼毛片视频| 一级黄色A片视频| 国产成人精品免高潮在线观看| 丁香五月激情啪啪| 毛片9| 天天操天天射天天爽| 久久嫩草精品| 国产AV一区二区三区四区五区 | 四川少妇BBw搡BBBB槡BBBB| 五月丁香色婷婷| 成人黄色免费网站| 亚洲乱淫| 91视频人人| 久久艹免费视频| 日韩h视频| 中文字幕手机在线视频| 春色AV| 中文字幕无码成人| 日本内射在线播放| 无码aⅴ| 在线亚洲一区| 日韩日韩日韩| 日日搔AV一区二区三区| 337P粉嫩大胆噜噜噜55569| 尤物网站在线观看| 青青草原国产视频| 亚洲中文中出| 视频一区二| 亚洲真人无码| 中文字幕日韩AV| 熟女高潮| 日韩精品一区二区亚洲AV观看| 亚洲阿v天堂| 中字AV| 少妇高潮日韩| 日韩免费高清无码视频| 超碰九色| 欧美乱伦内射| 免费视频在线观看一区| 嫩BBB槡BBBB槡BBBB百度| 黄片高清无码在线观看| 日韩欧美成人片| 国产无码性爱| 青青草大香蕉伊人| 91蜜桃传媒在线观看| 人人操人人干人人看| 777777国产7777777| 在线国产中文字幕| 黄片小视频在线观看| 久久久WWW成人免费精品| 在线观看成年人视频| 黄色a视频| 激情国产av| 中文无码在线视频| 日本操逼网站| 欧美一级内射| 四川少妇搡bbbbb搡多人| 在线播放你懂的| 69av在线观看| 午夜3D动漫AV| 午夜操爽| 免费观看高清无码视频| 欧美成人乱码一区二区三区 | 七十路の高齢熟女千代子下载| 亚洲综合在线播放| 91无码高清| 婷婷五月一区| 少妇bbw搡bbbb搡bbbb| 国产高清免费| 中文字幕性爱| 久久这里只有| 中文字幕在线字幕中文乱码区别| 国产内射视频| 最新AV在线播放| 黄色成人视频网站| 亚洲中文字幕第一| 中国12一13毛片| 成人午夜啪免费视频在线观看软件| 丁香啪啪| 亚洲AV无码精品久久一区二区| 国产精品午夜福利视频| 强伦轩一区二区三区四区| 99自拍| 安徽妇女BBBWBBBwm| 日本黄色免费视频| 海滩AV黑人| 99日韩无码| 成人黄色视频网| 夜夜爽夜夜| 这里只有精品视频在线| 51妺嘿嘿午夜福利在线| 先锋影音中文字幕| 北条麻妃无码中文| 一本道高清无码视频| 精品在线播放| 色94色.欧美.setu| 欧美一区电影| 7777精品伊人久久7777| 免费人成视频在线播放| 好吊顶亚洲AV大香蕉色色| 9999国产精品| 中文在线高清字幕| 日韩综合精品中文字幕66| 国产精品一二| 88海外华人免费一区| 在线免费高清无码| 一区二区三区四区成人| 无码中文一区| 亚洲性片| 色777| 女人的天堂av| 精品无码在线观看| 日韩免费在线观看一区入口| 成人久久大香蕉| 日韩三级片在线播放| 国产一级a毛一级a毛视频在线网站? | 国产精品久久AV电影| 国产美女久久久| 四虎最新地址| 国产精品综合| 综合色网站| 天天色色综合| 亚洲国产一区二区三区| 欧美日韩国产尤物主播精品| 无码小黄片| 毛片大香蕉| 久久精品久久久久久久| 福利三区| 一本色道久久综合熟妇| 少妇一区二区三区| 国产喷潮| av天堂一区| 草逼视频免费看| 嫩BBB揍BBB揍BBB| 亚洲一级在线观看| jizz亚洲| 福利老湿69| 台湾中文字幕网| 大香蕉免费在线| 97人妻精品一区二区三区视频| 精精品人妻一区二区三区| 青青操在线视频| 国产精品一品二区三区的使用体验| 中文免费高清在线| 青草青草视频| 人妻二区| 大香蕉一区二区三区| AAA片网站| 亚洲免费视频网站| 欧美伊人久久| 中文字幕一区二区三区免费2023| 偷拍一区| 日韩无码久| 中文字幕在线无码视频| 成人一级a片| 蜜臀精品| 五月AV| 黄色电影天堂网站| 欧美激情国产精品| 欧美婷婷综合| 在线永久看片免费的视频| 亚洲午夜视频| 五月色婷婷综合| 国产欧美日韩视频| 四lll少妇BBBB槡BBBB| 国产乱码一区二区三区四区在线 | 国产精品粉嫩福利在线| 五月婷婷视频| 中文字幕三级片在线观看| 台湾色综合| 中文字幕日本无码| 哪里可以看毛片| 国产黄片视频| 亚洲av黄| 日韩中出视频| 欧美亚洲日韩中文字幕| 中文字幕第4页| 91蝌蚪视频在线| 麻豆亚洲| 一本色道久久综合狠狠躁的推荐| 国产精品97| 毛片黄色片| BBw日本熟妇BBwHD| 色99视频| 精品三级| 丰满人妻一区二区三区Av猛交| 四虎成人在线| 怡红院欧美| 伊人一区| 日韩精品毛片一区二区视频免费| 午夜福利澳| 婷婷亚洲色| 影音先锋成人在线| 亚洲精品久久久久毛片A级牛奶 | 黄色片视频在线观看| 偷拍99| 精品成人Av一区二区三区| 亚洲成人AAAAA| 加勒比无码| 亚洲无码高清视频| 日本黄色大片网站| 亚洲日韩成人在线| 中文字幕成人网| 苍井空无码一区二区三区| 国产午夜精品一区二区三区嫩A| 92久久| 亚洲成人一区二区三区| 狠狠操狠狠插| 中文字幕在线日本| 人人操在线观看| 国产45页| 久久久久久久9999| 欧美亚洲一区二区三区| 91香蕉视频18| 日本一区二区视频在线观看| 91在线一区二区三区| 天天日天天干天天日| 在线观看免费欧美操逼视频| 九色PORNY国产成人| 免费操B视频| 日本一级特黄电影| 青青草原免费在线视频| 午夜福利久久| 欧美操逼图| 日少妇视频| 特级婬片A片AAA毛片AA做头 | 99热热| 97国产精品视频| 91视频成人版一区二区| 一级黄色生活片| 欧美一级网| 男人天堂AV片| 四虎在线免费视频| 日本a片在线观看| 日韩免费高清在线视频| 人人操人人妻人人爽| 国产91在线亚洲| 成人小说视频在线社区| 丁香五月综合啪啪| 内射在线| 亚洲无码免费视频| 亚洲3p| 久久久久久久久国产| 伊人成人视频在线观看| 色情小电影免费网站观看网址在线播 | 黄色自拍视频| 激情综合网五月| 北条麻妃无码在线播放| 人人艹在线观看| 国产亚洲中文| 国产精品97| 免费看黄视频| 亚洲偷拍网| 91AV视频| 亚洲第一成年人网站| 色欲av伊人久久大香线蕉影院 | 二级黄色视频| 欧洲成人在线观看| 久久黄色| 国产精品v欧美精品v日韩| 日韩肏屄视频| 中文字幕高清无码免费视频| 日韩无码链接| 91.xxxxx| 一级a一级a爱片兔兔软件| 国产AV小电影| 91日韩在线| 成人影视在线免费观看|