chigichan24のお気持ち表明

おきもちを表明している

ISUCON7の真面目な話

メンバーが真面目な記事を書いていて,自分のやったことがピザをデプロイしただけと思われると悲しい(?)ので,多少技術的なムーブメントというか真面目な補足を書こうかなというエントリです.

昨年は チーム (´・ω・`) としてISUCON6本選に出場していたので,その時の様々な反省を今回のISUCONでは(部分的には)活かせたかなと思います.

去年参加した経験を活かして,今回は自分はoperationの中心となり,問題の性質に応じてコミットする領域をわけながら取り組むことに注力しました.

インフラ,ネットワークの知識,設定に関する知識に k5 は長けており,また,euglena はRubyのコーディングスキルに秀でているため,彼らの力を最大化できることを目標に動きました.

唯一,彼らより私が秀でているのは競技としてプログラミングすることだと思います.プロダクションのコードではこういうことをしないとか,benchmarkerをjudgeのような振る舞いで使うことで普段はできないようなデバッグ方法をするように話をしたのですが,これはすぐには身につかなかったかなぁと思ったりしています.

やったこと

オペレーションな面

議論で大きく衝突することはないのですが,基本的に割れたときは最後に決断をバサッと下すことを心掛けました.短時間の競技は無駄に悩むくらいならやってみるというのが大事です.

また,コードのバグを無駄にとろうと必死になるくらいなら,競技の規模程度のコードに限っては絶対に書き直したほうが速いです.

技術的な話を含めた時系列

my.cnf,nginx.cnf,redis.confの導入をしました.昨年の経験や,練習会を通してwikiとしてためておいた汎用的な設定ファイルを導入しました.sysctlに関してだけはlinuxに関する知識がうすすぎたので,k5に投げました.

ktaribeでアクセスログを解析し,明らかにicons/によってログが埋まっていたため,すぐに静的配信することにしました.また,3台構成であったので,

1. まずiconsのGETをnginxで捌く.
2. 画像の管理をDBでするのをやめて,パスだけ保存する.
3. サーバの1つをコンテンツ配信用とする.

という方針をk5と話してたてました.

一方,アプリケーション改修担当のeuglenaはslow queryを見た結果そこまで遅いクエリがないという報告をうけたので,早急にindexを張るのを考える必要はないと判断して,line-profの導入をしてもらいました.

と言われつつ,userのnameでindex貼ったりしましたが,あんまり効果がなかったように思います.

このタイミングくらいで,euglenaからline-procの結果を渡されて,sleepが無意味に挟まっていたので直したり(sleepの意味に気がついていなかった),line-procをみても画像に対してWHERE掛けてるところが重いのが確定したので,早急に静的配信することにしました.

euglenaと話していると,redisに載せたい部分があるという相談を受け,少々悩みましたが,悩むくらいならやってみて早ければ導入するという感じでGOサインを出しました.

静的配信をnginxで設定したもののなぜか200で返っていたので,少々調整をしたら,10000点にのり,icons/ 以外の静的コンテンツも載せると 15000点に乗りました.

しかし,cacheのサイズを変えたりするとワーカーの数(並列度)は上がっても,2000点まで下がったりと不安定な挙動をしていて,私とk5で同居人との競合みたいな考察をしましたが,これは多分間違っていて,実際は帯域制限を食らっていたという k5 の考察を今日見て,納得しました.

何はともあれ,このときはそれに気が付かなかったので,設定ファイルを一から書き直しつつ最適化するというのをk5にしてもらっていました.

その間は,アプリケーションの一部をredis化していたので,私はそれ以外のN+1を直すため,また,アプリケーションのロジックをもう一度確認するためにコーディング側に回りました.

この間にrebootしてみると,Pythonが起動したりして,危ないところでした.

この間にも,k5 によって並列度を保ったままスコアを徐々に上げてもらい,euglenaにはredis化のコーディング & バグ取りをしてもらいました.

このあたりで,私達のチームはまだ,課題の本丸にたどり着けていないという焦りを感じながらコードを眺めてました.

一箇所,slowqueryに出なかったからといってい,WEHRE句で多用されているカラムなのに,indexを貼っていないところがあり,試しに貼ったらスコアが39000程でてびっくりしました.これはこの変更だけで30000点が上がったのではなく,今までの設定がやっと効き始めたという感じがありました.

再度kataribeを見ると,loginやregisterが少々重いので,nameとpasswordにindex貼って高速化したかったのですが,saltを発行しつつSHA1に掛ける実装をしていたので,難しかったです.今思えば,その実装も外して無理やりpassを平文で保存しても良かったかもしれません.

このあたりで,k5にDBから画像を切り離す実装をしてもらい,スコアが40000に乗りました.

その間私は SELECT *をなくし,必要最小限のカラムを取るように変更して,少々スコアを上げました.

そうこうしているうちに,euglenaの実装がほとんど終了しそうだったので,隣にいってバグ取りしました.力にならなくても相手に説明させることで,バグが取れるという経験は私は多くしていたので,行きました.

やっと手元ではredis化ができたようなので,benchmarkerを投げてみたら500が返ってきたので,終了30分前ほどだったのもあったので諦めました.

最後はきちんと指差し確認をしてログを切りました.再起動テストをすると, pumaに権限がなくて起動できないなどあったので,そこらへんを直して,最後はガチャをして,40088のスコアで終了しました,

まとめ

椅子に座ってイスコーンってしてたら,メンバーに本戦に連れて行ってもらえそうなので,良かったです.

ISUCON7に参加しました.

こんばんは. chigichan24です.

はじめに

ISUCONに今年も学生枠で出ました.学生なのでちゃらちゃらした記事を書きます.

チーム名は,何もしちょらんのに壊れた という某県の方言が前面に出ているチーム名でした.

メンバーは,

強い三編生の同級生 @k5342

強い三編生の同級生 @euglena1215

最近傘をパクられて気分が落ち込んでいる @chigichan24 でした.

言語は@euglena1215がRuby使いたいとうるさかったので(?) Rubyを使いました(大嘘)

予選のリポジトリはこれです.

github.com

ちなみに真面目な記事はこっちです.

chigichan24.hatenablog.com

他のメンバーのエントリは

euglena1215.hatenablog.jp

blog.ksswre.net

練習

github.com

github.com

github.com

やりました.k5はいわゆるインフラっぽいことが強く,euglenaはRuby力が高く,私は雑用力が高いので,それぞれの個性を活かして練習しました.特にk5に焼きそばパン買ってこいと言われてコンビニに走ったのはいい思い出です.

また,wikiや秘伝のタレ,チートシート,trelloを(前日から)作ることで,当日のムーブをスムーズにするようにしました.

f:id:chigichan24:20171022234815p:plain

当日

朝は,台風がすごくて(小並感),会場のk5ハウスに到達できるか不安でしたが,無事にびしょ濡れになって到着できました.しかし,typeC-typeAの変換ケーブルを買って会場入りするという目標が未達でした.

競技が始まるまで

ピザをデプロイするか,大変な議論をしました.これがこの日最大の議論になりました(大嘘).結局dominoピザをこの台風の大雨の中デリバリーしました.申し訳ないことをしたなぁと思いました.

RTKS(RIARU TAIMU KANSHI SHISUTEMU)を導入した.最高〜〜〜

はじまってから

時系列に振り返ってみます.ちゃんとした記事は二人が書いてくれるはずです.

13:00 > うわっ三台構成やんけってなりました.

13:20 > ユーザーをisuconではなくchigichan24でログインしようとしたら失敗一回目なのに,さくらのfail2banに引っかかってipがbanされて(?)ISUCONが終了するかと思いました.

13:30 > ピザのデプロイを待ちました.クワトロコケーコッコと高麗カルビを待ちました.

13:40 > ピザがデプロイされました.うれしかったです.

19:00 > 神の目でソース眺めてindexを張りました.

20:00 > kill starした.

21:00 > 気がついたら終わりました.

結論

椅子に座ってたらメンバーがいろいろやってくれたおかげで.予選通過しました.学生枠にすがって通過してしまいました.

が,通ったもんは通ったので頑張ります.本選の皆さんよろしくお願いします.

強い人達のソース読みます.

追伸

最近,githubプロフィール変えました.

github.com

2017年夏技術的知見集

きっかけ

どうもみなさんこんばんは.ちぎちゃんです.

刺激的で知見の連続だった夏休みだったので,備忘録的に書いておきます.

こうして振り返ると,無知だったなぁとよく分かるしまだまだ知らないことが世の中たくさんあるなぁ.

ちょっと一記事に様々な情報が載りすぎなのでそのうち,気が向いたら記事分けよう...

気をつけて記事を書いたつもりですが,多くがインターンシップで学んだことなので,これはまずいですよ...というのがあったら連絡ください.速攻で該当箇所を消します.

設計とかのこと

DDDについて

DDD (Domain Driven Design) (ドメイン駆動設計)とは エリック・エヴァンスが考えた設計手法.

関心の分離ユビキタス言語の2つがすっごく大きな鍵になる.しなやかな設計というワードもたまに耳にする.

特に,自分的にハマった部分は,ドメインの様々な要素(Entity,ValueObject,Factory,Service,Repository...)等にはそれぞれ責務があり,あまったからここに割り当てようという考えではない.なんとなくEntityとかにすると痛い目にあう.さらにServiceはDomainServiceなのか,はたまた,ApplicationLogicServiceなのかというのも非常に迷うことが多い.

加えて,ドメインの世界では実装の都合など考えてはいけない.例えばRepositoryにはEntityのライフサイクルの管理や,永続化などの役割があるが,ここでDBの都合なんか考えてはいけない.これが自称学生エンジニア ( ) には辛かった.実装ありきで設計を考えていたのがすごくわかった.

まだ,理解が足りない点として,DDDに基づいたリファクタリングのことが一番大きい.

これは引き続き勉強したいし,以下の二冊を買わないとなぁ.

これはあるあるだけども,和訳のせいで理解が逆に難しくなることがあるので洋書でもいいなぁ.

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

実践ドメイン駆動設計

実践ドメイン駆動設計

Clean Architecture について

Clean Architectureは名前から分かる通り,アーキテクチャの1つ.「あれ?DDDとはどんな関係なんだ?」と思った方.私もまずそこでつまづきかけましたが,DDDにおいてはどんなアーキテクチャを採用するかなんて縛りは無いんですよ.

だから,「関係は?」と聞かれたら「DDDの方が広い概念で,いろんなアーキテクチャにDDDの考えを取り入れることは可能」と答えれば3点くらいもらえるんじゃないでしょうか(ちょっと自信がない).

少々話がそれましたが,Clean Architecture の目的は レイヤ間での関心の分離変更に強い というのがあるかなと思います.やりたいことってシンプルに,

8thlight.com

なんだけど,これ最初読んだときはわかった気になるけど,10回くらい読むとわからなくなって100回目くらいになるほどだんだん分かってきたぞってなりました.まあアーキテクチャなので,特に実装しようとするとつまることが多々ある.

そのなかでも一番ビッグで,個人的にすげぇ解決策だなと思ったのは,先のサイトでも触れられているDIP(Dependency Inversion Principle) (依存関係逆転の原則).

関心の分離・変更に強いを実現しているのは依存の方向を中心に向かって作っている点.これをすれば,中心をきちんと作っておけば,外側で変更を施すだけなので変更に強い(多分)し,レイヤーで区切っているので関心の分離もできている.やったね.

Hexagonal Architecture について

基本的にはClean Architectureと同じで 関心の分離 を目指している.それはそうで,歴史的に見たらこっちのほうが古いし,この思想を引き継いでCAができている感があるので,まあ.

このアーキテクチャでは特に外部との関わり方みたいな部分にフォーカスを当てています.外部ってなんだっけ?というのは,アプリケーションロジックが依存したらまずい部分で,Adapterを介してアクセスしようね.その役割でポートを切ろうねという感じかな.

Alistair.Cockburn.us | Hexagonal architecture

これ読めばだいたい分かるから....(責任転嫁)

awsのこと

そもそも

awsは趣味として嗜む程度にしか触ったことがなかった.そもそも,一学生が恩恵を受けられるほどの大量のデータを処理する機会なんて好きなイケメン俳優の画像をクローリングしてほげほげするくらいしかないでしょ.というわけでめちゃくちゃ知見を得られたよ.

Redshift Spectrum

RedshiftからS3に蓄積されているデータに対して直接クエリが投げられます(!) そりゃあもちろん,Redshiftに格納してそれに対しておいたほうが処理は早いのは自明なんですけど,S3に対して,外部スキーマ外部テーブルさえ作っておけば,Redshiftにクエリを投げる感じと同じ感じで扱えます.RedshiftにあるテーブルとJOINとかもできます.

うまく,使い分けをできれば学生には優しいお値段で運用できるかもしれませんね.

Parquet

Redshiftは(多分BigQueryも)列指向型です.列指向はレコード単位でのクエリより,カラムを指定する感じのクエリを高速にさばけるという利点があります.で,これにParquetという保存形式がすごく相性がいいんですよ.なぜならCSVJSONとは違って,保存のときに列を意識して圧縮されます.つまりこれS3に保存するときに,(バイナリなのでそのままでは読めないというデメリットはあるが)Parquetにして,上述のSpectrumで叩けばいい感じに高速に捌いてくれそうですね.まあ別にRedshit使わなくてもAthenaとかで見てもらっても全然いいんですけど.

ちなみに,Parquetはさっき書いたけれども,バイナリなのでそのままでは私は読めません.なので,

github.com

こういうのを使ってスキーマとか確認できます. というかよくよく考えると別にaws絡んでなくても良いので,ここに書くべきじゃなかったかなぁ.

Glue

GlueはサーバレスなETLです.スキーマ情報をいじいじしたり,ジョブを作ったり,それを定期的に実行したりいろんなことができます.複数の昨日の集合体という感じなのでGlue - HOGEみたいなのが幾つかあります.

まずは私が一番感動したGlue Crawlerについて書きたいかなぁと思います.これはサーバレスにS3等のデータを見て自動的にスキーマを吐き出してくれて,それをデータカタログとして保存してくれます.それだけでなく,不必要なカラムを落としたり,型を変えたり,ディレクトリ構造からパーティションを切ってくれたりといろいろしてくれる凄いやつです.私がまだ知らない(使っていない)機能として, classifierというのがあるので,非常に気になりますね.凄いけどクセも強いのでなれるまで数日かかります.

あとはjobです,今までは多分Sparkとかでやってた部分がこれに移り変わるのかな?適当にやりたいことをGUIでポチポチしてるといつの間にか自動でPythonコードが出力されています.なにか凝ったことをしたいときはこれをさらに書き換えたりする必要があるのですが,CSVをParquetに変換するくらいの軽いjobならそのままjobを実行できます.凄いですね.

Kinesis

Kinesisデータをリアルタイムで加工して分析につなげよう!という感じのあれです.いちいちデータレイクに行ってから分析してたらデータの規模がやばくなったらつらいですよね?そういうのを解決してくれます.

基本的に

  • Kinesis Stream (データを引っ張ってきたり,どっかに運んだりする.)
  • Kinesis Firehose (保存先(S3 や Redshift等)を決めて流す.)
  • Kinesis Analytics ( 強化版クエリてきなやつを使って流れてくるデータを加工する. )

の3つから成り立っていてこれらを組み合わせながらやる感じです.実はあんまりさわれてないんですよね....

プログラミングそのものに近いこと

Android Architecture Components について

突然,Androidが出て来る感じの構成になってしまって申し訳無さがあります.これ自体は今年のgoogle I/O で発表されたものだからみんな知ってると思います.

まだ alpha ver ですがこれ来るんじゃね?感がすごいです.

今までそれっぽいMVVMとかアーキテクチャを作ろうと思うと,いろんなライブラリを大量に導入することで無理やり実現している感がありました. 有名所だと

  • Dagger
  • DataBinding
  • Butter Knife
  • Rx

ココらへんはだいたい使わないといけない.これはなんか流石につらい.ってことでココらへんを全部解決してくれるライブラリをgoogle先生が作ってるみたいです(神)

基本的にサンプルコードがJavaで書いてあることが多いのが悲しいですが,Kotlinで書いて近いうちにもう一本記事かこうかしら.

というかここで,詳細にこれに触れるとこの項だけで凄い行数になる気がするので(途中まで書いててヤバイことになることに気がついた),後日サンプルappを作って自分なりに解説しようかなと思います.

軽く触れるとイメージ的には下のような感じかな(ちょっと分かってない)?

f:id:chigichan24:20170930122940p:plain

依存は基本的に緑の矢印の方向に向かっていて,Rxのイベントを発行する感じ(observer pattern)で値を戻して,上に依存するという感じ. で,色んな所にAACが表れてくるので,という感じだね.まあもうちょっと深く勉強してから記事かくか.

あとこれ買ったので,早く製本されて届いてほしいなあ.

peaks.cc

Minimal Cake Pattern

Scalaにおいてdiを実現する最高で最強な方法の話.

ノリはこんな感じ.Repositoryって例として考えるとだいたいUserってなるよね()

//CAでいうと,DomainLayerとかに書いておく.実装はInfraStructureLayerで.
trait UsesUserRepository {
    val userRepository: UserRepository //UserRepositoryは下でtaritとして定義し,実際に外からつかときはこっちを見る.
}
trait UserRepository {
    //interfaceをひょひょいと書く.
}
//実装部分
trait MixInUserRepository extends UserRepository {
    val userRepository = UserRepositoryImpl
}
object UserRepositoryImpl extends UserRepository {
    //interfaceはDomainLayerにあるのでそれを実際に実装するところ
}
trait UserService extends UsesUserRepository {
  // ここにサービスつくる
}
object UserService extends UserService with MixInUserRepository // 注入

ここに全てが詳細に書いてあったので詳細は省略.というかドワンゴが考えだしたやつなのでね.これ最初に見たときに確実に静的解析が効く形で,かつ抽象に依存するというのを再現してて,コードが煩雑にならない感じがするので,すごくいいなぁと思いました.

特にCAをScalaでやったときに,あ〜綺麗ってなりました(小並感)

qiita.com

Scalaのfor式のこと

Scalaはこの夏初めて触りました.そのなかでもforに感動したので,これについてちょっとだけ書いてみようかなと思います.

Scalaはコップ本読みつつ,ブログ記事をあさりまくるというスタイルでこの言語はなにがしたいんだろうというのをちょっとずつ理解していった感じです. C言語からプログラミングを始めると,forってループを制御するやつという感覚が体に染み付いているのですが,Scalaを書いてると,だんだんOptionとかFeatureを引っ剥がすやつみたいな感覚になってきました.

例えば,Optionで包まれたStringを表示するメソッド

def show(value: Option[String]):Unit

を作るとします.Optionなので値が入ってるかもしれなし,入ってないかもしれないのでというのを考慮して

def show(value: Option[String]):Unit = {
    if (!value.isEmpty) {
        println(value.get)
    }
}

こんなコードを書くとうーんて気持ちになります.Scalaらしくないというか,なんというか... こういう問題設定だったら,

def show(value: Option[String]):Unit = {
    for ( v <- value ) { println(v) } 
}

のほうが綺麗に思います.なんでここで forって疑問に思うかもしれないですが,Option に対する forってシンタックスシュガーなんですよね.なので,IntelliJとかで書いてると,

f:id:chigichan24:20171001183050p:plain

が出てきます.で,これを押すとこんな感じに展開されます.

def show(value: Option[String]):Unit = {
    value.foreach(v => println(v))
}

なるほど,forforeachシンタックスシュガーなんだね.じゃあforeachはなにかのシンタックスシュガーなのかな?

Optionforeachがどういう定義になっているかを見ると,

@inline final def foreach[U](f: A => U) {
    if (!isEmpty) f(this.get)
}

ここに isEmptyあるじゃん!!!

だからこそ,はじめに書いたようなコードがScalaらしくないと言われる所以なんですね.言語として用意しているメソッドならそっち使ったほうが一般的な感じになるよね.という話でした.

ちなみにこのケースでは,

def show(value: Option[String]):Unit = {
    value.foreach(println)
}

こう書くのが一番きれいっぽい気がするなぁ.

Kotlinのこと

Android開発において主流はもうこの言語に移行したと思うんですけど,日本語のKotlinバイブル本みたいなのもはまだ無いような気がします.それゆえ,どうかくのが一般的なのかイマイチ分かってなかったです(実は今もあんまりわかっていない).けれど,これはアンチパターンだなみたいなのはちょっとずつ分かってきたつもりです.

Convert to Kotlinは万能ではない

AndroidStudioを使うことを前提に話します.理由は私がこれしか使ったことがないからです(EclipseAndroid開発していたのは遠い昔の話).JavaとKotlinは100%互換なはずなので,一応機械的に変換は可能です.ただし,そのコードってイケてない事が多いと思います.動作はしても,KotlinらしくなかったらKotlinを導入するうまみが小さい気がします.

特にstaticまわりが厳しくて,自動変換がうまく効かないことがあるので,注意したほうがいい.

scope functionがどれがどれなのかがわけわからんくなる

Kolinにはいくつかのscope functionがあります(余談だが,scope functionという命名が謎だと思っていたけど,最後に示すブログ記事見てなるほどってなった).

ScalaのmapとかflatMapとかそこら辺の奴らみたいないいやつです.

とこの記事を書いてる最中にもわからなくなったので,ぐぐったらいい感じのブログ記事を2つ見つけたので,先に貼っておきます.

qiita.com

nyanyoni.hateblo.jp

一つ目のはKotlinやってたら絶対に知ってる長澤さんの書かれた記事なのでめちゃくちゃわかりやすい!!!

let
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
with
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
run
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R = block()
apply
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
also
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }

定義を見ればなにができるのか一目瞭然だ!!!

github.com

わからなくなったら,これ読み込もう(原点回帰).ちなみにIntelliJなら [command ⌘] + クリックで定義元みれますよ.

Androidっぽいこと

Recycler Viewのはなし

今までListViewで殴ってきたり,そもそもViewまわり嫌いだったのでそっとしてたりしてましたが,本腰を入れて触りました.こっちのほうが自由度が高い分,例えばAdapterを自前で書くなど記述量は増えますがやっぱりなんでもできるようになります.まあここらへんの記述は✝コンパイルエラー✝が出ることが多いので良いんですが,やっぱりxmlでlayout書くのがどうしても体が受け付けませんでした.こういうケースはwrap_contentでこういうときは,match_parentだけど,これは例外みたいなのが結構多いので疲れます...

Mainframerのこと

話には聞いたことがあったが,リモートビルド良い.といっても個人での開発では使うことはほとんどないか.

github.com

AAC

上にも書きましたが,別記事で書きます.

その他

  • 保守性,拡張性を意識したプログラミングがあまりできてないことが分かってきた(いままで好き勝手書いてきたからなぁ).
  • アーキテクチャにすごい興味が出てきた.
  • intelliJ IDEA,まじで全然使いこなせていない便利機能がたくさんあるので,もっと開発したいね.
  • 世の中,まだまだ楽しいことがたくさんだぞ😊

最後に

まだまだたくさん学んだことはある気がする...ほんとに一つ一つちまちまと書いていたら時間が溶ける一方なのでここらへんで...

こういう最高な体験をする機会を与えていただいた皆さまありがとうございました.