F@N Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・nex8のエンジニア・技術ブログ

GoでSSP構築をやってみた

こんにちは。
3月25日〜3月29日までの5日間、インターンでお世話になりました澤です。
9月にもSDKインターンでお世話になりましたが、今回またお誘いをいただき、今度はSSP構築インターンに参加させていただきました。

課題

課題は、SSP(Supply Side Platform)を構築するというものでした。
よくWebサイトを閲覧したり、スマホでゲームをやったりする時に広告が出ていると思います。
Webサイトにその広告を配信しているのがSSPです。

簡単に言えば、SSPとは、Webページに広告を掲載したいという時に、いい感じに処理して、広告を配信してくれているサーバのことです。

前回、SSPやDSPに関する説明を受けた時に、アドネットワークの世界にはこんな物語があるのかと感動した記憶があるので、今回SSPというアドネットワークの一部に触れることができる課題で非常に楽しみにしていました。 

5日間の流れ

1日目

いくつかの書類を書いて、会社についての説明を受けました。
そして、今回の課題についての説明を受け、課題をスタートしました。
僕自身サーバサイドのプログラムの経験は乏しいのでとても不安なスタートでした。
どの言語で書くかを自由に決められたので、Goを使うことにしました。
理由としては、
・比較的速度が速い
・並列処理に強い
・ライブラリなどが充実していて書きやすい
というのが主な理由です。

ネット上の記事を参考にしながら、何となくですが触りの部分は実装することができました。

2日目

Go言語を書くのも初めての経験だったので、非常に苦戦しました。
 
例えば、このような構造体があったとします。
 

type DSPRequest struct {
	ssp_name     string
	request_time string
	request_id   string
	app_id       int
}

何とこのままでは、他のパッケージからアクセスすることができないのです。
他のパッケージからのアクセスを有効にするには、以下のように要素の初めの文字を大文字にしないといけないのです。

type DSPRequest struct {
	Ssp_name     string
	Request_time string
	Request_id   string
	App_id       int
}

Javaのようにpublicをつけるという訳ではないので、知った時は目から鱗でした。
これに気づくのに2,3時間かかってしまい、非常に痛いミスでした。

SSPの話ではなくGo言語の話になっていますが、Go言語の仕様に悩まされつつSSPの構築を進めました。
サーバサイドのプログラムだけでなく、Go言語の学習にも繋がったので良かったです。

3日目

SDKからSSPにアクセスし、SSPからDSPに広告を要求し、その結果である広告のURLをSDKに返すという一連のSSPの処理を完成させることができました。

Goもサーバサイドも初めてで苦労しましたが、何とか形にはできて嬉しかったです。

ソースコードが読みづらかったので、少し綺麗にしようと試みました。
しかし、結果10行程度の削減にしかならなかったので、もう少しコンパクトに書けるように訓練していきたいと思いました。

4日目

この日はローカルの環境ではなく実際のサーバ上で動くかどうかを確認しました。
結果、サーバ上でも動作したので良かったです。

また、DSPから100ms以内に返事がもらえないときにタイムアウトする処理の実装を忘れていたので実装を行いました。
しかし、タイムアウトの実装が非常に難しく一日行いましたが、終わりませんでした。
ネット上で色々探して、実装してみましたが、どれも上手くいきませんでした。

やっぱりGoはあまり好きではないと感じたので、時間があれば他の言語でも書いてみたいと思いました。
(あるいはサーバサイドのプログラムが好きではないのかもしれない)

5日目

引き続きタイムアウトの実装を続けて、昼前には何とかそれっぽいものが完成しました。
良いか悪いかは別として、チャンネルを使いこんな風に(取得する値の数次第では、修正する必要あり。)書いてみました。(全体像はこちら

ch := make(chan string)
for i := 0; i < 1; i++ {
	go func() {
		Request_id, Url, Price, err = communicateDSP(url, dspRequestJson)
		ch <- "ok"
	}()
}

// タイムアウトを設定する
timeout := time.After(100 * time.Millisecond)

for i := 0; i < 1; i++ {
	select {
	case result := <-ch:
		fmt.Println(result)
	case <-timeout:
		err := errors.New("timeout")
		return "", "", 0, err
	}
}


書いたものの、不安定なので、それからもどうしたらいいのだろうかと考えてました。
負荷をかけてみても結果はよくありませんでした。

色々後悔することはありますが、レビューをいただいて、ブログを書いてインターン終了しました。

まとめ

今回、実装したコードはGitHubに公開しているので興味のある方は是非ご覧ください。
github.com

初めてGo言語を触ったので言語仕様にもなれず非常に苦戦しましたが、良い経験になったと思います。
また、サーバ構築を本格的にしたのも初めてだったので勉強になりました。

時間がなくて取り組めなかったことや後悔していることとしては、

・捌けきれない量の通信が来てもいいように作成したプログラムの前にnginxなどを置くこと
・コードが綺麗ではなかったり、無駄なところ多かったりしたので綺麗に書きたかった
・もう少しサーバサイドの知識やGo言語の知識を身につけてインターンに臨みたかった
・英語が苦手だが、英語から逃げずに英語の文献やページも読んで実装したかった
・分かりやすいログを出してどこで詰まっているのかを明確にして取り組むべきだった

といったところです。

最後に

インターンを受け入れてくださり、ありがとうございました。
会社の雰囲気もよく、非常に過ごしやすい1週間でした。
特に机の高さが自由に変更でき、立っても座っても作業できるのは新鮮で良かったと思います。

メンターのy_kawasakiさんをはじめとしてサポートしていただいた社員の皆さんありがとうございました。

非常に楽しく自分のペースで進めていくことができたので、おすすめです。

F@Nのインターンに応募するか迷っているのなら、ぜひ応募することをおすすめします。

5日間という短い期間でしたが、ありがとうございました。