QRコードジェネレータをGKEからFirebase + Herokuに移行した。
GKEからFirebase + Herokuへ
こちらで作成したQRコードジェネレータを運用しているGCPの無料期間が切れてしまったため、移動先のホスティング先を検討していたところ、FirebaseとHerokuを組み合わせれば無料かつ簡単に移行できそうだったので実施しました。
Docker on Heroku
Goで書かれたAPIをHeroku上のDockerコンテナに移行しました。
公式の手順以外でやったこと
- Herokuデプロイ用のDockerファイルを新規作成
- 起動時はコマンドライン引数でポート番号を受け取りListenするように修正
注意点としては Listenするポート番号はHeroku側から指定された値を使う必要があるという点です。
expose
も使用することができません。
deploy heroku · yassun/crypto-qrcode-generator@59d7d0b · GitHub
Vue.js on Firebase Hosting
既存ではコンテナ上でbuildしたVue.jsをNginxに配置していたのですが、配置先をFirebase Hosting
に向けただけで特に何もしていないです。
$firebase init hosting
の際に public directory の場所を聞かれるので build先(デフォルトはdist
)に合わせるくらいでしょうか 。
deploy firebase · yassun/crypto-qrcode-generator@c2acb19 · GitHub
まとめ
フロントとバックエンドをそれぞれ別のコンテナにしていたことからホスティング先の選択肢が選べ、想定以上に簡単に移行することができ、コンテナベースで開発する恩恵を感じました。
無料枠では制限があるものの、検証用または簡単なサービスであれば十分すぎる環境かなと思います。
Go/Vue/KubernetesでBitcoinのQRコードを生成するWebAppを作った。
Crypto Qrcode Generator
Bitcoinの支払い用QRコードを生成するWebAppを作成しました。
Crypto Qrcode Generator:
https://crypto-qrcode-generator-web.firebaseapp.com/
同様のWebサイトは既に存在するのですが、先日BIP-21をGoで実装したライブラリを作成したことと、Go/Vue.js/Kubernetesの学習目的のために作成しました。
Github Link: github.com
BIP-21
BTCの送金先アドレスを指定する際に用いられるスキームを規定したBIP(Bitcoin Improvement Proposals の略)です。
Go/Vue.js
バックエンドにはGolang/Echoを使用しました。
Go.1.12を使用し、パッケージ管理にはModules
を使用しました。
フロントエンドではVue.js/Vuetifyを使用しました。
開発環境
開発環境用と本番用のDockerファイルを分けており、開発環境はdocker compose up
でGo/Vue.jsの両環境がホットリロードできる状態で立ち上がるようになっています。
本番側ではマルチステージビルドを使用してイメージのサイズを小さくし、Vue.jsはビルド後Nginxで配信する構成になっています。
Kubernetes
node構成は preemptibleのf1-micro
3台 + preemptibleではないf1-micro
1台 で運用しています。
外部アクセスの方法はingress + GCLB を選択しました。 L7ロードバランサとして動作しているためhttps化も後ほど対応しようと思います。
CI/CD
概要図
Github上でPull Requestを受けるとTravis上でテストが実施されます。
Masterブランチの場合に限り、Docker Buildの実施後、GCRにイメージがPushされます。
Pushが完了するとPod内のイメージをPushされたイメージでローリングアップデートを実施します。(kubectl set image
)
感想
事前に「Kubernetes完全ガイド」を一読していたのでマネージドな環境(GKE)で簡単なアプリを動かすのはそこまで難しくなかったです。むしろ開発環境やCIの方が時間費やしてしまいました。
とはいえ多機能かつ周辺ツールも色々登場してきているので本番のサービスレベルで使いこなすにはまだまだ学習が必要そうな印象です。
今後も監視ツールの導入や機能追加等をしながら学習していこうと思います。
ISUCON8の予選を通過しました。
k02というチームでISUCON8予選に参加し、予選を通過することができました。 528組中16位でした。
準備
kyokomi が事前に kibela を導入してくれていたので毎年よく使うコマンドやNginx/MySQLの設定ファイル等を予め追加していました。
当日の会場とディスプレイ等はwaniji が手配してくれたおかげで横並びで作業することができ、最高の環境でした。
当日
なんとか起床に成功し、恵比寿に集合することに成功。
起床失敗しそうだった…。 #isucon
— Yasu@k02 (@_Yasuun_) 2018年9月16日
ひとまず全員でレギュレーションの読込み後、サービスの機能一覧を確認しました。
この時点で h2o
と MariaDB
の存在に気がついたのですが、一旦後回しにし、アプリケーション側のチューニングに集中することに。
今回も諸事情でGo実装を選択していましたが、普段の業務では使っていないためRuby実装とGo実装を交互に読みながらソースを確認していました。
ソースリーディング中はkyokomiが出力してくれたER図がとても役に立ちました。
N+1、インデックス追加、Sheetテーブルのキャシュ等を行いましたが、DBのCPU使用率が高すぎてベンチの結果が上がらなくなったため、早々にDBを別サーバに切り出すことにしました。
このあたりからスコアが徐々に伸び始めて10000点くらいになり、10位代をうろうろしていました。
その後いくつかの変更を加えた後にDBのコネクション数を変更してみたところ、30000点を超えて暫定4位を記録しました
が、/admin/api/reports/events/:id/sales
の結果に整合性がない?みたいなエラーが出るようになり、
ベンチーマークの結果がなかなか安定せず、数回に一回だけ成功するガチャ状態に陥ってしまいました。
原因が掴めずここでかなり時間を消費してしまいました...。
うるせー! しらねー! final fantasy! #isucon
— Yasu@k02 (@_Yasuun_) 2018年9月16日
この間にシート予約時の場所をランダムではなく、順番に着席させてみたら怒られたりしてゲラゲラ笑ってました。
order by randを雑にlimit 1にして順番に着席させたるわ!っていう悪魔的発想で改修したら、ベンチマークツールに速攻で座席がランダムではありません!って怒られたのは爆笑した。
— きょこみ@k02 (@k_yokomi) 2018年9月16日
終盤間際で排他処理が正常にできていないことに気が付き、ベンチマーク結果を安定させることができました。
そのまま終了3分前くらいに、その日の最高得点が出たので終了しました。
感想
10年くらい前に新卒の頃に出会った二人とisuconの予選突破できる日が来るとは… 本当に感慨深い…。
— Yasu@k02 (@_Yasuun_) 2018年9月16日
2017年ふりかえり。
今年も残り数時間なので恒例のふりかえり。
帰国
約1年半のフィリピン生活を終えて、日本に返ってきました。
食のレベルの高さ、治安の良さを改めて感じました。
帰国直後は毎日セブンイレブンの商品を食べて感動していました。
時々フィリピンの大雑把さや底抜けに明るい雰囲気が恋しくなることも。
フリーランス
昨年から引き続き、リモート中心のフリーランス活動をやっていました。
Rails だけでなくGoやReact関係にも関わることができて勉強になりました。
お仕事を下さった方々/ご紹介して頂いた方々には本当に感謝です。
引越しと断捨離
フィリピン -> 日本(実家) -> 東京(1) -> 東京(2) と今年だけ4回ほど引越しをしました。
引っ越す度に最低限必要なものだけを残してきたため、最終的には全ての持ち物がトランクケース1個になりました。
これを機に定期的に断捨離していこうと思います。
スタートアップにジョイン
入社しました!
来年に向けて
来年は腹筋割りたいです。
それではよいお年を!
未使用アウトプットに基づくトランザクションの生成/署名/送信
Mastering Bitcoinの「未使用アウトプットに基づくトランザクションの生成/署名/送信」を実際にコマンドを実行しながら確認します。
環境は前回作成したDocker環境を使用します。
Bitcoin Coreを試すためのDocker環境を作った。 - DC4
Raw Transaction の受取先アドレスを作成します。
# アドレスの作成 root@56451b900162:/# bitcoin-cli -regtest getnewaddress testuser1 mrmcNKkhippXe8WTm7BbLNSoy5CydCZHhV
Raw Transaction に含めるUTXOを選択
#未使用のアウトプット(UTXO)を確認 bitcoin-cli -regtest listunspent ... { "txid": "5f76f24fe419f09e7da5010d8e3d110db4189f3b51f797026d619a7ca95416f8", "vout": 0, "address": "mzLCAPscRZtYZysh2RjUz8XEgXZuAU7e9v", "scriptPubKey": "2103562423e4bd01816ee0e06df4b327970b6f5f04ac817ad9e66ab039d20bd34db7ac", "amount": 50.00000000, "confirmations": 147, "spendable": true, "solvable": true, "safe": true } ...
Raw Transaction の作成
# > bitcoin-cli createrawtransaction "[{\"txid\":\"myid\",\"vout\":0}]" "{\"address\":0.01}" # `txid` 、`vout` に 上記のUTXO、受取先アドレス、送金額(10BTC) / お釣り(39.9995BTC) (手数料: 0.0005) を指定する。 root@56451b900162:/# bitcoin-cli -regtest createrawtransaction "[{\"txid\":\"5f76f24fe419f09e7da5010d8e3d110db4189f3b51f797026d619a7ca95416f8\",\"vout\":0}]" "{\"mrmcNKkhippXe8WTm7BbLNSoy5CydCZHhV\":10, \"mzLCAPscRZtYZysh2RjUz8XEgXZuAU7e9v\":39.9995}" 020000000100cc5d9cf910e58d423e4e686d67c9719e6e300eb93be1ecdc92ab53e274b2310000000000ffffffff0200ca9a3b000000001976a9145e4973ba22b718b8336c53cc70504ed16e07caf688acb0646aee000000001976a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac00000000
vout・・・1つのトランザクションを分割する際の番号
出力された16進数をデコードして内容を確認します。
bitcoin-cli -regtest decoderawtransaction 020000000100cc5d9cf910e58d423e4e686d67c9719e6e300eb93be1ecdc92ab53e274b2310000000000ffffffff0200ca9a3b000000001976a9145e4973ba22b718b8336c53cc70504ed16e07caf688acb0646aee000000001976a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac00000000 { "txid": "086065375607d9afd95a105eda40c362dec067bff7d2ba1cedc7002a5b27ce1e", "hash": "086065375607d9afd95a105eda40c362dec067bff7d2ba1cedc7002a5b27ce1e", "size": 119, "vsize": 119, "version": 2, "locktime": 0, "vin": [ { "txid": "31b274e253ab92dcece13bb90e306e9e71c9676d684e3e428de510f99c5dcc00", "vout": 0, "scriptSig": { "asm": "", "hex": "" }, "sequence": 4294967295 } ], "vout": [ { "value": 10.00000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 5e4973ba22b718b8336c53cc70504ed16e07caf6 OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a9145e4973ba22b718b8336c53cc70504ed16e07caf688ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mp7VodBS75f57jFgGWHb6NHNCrDH54CxNr" ] } }, { "value": 39.99950000, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 ce6164048e09beba6beb0ea63fc9a7edc501393e OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mzLCAPscRZtYZysh2RjUz8XEgXZuAU7e9v" ] } } ] }
scriptSig
がnullなので、署名が行われていないことが確認できます。
署名の実施
root@56451b900162:/# bitcoin-cli -regtest signrawtransaction 020000000100cc5d9cf910e58d423e4e686d67c9719e6e300eb93be1ecdc92ab53e274b2310000000000ffffffff0200ca9a3b000000001976a9145e4973ba22b718b8336c53cc70504ed16e07caf688acb0646aee000000001976a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac00000000 { "hex": "020000000100cc5d9cf910e58d423e4e686d67c9719e6e300eb93be1ecdc92ab53e274b23100000000484730440220171a3a74c11ce5e7ffcc2a3ee6cf86957edfa955dd0ca3052ea3d1631eb616f5022054a24b3201cbf3d3b979c4d3074ef490be5cf89b8857056021933201d1f2b7e501ffffffff0200ca9a3b000000001976a9145e4973ba22b718b8336c53cc70504ed16e07caf688acb0646aee000000001976a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac00000000", "complete": true }
もう一度デコードして内容を確認します。
{ "txid": "7c7f41ccd1d0df0f3ab1009ab7993ec32ff161b9edaa3c196e6644dda54c8efb", "hash": "7c7f41ccd1d0df0f3ab1009ab7993ec32ff161b9edaa3c196e6644dda54c8efb", "size": 191, "vsize": 191, "version": 2, "locktime": 0, "vin": [ { "txid": "31b274e253ab92dcece13bb90e306e9e71c9676d684e3e428de510f99c5dcc00", "vout": 0, "scriptSig": { "asm": "30440220171a3a74c11ce5e7ffcc2a3ee6cf86957edfa955dd0ca3052ea3d1631eb616f5022054a24b3201cbf3d3b979c4d3074ef490be5cf89b8857056021933201d1f2b7e5[ALL]", "hex": "4730440220171a3a74c11ce5e7ffcc2a3ee6cf86957edfa955dd0ca3052ea3d1631eb616f5022054a24b3201cbf3d3b979c4d3074ef490be5cf89b8857056021933201d1f2b7e501" }, "sequence": 4294967295 } ], "vout": [ { "value": 10.00000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 5e4973ba22b718b8336c53cc70504ed16e07caf6 OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a9145e4973ba22b718b8336c53cc70504ed16e07caf688ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mp7VodBS75f57jFgGWHb6NHNCrDH54CxNr" ] } }, { "value": 39.99950000, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 ce6164048e09beba6beb0ea63fc9a7edc501393e OP_EQUALVERIFY OP_CHECKSIG", "hex": "76a914ce6164048e09beba6beb0ea63fc9a7edc501393e88ac", "reqSigs": 1, "type": "pubkeyhash", "addresses": [ "mzLCAPscRZtYZysh2RjUz8XEgXZuAU7e9v" ] } } ] }
今回は scriptSig
が設定されている事が確認できます。
この状態で 署名されたhex
を sendrawtransaction
等を使用してブロードキャストすることができます。