「Googleのソフトウェアエンジニアリング」を読んだ

www.oreilly.co.jp

目次はこちら

第1部 主題
1章 ソフトウェアエンジニアリングとは何か
第2部 文化
2章 チームでうまく仕事をするには
3章 知識共有
4章 公正のためのエンジニアリング
5章 チームリーダー入門
6章 スケールするリーダー
7章 エンジニアリング生産性の計測
第3部 プロセス
8章 スタイルガイドとルール
9章 コードレビュー
10章 ドキュメンテーション
11章 テスト概観
12章 ユニットテスト
13章 テストダブル
14章 大規模テスト
15章 廃止
第4部 ツール
16章 バージョンコントロールとブランチ管理
17章 Code Search
18章 ビルドシステムとビルド哲学
19章 GoogleのコードレビューツールCritique
20章 静的解析
21章 依存関係管理
22章 大規模変更
23章 継続的インテグレーション
24章 継続的デリバリー
25章 サービスとしてのコンピュート
第5部 結論

Googleのエンジニアが社内でいままでにどのようにソフトウェアを開発し、レビューし、テストし、ドキュメンテーションし、デプロイしてきたかを書いた本で、一人の著者が書いたわけではなくて章によって分担して書かれている。600ページを超える大著。

 

この手の本だと、Googleじゃないとできないよね?みたいに感じられる部分が多少あるのはしょうがないかなと思いつつ、Googleも最初から今のようであったわけではなく、徐々に改善していったことも伺える。

 

例えば1章でそんなような話が出てくる。

ここでHyrumの法則が紹介されている。

ある API に十分な数のユーザーがいるとき、API を作った者自身が契約仕様として何を約束し ているかは重要ではない。作られたシステムが持つあらゆる観察可能(observable)な挙動に関して、それに依存するユーザーが出てくるものである。

ああ、そうだよね、あるよねと思いつつよんでいき、一つの例としてハッシュテーブルの要素をiterateするときにアプリ側は当然その要素の順番に依存した実装をしてはいけないわけだが、膨大なコードベースがあるときにはたして全部依存してないといえるのか?

Googleは2006年にコンパイラーのアップグレードをした際にその作業は苦渋の極みとなったそうだ。しかし

G o o g l e が本当に非凡であったのは、アップ グレードのタスクが苦難に満ちていたという事実を受けて、スケーリングの問題を克服しスケール を我々の長所に変えるべく、技術と組織の変化の必要性を認めた上でそこに注力し始めたことだ。

Googleが共通インフラをいかに重要視、投資しているかは他の章を読んでいてもわかるし、例えば、18章 ビルドシステムとビルド哲学の最後の結論で、エンジニアの権力と柔軟性を制限することによって生産性を上げたとあって、やはり共通部分の開発にリソースさけるのは強い。

 

一方でGoogleがまだ完全に対処したとは言い難く改善途中なのかなという話が4章の「バイアスこそデフォルト状態である」で、2015年にGoogle Photosの画像認識アルゴリズムが黒人を「ゴリラ」と分類するという大きな問題を起こした。この理由はアルゴリズムのデータセットが母集団を正しく表現していなかったことからくる。

 

これほど大問題になるケースはそこまで多くないだろうけど、例えば何かの認識アルゴリズムを使うソフトウェアのドッグフーディングを社内で行ったけど、そもそも社内だとエンジニアが大半で、エンジニアだとその国の男性が大半というケースはありそう。

 

第2部文化は具体的なソフトウェアとかツールではなくて、チームとかリーダーとかそういう話が中心で、5,6章あたりは僕の今のrole(Techinical Program Managerが近いと思う)と関連するところもあり、興味深く読んだ。まあ新しい発見は特になくてそうだよねという感じではある。そして6章でこんまり(近藤 麻理恵)が登場してた。

 

第3部プロセスはコードレビュー、ドキュメンテーション、テストの話。Googleドキュメンテーションwikiを使うのをやめてmarkdownで書いてソースコード同様repository管理にしてるのね。

 

 15章 廃止 で、コードは債務であり、資産ではない。なぜならコード自体は価値をもたらさず価値をもたらすのは、コードが提供する機能だからとあって、確かにな、となるなど。

 

第4部ツールは割りと読み飛ばしたが22章大規模変更で出てきたApache Commonsライブラリの脆弱性はこれっぽい。デシリアライズ時にRCEになる。https://nvd.nist.gov/vuln/detail/CVE-2015-6420

去年末騒がせたLog4J問題を思い出してしまった。

https://nvd.nist.gov/vuln/detail/CVE-2021-44228

 

以上、ざっくりと感想めいたことを書いたけど、総じて勉強になる本だったし、やはりソフトウェア開発においては基本的な改善を着実に進めていくのが(どんな企業規模であれ)大事なのだなと感じさせられた。

Presto Conference Tokyo 2019で発表してきた

https://techplay.jp/event/733772 で発表してきました。

