うたもく

i am a student.

サイバーエージェントインターン(エンジニアJOB)

サイバーエージェントエンジニアJOBに約1ヶ月間(2/16-3/14)行ってきました。

www.cyberagent.co.jp

内容としてはいわゆる就業型インターンってやつです。
写真を撮ることを忘れていたのできらきらインターン生にはなれませんでした。
今回はアドテクの部署でインターンを行いました。

アドテクとは

めっちゃめちゃいっぱいアクセスくるので頑張る分野です。
僕なんかより知識がある人が詳しくかいているのでこちらをどうぞ。
一言でいうと広告です。
あのなんかみたことある商品に近いものが広告で出てくるあれです。
以前にサイバーエージェント主催のアドチャレというアドテク関係のイベントにも参加していました。

f:id:utam0k:20180324170726j:plain
うまい肉

Dynalyst

配属された部署はアドテクのDynalystでした。
初めにDynalystと聞いたときは何かの役職かと思っていました。
ホームページによると

Maximize Revenue and In-App Conversions with Re-Targeting Campaigns

www.dynalyst.io

Re-Targeting 世の中には難しい単語がいっぱいありますね。
Dynalystはアドテクでいう DSP というところです。世の中には難しい単語がいっぱいありますね。
CAのアドテクではScalaを採用しているプロダクトが多くDynalystもScalaを採用していました。

働く環境

最高でした。広い作業スペースに良い椅子に最高でした。
渋谷駅のマークシティ最上階(23F)でした。毎朝渋谷を見下ろせます。
住む場所はサイバーエージェントのエンジニア男性のみしかいないシェアハウスでした。 会社には徒歩で着くので電車乗らなくて済みました。 adtech studioっていうおしゃれなとこでした。

www.youtube.com

フットサルみたいなかっこでずっと通っていたらスポーツしに来たのってめっちゃ言われました。
それ以外服をもってきていなかったのです...

使った技術

詳しいことは書きません。

Scala

Scala初体験でした。 もともと関数型プログラムには少し興味があったので大きめのScalaのプロダクトに触れれるのは楽しみでした。

Akka Streams

これは楽しいやつです。
Akka界隈もScala界隈もわからないんですが、きっと結構新しくてわくわくするものだと思います。

doc.akka.io

f:id:utam0k:20180324170657j:plain
うまいすき焼き

行く前にやったこと

カラーコップ本

個人的にはすごいH本のScala本という感じで面白かったです。
Scalaの関数型としての側面です。

book.impress.co.jp

コップ本

知人にこれやったほうがいいと進められて14章くらいまでやりました。
カラーコップ本を先にやりましたが、おそらくこちらを先にやるべきでした。

book.impress.co.jp

Akka http

ちょこっとだけやりました。

doc.akka.io

やったこと

前菜

土日や終業後の時間を使ってDynalystのコードを垣間見ていました。
やはり人間は隠されているものは見たくなるものです。
自分が見てる商品とかどうやってわかってるのかとか詳しく知りたくないですか!?
いままでのインターンだとWeb開発が多かったのでアドテク初体験なので楽しくやれました。
その代わりわからない単語や知らないことが多くて調べものもしました。
まずはチームWikiの初心者向けを探してとりあえず一通り読んでました。
あとはプロトコルのOpenRTBというのが割りとというかかなり肝だったので仕様や単語も眺めていました。

www.iab.com

最初の方はRFCで探してて見つからなくて泣いていました。
これからアドテクに関わる人は読んでおくとプロダクトのコードの変数名の意味等わかるかもしれません。

f:id:utam0k:20180324171140j:plain
うまいかつ丼

メインディッシュ

今回のインターン前回のミクシィとは異なり大きめのタスクを与えられて1か月でそれをこなしていくというスタイルでした。
多分どんなタスクになるのかは配属される部署やメンターさんによって異なると思います。
僕のタスクは既存の基盤をAkka Streamsで再実装して置き換えるというものでした。
アドテクでは大量の処理を高速に処理する必要があるためいろんなことを並列にして高速で処理する必要があります。
僕のもAkka Streamsで並列で処理してQPSを目標のところまで上げないといけませんでした。
動く物自体は割とすんなりすぅとできました。
しかし、QPSが目標値まででない...
そして始まる並列処理のデバッグ...
そして、Akka Streamsは様々な部品(Source, Flow...)で構成されていて1つ1つがマイクロサービスぽくなっているので
さらにデバッグが難しくなりました(⋈◍>◡<◍)。✧♡
ここからではかなりいろいろな知見が得られました。
スレッドダンプ初体験でした。

