| @技術/プログラミング
関連記事に画像を表示するようにして喜んでいたが、先月の AWS の請求額を見てビックリ。普段の 15 倍くらいの金額になっていた。デイリーの利用料金を見ると関連記事に画像を表示するようになった日...

関連記事に画像を表示するようにして喜んでいたが、先月の AWS の請求額を見てビックリ。普段の 15 倍くらいの金額になっていた。デイリーの利用料金を見ると関連記事に画像を表示するようになった日から高くなっている。

CloudFront 転送量

このブログの画像は S3 に置いてあって CloudFront から配信している。これまでたくさん写真を掲載しても特にコストは高くなかった( Route 53 の費用など含めても $3 くらい、転送量だけだと $1.5 くらいだった)のが、転送量だけで $30 オーバーになっていた。ブログのサーバー代は Adsense 広告と Amazon アフィリエイトでまかなうつもりでやっているので、これでは完全に赤字になってしまう。

なぜ高くなったのかというと関連記事にサムネイル画像を表示することで、 imageproxy から CloudFront へのアクセスが発生するようになったからのようだった。こんな感じ。

image-data-transfer-infrastructure-1.png

imageproxy にもキャッシュの仕組みはあるが、 CloudFront が返す Cache Control ヘッダーの内容を理解せず決め打ちの時間でキャッシュを Expire させるので効率が悪い。

恐らく以下のように画像関連のインフラは AWS に寄せるのが一番効率的だと思う。Amazon の優秀なエンジニアが作ってる CDN が一番前段に出てブラウザーからのリクエストに答えるのがもっとも効率的に画像を配信できると思う。

image-data-transfer-infrastructure-2.png

ただ個人のブログレベルでここまでやるのは割に合わない感じがしたのでとりあえずは以下のような構成にした。

image-data-transfer-infrastructure-3.png

Nginx の proxy cache を使う。

キャッシュ時間は長めにとって 30d にしておいた。

あわせてキャッシュの HIT 率を計測するようにした。ログに $upstream_cache_status を書き出すようにして、 awk で定期的に集計するようにした。こんな感じ。

cat log/access.log \
  | grep 'cache_hit:' | grep -v 'cache_hit:-' | cut -f16 | sort | uniq -c \
  | awk '{
      if ($2 ~ /HIT/) {
        hit = $1
      };
      if ($2 ~ /EXPIRED/) {
        expire = $1
      };
      if ($2 ~ /MISS/) {
        miss = $1
      };
      sum += $1
    } END {
      hit_rate = hit/sum*100;
      expired_rate = expire/sum*100;
      miss_rate = miss/sum*100;
      print "HIT\t"hit_rate"%\nEXPIRE\t"expired_rate"%\nMISS\t"miss_rate"%"
    }'

こいつを Lokka の Dashboard に表示させる。

キャッシュヒット率

加えて、 Google の以下の記事を参考に、画像の遅延読み込みを行うようにした。

とりあえずはこれで様子を見たい。いまのところ、ちょびっとずつ転送量は下がってきているような感じがする。もうちょい下げたいところ。

CloudFront 転送量

しかし、画像の配信で毎月 $30 もかかるようであれば自前で画像をホストするのは諦めて Flickr に金払って PRO プランを継続した方が安いなと思い始めてしまった…。 Google Photos でも良いが、 Exif がわからなくなるのと埋め込み用の画像を取得する作業(公開用のアルバムを作ってそこに埋め込みたい写真を入れていく必要がある)が面倒くさいので移行に踏み切れない。

| @技術/プログラミング
Archive ページ をリファクタリングした。これまで gulp をビルドに利用していた(Archive ページを React Router 化)が、 webpack を使うように変えた。Re...

Archive ページ をリファクタリングした。

これまで gulp をビルドに利用していた(Archive ページを React Router 化)が、 webpack を使うように変えた。

React のコードも見直して、 DOM の状態に依存して表示・非表示を切り替えるコードがあったりして( 🐙 Archive ページにカテゴリごとの記事件数を表示する機能を追加 )ごちゃごちゃしてたので DOM を直接ごちゃごちゃ操作するのをやめて React で管理するように変えた。親コンポーネント、子コンポーネント、孫コンポーネント、子コンポーネントの兄弟コンポーネント間で状態を共有する必要があって、結構難儀した。

Archives React Component 1.png

実際の画面を見るとこんな感じ。

Archives React Component 2.png

App というコンポーネントがルートにあって、子に CategoryListCategoryList の子コンポーネント( App からすると孫)に Category コンポーネントがある。記事一覧自体は CategoryList と兄弟コンポーネントである Archive コンポーネントが担当している。

Archives React Component 3.png

こんな感じで特定の Category が選ばれたことを Category のクリックイベントをトリガーに CategoryList に伝達し、 CategoryList はさらにそれを App コンポーネントに伝える。その結果が App から Archive コンポーネントに伝えられ、表示内容が変更される。

