サイバーエージェントのDSPを作る3日間ハッカソン型インターン「アドテクコンペ」に参加して準優勝してきた

きっかけは、所属している若手エンジニアサークル「Cpaw」代表のpallocさんにサイバーエージェントがハッカソン型インターンを実施すると教えていただいたことです。教えてもらわなければチャンスもなかったので、本当に感謝しています。実はインターンは初めてなので不安でしたが、無事選考を通過し参加することが出来ました。

今回は広告ネットワークにおいてDSPと呼ばれるものを作って、利益率や安定性を競うのがテーマです。詳細は省きますが、なかなかおもしろい仕組みになっています。

運営によって割り振られた[サーバ2人+データ分析2人] x 8チームで戦い、なんと準優勝することが出来ました。賞品の文鎮ももらい、こうしてドヤ顔で参加記を書けています。本当に良かった…

普段はピクシブにてバイトなんでもエンジニア(主にPHPでサーバサイド)をやっていますが、その経験により、「実プロダクトとして運用できる?」 「それスケールすんの?」 「可用性は?」 という発想を持てていたのも生きました。お世話になっている皆さんにも感謝です。

最初に分担を決めたのですが、Goをしっかり書けるもう一人にサーバサイドコードの7割くらいをお願いしたことで、私は全体設計とインフラと残りのサーバサイドコードに集中できました。また、データの二人が予測器の製作に特化できるようにするための支援も行いました。

1日目に全体の構成を考えた結果、以下のような構成になりました。今回のコンセプトは「高スケーラビリティ・高可用性な分散型DSP」です。

これをGCE(Google Compute Engine)で展開しました。お金はいくらでも使っていいという話だったので台数を豪勢に20台+1台使いましたが、APサーバを4コアにしたため、トータルでも18000円程度に収まりました。

team_a

当時の私は最高に冴えていたのですが、この予算をMaster walletから各APサーバのLocal walletに分散する仕組みはかなり良くて、講評でも高く評価されました。ポイントとしては

  • ほぼ無限にスケールする。Masterをさらに階層構造にすることもできる
  • 運用中にAPサーバを自由に増減できる

ということがあります。今回はAPサーバ20台とMaster walletサーバ1台の21台で構成しましたが、何台でも増やせます。今回は2000QPSでしたが、リソース利用率は20%程度だったので、この台数で9000QPSくらいまでは耐えられるはずです。それ以上増えても構成は変えずにGCEのコントロールパネルから台数を増やして、デプロイスクリプトを実行するだけの数分で対応できます。今回は十分な余裕を確保したのもあって、正常レスポンスを100.0%のリクエストに対して返すことが出来ました。これは他のチームに比べてもダントツの信頼性だったようで、誇らしいです。

systemdでコア数ぶん(今回は4つ)のAPデーモンとそれに対応するPythonの予測エンジンを立ち上げて、各APデーモンのポート番号を直接ロードバランサに指定することで、APサーバ内にはロードバランサが存在しません。こういったムダをなくした構成により、95パーセンタイルレスポンスタイムを10msまで縮められました。

最初は予測エンジンのレスポンスが遅すぎて困ったのですが、line_profilerというモジュールで行ごとの実行時間を計測してボトルネックを発見し、高速なレスポンスを返せるようになりました。

GCEから呼び出せるStackDriverというモニタリング画面も便利でした。実施時間は13:32 ~ 17:32です。それ以降は気にしないでください。

スクリーンショット_2018-09-23_20-47-20

こちらが本番中の画面です。他チームとの違いとしては、本番中にパラメータを調整できるようにしたことがあります。便利だったコマンドは journalctl -f | grep Win で、デーモンが標準エラー出力に吐き出したログをリアルタイム監視ができます。このように監視プログラムやデプロイプログラムを複数用意したので、本番中にすぐに異常に気が付けました。

スクリーンショット_2018-09-23_14-29-10.png

今回学んだこととしては、細かい単位での動作チェックを繰り返すことが大事というのがあります。開発はGitHubを軸に行いましたが、これのwikiにcurlでAPIを叩くテストパターンと想定レスポンスを数パターンずつ記載しました。機能を実装する前に明示しておくことで、チームで理解の齟齬が生じにくくなります。これは後半になってから実施したのですが、役立ちました。

