/home/by-natures/dev*

データ界隈で働くエンジニアとしての技術的なメモと、たまに普通の日記。

2021/02/03 「内向型を強みにする」を読んで

ブログがすっかりご無沙汰になってしまいました。今見たら2019年の6月に書いたのが最後でしたね。

2019年、夏頃にチーム内の上長が退職してしまって、その代わりを務めることになってマネージャーとしてタスク管理や目標設定・面談なども行うようになりました。最初は私で良いのかなと思っていましたし不安でしたが、移動元の部署とやり取りすることが多いチームなので何とか働けています。

近々、今取り組んでいるデータマネジメントへの取り組みも思考整理のために書き出してみようかと思いますが、今日は最近読んだ本を一つご紹介です:

「内向型を強みにする」 https://www.amazon.co.jp/dp/B00DEEK1EY/

去年買って Kindle に入れたものの読んでいなかったんですが、ふとタイトルが目について読んでみたところ、とても面白い本でした。外向型・内向型という分類(もちろん明確に分けることはできない)を紹介していて、それぞれの特徴や、外向型が多い現代社会において、内向型の人間がどう適応していくかといったことが書かれています。適応先も、恋愛・仕事・子育てなどシチュエーション別になっていて、思わずうなずきたくなる場面が多かったです。

外向型か内向型かの判別方法がいくつか紹介されているのですが、最も簡単なものを抜粋します。A と B、どちらが多く当てはまるかというテストです:

(A)
  • 物事の中心にいるのが好きだ。
  • 多様性を好み、単調だと飽きてしまう。
  • 大勢知り合いがいて、その人たちを友達だと思っている。
  • 相手が知らない人でも、おしゃべりするのは楽しい。
  • 活動のあとは高揚し、もっと何かしたいと思う。
  • 前もって考えなくても、話したり行動したりできる。
  • たいてい元気いっぱいだ。
  • 聞き手になるより話し手になることが多い。
(B)
  • 自分ひとりか、二、三人の親しい友達とくつろぐほうが好ましい。
  • 深くつきあっている人だけを友達だと思っている。
  • たとえ楽しいことでも、外で何かしたあとは、休息をとる必要がある。
  • 聞き役になることが多いが、自分にとって重要なテーマについてはたくさん話す。
  • 無口で冷静に見え、観察するのが好きである。
  • 話したり行動したりする前に、考えることが多い。
  • 人前で、または、プレッシャーがかかったときに、頭が空っぽになったことがある。
  • せかされるのは好きでない。

私の場合は A 2 or 3個/8個, B 7個/8個 でB(内向型)に寄っているようです。考えながら話すとか、人と話すとそれが楽しいものでも疲れる(外向型の場合は人と話すことがエネルギーの充電になるとのこと)、1日に予定は詰め込みたくない等々、当てはまる性質が多いです。ふいに電源が切れたように思考や口が回らなくなったりする、といったことも書いてあって、驚きました。実はよくあるんです。慣れない環境だったり、一緒にいることがストレスな人と長時間いると急に電源が切れたりして、そういう時は静かな場所で充電しないと次の活動ができません。

仕事では人に何かを伝えることを遠慮して業務を抱え込みがちな反面、人の話をしっかり聞いて熟考した上で判断するので上司には向いているともあって、弱みを理解して対処するようなノウハウはありがたいです。

ところでこの「外向型」「内向型」という分類、HSP, HSS といった分類にも少し似ているかもしれません:

studyhacker.net

この分類だと、HSP, 非HSP と HSS, 非 HSS の2軸があって、人間の性質を4象限に分けることができます。ただ「外向型」「内向型」はこの軸とはまた違いますし、何らかのフレームワークに人を当てはめるのは難しいことも多いです。どちらの分類にしても自分に近しい性質を見つけたり、近しい人たちとうまくコミュニケーションを取るための判断材料の一つとして使うなどして、うまく生きていくための術を得られればよいかなと思います。

2019/06/24 PlantUML によるロバストネス図

ユースケース駆動開発の手法を実践しているのですが、ロバストネス図・シーケンス図・ドメインモデルと、とにかく「図」を作ることが多いです。これを簡易にしないと作業効率がとても悪いということで、調べたところ PlantUML というツールがありました。

