Serverless 架構應用開發(fā)指南:創(chuàng)建自己的 Serverless 短鏈服務

在想用 Serverless 可以做點什么簡單的在線應用后,我想到了一個是在線短鏈生成服務。最后的結(jié)果見:http://x.pho.im/,一個非常簡單的在線應用。

這里的代碼基于:https://github.com/vannio/serverless-shrink。

因為上面的代碼中,不能自動創(chuàng)建域名。然后,再針對數(shù)據(jù)庫進行了一些優(yōu)化。

代碼邏輯

這里的代碼邏輯比如簡單:

  • 創(chuàng)建短鏈時,使用生成一個四位的字符串
  • 將原有的 URL 和生成的 URL 存儲到 DynamoDB 中
  • 在返回的 HTML 中,輸出對應的 URL
  • 重定向時,從 DynamoDB 讀取對應的短鏈
  • 如果短鏈存在,則執(zhí)行 302 重定向;如果不存在,則返回一個 404。

創(chuàng)建首頁

首頁只是一個簡單的 HTML 表單:

const base_page = `<html>
<h1>Hi!</h1>
  <form method="POST" action="">
    <label for="uri">Link:</label>
    <input type="text" id="link" name="link" size="40" autofocus />
    <br/>
    <br/>
    <input type="submit" value="Shorten it!" />
  </form>
</html>`

module.exports.handler = (event, context, callback) => {
  console.log(JSON.stringify(event));

  callback(
    null,
    {
      statusCode: 200,
      body: base_page,
      headers: {'Content-Type': 'text/html'},
    }
  );
}

當我們提交的時候,就會觸發(fā)對應的 POST 請求。

生成短鏈

如上所述,對于個短鏈請求,我們要做這么幾件事:

  1. 解析出提交表單中的鏈接
  2. 根據(jù) URL 生成對應的短鏈
  3. 將對應的 URL 和短鏈的對應關系存儲到 DynamoDB 中
  4. 如果成功,則返回生成的短鏈;失敗則,返回一個 400

事實上,在存儲 URL 和短鏈的 map 之前,我們應該先判斷一下數(shù)據(jù)中是否已經(jīng)有相應的短鏈。不過,對于這種只針對于我一個用戶的短鏈服務來說,這個步驟有點浪費錢——畢竟要去掃描一遍數(shù)據(jù)庫。所以,我也不想去添加這樣的擴展功能。

接下來,讓我們回到代碼中去,代碼的主要邏輯都是在 Promise 里,按順序往下執(zhí)行。

解析出提交表單中的鏈接

首先,我們通過 querystring 庫來解決中表單中的鏈接。

const submitted = querystring.parse(event.body).link;

根據(jù) URL 生成對應的短鏈

接著,使用 Node.js 中的 crypto.randomBytes 方法來生成八位的偽隨機碼。

crypto.randomBytes(8)
  .toString('base64')
  .replace(/[=+/]/g, '')
  .substring(0, 4)

由于生成的偽隨機碼是 Buffer 類型,因此需要轉(zhuǎn)換為字符串。同時,因為生成的短鏈中不應該有 "=+/",它會導致生成的 URL 有異常。于是,我們便替換掉偽隨機碼中的這些特殊字體。最后,截取生成的字符串的前 4 位。

現(xiàn)在,我們就可以將其存儲到數(shù)據(jù)中了。

存儲到 Dynamo 數(shù)據(jù)庫中。

對應的存儲邏輯如下所示,我們 new 了一個 DocumentClient 對象,然后直接存儲到數(shù)據(jù)庫中。put 函數(shù)中的對象,即是對應的參數(shù)。

return docClient.put({
  TableName: tableName,
  Item: {
    slug: slug,
    url: submitted
  },
  Expected: {
    url: {Exists: false}
  }
}).promise().then(() => { return slug; });

最后,我們返回了 slug,用于接下來的處理。

返回短鏈給用戶

一切處理正常的話,我們將向用戶返回最后的內(nèi)容:

return callback(
  null,
  {
    statusCode: 200,
    body: RenderPage(path.join(prefix, slug).replace(':/', '://'), prefix),
    headers: {'Content-Type': 'text/html'}
  }
);

其中的 HTML 部分的渲染邏輯如下所示:

function RenderPage (link, submitted) {
  return `
<html>
<body>
<h3>
  <a href="${link}">${link}</a>
</h3>
<p>URL ${submitted} was shortened to:
  <a href="${link}">${link}</a>
</p>
</body>
</html>`
};

是的,只是返回短鏈和原有的鏈接了。

好了,現(xiàn)在我們已經(jīng)擁有這個短鏈了。接下來,就是點擊這個短鏈,看看背后會發(fā)生些什么?

重定向短鏈

首先,我們先在我們的 serverless.yml 中,將短鏈的路徑配置為參數(shù):

functions :
  ...
  redirect:
    handler: redirect/index.handler
    events:
      - http:
          path: /{slug}
          method: get

然后,從數(shù)據(jù)庫中按短鏈的 slug 查找對應的 URL:

const slug = event.pathParameters.slug;

docClient.get({
  TableName: tableName,
  Key: {
    slug: slug
  }
}, (err, data) => {

})

如果存在對應的短鏈,則 302 重定向?qū)υ械?URL:

const item = data.Item;

if (item && item.url) {
  callback(
    null,
    {
      statusCode: 302,
      body: item.url,
      headers: {
        'Location': item.url,
        'Content-Type': 'text/plain'
      }
    }
  )
}

如果沒有,則返回一個 404。

我們的代碼就是這么的簡單,現(xiàn)在讓我們來部署測試一下。

部署及測試短鏈服務

如果你還沒有 clone 代碼的話,執(zhí)行下面的命令來安裝:

serverless install -u https://github.com/phodal/serverless-guide/tree/master/url-shorter -n url-shorter

然后執(zhí)行 yarn install 來安裝對應的依賴。

如果你在 Route53 上注冊有相應的域名,修改一下 serverless.yml 文件中的域名,我們就可以使用 serverless create_domain 來創(chuàng)建域名的路由。

緊接著,執(zhí)行 serverless deploy 來部署。

api keys:
  None
endpoints:
  GET - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/
  POST - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/
  GET - https://4rr5ndhaw3.execute-api.us-east-1.amazonaws.com/dev/{slug}
functions:
  main: url-shorter-dev-main
  create: url-shorter-dev-create
  redirect: url-shorter-dev-redirect
Serverless Domain Manager Summary
Domain Name
  x.pho.im
Distribution Domain Name
  d2s4y0p5nuw3k7.cloudfront.net
Serverless: Removing old service versions...

一切準備就緒了。

  1. 訪問 https://x.pho.im/
  2. 然后輸入一個鏈接,如:https://github.com/phodal/serverless-guide
  3. 復制生成的地址:https://x.pho.im/rgQC,并返回
  4. 看是否會重定向到我們的網(wǎng)站上。

Done!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評論 25 709
  • 本文是GitChat《Serverless 風格微服務的持續(xù)交付(上):架構案例》部分內(nèi)容已做修改。文章聊天實錄請...
    顧宇閱讀 3,350評論 1 13
  • 高考那年有作文題目是拒絕平庸,但生活中往往是甘于平庸。諺語,槍打出頭鳥。正好說明了這個道理,比如上學的時候,我父母...
    社會我夢妮閱讀 715評論 0 0
  • 陰山多寶,世人皆知,所以來陰山的人不勝枚舉。 一日,陰山來了位俊俏少年,來陰山的人只有一個目的,尋寶。這少年也不例...
    襲姝Liner閱讀 428評論 0 0

友情鏈接更多精彩內(nèi)容