f:id:utam0k:20180325171222p:plain

完成しないと島根に帰れないとところでした。(冗談だったと思います。たぶん。)

感想

今回のメンターさんが新卒の方でした。
僕のイメージだとインターンのメンターさんはベテランの方と思っていたので最初はびっくりしました。
以前の就業型の場合だとメンターさんもある程度その部署にいて使う技術に触れ続けているので、てきとーに質問してもこっちの意図を理解してもらうことができました。
今回のインターンだとしっかり問題の根本について自分の頭のなかで整理してから伝えるようにしました。
この辺はかなりよい経験をさせていただきました。

Scala初挑戦でした。
implicitワカラン...

個人的にはアドテクの技術分野について知識がなかったのでめっちゃ面白かったです。
めっちゃアクセス来るのを生で見れたりする体験はなかなかできないので楽しかったです。

また、Dynalystは営業の方々がすぐ近くにいたり、朝会を一緒にしていました。
数字にストイックな感じはなかなか体験できないので面白かったです。

Dynalystはインターン生初受け入れとのことでした。
Scala初体験のインターン生を快く受け入れていただきありがとうございました。
お世話になりました。

f:id:utam0k:20180324171620j:plain
うまい担々麺

おまけ

チームのエンジニアさんが僕のインターン期間中にCircleCI2.0を傷つけていました。

ドワンゴ/二コフレ サマーインターン

どうも、うたもくです。
この記事は nico.friends Advent Calendar 2017/12/08の記事です。
ドワンゴのサマーインターンでの二コフレ*1の機能作りをどんな感じでやったのかを書いていきます。

adventar.org

ドワンゴサマーインターン

いやー最近は暑いですね。(インターンが終わってNヶ月も経ってしまった。)
内容は二コフレの新機能開発でした。インターン生2人で1チーム開発。
チーム名: 「WebサービスRubyでつくるか?PHPでつくるか?」(以下: WRP)
相方ちゃん

https://internship.dwango.co.jp/2017/engineer/internship.dwango.co.jp *2

お先に読むといいもの

新機能ができるまで

  1. 案出
  2. 実装
  3. 最終プレゼン
  4. リリース

案出

案を考える上で大切なのは二コフレの世界観です。
1ヶ月間この世界観を考え続けました。
WRP内で出ていた案は僕が覚えてる限りだと

  • 新カコ*3支援機能
  • 部活支援機能
  • カスタム絵文字*4

とか出ました。*5

実装

ハト先生*6との話し合いもありWRPはカスタム絵文字を作ることになりました。
WRPは2人の得意分野(サーバー/フロント)が両極端でした。
相方ちゃんがかなり優秀なフロントマンだったのでフロントは全部お任しました。
とは言えまずはペアプロでお互いの分野を知ることをやりました。
僕はといえばRails2/Ruby1.8という化石だったので脳内アップデートを頑張りました。
なんだかんだ順調にカスタム絵文字の開発は進んでいきました。

「よっし、そろそろカスタム絵文字で遊べるドン」
そんな矢先ハト先生から恐ろしいお知らせが…
3連休が明けた9/19はインターン時の最悪の日になりました。

非、非常に厳しいお知らせ????

f:id:utam0k:20171207114414p:plain

カスタム絵文字が本家にマージされたのです。 github.com

だれも悪くないのです。
僕たちが欲しい機能は本家も欲しかった。
それだけなのです。これがOSSか...
本家と同じ機能をカスタムとして入れるのは技術的負債にしかなりません。
ということでWRPが作ってきたカスタム絵文字はきれいさっぱりなくなりました!
わーい\(^o^)/
ちなみにWRPが作っていたカスタム絵文字はある限定的なユーザーは絵文字の登録ができるようになっていました。

最悪の日がいつ起きたのか?
残された時間はどのくらいなのか?

f:id:utam0k:20171207134203p:plain

最高にたのしーインターンの幕開けでした。 *7