スライドや参加レポートに関しては https://prestosql.io/blog/2019/07/11/report-for-presto-conference-tokyo.html にちゃんとまとまっているのでこれをみるのが良いです。

togetterは https://togetter.com/li/1375730 

ここでは上記に書かれてないことを思い出してメモっときます。

API

prestoには大きく以下3つのAPIがあります。

  1. HTTP API
  2. presto-client
  3. presto jdbc driver

上記1は例えば https://github.com/prestosql/presto/wiki/HTTP-Protocol に書かれています。これが変わることはそんなに無いと思いますが、個人的経験では/v1/executeが消えてshibを直したことがあります。https://github.com/tagomoris/shib/pull/68

上記2は https://github.com/prestosql/presto/issues/224 のやりとりでもあるように、internal libraryなので変更の可能性が高いですし、基本的にpresto CLIコマンドから使われることを想定しているので、それ以外の用途で使うことは推奨されていないと思います。

とはいえ、うちの環境では普通に使われてますし、TDでも使われてると言ってたような。

例えば https://github.com/yanagishima/yanagishima では1と2を使ってます。

2だけでなく1を使う理由はクエリの進捗状況を取得したり、クエリをキャンセルしたり、構文エラーの時に行番号をハイライトしたりするためです。

進捗状況やキャンセルに関しては3のjdbcでもできると思うんですが、エラー行ハイライトは出来ないと思います。

本来はjdbc使うのが正しいし壊れにくいと思いますが、そうはいってもエラー情報をクライアントに提供するなどのきめ細やかなことをやろうとするとjdbcでは不十分なのかなと。

Apache Zeppelinのような高機能でjdbcさえあればあらゆるdbにつなげることを想定するなら上記1,2のようなプロダクト特有の機能を使うのは望ましくないです。ただそれはそれで、きめ細かな機能を提供出来ないので使い勝手が悪くなりがちです。pros/consありますね。

書籍

Presto開発者からはClean Code, Effective Java, Java並行処理プログラミングが良い書籍として紹介されていました。

プロファイラ

Presto開発者がJVM周りのトラブルシュートに何使ってるか聞いたらLinux perf, YourKitだと言ってました。JMCが出てこなかったのはまだJava8がメインだからかなあ。

Batch

Facebookではprestoでバッチ書いてたみたいで、impersonationどうしてたの?って聞いたら使ってなかったとのこと。安定性に関してはpresto専用クラスタでリソースをフルに使える環境だったからそんなに問題出なかったらしい。そうなのか。ただJava11使えばGCの性能が改善されてるので 試してみると良いのではと言われました。

date関数

prestoのdate関数はMySQL由来なので%y%M%dとかになるけど、hiveの方はJava由来なのでyyyyMMddになってるとのこと

Elasticsearch, Kibanaを6.7.1から7.1.1にupgradeした

やり方は https://wyukawa.hatenablog.com/entry/20180124/1516762676  と同じで上書きアップグレードじゃなくて新旧double writeして切り替えました。

うちの環境だとfluentd→kafka→kafka-fluentd-consumer→fluentd→Elasticsearchという経路でElasticsearchに書き込んでいます。

すんなり行くかと思いきや結構難航しました。もっとも今回問題に遭遇したのはElasticsearchではなくそこに入れるfluentdのところでした。

もともとはfluentd 1系で、fluent-plugin-elasticsearch 2.11.10を使ってElasticsearch 6にデータを入れていました。

Elasticsearchは7からタイプが無くなるのでfluentdの設定ではtype_name _docとします。 https://www.elastic.co/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0

またindex templateで_default_をなくす必要があります。

fluent-plugin-elasticsearch 3.4.2以前だと https://github.com/uken/fluent-plugin-elasticsearch/pull/573 が入ってないので下記のWARNが大量にでます。

[warn]: #0 [...] Detected ES 7.x or above: `_doc` will be used as the document `_type`.

一方で、当時最新だった3.4.2だと https://github.com/uken/fluent-plugin-elasticsearch/pull/586 の影響でCPU使用率が高くなります。 https://github.com/uken/fluent-plugin-elasticsearch/issues/584

そこは対応してもらって、https://github.com/uken/fluent-plugin-elasticsearch/pull/586 3.5.1でbulk_message_request_threshold -1にしました。

これで解決と思いきやElasticsearchを再起動するとfluentd側でdeadlockが起きてログ送信に失敗し続けます。

fluent-plugin-elasticsearchの問題なのかelasticsearcy rubyの問題なのか判断がつかなかったので両方にissue登録しました。 https://github.com/elastic/elasticsearch-ruby/issues/656 https://github.com/uken/fluent-plugin-elasticsearch/issues/587

で、その後fluent-plugin-elasticsearch 3.5.2, elasticsearch ruby 7.1.0にあげたらこの問題が起きなくなったのでこのissueはcloseしました。