結局時間は全く足りず、2日目の夜にカラオケで1曲も歌わずにひたすら作業をする羽目になりました。とりあえず、徹夜は向いていないことがわかりました。脳が動かなくなって効率が20%くらいまで落ちます。もう1日あれば、少なくとも徹夜はしないで済んだかもしれないです。

デバッグでどうしようもなくなったときや、監視が本当に動いているのか心配になったときには、 tcpdump -w out.pcap でキャプチャしたデータをscpで手元に転送してWiresharkで見て解決できました。結局本当に流れているデータはキャプチャを見るのが一番確かなので、今後もtcpdumpは積極的に使っていきたいです。

リモートでGitHubのプライベートリポジトリからpullするのには、ssh -A でエージェント転送するとよいです。自分以外も管理者権限を持っているサーバ上においた秘密鍵をGitHubに登録はしたくないので。 ssh -A は多段もできるので、適当なAPサーバにsshしてからさらにDBサーバにsshすることもできます。

デプロイはシェルスクリプトで前述のssh -Aを順番に打ってサーバでpullしていくシンプルな方式にしました。今思えば、最後に&をつけて並列にしても良かったかもしれません。また、CircleCIなどの今時の方法を使う手もあったかもしれません。

しかし、当時のベストを尽くせた気はするので満足しています。開催してくださったCAの皆様、素敵な機会を提供してくださってありがとうございました。楽しかったです!

広告
カテゴリー: コンピュータ, 通信, 行ってきた | コメントをどうぞ

MIPSコアのPIC32を始めた

以前から挑戦したかったPIC32 32bitマイクロコントローラをついに始めた。石は適当に買っていたDIPのPIC32MX230F064Bを使用。

PIC16F1しかやったことがなかった身としては、引っかかるポイントが多かった。

ICSPの配置が異なる

単純に異なる。PICといえばPIC16で、情報がないので、書き込み回路の結線すらデータシートとにらめっこする必要がある。PGED1とPGEC1を使用した。

駆動に必要なピンが多い。キャパシタが必要

4.7uFをVcapに接続する必要がある。

__delay_ms() がないので、タイマーを作ってコールバックで呼んであげないといけない

コールバック関数としてmain.cに作成した
void MAIN_TMR1(void) {
IO_RB15_Toggle();
}
を指定することで、1秒間隔でタイマーは駆動するようになった。

駆動電圧が 2.3~3.6VなのでUSB直結で動かせない。レギュレータなどが必要

ちょっとつらい。とりあえず安定化電源でやっているけど…

PORTBの一部のピンがGPIOで制御できない。

これは本当に苦しんだ。しかたなく他のポートを使ったけど、気づくのに時間がかかった。JTAGとかと干渉しているのか?

ともあれ、MIPSデビュー。現状8MHz、最大60MHzだけど間違いなくMIPS。USBデバイスとかを作ってみたい。

カテゴリー: コンピュータ, 電気電子 | コメントをどうぞ

IPv6の功罪 知らぬ間にインターネットにポートが露出していることの危険性

先日、これまでVDSL onlyだった自宅マンションにNURO光が引かれたので、速度に惹かれて即座に回線を乗り換えました。NURO Bizではなく、家庭向けの回線ですが、コンスタントに高い速度が出るので、とても満足しています。家庭向けの回線なので、これまでの回線で使えていた固定IPv4アドレスと逆引きが使えなくなったのは残念ですが、仕方ありません。もっとも、調べてみるとIPv4アドレスはほぼ変わらないようです。こちらは要確認です。

代わりに、以前は使えていなかったIPv6が使えるようになりました。ほぼ変わらないグローバルIPv6プレフィックス(/64)がONUに割り当てられています。ICMPv6のRS(Router Solicitation)とRA(Router Advertisement)により、端末のインターフェイスのMACアドレスから生成されたグローバルIPv6アドレスをインターフェイスに割り当てることができます。