ということで即日Skypeハト先生と再度話し合いが行われました。
そこで浮上した案がプロフィール絵文字でした。
WRPは地獄から生還しました。
プロフィール絵文字は「:@username:」とトゥートするとユーザーのアイコンに変わってくれます!

friends.nico

プロフィール絵文字の主な利点

  • 既存のリソースであるユーザーのアイコンを使える
  • DBへの変更がない
  • すごーい! たーのしー!

色々細かい機能も頑張りました。

  • プロフィール絵文字をクリックすると該当ユーザーへのジャンプ
  • usernameの補完機能
    これはもともとあったユーザー補完機能を流用することで工数が少ないかつ効果があるという判断で最優先でやっていました。
  • プロフィール絵文字のコピペ
  • プロフィール絵文字をマウスオーバーすることでの拡大
    GIFをどうするかに話し合いはしました。
    意図しないときに拡大することがないように調整したつもりです。
  • トゥートだけでなくCW*8やプロフィール欄その他もろもろに対応

あとプロフィール絵文字ではプロフィール絵文字に使われたユーザーに通知がいかないようになっています。

懸念点としては好きな絵文字を使いたいがためにテキトーな新規ユーザーを大量に作るという点でした。
そのためEmailブロックリストも作ってみました。
こちらはニコフレのみならずMastodon本家にも必要だろうということで本家にv2.0から新機能入り。

github.com

最終プレゼン

最後はメンター陣+インターン関係者の方々の前でプレゼンが行われます。
ここでリリースされるか否かが決定します。
リリースされるかが決まるのでガチです。
ガチガチのガチです。

リリース

なんやかんやで実装は間に合い9/28にリリースされました。

friends.nico

詳しく書いていただきました。

www.itmedia.co.jp

リリースされた直後に二コフレのみんなが使ってくれて非常にうれしかったです。

その後

まさらっきさんが中心となってプロフィール絵文字を本家にプルリクエストを出しています。

github.com

最後に

二コフレはインターンで初めて触れました。
今や青い鳥より見てる時間が多くなりつつあります。
オフ会にも参加しました。 なんか雰囲気が好きなんです。
二コフレのみんなが少しでもプロフィール絵文字で遊んで楽しんでくれていたら幸いです。
メンターの皆さんお世話になりました。

おまけ

インターンで習得した単語

  • 世界観
  • 左様か
  • 納得

次はao_39lさんです。よろしくお願いします!

*1:ドワンゴが運営するマストドン

friends.nico

*2:そのうちリンク切れすると思います。

*3:新規ユーザーが初トゥートした時にユーザーみんなでお祝いする儀

*4:Slackのやつ

*5:公式の意見ではないです。 今後作られるかどうかなんてわかりません。

*6:二コフレプロデゥーサーさん

*7:インターンは11:00-19:00で帰らなければならないのでブラックにはならなかったです。

*8:Contents Warning

AdTech Challengeで初めてGinに触れて感動した話。

CyberAgentさんのAdTech Challengeに参加してきました。
その時にGinを用いて少し感動した話です。
そもそも筆者はこのハッカソンでGoを初めてちょっと本格的に触れました。
www.cyberagent.co.jp

ハッカソンの内容

  • 2000QPSで位置情報が投げられる(タイムアウト: 100ms)のでどうにかする
  • 学生3人 + 社員1人のチーム開発
  • うちのチームはGin + MySQL + Kubernetsで構築

何が気になったか

うちのチームは「まぁまずは2000QPSを体感するか」ということで
まず、手始めに受け取ったデータをいい感じにしてDBに打ち込みだけのものを作ってみました。

僕の予想では

  1. DBに触れ過ぎで死ぬ
  2. タイムアウトしてリクエスト中身を見れない

かなと思いながら見守っていました。

実際にやってみると何と2の方は問題がありませんでした。
「え???」
ってなりました。
実際にリクエストの処理をし始めるまでに100ms経過していました。
その場では開発時間が短いのもあって
「Ginがいい感じにしてるのだろう。以上!」
って感じで1の方のボトルネックの解決をしていきました。
2の方が気になった点だったので終わった後に少しだけ調べてみました

Ginが何をしていたのか

