AWSの話題を中心に、日々の業務やプログラミングの徒然を綴るエンジニアブログです。

HANDS LAB

HANDS LAB ENGINEERS BLOG

ハンズラボエンジニアブログ

ハンズラボが採用しているユニケージという謎テクノロジーについて 第4回

Pocket

Pocket

 謎テクノロジー第4回目です。多分これで最後ですね。

季刊どころではなく年報レベルになりました。モチベモチベ。

 前回は、ユニケージの具体例を、仮想アプリケーションをもとに説明しました。
今回は、

  • ぼくのかんがえたさいきょうのくらうどあーきてくちゃ
  • クラシックユニケージのpros/cons

について議論します。

 またクソ長くなってしまったのですが、想定読者層はそれでも読んで下さるようなエンスーな方々なので、
特に気にせず参ります。

目次

  • ぼくのかんがえたさいきょうのくらうどあーきてくちゃ

    • ぼくのかんがえたさいきょうのくらうどあーきてくちゃの特徴
      • Elastic Beanstalk SQS worker や EMR でやるようなところを ユニケージ で構築
      • とりあえず集計検索系を RedShift に
    • くらうどあーきてくちゃまとめ
  • クラシックユニケージのpros/cons

    • pros
    • cons
  • 連載のまとめ

ぼくのかんがえたさいきょうのくらうどあーきてくちゃ

 弊社小林たちが作ってくれました。さすがっすね。
APN Architecture of the Year 2015を受賞しました!
そして多分データでは初出しになりそうなちょっと詳細な図。

以上!!!!

……ではあまりにアレなので、もう少し。

 上記アーキテクチャをざっくり説明すると、

  • データは全て DynamoDB に投入される。これらのデータを正とする。
  • リアルタイム処理(POS, EC)は、DynamoDB を直接参照するAPI経由で行う。
  • DynamoDB では集計操作が困難であるので、非同期で集計用データを RedShift へ投入する。
  • RedShift にデータを投入するバッチはユニケージ(EC2)で行う。
  • ユニケージバッチが加工するデータはS3から取得する。
  • ユニケージバッチ用のデータは、Lambda(Node.js) を介して、DynamoDB Stream から取得してS3に配置される。
  • 内部メンバ向けの会員データ管理画面の検索用に、同様にLambda(Node.js) を介して、 DynamoDB Stream からElasticSearchにデータ投入する。

前回もリンクをはりましたが、下記スライド 91ページ のリファレンスアーキテクチャを仮想クラスとしたときの、ひとつの具象クラス、という感じですね。
Deep Dive: Amazon DynamoDB

 議論したい特徴の有るポイントは、

  • Eleatic Beanstalk SQS worker や EMR でやるようなところを ユニケージ で構築。
  • とりあえず集計検索系を RedShift に。

の2点です。

上記2点について、少し批判的に掘り下げます。
自社の成果ですが、公の場で批判的に議論することができてこそ、進歩があると信じて書きます。


ぼくのかんがえたさいきょうのくらうどあーきてくちゃの特徴

Elastic Beanstalk SQS worker や EMR でやるようなところを ユニケージ で構築

 ここがクラウドネイティブ感薄くて、もうちょっと頑張って欲しかったところです。(えらそう)

 バッチ処理システムとしてのユニケージは、特定の状況によりものすごいコストパフォーマンスを発揮します。
以下、本連載に反応していただいた千葉工業大学の上田先生のエントリから引用します。一部改行を改変。

ハンズラボさんが採用しているユニケージという謎テクノロジーについてについて

 ですが、取り回すデータのサイズがさらに大きくなったり、同時処理数が増えたり、データ設計が複雑になってくると、さすがにつらくなってきます。
また、ユニケージはクラウドインフラがブレイクする以前の開発手法で、以降の新しい要素技術へのキャッチアップが控えられています。
例えば弊社田部井らが考案したような、S3 など、クラウド上のオブジェクトストレージを、本来のユニケージのDB(ローカルマスストレージ上のテキストファイル) のように使うことは想定されていません。
ハンズラボシステム導入事例:AWSを活用したポイントシステム

 また、同様に、実行マシンのスケーリングについても考慮されていません。
