Carpe Diem

備忘録

pipeエラーのハンドリング

概要

write: broken pipeといったクライアント側の強制的なコネクション切断でのエラーハンドリングをする際の知見まとめ。

環境

  • go 1.13.3

事前知識

知っておくと良い知識を先に説明します。

そもそもpipeとは

pipeはプロセス間通信をするための単方向のデータチャネルです。IOストリームを扱います。
読み出し側と書き込み側それぞれのfdを経由してプロセス間の通信を可能にします。

例えば親子プロセスで通信を行いたい場合、親プロセスでpipeを開きそれをforkして子プロセスを用意します。

f:id:quoll00:20191107004201p:plain

続きを読む

様々なrate limitアルゴリズム

概要

インターネットに晒されているWebサービスでは

  • TV等で紹介されたことによる大量流入
  • 悪意ある人物からの攻撃
  • クライアントのバグに依る大量リクエス

など、本来想定していた以上のトラフィックが来ることはよくあります。
単純にシステムを構築すると大規模トラフィックに対応できずシステムがスローダウンしてしまうため、何かしらrate limitをかけておいた方が良いです。

ただしrate limitと一口に入っても色々あるため、今回は主なrate limitアルゴリズムを紹介します。

Leaky bucket

Leaky bucketはデータ転送レートを一定にする(=上限を設定する)アルゴリズムです。
下の図のように、様々な流量の水流がそのバケツに流れ込んでも小さな穴からは一定の水流が流れ出す仕組みです。

f:id:quoll00:20191024063454j:plain

ref: What is the difference between token bucket and leaky bucket algorithms? - Quora

続きを読む

Goのnet/httpのkeep-aliveで気をつけること

概要

Idle connectionをプールするkeep-aliveの仕組みですが、golangで適切に使用するためにはいくつか注意があります。

環境

TCP Keep-Aliveの挙動をパケットキャプチャで確認する

例えば以下のようにDefaultTransportの一部の設定(①、②)をイジってリクエストを送ると

client = &http.Client{
      Transport: &http.Transport{
              DialContext: (&net.Dialer{
                      Timeout:   30 * time.Second,
                      KeepAlive: 10 * time.Second,  // ①
                      DualStack: true,
              }).DialContext,
              ForceAttemptHTTP2:     true,
              MaxIdleConns:          100,
              IdleConnTimeout:       60 * time.Second,  // ②
              TLSHandshakeTimeout:   10 * time.Second,
              ResponseHeaderTimeout: 10 * time.Second,
              ExpectContinueTimeout: 1 * time.Second,
      },
      Timeout: 20 * time.Second,
}

以下のようにレスポンスが返ってからもIdle connectionを保持し続ける挙動がwiresharkのパケット解析で分かります。

続きを読む

Goのnet/httpのtimeoutについて

概要

タイムアウトと一口に言ってもサーバ・クライアント、そして各フェーズによって細かく設定があります。
今回はGoのnet/httpのtimeoutについて1つ1つ説明していきます。

環境

Server

全体図

サーバ系timeoutと各フェーズは以下の関係になっています。

f:id:quoll00:20191001141248p:plain

続きを読む

MongoDB 4.2でシャーディング・レプリカセットのクラスタ構築

概要

気づいたらMongoDBも4.2になっていました。
以前に

DockerでMongoDBのレプリカセットを構築 - Carpe Diem

レプリケーションを、

MongoDBでシャーディング - Carpe Diem

でシャーディングを構築しましたが、設定項目が代わっていたりしたので復習がてらdocker上で構築検証しました。

大まかな流れは変わらないため、↑の記事を読んでおくとスムーズに進められます。

環境

  • MongoDB 4.2
  • Docker 19.03.2

クラスタ構成

種類 レプリカ名 台数
config configRepl 3
mongod shard shardRepl_1 3
mongod shard shardRepl_2 3
mongod shard shardRepl_3 3
mongos - 1

の計13台です。

続きを読む

技術書典7でAbemaTVの合同誌にHashiCorp Vaultについて寄稿しました

概要

AbemaTVの合同誌にHashiCorp Vaultについて執筆しました。

techbookfest.org

どんな内容

基本的にはこの技術ブログで紹介した内容を体系的にして、最新バージョンで改めて動作確認した感じにしています。

初めてHashiCorp Vaultを使う人にとって読みやすくなっていると思います。逆にすでにここの記事を読んでいた人には物足りないと思います(^_^;)

僕以外にも12人もの執筆者が各々の内容で執筆しており、かなりボリュームがある本だと思います。

当日は見本誌もありますので、是非手にとって内容をチェックしてみてください。

gRPCでエラー詳細を渡す方法

概要

以前

christina04.hatenablog.com

こちらの記事で、アプリケーション内でのレイヤ間のエラーハンドリングについてまとめました。
ではマイクロサービス間でそのエラーコードを伝播していくのはどうすれば良いのか、というのが今回の主題です。

課題

gRPCはレスポンスコードを持っています
しかしこれだけでは下記のようなケースをハンドリングできません。

  • フォームのvalidationエラーを伝える際に、どのフィールドの不備が原因か
  • カード決済時のエラーで、カードの何が問題でエラーが起きているのか

このような詳細なエラーをクライアントに伝えられない場合、クライアントは抽象的なエラー文言しかユーザに出せず、結果としてユーザは問題を解決することができなくなります。

続きを読む