結論はGinがいい感じにリクエスト等をPoolをしていてくれたおかげでゆっくり処理をしてもタイムアウトした後でもリクエストの中身を処理していました。
今回の場合だと大量のリクエストをDBに格納するのみでした。
そのため、レスポンスはなくても良かったので問題ありませんでした。
Ginは軽いフレームワークだと認識していたのでそこまで手厚くしてくれると思っていなかったので少しびっくりしました。
間違いがあったらごめんなさい。

結論はそういうことだったんですが、とりあえず原因探しでGinのコードを追ってみました。

Engineをみてみるとpool...
あっそれっぽいのがありました。

https://github.com/gin-gonic/gin/blob/v1.2/gin.go#L46

type Engine struct {
    RouterGroup
    delims           render.Delims
    secureJsonPrefix string
    HTMLRender       render.HTMLRender
    FuncMap          template.FuncMap
    allNoRoute       HandlersChain
    allNoMethod      HandlersChain
    noRoute          HandlersChain
    noMethod         HandlersChain
    pool             sync.Pool
    trees            methodTrees
               ・
               ・
               ・

sync.Poolとはなんぞい。

sync - The Go Programming Language

いい感じにPoolしてくれそうだ。 それでそれで何をPoolしているのだ?

https://github.com/gin-gonic/gin/blob/v1.2/gin.go#L108

func New() *Engine {
    debugPrintWARNINGNew()
    engine := &Engine{
        RouterGroup: RouterGroup{
            Handlers: nil,
            basePath: "/",
            root:     true,
        },
        FuncMap:                template.FuncMap{},
        RedirectTrailingSlash:  true,
        RedirectFixedPath:      false,
        HandleMethodNotAllowed: false,
        ForwardedByClientIP:    true,
        AppEngine:              defaultAppEngine,
        UseRawPath:             false,
        UnescapePathValues:     true,
        trees:                  make(methodTrees, 0, 9),
        delims:                 render.Delims{"{{", "}}"},
    }
    engine.RouterGroup.engine = engine
    engine.pool.New = func() interface{} {
        return engine.allocateContext()
    }
    return engine
}

あっpool.Newしてる。。。

ContextをPoolしてるみたいだ。hmhm。
https://github.com/gin-gonic/gin/blob/v1.2/gin.go#L141

func (engine *Engine) allocateContext() *Context {
    return &Context{engine: engine}
}

あっpool.Get()してる。あっServeHTTPだ。

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    c := engine.pool.Get().(*Context)
    c.writermem.reset(w)
    c.Request = req
    c.reset()

    engine.handleHTTPRequest(c)

    engine.pool.Put(c)
}

調べた感じこんな感じでした。
いや、さすが並列処理に強そうなGo言語なだけあってサクッとできてますね。
しゅ、シュゴイ。
Goの力の片鱗を体感しました。

もともとchannelでやってたのを変えてたみたいでした。 github.com

ハッカソンの結果

審査員特別賞をいただきました。
ボトルネックを的確に判断して、最小限の構成でいったのが評価されたみたいです。
景品にギンピカAbemaくんをいただきました。
f:id:utam0k:20171024000429j:plain

Dive into mixi GROUP 2017 Summerに参加した話

やったこと

8/1~31の1ヶ月間ミクシィDive into mixi Groupという長期就業型インターンをして来ました。 f:id:utam0k:20170901171705j:plain

Dive into mixi Groupミクシィグループの様々なサービスに振り分けられて就業型のインターンを行います。
僕はミクシィグループの株式会社フンザインターンを行いました。

hunza.jp

株式会社フンザ

チケットキャンプを運営している会社です。

ticketcamp.net

他にもエムクエを運営しています。

https://mque.infomque.info

ミクシィインターンに参加する理由

この辺はらりょすさんと同じだったのでこの辺をみてください。

raryosu.hatenablog.com

長期インターンかつ面白そうだったから! これが主な理由です。

インターンに行くまで

〜内定

Dive into mixi Groupの内定をもらうまでにはES + 面接N回を行いました。
普通の形式でした。僕の場合は地方だったのでスカイプ面接で全てを済ませてもらえました。 ワイワイと人事の方とお話しました。 どこの会社や部署に配属されるかは希望も出せます。
僕の場合は人事の方に見極めてもらいました。
実際に行ってみると僕以外のインターン生はほとんど逆求人とかから気がついたら決まってたみたいな人が多かったです。

内定〜インターン初日