ユニケージは本来的には、片方がホットスタンバイの2台構成マシンの想定のアーキテクチャを想定しています。
(uspBOA はまた異なる。ハンズラボでは利用実績無し。)
Lambda でbash アプリケーションが動くようになったとしたら?という声も一瞬聞こえましたが、
そもそも他言語の実行環境と比べ起動時のオーバーヘッドがかなり大きい bash が計算時間課金のLambda で動いたとして、
果たしてコスト的にうれしいのか?という疑問もあります。多分論外だと思います。


とりあえず集計検索系を RedShift に

 ポイントは、”とりあえず”、です。(またえらそう)
集計やデータ分析に関しては、確かにRedShiftがよいのですが、
これ、Aurora でよくね?という気もします。
少なくとも、Aurora などRDSとのベンチマークをすることなく、RedShift が導入されています。

 みなさまご存じの通り、RedShift は カラムナ型DB です。
よって、PostgresSQL 互換のインターフェースがあるとはいえ、
データ取得時のパフォーマンスに関しては、各々のクエリに対し、PostgresSQL など通常の行指向RDBMS と傾向が異なるだろうという True or False の仮説を立てることは、
まっとうなエンジニアであれば詳細に考える前に到達可能な結論でありましょう。
 また、データ分析での利用上の観点ですが、現在ハンズに根付いているデータ分析文化は、まだこれを十分に利活用する段階にないかな、という認識です。(個人の認識ですのであしからず)
Tableau などBIツールはまだまだ検証段階ですので。
結果オーライ的な観点では、大きな問題なくまわっていますが、この段階ではRDSとの比較が足りなかったのでは?と思います。
コスト的な観点でも、Aurora で良かったのでは、という可能性が捨てきれません。

 AWS に限らず、クラウドサービスも、ミドルウェア・ソフトウェアも、適時適材適所があると考えます。
その時期に、将来の更新も見据えつつ、部分的にも全体的にも適したアーキテクチャでシステムを構築するのが一番ですね。
特定要素技術への愛も大切ですが、その選択をできるだけ正しく行うには、ベンチマークは出来るだけ行うべきですよね。
不要な技術的負債を抱えないようにするために、重要なことだと思います。
ソフトウェアエンジニアの本分は、話題のアーキテクチャの事例を作ることでなく、
価値を創造しユーザに届け、その価値創造・提供を継続的に行うことなのですから。


くらうどあーきてくちゃまとめ

 そんな感じで、なかなかいい感じなのですが、良くする余地は結構あるなーと思います。
“ぼくのかんがえたさいきょうのくらうどあーきてくちゃ”は、
みんな気付いて、いや、有るべき形が自然と見出されて、だいたい実現されました、というお話でした。
生物学の進化論の収斂のようなものだと思うので、だいたいこんな感じになるのだと思います。

……あ、これが、クラウドデザインパターン、ってやつか。なるほど。

クラシックユニケージのpros/cons

 ここでは、クラシックなユニケージ(bash + ユニケージコマンド + テキストファイル)の pros/cons (いいところと悪いところ、程度の意味合い) について論じます。
この一連の記事を見て下さっている人や、ユニケージに関して調査している人や、ユニケージの実務経験者なら、ある程度気付いている方々がいると思いますが。


pros


開発者の学習曲線が早熟型である

 bash があり、ユニケージコマンドが配置され PATH が通っていて、WebアプリケーションならApache httpd/nginxなどのWebサーバのセットアップ程度で、
とりあえず動くものが作れるというのは、初学者がまず動くアプリケーションを作成して、動くものを作ることができる、という点において、素晴らしいと思います。
アプリケーションそのものにとっては本質的でない、RDBMSのセットアップや、confファイルの設定もほぼいりません。
プログラミングができる人間を増やすという営みは、今の人類にとって必要なことだと考えていますので、その流れに貢献していることは素晴らしいと考えています。

