GWに最新技術ブログまとめサイトを開発した話

9 min read読了の目安(約8200字 1

こんにちは!
株式会社Devlandのジェイです。😄

皆さん、GWはゆっくり過ごせましたか?
私はGW中に勉強がてら最新技術ブログまとめサイト「Devland」を開発していました。

紹介

冒頭にも書きましたが、一言で表すと最新技術ブログまとめサイトです。
サービス名の由来は、Developer + Land で、Developerにとって役立つ場所にしたいという思いからDevlandと名付けました。

Devland - https://dev1and.com

モチベーション

  1. GWの間に何か新しい技術の勉強をしたいけど、丁度いいものないかな〜
  2. Zenn、Qiita、個人ブログ、企業ブログがいい感じにまとまったサイトないかな〜
  3. 作るなら私はもちろん他のエンジニアにも役立つサービスがいいな〜

という気持ちから開発をスタートしました。

新しい技術の勉強

私のスキル的なところから話をしますと、インフラからモバイルまで一通り実装した経験があるフルスタック浅いエンジニアです。😅

まず、普段の業務で接することが少ない最新フロントエンド技術を勉強したいという思いがありました。
俺はITギグワーカーになりたいのだ!」記事の最後に紹介したギグギグを作った時、自作でSSGを実装したと知人に話したところ、知人から「フレームワークを使うとより簡単に実装ができるよ」とアドバイスをいただいたのです。そこで、SSG(Static Site Generator) ができるNextまたはNuxtのどちらを学ぶべきか考えてみることにしました。

技術を選定する時には大きく三つの観点から選びました。

  1. 限られた時間内にアウトプットが出せるか → GW中に結果を出せるか
  2. 今後、そのままモバイル開発の勉強まで繋げられるか → クロスプラットフォームフレームワークでのモバイル開発
  3. 将来性 → 他でも使えるか

Nextは、Reactを5年前に勉強したのが最後でほぼ0から勉強しなおす必要がある上に、Nextも勉強しなければいけないため、学習コストが高く感じました。
一方でReactを勉強しておけば、今後React Nativeの勉強のハードルを下げることが大きいメリットだと思いました。

Nuxtは、複数プロジェクトでVueを使ったことがあったため、Nuxtさえ勉強すれば大丈夫という状況でしたので、Nextよりは学習コストが低いと感じました。
しかし、React NativeとVue.jsでラップしたVue Nativeを使ってのモバイル開発は、現状の市場からは需要が少ないことがデメリットでした。

今回は、限られた時間(GW)内にアウトプットが出せるか?が一番重要なポイントであるため、
学習コストが少ないNuxtを使うことにして、クロスプラットフォームフレームワークでのモバイル開発は、Flutterを勉強することにしました。

企画

まず最初に、コンセプトやスコープを決める必要がありました。

コンセプト

エンジニアにとって有用なリンクを集めて提供することにしました。

例えば、

  • IT News
  • 技術ブログ
  • セキュリティー
  • オンラインツール
  • イベント情報
    など

スコープ

まずは、技術ブログを中心としてまとめることにしました。

ターゲットユーザー

最新技術トレンドや情報に興味がある人 → ITで働く人、学生

市場調査

すでに世の中に同じサービスがあるならば作る必要はないので、市場調査を行いました。

それぞれに特化しているサービスはあるが、気軽に個人・チームブログなどを横断して見ることができるWebサービスはありませんでした。

ユーザーが持っている課題またはニーズ

知り合いのエンジニアの何人かにヒアリングを行いました。
※ この場を借りて、付き合ってくれた方に感謝いたします。🙏

  • 最新・人気情報を色んなサイトを巡回してみなければいけない → 時間、クリック数、動線、UI/UX
  • 他の人は何に興味があるか? → トレンド、人気、話題
  • アクセスビリティ → PC、Mobile、メール、API、RSS、会員登録X

開発

・どうやって情報を収集するか?
・ユーザーに見せるところはNuxtで決まったが、それ以外はどうするか?
・収集する対象が増えることを考慮した構成にするためには?
・サーバーのコストを下げるためには?

などを考慮した上で技術やシステムを開発する必要がありました。

システム構成

結論から言うと以下の構成と技術選定をしました。

どうやって情報を収集するか?

情報を収集するためには、大きく三つ存在します。

  1. RSS(Feed)
  2. API
  3. スクレイピング(Crawler)

上記の順番で情報を収集することができるかを考えます。
スクレイピングは最後の手段で費用対効果をよく考えた上で実装する必要があります。
RSSやAPIはほぼフォーマットが変わることはないですが、スクレイピングは対象となるサイトのデザイン(Dom)が変更されるたびにメンテナンスコストが発生します。

今回は、APIやスクレイピングが必要な一部のサイトを除いて全てRSSで取得するように方針を決めました。

さらに取得するサイト情報をGithubに公開して定期的にデータベースと同期を取ることにしました。
※ 何か追加したいサイトがありましたら、気軽にPRまたはIssueでお知らせください。

ユーザーに見せるところはNuxtで決まったが、それ以外はどうするか?

ここからは、Nuxt以外の開発時間を短縮させるために既にあるリソースをフル活用することで考えました。

つまり、手元にあるソースコードとGithubに公開されているサンプルソースコードのカスタマイズです。
もちろん、その中で新たな仕組みを作ったり、新しいライブラリを検証をしたりしました。

ここで大事なのは新しく挑戦することとそのまま活用できることをしっかり意識することです。
今回の例で言うとNuxtにたくさんの時間を割り当てることを第一に考えなければいけません。

収集する対象が増えることを考慮した構成にするためには?

サーバ(1) - プログラム(1)※
      ↓
サーバ(1) - プログラム(N)
      ↓
サーバ(N) - プログラム(N)

と変化する必要があります。
※ 一つ一つ処理が終わったら次にリクエストを送ることとします。

対象が少ない場合は、サーバ(1) - プログラム(1)で時間内に取得ができますが、

対象が増えると時間内に取得が難しくなります。
例えば、60秒以内に100サイトを取得しなければいけない場合に1リクエストあたり1秒かかると60サイトしか取得することができません。

それを改善したものが サーバ(1) - プログラム(N) です。

プログラム(N)には、例えば以下のやり方があります。

  • Multi Process → 単純に実行する同期処理プログラムを増やす
  • Multi Thread → 実行するプログラムの中のメインスレッドからスレッドを増やす

上記の仕組みを用いることで同時に複数のリクエストを送ることができます。

しかし、一つのサーバーから同時に大量のリクエストを送るとリソース(CPU、Memory)、TCPのエフェメラルポート、ファイルディスクリプタの上限に引っかかり、同時にリクエストが送れない状況となります。
それを回避するためには、以下のようにサーバーを増やすしかありません。

Devlandでは、JobをQueueに登録して複数のプログラムから順番に取り出してリクエストを送るように方針を決めました。

サーバーのコストを下げるためには?

まずは、サーバーの費用を考える前にユーザーへ提供できるサービスレベル目標(SLO)を考慮しながら決める必要があります。
※ もちろん、逆のパータンもあります。

今回は、可用性を中心にSLO(Service Level Objective)を考えます。

例えば、提供するサービスが金融、医療、大学などサービスが長く停止すると社会に甚大な被害を与えるサービスはSLOを高く設定する必要があります。

SLOを99.999%(ファイブナイン)に設定すると、以下の可用性を守る必要があります。

  • 年: 5.26分
  • 月: 25.9秒
  • 週: 6.05秒
  • 日: 0.87秒

計算式

1年 = 365日 (31,536,000秒)
1月 = 30日 (2,592,000秒)
SLO = 99.999%
年: 31,536,000 * (1 - 0.99999) = 315.36秒 → 5.26分
月: 2,592,000 * (1 - 0.99999) = 25.92秒
週: 604,800 * (1 - 0.99999) = 6.048秒
日: 86,400 * (1 - 0.99999) = 0.864秒

Availability Tableから参考
稼働率 => 月間ダウンタイム計算ツール

上記のように僅かなシステムダウンしか許されません。
万が一災害などによってシステムが落ちてもすぐ復旧できるようにしておかないといけません。そのためには膨大なお金がかかることとなります。

今回作るシステムでは、サービスが落ちても甚大な被害を与えたりはしないので
週に約1日落ちても良いようにSLOは90%と設定しました。

  • 年: 36.5日
  • 月: 3日
  • 週: 16.8時間
  • 日: 2.4時間

これでサービスレベル目標(SLO)が決まりました。

次は、コスト面を考えます。

  • DB
  • Queue
  • API
  • Web
  • Worker
  • Scheduler

などを置くサーバーが必要になります。
サービスレベル目標(90%)に基づいて、月に3日のシステムダウンを許容することで復旧まで余裕ができたため、冗長化は考慮せず、サーバーを増やさないことにしました。これにより、コストが抑えられます。

さらにコストを削減するためには、できるだけ無料サービスを使って組み合わせた方が良いです。
※ 期間限定も含めて

例えば、

  • Activity Feeds : PubNub, Pusher, Stream
  • App Hosting : EC2, Azure App, GearHost, GAE/GCE, Heroku, OpenNode, Vercel
  • APM : Datadog, Elastic APM, New Relic
  • App Testing : Applitools, LambdaTest, Sauce Labs, TestingBot
  • Code collaboration tools : Bitbucket, Cloud9, GitHub, Gitlab, Codeanywhere, Launchpad
  • Code Review & Coverage : Codecov, Coveralls
  • Contents as a service : Contentful, FakeJSON, Image Charts, Storyblok
  • CDN : Cloudflare
  • CI : AppVeyor, CircleCI, GitLab CI, ContinuousPHP, TeamCity, Shippable, Travis CI, VSTS
  • DB Hosting : DynamoDB, CouchDB, Dydra, Firebase, Google Cloud Datastore, Heroku Postgres/Redis, MongoDB
  • Data Mining : Count, Metabase
  • DNS Hosting : LuaDNS
  • Email : Elastic Email, Emaillabs, Postmark, SparkPost
  • Error Reporting : Bugsnag, LogRocket, Sentry
  • File transformation : Cloudinary, Filestack
  • Messaging queue services : CloudAMQP, Google Cloud Pub/Sub
  • Mobile analytics : Amazon Mobile Analytics, Firebase, Flurry, Mixpanel, Segment
  • Monitoring : Google Stackdriver, Healthchecks.io, Librato, Uptime Robot
  • Push Noti : Azure Notification Hubs, Batch, Firebase Push, OneSignal
  • Searching : Algolia
  • Serverless app hosting : AWS Lambda, Google Cloud Functions, Hook.io
  • Static app hosting : AWS S3, Cloudflare Pages, GitHub Pages, Netlify, Surge, Vercel
  • User authentication : Auth0, AWS Cognito, Firebase authentication, Ionic Auth, Okta
  • Web Scraping : Apify, ProxyCrawl, Scraper API

Stack on a budget (Free Tier Driven Development FTDD)

無料のサービスはお金がかからないメリットは大きいですが、
システムが複雑になったり、レイテンシが大きくなったり、サービスを使うための学習が必要だったりすることがデメリットとなります。

頑張れば、今回の構成では十分に無料のサービスだけで完結できたかもしれません。
しかし、サービスを使うための学習をする時間はあまりなかったので
今すぐ使える無料サービス(GAE)は使って、それ以外はリソースが余っているサーバに相乗りする形にしてサーバーのコストを0にしました。

反応とFB

周囲に公開したところ、良い反応をいただきました。✌️

  • 最新と週間人気を分けて表示して欲しい
  • 言語別に分けて欲しい。
  • 主題別に分けて欲しい。

今後

  • サイト改善(FB、UI/UX、画面崩れ)
  • 一覧機能追加
  • 全文検索追加
  • RSS強化(言語、主題別など)
  • API強化(言語、主題別など)
  • 購読サービス(メール)
  • モバイルアプリ開発
  • イベント情報追加
  • オンラインツール情報追加
  • SNS(Twitter, Facebookなど)へ自動投稿

など機能を拡張していきたいと思っています。
FBは大歓迎!IssueまたはGitterからお知らせください。

最後に

最後まで読んでいただき、ありがとうございました。🙇‍♂️