同じユースケース駆動開発を実践されているかたのブログも見つかりました。この方は vscode を利用されていますが、Atom にも PlantUML 可視化のツールがあったので、Atom でも大丈夫です。UML をコーディングしながらそれがすぐに可視化されて、そこからベクターファイルにも変換できるのでとても便利でした。

tk2000ex.blogspot.com

こちらは PlantUML の公式サイトです。各図の作成方法が詳しく紹介されています。

plantuml.com

私は既存のプロジェクトに対してユースケース駆動開発を当てはめようとしていて、ドメインモデルを構築するのがかなり煩雑で、言わんやクラス図をや・・・といった状態ですが、ロバストネス図までなら適切な工数で適切なアウトプットが出せそうかなと試行錯誤しています。どちらにしてもロバストネス図は必要なので、ひとまずここをターゲットに整理しています。このあたり詳しい方と話がしたい昨今。Twitter でご連絡お待ちしています〜。

2019/06/19 Elastic Beanstalk の ALB の scaling trigger では RequestCount がうまく機能しない

Elastic Beanstalk では ALB を簡単に定義することができます。今構築しているアプリケーションでは、リクエストがシンプルかつ大量であるため、リクエスト数に応じてスケーリングさせようと思い、スケーリングトリガーのメトリクスで RequestCount を設定していました。

ただあまりこの値を利用している例が見つからず、、AutoScalingGroup で直接、RequestCountPerTarget を設定している方はいましたが、RequestCountPerTarget は Elastic Beanstalk の管理画面では設定できません。ひとまずインスタンス化下限を十分大きな値にしてステージング環境で色々と調べたところ、RequestCount は ELB に対する指標で、有効指標が Sum であることから、ロードバランサーにどれだけリクエストが届いているか、という値で、いくらスケーリングしてもこの値は変化することはないようです。この辺りのフォーラムと:

https://forums.aws.amazon.com/thread.jspa?threadID=247542

https://forums.aws.amazon.com/message.jspa?messageID=399607

あとは公式の指標説明のドキュメントが役に立ちます:

docs.aws.amazon.com

そうすると、TargetResponseTime を使うか、NetworkIn/Out を使うかといったところで(CPU 消費するアプリケーションならCPUが良いと思いますが今回はCPUほとんど消費しないアプリケーションなのです)、リクエストがシンプルなので NetworkOut が有効指標になるかなと思っています。まだクラスタ立ち上げたばかりなので多めのインスタンスで立てておいて様子見中です。Beanstalk の公式ドキュメントでは NetworkOut をベースに説明されていて、初期値も NetworkOut の下限2MB上限6MBなので、とりあえずこれを参考にしつつ閾値調整かなぁと思っています。

docs.aws.amazon.com

2019/06/18 AWS ELB 配下の tomcat が X-Forwarded-For を取得できない? -> 解決しました

ロードバランサー配下のWebサーバは、ロードバランサーがもともとのクライアントのリクエスト情報を保持するために X-Forwarded- というHTTPヘッダを追加します。このリクエスト元の情報を保存するヘッダはただのデファクトスタンダードでしたが、今は RFC にもなっているようです。

X-Forwarded-For - Wikipedia

AWS 環境でもこれは同じで、公式サイトや色々なブログでも、ELB配下のWebサーバは X-Forwarded-For を利用してクライアントのIPアドレスを取得できると記載されています。例えば tomcat のアクセスログでは、以下のように変更することでリクエスト元のIPアドレスを取得することができます:

# デフォルトのアクセスログフォーマット
pattern="%h %l %u %t "%r" %s %b"

# X-Forwarded-For などの、リクエスト元の情報を追加したアクセスログフォーマット
pattern="%{X-Forwarded-For}i %{X-Forwarded-Proto}i %h %l %u %t "%r" %s %b"

ここで私がハマった、、というか今でもよくわからないのですが、サーブレット側で X-Forwarded-For を取得しようとすると null が返ってきてしまいました。アクセスログで X-Fowarded-For にクライアントのIPが出力されたところで安心していて、アクセスログで出力している HTTPヘッダがサーブレットで取得できないなんて考えも及びませんでした。。サーブレットでHTTPヘッダを全て出力させましたが、 X-Forwarded-Proto はあるのに X-Forwarded-For が見当たりません。

// これが null になる、アクセスログでは取得できているのに
String clientIP = request.getHeader("X-Forwarded-For");

検索すると同じ問題を質問している AWS スレッドがありました: Forums | AWS re:Post