なので最終的なGemfileのbefore/afterは下記です。

before

source 'https://rubygems.org'    
gem "fluentd", "1.2.5"  
gem "oj", "3.6.7"   
gem "fluent-plugin-ping-message", "1.0.0"   
gem "fluent-plugin-record-reformer", "0.9.1"    
gem "fluent-plugin-suppress", "1.0.0"   
gem "fluent-plugin-elasticsearch", "2.11.10"    
gem "typhoeus", "1.3.0" 
gem "fluent-plugin-prometheus", "1.0.1"

after

source 'https://rubygems.org'
gem "fluentd", "1.4.2"
gem "oj", "3.7.12"
gem "fluent-plugin-ping-message", "1.0.0"
gem "fluent-plugin-record-reformer", "0.9.1"
gem "fluent-plugin-suppress", "1.1.0"
gem "fluent-plugin-elasticsearch", "3.5.2"
gem "typhoeus", "1.3.1"
gem "fluent-plugin-prometheus", "1.3.0"

他にはCuratorによるdaily batchでのindex削除をやめてIndex Lifecycle Management(ILM)を使うようにしました。 index delete用のpolicyをKibana上から作って、cerebroで下記のようにindex templateを指定します。

  "settings": {
    "index": {
      "lifecycle": {
        "name": "delete-daily-policy"
      },
      ...
    }
  },

index templateをいじるときはcerebro使ってます。

これでめでたしと思ったらKibana monitoringでNodeが見れない! search.max_bucket増やして一瞬解決したと思ったけど、結局Kibanaのbugらしい。 https://github.com/elastic/kibana/issues/36892

他にはthread_pool.write.queue_size: 1000と増やしてもやっぱり下記のようなエラーがたまに出る。もっと増やす必要があるのかなあ。

Description: last_log: [2019-07-03T00:00:42,038 +0900][ERROR][o.e.a.b.TransportBulkAction] [...] failed to execute pipeline for a bulk request
org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution of org.elasticsearch.ingest.IngestService$4@677150d7 on EsThreadPoolExecutor[name = .../write, queue capacity = 1000, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@edd1093[Running, pool size = 40, active threads = 40, queued tasks = 1087, completed tasks = 23132289]]

南魚沼グルメマラソン

6年連続6回目の参加です。結果はネットタイムで1時間54分41秒でした。

 

去年とは違って8:26に浦佐駅につく一本遅い新幹線で来たけど9:00のスタートに普通に間に合ったので来年参加する場合もこれでいこうかな。

今年は荷物預かりの場所が変わって、グルメ村から少し遠くなって、預け入れ・受け取りに時間がかかるようになってた。それ以外はいつも通りの素晴らしい大会でした。

 

いつものようにゴール後はごはんとつまみとビール。この後、鮎の塩焼きと汁物とビール2杯目もいっちゃった。鶏肉を焼いてるのがすげーうまそうだったけど、並んでたので断念。

https://www.instagram.com/p/ByeS3l0A1yk/

gourmet marathon done

 

黒部名水マラソンで走ってきた

去年申し込んだけど諸事情で参加できなかった大会に行ってきました。

感想は、ともかく暑かった。。常時30度超えのなかネットタイム4:31:59はまあよく走った方でしょう。

ほぼ2kmごとに給水があるのでそれで完走できました。

36kmのエイドではアイスがあってしかもベンチもあったのでちょっと座ってゆっくり食していました。アイスうまい。ついでにトイレも行ってスッキリして残り頑張れました。

掛川・新茶マラソンで走ってきた

去年に続いて5回目の参加です。
https://wyukawa.hatenablog.com/entry/20180415/1523793968

結果はネットタイムが4時間7分58秒でした。前半はよかったけど30km以降失速。

おにぎり、戦国汁、バナナ、メロン、いちご、オレンジいただきました。ごちそうさまです。

今年は更衣室と荷物預かりの場所がスタート、ゴール地点の近くになってて良かった。

この大会は坂がきついもののエイドも充実してるし、関東近辺なら日帰りで行けるし、人数がそこまで多くないせいかスタート前のトイレもそんなに混んでなくて、良い大会だと思うんだけど、runnetの評価があんまり高くないのはなんでだろう。

鳥取マラソン

鳥取ラソンで走ってきた。

www.nnn.co.jp

 

記録はネットタイムでギリギリサブ4の3:59:31

シーズンに1回はサブ4出したいと思っててなんとか達成できた。

しかし代償としてエイドのうどん食いそびれたw

 

大会としては良い大会なんだけど、もうちょっと給水を増やしていただけるとありがたい。。

 

鳥取砂丘のそばからスタートして県庁、とりぎんバードスタジアムを通り陸上競技場がゴール。地味にアップダウンがあり雨も降っててちょっと大変だったけど、最後までペースは保ててゴールできた。

 

ゴール後は牛骨ラーメン500円とランナーには無料配布されるおしるこ食って帰宅