ここでポイントは2点あります。ひとつめは、DHCPv6ではなくRAによる生成なので、割当プレフィックスに変化がなければアドレスは不変です。また、各端末のインターフェイスにグローバルIPv6アドレスが割り当てられます。今日はこれが本題です。

ルータ(ONU)は挟まっていますが、NAPTやNATは行わないので、インターネットに各端末が直結している形になっています。これはなかなか不安になりますね。試しに [::]:適当なポート にHTTPを割り付けてみただけで、ネットワークの設定はせずに外部からのアクセスができてしまいました。とても便利ですが…NAT設定を変えなければ大丈夫という古い考えの場合、大きなリスク要因です。

自宅のサーバについてnetstat -aしてみたところ、Sambaがインターネットから直接アクセスできる状態でした。そのため、アタッチするIPアドレスを固定して、v6では使えないようにしました。パスフレーズは設定していたので、直ちに問題になる状況ではありませんでしたが。

考えられる事故事例

  • 家庭内にNASを設置している場合、プライベートネットワーク内からしか見られないと勘違いしてパスフレーズを設定していなかった。しかし、NASにもグローバルIPv6アドレスが割り付けられ、外部から参照可能であり、情報流出・改ざんが発生した。
  • NASを設置しており、パスフレーズは設定していた。しかし、メンテナンス用にtelnetが開いており、簡単な既知のパスフレーズでシェルに入ることができたため、情報流出・改ざん、ネットワークへの侵入が発生してしまった。
  • イントラネットのみに公開していた社員専用Webサービスにアクセスされ、いたずらでSQLインジェクション攻撃をされ、データベースが破壊されてしまった。

以上のように、これまではNATにより守られていた機器がインターネットに露出することにより、危険性は上昇します。

不特定多数への攻撃なんてあるのかと疑問に思うかもしれませんが、現実的にありえます。NICTのNICTERの資料などをご覧ください。先日のNICTオープンデイでも、当該研究をされている研究員の方にお話を伺いましたが、特に家庭用ルータ管理画面の脆弱性を狙ったものが無差別に来ているようです。