一定の範囲においてコストパフォーマンスの良いバッチ処理システムが作成出来る

 前述引用済みの上田先生の通りですね。
ハンズラボさんが採用しているユニケージという謎テクノロジーについてについて

シェルスクリプトに詳しいアプリケーションエンジニアが育つ

 クラシックなユニケージは徹頭徹尾ユニケージコマンドとシェルスクリプトを駆使してアプリケーションを構築するので、
必然的にシェルスクリプトに詳しくなります。ならざるを得ません。
若干知識に偏りは出ますが、ぶち当たる壁を越えるほどに、上手くすればインフラ専業のエンジニアの人に引けを取らないレベルまでいけると思います。
 また、sedやawkなど通常のUNIX系コマンドも駆使するので、簡単なログ集計や、データ分析のETLが非常にやりやすくなります。
ユニケージはパイプラインでテキストファイルを順次処理していくので、探索的なデータ抽出がやりやすいです。
処理途中データも、ストレージが許す程度のものならば、ファイルに保存すればよいだけで、そのまままた開いて再開したり別の処理に分岐させたりればいいだけです。
データを真面目に設計したり抽象化考えたりしてる暇があったら生データから暫定的な集計をどんどんやって知見を得た方がいいような状態のケースには、かなりマッチすると思います。
真面目に考える必要はいずれ出てきますが。

いわゆるNoSQL的な考え方の訓練になる

 テキストファイルの2次元表でデータを記録・保持し、それらに対してできるだけアプリケーションレイヤーで ACID がんばる、
ということの訓練になります。
データの実体が原始的で人間可読なので、それらをどう取り回すかということにフォーカスして考えることができます。
 また、ユニケージの発生データを消さず、発生データを全体的に見て整合性を保つ、という考え方は、
以下で紹介されているようなイベント・ソーシングの考え方にも通ずるという理解に至りました。


cons

開発者の学習曲線が早熟型過ぎる

 ただし、学習曲線が早熟型という利点は、数年前において強みであったと考えていますが、現在では弱まっていると考えます。
 理由としては、実用的なWebアプリケーションフレームワークの Getting Started + scaffold -> heroku や Beanstalk へ push で、同等のことが出来てしまうような時代になってきたからです。
初学者がまず動かせるものを自分の手で作って、手応えを感じる、またもっと動くものを作る -> (loop)
というルートが、昨今加速度的に発達しているので、ユニケージのアーキテクチャがシンプルであるから誰でも学習しやすい、
という風に強く言えなくなりつつあると思います。

 また、はじめの一歩に必要な知識がシンプルすぎるため、初学者がユニケージ以外の技術を学習する意欲が高くなくあまりにも業務系知識に偏っている場合、
技術的向上心が醸成されにくく、結果としてチーム・組織全体の技術レベルにキャップがかかってしまうおそれがあります。
ユニケージアプリケーションの直接の範囲外(ハードウェア、OS、ネットワークなど)の困難に対する対応力も成長しづらいのでは、と考えます。
ミドルウェアなどはさまずOSのパワーを直接引き出す、というようなうたい文句もありますが、引き出しすぎてしぬケースがあり、その対応力はユニケージアプリケーション開発だけでは身につきにくいものです。

自らC10K問題を引き起こす

 ユニケージは、適切な使用範囲を超えた使用を行うと、自らC10K問題を引き起こして、OSレベルで動作不安定となるケースがあります。
C10K問題については、以下を参照して下さい。
TheC10kProblem – 「C10K問題」(クライアント1万台問題)とは、ハードウェアの性能上は問題がなくても、あまりにもクライアントの数が多くなるとサーバがパンクする問題のこと

 クラシックなユニケージは、独自コマンドとUNIX系コマンドを駆使してテキストファイルを編集し、それらコマンドはパイプラインで繋がれている、