この辺を参考にして実装した。コールバック関数を props として引き回し、状態を回収する感じ。

ただこういう込み入った状態の管理を React で行う場合は Redux などを利用するのが良いようだった。

前職のとき、 Redux とか Flux が出てきた頃に F/E のエンジニアの人たちが熱狂してたけど自分はいまいち理解できなくて、傍観するだけだったが、いまさらにして何となく Flux アーキテクチャの概要的なものを把握することができた気がする。ただ自分の場合は深みに入り込まず極力シンプルに作りたいと思っていたので Redux などには手を出さず、 Callback で愚直に状態を親コンポーネントに伝達していく方法をとった。

React 、やっぱり大分良いものだとという感じがした。 jQuery でクラスや CSS で show - hide を Toggle していた頃とは隔世の感がある。

| @技術/プログラミング
久々に開発環境をいじってて brew upgrade tmux したら色々ぶっ壊れてつらい。具体的には以下のブログを参考に、 pane の swap を screen 風にしていた設定が効かなく...

DSC_3779.jpg

久々に開発環境をいじってて brew upgrade tmux したら色々ぶっ壊れてつらい。

具体的には以下のブログを参考に、 pane の swap を screen 風にしていた設定が効かなくなってしまった。

## paneの入れ替えをscreenっぽく
bind-key C-n swap-window -t:+ \; swap-pane -s:-
bind-key C-p swap-window -t:- \; swap-pane -s:+

こういう使い方をしていた。

# 状態 1
window 1 A|[B] <- window 1 の pane B がアクティブ
window 2 C     <- window 2 に pane C が単独で存在

C-b C-n を入力し、以下のような配置になっていた(これまで)。

# 状態 2 (tmux 2.8)
window 1 A|[C] <- window 1 の pane B があったところが pane C になる
window 2 B     <- window 2 には pane B が単独で存在

ところが tmux 2.9a 以降ではこんな風になってしまう。

# 状態 2 (tmux 2.9a)
window 1 [B]   <- window 1 pane B が単独で存在しアクティブ
window 2 A|C   <- window 2 に pane A と C 単独で存在

このほかにも tmux-powerline が綺麗に動かなくなったりして色々厳しい。 tmux は 2.8 までが安定している気がする。

仕事ではほとんどコード書かなくなってしまったのでたまの休みで時間があるときになんかやろうとするとこういうトラブルに遭遇して死んでしまう。プログラミングスキルのみならず開発環境の維持・セットアップにいたるまで、プログラミングに関連するあれこれは料理人が日々包丁の手入れをするように常日頃から磨いていないとさび付いてしまう。

追記

tmux の件は以下なんかを参考にしてみようかな。

さらに追記(2019-08-25T11:34:25)

.tmux.conf を以下のようにしたら解決した。

bind-key C-n swap-pane -t:-
bind-key C-p swap-pane -t:+

むしろ最近の変更で tmux の pane スワップの挙動が自分の好み( screen 風)に近づいたみたい😅

| @技術/プログラミング
Lokka のプレビューはサーバーサイドに保存時と同じパラメーターを POST して、 DB にレコードを保存せずレンダリングだけ行うが、 GitHub や Kibela のようなタブ切り替えで...

2019-08-24 06.57.38.gif

Lokka のプレビューはサーバーサイドに保存時と同じパラメーターを POST して、 DB にレコードを保存せずレンダリングだけ行うが、 GitHub や Kibela のようなタブ切り替えでインスタントに Markdown のプレビューができると便利だろうと思って、 Markdown で編集中に Edit と Preview をタブっぽい UI で切り替えられるようにしてみた。

Markdown のレンダリング自体はサーバーサイドで行っているので、プレビューしたときと実際に保存したときで Markdown の解釈が異なるということもない。

ただリモートで生成した HTML 文字列を DOM に挿入するときに単純に document.innerHTML = body; のようなやり方をしてしまうと JavaScript が動かず困ったので、 iframe を作って document.open(); document.write(body); document.close(); するやり方をとった。そうなると今度は iframe の高さを body のレンダリング終了後に調整する必要があって色々面倒だった。たまに高さがずれたりはするが、基本的にはめっちゃ便利。

Lokka の利用者少ないと思いますが、 Lokka 本体にも入れようと思います。 Ruby の最新版への追従へも最近は行えてないのでこれもやります。

| @技術/プログラミング
このブログの記事投稿画面で、画像をコピーアンドペーストでアップロードできるようにした。以前、ドラッグアンドドロップではアップロードできるようにしていたが、 GitHub や Kibela ではコ...

このブログの記事投稿画面で、画像をコピーアンドペーストでアップロードできるようにした。以前、ドラッグアンドドロップではアップロードできるようにしていたが、 GitHub や Kibela ではコピーアンドペーストでアップロードできるようになっておりはちゃめちゃに便利だったので真似してみた。こんな感じ。

2019-08-18 15.31.56.gif

ハイパー便利。

Reference