メンターさんとCTOさんとの面談がありました。
メンターさんとの顔合わせやインターンまでにやっておくと良いことなどがご鞭撻されます。
Djangoのドキュメントを読んでおいてと僕は言われました。
チュートリアルのその4くらいまでしかやっていきませんでした。

インターン内容

初日

ゆで卵を食べろと言われました。

環境

  • 椅子と机
    シュゴイ。 とにかくたかそうです。 机が上下に動いて立ちながら作業できます。 インターン生にもきちんと社員さんと同じように1テーブルをもらえます。

  • ドリンク
    フリードリンクです。 コーヒを飲みすぎると無限にお花を摘みに行く羽目になるので注意です。 社内に半額くらいで飲めるバイロンベイコーヒーというカフェが入っています。 ラテアートが毎度毎度かわいかったです。

https://www.wantedly.com/companies/hunza/post_articles/74324www.wantedly.com

  • 勤務時間
    10:00-19:00でした。
    フンザの場合は9:45から朝会があるのでそれより少し出社して19:00より少し遅く退社という感じでした。

  • 住みどころ
    高田馬場にマンスリーマンションを用意してもらえました。 山手線で乗り換えなしでいけるので良きでした。

  • 開発環境(物理)
    最新のmac bookが支給されます。
    ディスプレイも支給されます。
    欲しいものを言えばだいたいある印象を受けました。 自前でキーボードとトラックパッドを用意してました。

  • 開発環境(ソフト)
    これは配属される場所によって多少変化があると思います。 基本的には開発は
    git + github + slack
    エディタは自由です。pycharmを使ってる人が多かったです。
    僕はvimを使っていました。
    隣のエンジニアさんがemacsでした。  

その他の詳しい話やお金の話はこちらをどうぞ。

pr.mixi.co.jp

インターンでやったこと

配属される場所によって違いがあると思います。
就業型は就業型でした。
githubにあるissuesからメンターさんが適切に選んで割り振られます。
それをこなしていきます。
以上です。

本当に現場(チケキャン)の問題を解決していきます。ハッカソンとかではないです。 機能追加やbug fixなど様々です。
メンターさんは隣にいてくれます。困ったら聞いていました。

もちろん会議にも参加していきました。 自分の意見を言ってもきちんと聞いてもらえます。 社員さんとほぼほぼ遜色ない扱いを受けさせてもらえます。

僕は
フロントやりたくない! AWS触ってみたい!
とわがままを言ってみるとそれについて考慮してもらえました。 インターン生に触らせると怖いであろうAWSに触らせてもらえました。
圧倒的感謝です。
terraformを使っているイケてる会社です。

フンザならではのこと

日本最大級のDjangoプロジェクトに触れます。
歴史があるプロジェクトに触れます。

コードレビューが厳しいらしいです。 と言うのも長期インターンが初めてなので比較ができませんでした。 周りの人が言っていたので多分厳しいのだと思います。 PullRequestが一発で通ることは他のエンジニアさんのもほとんど見ませんでした。 いっぱいボコボコにしてもらえました。 コードレビューが厳しいだけあってコードが綺麗でした。 スラスラリーディングできて気持ちいいです!! DjangoAWSのプロがいっぱいおられました。

エンジニア以外のこと

ランチをいっぱいセッティングしてもらえました。 同じ高専生の方やギークエンジニアの方等設定してもらえました。 さすがなだけあってレベルが高い方いっぱいおられました。 僕がボソッと
SRE...
と言うと人事の方がXFLAGのSREエンジニアの方とランチを設定してもらえました。 Googleのネットワーク障害の話やXFLAGにおいてのSREの定義などの話ができて最高に楽しかったです。

ランチ以外にもインターン生懇親会やインターンMTGなどありました。
懇親会での料理はとても豪華でした。 f:id:utam0k:20170901174427j:plain

人事の方達がとにかく僕たちの意見を聞いて何かしらのアクションをしてくれます。 本当にすごいです。 学生のことを本当に考えてくれる人事の方達でした。

その他

8月が人間とは思えないくらい草が生えました。 utam0k (utam0k) · GitHub

無事にDive into mixi GROUP 2017卒業生第1号となれました。
会社が快適すぎて最終日の次の日も遊びに行ってこうしてはてブを書かせてもらってます。
これから送別会を催してもらえます。
感謝感謝です。

まとめ

長期就業型のインターンはいいぞ。