かいつまむと、理由はわからないが Tomcat(というかサーブレット) だと request.getRemoteAddr() でリクエスト元のIPアドレスが取得できる・・・ということです。 getRemoteAddr() はネットワーク層のリクエスト元 IP アドレスを返却するようなので、本来であれば EC2 インスタンスの手前にある ELB のIPアドレスになるはずです。上のスレッドに回答は付いていないのですが、手元のAWS環境で試すと、確かに getRemoteAddr() でリクエスト元のIPアドレスが取得できました。

今後 X-Forwarded-For でリクエスト元の IPアドレスが取得でき、 getRemoteAddr() でELBのIPアドレスが返ってこないとも限らないので、 X-Forwarded-For をチェックして null であれば getRemoteAddr() で埋めておくのが無難でしょうか。どなたかこの辺りの事情詳しければぜひ教えてください。

追記

Twitter で先輩から、tomcat の機能でそうなっているのではないか、ということで以下のモジュールを紹介してもらいました:

RemoteIpValve (Apache Tomcat 8.5.90 API Documentation)

このモジュールはクライアントのIPアドレスなどを X-Forwarded- 系のプロトコルの値と置き換えるモジュールで、今回の挙動が説明できます。実際に、Elastic beanstalk 経由で入れた tomcat の server.xml には上記モジュールが設定されていて、内部プロキシのIPアドレスも定義されていました。

<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" internalProxies="10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|169\.254\.\d+\.\d+|127\.\d+\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[0-1])\.\d+\.\d+" />

2019/06/12 Hive CLI のアーキテクチャ

hive CLI コマンドは非推奨で、今後は beeline 推奨(JDBC/Thrift で HiveServer2 へ接続)とのことですが、どうにも HiveServer2 は運用していて良い思い出がないので(私が利用している環境だと定期的に再起動しないと応答がなくなる。。)、最近あまり状況追っていないのでどうなっているのかなぁと思いつつ、そもそも hive CLI ってどういう風に動いているんだっけ?と思って調べました。

cwiki.apache.org

公式はざっくりした図です。

beeline は HS2 に接続するだけなのでシンプルですが、hive CLI は自分自身で metastore に接続したりクエリパースしたり、ジョブを投げたりしています。ですので hive CLI を動かす環境にも hive-site.xml などクラスタに接続する設定情報が必要になります。

ただ、簡単なクエリ(例えばパーティションに対する SELECT * )を動かすと、MapReduce に変換されずに hive CLI が直接 HDFS にデータを取得しに行っているようです。上の図だと Execution Engine が簡易的なものになるイメージでしょうか。簡単なクエリでも巨大なパーティション群に対してスキャンが掛かると kill したいことがたまにあるのですが、YARN アプリケーションに変換されていないのでやや面倒です。

2019/04/09 Java でのメモリチューニング

メモリチューニングを久々に。前回は OOM でアプリケーションが落ちる問題に対して調査したのですが、今回はマイナーGCが多発していました。

簡単な処理を大量にさばくアプリケーションなので基本的には Eden からすぐにメモリ解放されるオブジェクトばかりなのですが、処理時間は数十msほど、頻度が数分に一度だったので気になって調整を試みました。当たり前といえば当たり前なのですが、Eden 領域を増やすとマイナーGCにかかる時間が増え、頻度が減ります。Eden 領域を減らすと逆のことが起きました。Eden 領域だけが対象になる GC だとアルゴリズム間で大差ないかもしれません。(環境が Java7 だったので G1GC は試していないです)

余談ですが tomcat は <tomcat>/bin/setenv.sh に Java のオプションを追加していました。Java の起動オプションを変更したくて、起動スクリプトや conf/ のしたばかり探してしまって少し手間取りました。 bin/ の下のファイルを書き換えるのはいつも抵抗あります。

以下のブログではコンカレントGCを利用しない場合の各種パラメータの意味や設定例が紹介されています。コンカレントGCを利用すると、いくつかの値のデフォルト値が大きく変わってしまいますので注意。

d.hatena.ne.jp

GCViewer の紹介。簡単に使えました。

qiita.com

CMS

各種オプションの紹介。コンカレントGC を利用した時の各値の変化も記載されていて分かりやすいです。

fomsan.sakura.ne.jp

G1GC

G1GC を簡単に解説しつつ、他の GC のアルゴリズムとの比較も紹介されています。

qiita.com