もっとも、IPv6はアドレス空間が極めて広大なため、ランダムなIPv6アドレスへの攻撃は難しいです。現状でIPv6にもそのような攻撃が存在するのかを調べてみたところ、2013年の研究( https://www.idsv6.de/Downloads/2013-13-06-BMBF_10_darknet.pdf )では、9ヶ月ハニーポットを運用して、1IPv6アドレスにつきTCP反射パケット(IPアドレススプーフィングなど)が1157パケット、ACKスキャンが15パケット来たそうです。現状ではランダムな攻撃を受けるリスクは大きくないですが、IPv6アドレスが攻撃者の手に渡らない前提のセキュリティは危険でしょう。

 

 

カテゴリー: コンピュータ, 通信 | コメントをどうぞ

Yahoo! Japan主催のハッカソン「HackU 法政 2018」にCpawとして出場して、最優秀をもらった話

IMAG0508

大学とヤフーが共同でハッカソンをやるという話が来たので、最近関わっているサークルの「Cpaw」で出ることになり、学部1年の私と院生5人の6人チームで参加してきました。なぜか開発期間は1ヶ月もありました。

ハッカソンはHackUという名前で、大学個別のものと一般参加のできるものがあり、今回は大学別のものです。一般参加のほうが勝負しがいはあったかもしれませんが。

作ったものは「顔認識でユーザーを識別して、音声コマンドで物品を購入すると、ドアが開いてユーザーが取り出せる」ボックスです。名前は「Chash BOX」といいます。私は箱そのものの製作、電子回路設計、実装、PICファームウェア実装、ネットワークまわりなどを行いました。

今年は各チームともレベルが高かったのですが、技術の高さを評価され、結果的に最優秀賞をいただけました。各位に感謝です。

動作している様子の動画はこちらです

Hack U 法政大学 2018 プレゼンテーション・作品展示会・表彰式 – YouTube

詳細についてはこちらのCpaw公式ブログに載っています
https://www.cpaw.site/2018/08/07/hackuhosei2018/

上の段に普通のコンピュータが2台も入っているので、排熱と消費電力が問題でした。業務用1Uルータについていたファンを取り付けて強制空冷しています。

電子回路とPICファームウェアはノイズ耐性に重きをおいて開発をしたので、一度も問題は起きませんでした。木製ボックスを採用したことにより、歪まないように天板を取り付けるセッティングの手間がかかったのは、改善の余地があります。

扉の開放には定格DC36Vのソレノイドに0.3sだけ40Vをかけることで、どうにか確実な開放を実現しました。ちょっとマグネットキャッチャーの磁力を高く設定しすぎましたね…

余っていたノートPC用の15VACアダプタと昇圧・降圧DC-DCコンバータを組み合わせることで、5V(PIC・LEDライト)/15V(ソレノイドラッチ)/40V(ソレノイドオープナー)の3電圧を供給しました。床に転がっていた中国製謎DCDCコンバータを採用することで、低コストで実現できました。

開発のながれ

最初に仕様を決定

回路図(っぽいイメージ図)を設計

最低限の可動部分をブレッドボードに実装、動作確認

PICでファームウェアを書く

PICを使った回路をブレッドボードに実装、動作確認

パラメータの変更、プログラムの調整

部品配置図、実体配線図の検討

ユニバーサル基板に実装、動作確認

反省点

反省点としては、技術偏重になってしまい、ユーザーから見えないところに重きを置きすぎてしまった点があります。また、中央のサーバで処理するのではなく、小型のボックスとして各事業所に置くわけなので、シンプルで信頼性の高いことを優先して開発を進めるべきでした。

このような知見が得られたことも含めて、よく勉強になりました。近日中にまた機会がありそうなので、楽しみです。

カテゴリー: コンピュータ, 電気電子 | コメントをどうぞ

SPARC64+Solarisのスライド書いた

スライド2本書きました。よんでください

カテゴリー: コンピュータ | コメントをどうぞ

DE15のマスコン(MC45D主幹制御器)から指示値を取得するやつをつくった

ひきつづきPICをぼちぼちやってます。PIC/Pythonのコードを書いてから端子を圧着するのが面倒で放置していたのですが、昨日やっと重い腰を上げて動かしました。一発でうまく動いてよかったです。PICのコードはビットシフトをほとんどノーコメントでつかっていて、自分でも何をやっているのか思い出せないです。DE10の教本を読みながらノリで書いたのですが。

これを先日作った鉄道模型コントローラなどと連携させたいです。心が折れないようにモチベーションを出すのが一番難しいです。

IMG_1575

カテゴリー: コンピュータ, 鉄道, 電気電子, Python | コメントをどうぞ

PICでCPUと対話している

CPUと対話する感じのことをしたかったので、PICでアセンブリを書きました。

asmを書いたのはこれが初めてです。1から16まで足し上げた結果をPORTCに出力するコードです。実機での動作を(テスターで)確認できました。実にプリミティブ。

普通に書いたコードをベースに、さらに変なインクルードレスプログラミングをしてみました。コンピュータと触れ合えた気がします。まだ脳ではPIC16F1命令セットの実行はできませんが。

ORG 0を入れたり、ANSELをクリアしないと出力されなかったり、16F1ではバンク切り替えに新しいMOVLB命令を使う(1命令でバンク切り替えできる)などといった知見がまったくなかったので手探りでしたが、とても勉強になりました。実はMOVLBも直接使う必要がなくて、BANKSEL PORTCのように疑似命令を使うとその品種で当該レジスタのあるバンクに切り替えてくれます。

アセンブルされて書き込まれたメモリ上のデータです。なお、1命令が14bitなので、たぶんそのままではバイナリエディタでうまく見られません。バイナリエディタでのうまい見方を知りたいです。

たった16命令でプログラムが完結するなんですごい。もうちょっと実用的なプログラムを書いてみたいですが、実用性ならCで書けばいい話なんですよね。しかし、せめて電卓的なものくらいは作ってみたいなぁ

キャプチャ

カテゴリー: コンピュータ, 電気電子 | コメントをどうぞ