Google Photos の画像をダウンロードして、ブログの画像を別の画像に差し替える
Google Photos は様々な Web サイトから Google Photos にアップロードした写真を貼り付けできる*1、という太っ腹な Picker API という機能がある。
ただ、この機能は他の Web サイトが無料で Google Photos の生 JPEG 画像を使え、Google 側に旨味はほぼないため、いつかはなくなるんだろうなぁ、けど無くならないと嬉しいな、という気持ちで使っていたら、Google Picker API で貼り付けた画像が「画像所有ユーザ以外は過去画像含め見れなくなる」という斜め上の変更が入ったため(この辺の認証メカニズムの変更の影響?)、数千枚の旅行写真を Google Photos から貼り付けていた 自分は悲しみに明け暮れていた。
またはてなブログでは、この Google Photos の貼り付け機能をはてなブログから利用できる機能としてユーザに提供していたため、
というアナウンスが出ていて、いつかは対応されると思うのだけど、一足先に自分でスクリプトを書いて対応してみた。
やっていることは難しくなくて、
- はてなブログの記事を blogsync でダウンロードする
- google フォトぽいURLを抜き出す
- その URL を元に、認証情報を持った Google Chrome 経由でオリジナル画像をダウンロードする
- はてなフォトライフに画像をアップロードする
- はてなブログの記事を、Google フォトからフォトライフへと文字列置換する
- blogsync で再度はてなブログを更新する
- ただ、og:image の画像は差し替えられず…
みたいな流れで置き換えを行っている。これで自分のブログや妻のブログは無事フォトライフに(og:imageやサムネイル以外は)差し替えができ、旅行の写真を再び公開することができた。
今回の教訓で、当たり前なのだけど、この事業/機能は儲からないじゃ、というものはやっぱりなくなった、ということだった。無料(もしくは容量を考えたら月額安すぎる)でアップロードし放題のストレージサービスが出たときも、こそって消えていったのだけど、Google フォトのこの機能は Google だから無料で使い続けられるはず、なんてことはなく、やはり消えていったのであった*2。
惜しまれながら終了した、はてなグループの日記を静的サイトとして生成するジェネレータを GatsbyJS で作った
はてなグループが終了してしまい、はてなに頼んでエクスポートしてもらった MovableType 形式の日記が記載されている .mt データは手元にあれど、手元のストレージの肥やしになっている方はいませんか、私はそうでした。
というわけで、せっかく10年以上書いていた日記がWeb上から消えてしまって悲しいので、もう一度再び公開できるように静的サイトジェネレータを作った。
- https://subtech-secondlife.netlify.com/ (サブテク日記再び・懐かしのデザイン…)
- https://github.com/hotchpotch/hatena-group-static-generator (ソースコード)
これを使えばみなさんはてなグループ日記をまたどこかに公開できるので、よかったら公開しよう!!1
GatsbyJS を使って作った感想
静的サイトジェネレータは一昔前は Octopress, 最近は Hugo をよく目にするけど、GatsbyJS のアーキテクチャに興味がったので練習がてら使ってみた。なお React.js のサイトも GatsbyJS で生成されている。
GatsbyJS はデータソースからすべての静的ファイルを生成するという、生成コストは高い富豪的アプローチなのだけど、一度生成されたファイルは静的ファイルなので当たり前だけど早い。に加え、フロントエンドができるだけ早くなるようにの工夫や、画面領域に表示されたリンク先の json のプリロードなんかも標準では行っているので、ページ遷移もとても早い。なおふつうに GatsbyJS のレールに乗って開発しているだけで、Lighthouse の Performance は高得点間違い無しの感じ。
エコシステムもうまい感じに育っていて、plugin 各種を突っ込むだけでいい感じになる。学習コストも、オフィシャルサイトとドキュメントが良く出来てるので、一日あれば大枠は十分把握できる(静的サイトジェネレータの学習にそれほど時間かけてられるか、という話もありそうだけど…)。UI 面は React なので、React を知ってれば特に難しくなく実装していける。
また、すべてのデータソースは GraphQL に集約し、基本はデータは GraphQL を通じて取得するというのが面白い。データソースがローカルファイルだろうが、RDBだろうが、リモートのWebAPIだろうが、全部 GraphQL に一度はデータを入れてそれを利用する。GraphQL のレイヤーが必ず入る(別に無理に使わなくてよいのだけど、そうすると Gatsby の標準的な使い方ではなくなってしまう)ので、普通に値を渡していくことに比べ、そのためにデータ加工、取得がめんどくさくもあるのだけど、斬新なアプローチだ。
そのため、例えば検索ライブラリのGatsbyJS プラグインを作ろうと思ったら、GraphQL のデータソースのマッピングをするだけでデータ取得はすんだりと、開発するためのエコシステム上でもデータソースが一元化されているメリットは大きい。
このサイトジェネレータでも、MovableType形式のデータを、起動時に一度全部 GraphQL に突っ込んでいる。
ただ残念ながら、GatsbyJS とそのエコシステムは TypeScript との相性が良くなく、TS化すると重くなったり、ほとんどのプラグインはTS対応してなかったりと、TSを使ったほうがGatsbyJSの生産性が上がるとは現時点では言い難い。GraphQL は型生成できるから TypeScript と相性が本来良いのに、簡単に使えないのが悲しみ。
他にもエコシステムにテストを書く文化(というか書きやすさかな)がないので、このまま TypeScript 化がしにくく、かつテストが書きにくいと、将来的には負債を抱えてしまいそうな気もしそうだなーとか思いつつも、とても良くできた静的サイトジェネレータフレームワークなので、触ってみると楽しいかもしれない。
【追記あり】 モバイルインターネット環境の通信速度を TCP BBR が有効な ShadowsocksR で10倍速にする
追記 kazuho さんからの指摘いただいた通り、TCP BBRアルゴリズムがモバイル環境の通信速度向上に影響を与えているわけでは無く、キャリア/ISPが制御している回線(本記事ではIIJmio回線)を、BBR+SSRという特殊なコネクションにより、トラフィックシェイピングの挙動を変えてしまい*1、そのため帯域幅が増えたと推測されます。この利用方法では、TCPの公平性に悪影響を与えてしまう行為になる可能性があり、一般良識の範囲内で試すなど、定常的な利用は控えた方が良いでしょう。
さらに追記
IIUC同僚氏いわく、kernelのtcp実装ならBBRv1。モバイルキャリア内にありがちなユーザ毎のキューがボトルネックか、同一ユーザが並行ダウンロードを行なって確認すればいい(バンド幅の総和が不変ならユーザ毎のキューあり)。キューがあってそこがボトルネックなら輻輳制御間の公平性の懸念はない
— Kazuho Oku (@kazuho) 2019年4月23日
モバイルキャリアのボトルネック測定をすることによって、TCP輻輳制御の公平性に悪影響を与えてしまっているかどうか観測できそうです。
まずこの結果を見て欲しい。同じ時間・場所に、同じ端末、同じ回線(IIJmio タイプD)測定した、fast.com のインターネット速度の結果だ。
ダウンロード速度が片方は約4Mbps、片方は48Mbpsだ。約12倍差である。違いは一つ、TCP BBR が有効な ShadowsocksR (以下SSR) サーバを経由している*2か、である。他にも同時間帯にいくつかのネットワーク回線速度のサイトで速度測定してみたが、軒並み5-12倍ぐらい速い速度だった*3。
IIJmioを含む、いわゆる格安MVNOは時間帯によって速度が異なるが、昼時の通信が集中する時間帯はSSR未接続時0.5-0.7Mbpsな速度が、SSR接続時は3〜6Mbpsと、五倍以上の通信速度が出た。また夜の格安MVNOでも高速な速度が出る時間帯も、SSR未接続時は30Mbpsな通信速度がSSR接続時は50Mbpsと、2倍弱ぐらいの速度が出た。
上記画像は、昼時の iPhone 7 での速度測定。MVNO回線での通信速度向上を一番体感できるのが昼時で、0.5Mbpsな速度だと、様々な画像表示が遅く感じ、例えばニュースアプリを見るとサムネイルがなかなか表示されないが、3Mbpsあると大分ましな速度で表示される。
TCP BBR とは
TCP BBR ( Bottleneck Bandwidth and Round-trip propagation time ) とは、Google が開発した輻輳制御アルゴリズムだ。輻輳制御の新アルゴリズム TCP BBR を GCP に導入 の「BBR とは何か 」の項に詳しい説明が載っているが、TCPのスループットの向上・レイテンシの低減が大きなメリットだ。
実際に私も、MacのNetwork Link Conditionerを使い、パケロスと高レイテンシ環境をシュミレートし、通信を行ったところ、サーバのLinuxカーネルがBBRを利用しない設定と比べ、サーバのLinuxカーネルをBBR有効にした環境では、iperf での単純なネットワークテストも、約1.5倍〜2倍速とネットワーク速度の向上が確認できた。
この BBR は、高レイテンシやパケットロスが発生しうるような通信が不安定な環境だと大きく速度改善するため、モバイル回線もこれに該当する環境が想定されるため、モバイル回線のスマートフォンにも適用してみた物が冒頭のモバイルインターネット速度の向上だ。
さてこのTCP BBRの通信を、手元のスマートフォンのモバイルネットワークに手軽適用するにはどうするか、一つの解が SSR を使うことである。
Shadowsocks / ShadowsocksR とは?
中国のグレートファイヤーウォール(以下GFW)を問題無くすり抜けるため、中国のエンジニアが作った、SOCKS プロキシの上で暗号化通信を行う技術・実装が Shadowsocks だ。Shadowsocks にさらに暗号化方式の追加や、難読化手法を追加し、改変した物が ShadowsocksR (以下 SSR) である。
GFWを超える為の様々な技術が詰め込まれ、一般的な TCP パケットと判別をつけることが難しく、2019年4月現在、中国国内から安定したGFW超えが出来ている*4。2018年夏ごろから、以前にも増してVPN通信への規制が強化されたが、SSR は今のところ安定した通信が出来ている。また、Shadowsocks / SSR クライアントは更新される ACL + ブラックリストもしくはホワイトリストにより、例えば中国国内のネットワークやドメインへは直接SSRを通さず接続し、中国国外への接続のみSSR経由の通信をするなど、中国国内で快適に使える機能が多々実装されている。
なお、中国のエンジニアで、Shadowsocks の開発者である Clowwindy 氏や、SSR 開発者の breakwa11 氏は、中国当局の介入が入ったとされ、現在は開発を行っていない。この話しは、一つのコードが中国のインターネットを変えた | Shadowsocksに纏わるストーリー にとてもよくまとまっているので、興味がある方は読んでみてほしい。
SSR のメリット
SSR は、一般的にはGFWを回避するコンテキストによって語れるが、GFW 回避技術や暗号通信以外にも、以下のメリットがある。
- VPN のように、OS 上のほとんどの通信を SSR 上の通信経由にすることが出来る
- サーバへの接続がとても速い。モバイル端末からでも2〜3秒で接続できる
- 各種 OS から一般ユーザが簡単に利用できるクライアントが充実している
- 設定がQRコード経由で配布できるため、利用ユーザの設定がとても楽。設定をQRコードとして表示できる機能を持っているクライアントアプリも多いため、例えば Mac で設定した SSR の設定を、QR コード読み取りで Android や iOS で簡単に利用できる
Shadowsocks / SSR がオープンソースで開発されていることもあり、各種プラットフォームのエコシステムがとても充実しており、一般ユーザも利用しやすい環境が整っている。なおデメリットとしては、アップロード速度は遅くなることが多かったり、大本の通信が快適なときはかえってレスポンスが悪くなったり、一部アプリの通信では SOCKS プロキシ経由ではうまく動かなかったり等もある。
BBR + SSR サーバの構築方法
TCP BBR の利用には Linux カーネル 4.9 以降がサポートされていればよい。そのため最近のディストリビューションでの導入は簡単だろう。例えば Ubuntu 16.04 LTS でも、カーネルイメージのパッケージを apt で更新して再起動し、sysctl でカーネルパラメータを変更すれば利用が可能だ。Raspberry PI の Raspbian OS も2019年4月のバージョンではカーネル 4.14 なので導入が出来る。
また、BBR の有効化から、SSRサーバの構築は Teddysun 氏が公開している BBR や SSR のインストールスクリプトを利用すると、非常に簡単に導入できるだろう。
の記事では、Raspberry PI への導入と、SSRサーバの設定・コンフィグを一部解説している。上記記事の方法で、 Ubuntu 16.04 / 18.04 LTS なサーバでも BBR + SSR サーバも構築してみたが、簡単に構築出来た。
SSR クライアントからサーバに接続する
SSR クライアントは(Android以外は)たくさんあるので、好きな物を利用すれば良いと思うが、私は iOS は Shadowrocket を、MacOS は ShadowsocksX-NG-R を、Android は SSRR を使っている。
基本的に複雑な設定はいらず、簡単に設定することが出来るだろう。
おわりに
本エントリーでは、モバイル回線 + スマートフォン環境からも、基本的な通信を SSR を通して BBR を有効なサーバを通すことで、通信が大幅に高速化できる事例を紹介した。MVNOキャリアの回線速度上限に縛られると思っていた速度が、TCP 輻輳制御アルゴリズムの変更で高速化されるとは、今まで知っていた感覚と違っていたので驚いた。
GCP を初め、BBR が有効なサーバ環境が今後増えてくれば、ネットワーク全般の速度が向上し、今後は不要になっていく方法だとは思うが、今現在は SSR + BBR 利用で通信速度向上の恩恵を、取りわけMVNO回線混雑時は受けることができると思う。また BBR + SSR なサーバは Linux を使える人なら簡単に構築出来ると思うので、興味ある方は試してみると面白いと思う。Tokyo リージョンもある VPS、Vultr VPS は、今紹介リンク経由で登録すると、50$分のクーポンが貰えるので、VPSでカジュアルにSSRサーバを試してみる事も出来る。
謝辞
SSRについて調べていたとき、QiitaのGoogleのTCP BBRでTCPを高速化しProxyもその恩恵にあずかる の記事を読んで、中国本土→日本へのネットワーク速度の向上のみならず、日本のモバイル環境でも高速化する可能性があるのでは?と思って設定・測定してみたので、記事主の fallout 氏に感謝です。
おまけ
回線測定をたくさんした結果
二日でモバイル帯域を7GBぐらい使ってしまった…。
*1:そのため、cubic + SSR 環境では速度向上は発生しません
*2:そのため、片方は右上にVPN接続時に表示される鍵アイコンが出ている
*3:計測値は東京、SSRサーバは、東京と大阪で、計測先の fast.com や Google スピートテスト (mlab) は大阪もしくは東京経由の転送の模様
*4:ただ、SSRサーバへ、分散したIPから大量のネットワーク接続が一極集中で行われるなど怪しいと判断された場合、通信の内容は関係なく、ネットワーク通信自体が規制される場合もある