ということに関しては、ここまでで述べていると思います。
パイプラインでつなぐコマンド数は、少なくとも3、多ければ10を超える事はざらです。
1クライアントが同時に発生させるプロセス数が平均的に多いということは、それだけOSのリソースを消費し、
コンテキストスイッチの発生を増加させる、ということになります。
並列化もいいですが、CPUコア数を1桁以上上回るプロセス起動させても、処理速度の恩恵に限界はあります。
 実行スケジュールが適切に計画されたバッチ処理のみを行うシステムや、社内の少数のユーザのみがリアルタイムアクセスするシステムの場合には、大きな問題となりませんが、
特定時間帯に社内多数、あるいは外部からの多数のリアルタイムアクセスが発生するシステムの場合に、この問題が顕在化します。
代表例として、かつての東急ハンズ ネットストア のバックエンド環境の例があります。
これについては、2015/11/03 の JAWS FESTA Kyusyu における弊社井上の発表でも言及されています。
JAWS FESTA Kyusyuにて登壇・運営・協賛しました!

つまり、
ちょっとアクセス数が増える
-> ちょっと負荷が上昇する
-> Webサーバのプロセス数が増える
-> OSリソース減ってきてさらに負荷上昇しやすくなる。実際増える。
-> Webサーバのプロセス数もユニケージコマンドのプロセス数もしぬほど増える。このくらいになると処理終わっててもゾンビになりがち。
-> httpd のプロセスフォークが出来なくなったりsshで様子をみること出来ないくらいOSがビジーになって死亡
-> ついでにメモリもバカ食いしていたら OOM Killer も走ってテキストファイルが中途半端に保存されたりして死亡
というケースが、ユニケージ以外の通常の他のプログラミング言語を用いたアプリケーション環境よりも容易に発生してしまいます。

 参考となる実測値ですが、dstat コマンドによりしぬほどビジーにはなっていないが、そこそこの処理が同時に走っているユニケージアプリケーションサーバの様子を見たところ、
csw(コンテキストスイッチ) の値は数万から10万台、という状態でした。
非ユニケージアプリケーションが動作している、そこそこの処理が走っているサーバの場合、数百から数千程度で推移していました。

開発者がスケールしない

 これはいろいろな意味があります。
 ひとつは、開発者の学習曲線が早熟型過ぎる にて論じた、技術的向上心に関する点です。
エンジニアの能力がスケールアップしづらい、ということです。

 もうひとつは、そもそもユニケージ開発者の絶対数があまりにも少なく、
いざというときに外部の方の力を一定期間借りたり、その日からユニケージ開発に参画できる中途エンジニアを採用する、ということがしづらい点です。
エンジニアの数がスケールイン/アウトしづらい、ということです。
以下、外部の方の力を借りるケースについて論じます。

 なんらかのアプリケーション開発の経験があり、Linux系OSでの作業経験があれば、
“ユニケージのアプリケーションコードを書いたり修正したりすることができる”
という意味では、数日で十分にキャッチアップ可能であると思います。
ですが、そもそも内製を中心にやっていて、そういう外部の方の力を一定期間借りるケースは非常事態なので、
ユニケージへのキャッチアップが時間の無駄とも考えられます。
一定以上習熟済みの開発環境で、即戦力で1~数ヶ月力を借りる、というケースが、こういった場合助けになるのに、
結局未知の環境に慣れてもらって、せいぜい初級者みたいな状態でヘルプしていただくのも、いかがなものかと思います。
 ユニケージは内製案件が中心なので、そういった方には頼らないのでは?と思われるかもしれませんが、
むしろ内製案件こそ、状況によってはカットオーバーが厳守であったりするケースがあります。まさに前述の非常事態です。
機器やソフトウェア保守の関係上、リプレースが遅れることで業務に致命的な支障を来すシステムの場合は、
通常のSIと同等かそれ以上に局所的にヘルプが必要であることは少なくありません。

 さらにもうひとつは、ユニケージでアプリケーションを書く、業務系スタッフからの転向ではない、普通のエンジニアのキャリアに関する点です。
