普通のWebサイトをServerlessで作ってみた話

  • 12
    いいね
  • 0
    コメント

Serverless(2)アドベントカレンダーの6日目の記事です。

なにげにQiita上には初投稿なのでお手柔らかにお願いします。
普段はQiita team使っているので、そっちと記事との共有ができれば良いのになーと小言を言ってみたり。。。

今回は、表題の通り、サーバーレスでWebサイト作った話です。

Webサイトの要件

  • ブログのようなサイト
  • 静的URLで配信したいが、動きとしては動的な部分もあり

実現してみた方法

API Gatewayでhtmlを返しただけ
※当初はコンテンツをAjaxで取ってくる形式にしてたのですが、クローラーさんの結果がうまく行かず、サーバーサイドレンダリングにしちゃいました

実装環境

  • Serverless Framework 0系
  • node.js 4.3
  • Typescript 1系

アーキテクチャ

スクリーンショット 2016-12-05 18.55.17.png

  • cloudfrontでパスを振り分け
    • 静的なコンテンツのみS3へ振り分け
    • 動的ページはAPI Gatewayに振り分けて、LambdaがRDSからデータ取得して、HTML形式に変換して返却

レスポンスの定義

下記のような設定でレスポンスでもってコントロール
※まだServerlessFramework 0系で実装しています。

s-function.json
"responses": {
        "400": {
          "statusCode": "400"
        },
        "503": {
          "selectionPattern": ".*Task timed out after .+ seconds",
          "statusCode": "503"
        },
        "404": {
          "selectionPattern": "(.|\\n)*\\\"status\\\"\\:\\s*\\n*\\s*\\\"notfound\\\"(.|\\n)*",
          "statusCode": "404"
        },
        "default": {
          "statusCode": "200",
          "responseParameters": {},
          "responseModels": {
            "text/html": "Empty"
          },
          "responseTemplates": {
            "text/html": "#set($inputRoot = $input.path('$'))$inputRoot.variableHTML"
          }
        }
      }

lambdaのコードの一部

lambdaのコードはtypescriptで実装しています。
vue-serverでレンダリングしてhtmlを返却しています。

handler.ts
var root = new Vue({
        template: htmlPage
    });

    root.$on('vueServer.htmlReady', function(html: string) {
        var htmlPretty = require('html');
        html = htmlPretty.prettyPrint(html, { indent_size: 2 , indent_caractor: '\t\t'});

        const $ = cheerio.load(html);

        $('title').text("ほげほげ");
        $('h1').text("ほげほげについて");

        var result = {
            variableHTML: $.html({decodeEntities: false})
        }   
        cb(null, <any>result);
    });

ハマりポイント

ENI作成処理によるタイムアウト
西谷さんが下記の記事で書いている通り、Lambda→RDSの通信で同じVPC内でもENI作成処理に数十秒かかる場合があるようで、
結構タイムアウトが頻発してました。
記事にもある通り、完全な解決策はないようですが、
5分ごとにポーリングする設定を入れたらほぼタイムアウトは出なくなりました。
http://qiita.com/Keisuke69/items/1d84684f0511a062e968

パフォーマンスが出ない
これはアーキテクチャに少し依存するのですが、cloudfrontとAPIGatewayを置いているので、デフォルトで数百ms × 2のレイテンシが発生しています。
※APIGatewayも内部的にCloudfront使っているため
ここの解決策は、今後キャッシュ戦略をどうとるのかにかかっているので課題です。

まとめ

突貫で記事書いたのでまとまりなくて申し訳ないです。
SEO条件なんだよーとか、前提条件をあまり書けてないですが、Serverlessを検討している方の参考になれば幸いです。

この投稿は Serverless(2) Advent Calendar 20166日目の記事です。