ユニケージはケースにはまれば非常に有用で素晴らしいツールですが、それ単体で見ると、
マイナーなよくわからない、それゆえ現状ではエンジニアの人材市場では即戦力需要の無い技術である、という点は客観的に否定できないと思います。
このような点は、エンジニアのキャリア上、よろしくなかろう、ということは理解して頂けるでしょう。
 ユニケージを使って何を成したか、ということが、ユニケージを使う正当性が無かった場合、説明困難となり、
大袈裟なことを言えばキャリアパスに影響が出るのでは?と考えています。
そもそもユニケージが、ごく狭義には、業務をやっていた通常の非技術系社員が、これを使って業務系ITを整理・推進するためのもの、
そして基本的にその社員はその会社で勤め上げること前提である、
というのに近いので、雇用の流動性が高いエンジニアとして生きていく人間には違和感を覚えるところがあります。

 上記の様な詳細な認識までは持たずとも、通常のITエンジニアのシェルスクリプトでのアプリケーション開発に対する先入観から、
エンジニア採用不利となる可能性もあり得ます。
エンジニア売り手市場の状況では、この理由でもスケールインを困難にする可能性があります。

 アプリケーションを乗せるインフラが完全スケールするのに、それを作りあげるエンジニアがスケールしにくいとはこれいかに、ということですね。

(主観的) シェルスクリプトがレガシーでつらい・つまらない

 致し方無いのですが、シェルスクリプトそのものでアプリケーションコードを書くのは、結構苦行です。
 21世紀も16年目となるのに、Perl で CGIを書く時代より前に戻るのかよ、みたいな。
C言語で書くよりはマシですが、json を取り回すのですら山のような苦労があります。
外部APIの呼び出し結果などを jq でフィルタしてちょっと読むくらいはいいですが、
そこからゴリゴリアプリケーションコードを書いて処理してフラットファイルを出すことを想像して下さい。
本質的でないところに気をやる必要がかなりあり、だるいです。

 後は単純に、生きた化石のようなスクリプトを書いているのが、量がかさんでくるとどんどんつまらなく感じるようになります。

 本当に主観ですが、シェルスクリプトとは適切な距離を持って付き合っていきたいですね。べたべたしたくない。

連載のまとめ

 一旦これでユニケージに関する考察に関しては筆を置きたいと思います。

 繰り返しになりますが、ユニケージはケースにはまれば非常に有用で強力なツールですが、
使用ケースや使用者のハンドリングを誤ると、不幸になる場合もあります。
 また、RDBMSのサポートが無い分、より高いデータ設計能力が求められます。
数テーブル程度の参照系では問題は顕在化しませんが、しっかりとした基幹システムレベルの設計では如実にあらわれます。
規模が大きくなるほどに、決して簡単な開発技法とはいえなくなります。
 本当に簡単であれば、内製開発において、ドメイン駆動設計におけるドメインエキスパートと開発者を一致させることが出来、銀の弾丸ここにあり!といえそうな気がしますが、
なかなか永遠にその状態を継続することはできません。
ユニケージは銀の弾丸ではないのです。

 とはいえ、抽象度の低い関数型っぽいデータフロープログラミングが可能な手法の一つであり、
RDBMS 以外のデータストア(NoSQL)の正しい使用方法に対する示唆も得られるため、
データフロープログラミングの一実装、およびNoSQL データストアの利用プラクティスの一例としては、現代的に意味のあるものでありましょう。

 万事、各々の場所・状況で、考え得る最善を考えて、アーキテクチャを選択することが、正しいソフトウェアを作ることに繋がります。
ユニケージはその選択肢のひとつに過ぎず、極端に拘泥してはならない、という抽象的な結論で、本連載(4回だけで1年以上かかったけど)を締めたいと思います。

Pocket