Slide 1

Slide 1 text

長年運用されている Web サービスと 通信をするクライアントを Go で作ってみた話 commojun (株式会社カヤック)

Slide 2

Slide 2 text

自己紹介 commojun (大澤 純) 2016年新卒入社 サーバサイドエンジニア ぼくらの甲子園!ポケットというソーシャルゲームの運用に従事 趣味 - 🎺 - 異世界転生アニメ - 最近娘が1歳になった

Slide 3

Slide 3 text

今日の内容 https://fortee.jp/yapc-hiroshima-2024/proposal/d2140bb9-c915-46cc-a05d-24532a190263

Slide 4

Slide 4 text

ちなみにEC2からECSに移行をやったこともあります 今日はSREの発表が多いので… https://yapcjapan.org/2022online/timetable.html#talk-21

Slide 5

Slide 5 text

本題へ

Slide 6

Slide 6 text

甲子園ポケットとは 高校球児をロールプレイする野球ゲーム 15人vs15人のユーザで野球をするGvG 2014年リリース、今年で9周年

Slide 7

Slide 7 text

このプロジェクトに長らく従事しています 甲子園ポケットのサーバはPerlでできています

Slide 8

Slide 8 text

カヤックはGoに力を入れます宣言 https://www.kayac.com/news/2014/08/golang ※

Slide 9

Slide 9 text

このままだと僕のキャリアの行方は…? 2010年代前半のものづくりの延長線でしかキャリアを積めていない このままで大丈夫か?という疑問が ※ 開発部署によってこれ以外の言語も多様に選ばれています

Slide 10

Slide 10 text

Perlエンジニアの年収が高い? https://ledge.ai/articles/persol-hr-forecaster-map

Slide 11

Slide 11 text

Perlエンジニアの年収が高い? https://ledge.ai/articles/persol-hr-forecaster-map ledge.aiの記事より引用 > いま平均年収が高い言語は、以前からニーズが高く、経験や知識が豊富なエン ジニアが多いため、学びたい言語と年収の高い言語の順位に乖離が生じたと考え られる。 (※学びたい言語 ≒ 現在人気の言語)

Slide 12

Slide 12 text

優秀なPerl技術者は、Perlだけにとどまらず、 時代によるトレンドの変貌の波にうまく乗って力強く生きている

Slide 13

Slide 13 text

やはり新しいことに挑戦すべき 自分の社内ニーズを上げるため 今後のキャリアのため Goでなにか1からシステムを書いてみよう その事実を作っておけば、チャンスが来たときに声がかかりやすい

Slide 14

Slide 14 text

考えた題材:ゲームを勝手にプレイするAI ● サーバに対してAPI通信を行うクライアントをGo で書く ● Unity製のクライアントアプリと同等のことができ る ● ただし、何をするかを人間が考えるのではなく、 AIが自律的に判断して行動する Goでなにかを作ってみる題材としてはかなり多くのこ とが学べそう

Slide 15

Slide 15 text

AIの話はありません! AIと言いましたが… ◯ Perl製の既存プロジェクトに対してクライアントがAPI通信   できるようになるまでに苦しんだこと ✕ AIの内容、作り方、効果 AIの中身について考えられるほ ど制作は進捗していません

Slide 16

Slide 16 text

API通信をするにあたって必要なこと サーバとデータをJSONでやり取りする Goは静的型付け言語なので、JSONに含まれる要 素と型情報を構造体に列挙しなければならない JSON <-> Go構造体変換をしつつ、httpリクエスト を組み立てたり、レスポンスを解釈するコードをす べてのAPIに対して書く必要がある

Slide 17

Slide 17 text

なにか良いツールはないか? ● 自分はGo初心者なので、既にあるツールをうまく使って車輪の再発明を避けたい ● サーバ - クライアント間でJSONをやりとりしてくれるコードをいちいち書くのが面倒 という悩みはみんな持つはずだ! ● そういったコードを自動生成してくれるツールが絶対世の中にあるはず ● みんなが使うツールに乗っかってこそ、初心者を脱出できるはずなんだ!

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

OpenAPIとは ● 元はSwaggerと呼ばれていた ● REST APIの仕様を記述するためのとても有名な フォーマット ● yml形式でAPI仕様書を書く ● API仕様書にリクエストとレスポンスの要素・型情報を 書けば、(Goも含め)様々な言語のコードを生成 してくれる ● webUI上で編集したり、モックサーバを作成できたり 多機能 とても名のあるツールなので、使えるようになっておこう!

Slide 20

Slide 20 text

生成したコードを使うと… リクエストをJSONに変換する部 分や、レスポンスで受け取った JSONを解釈する部分を意識せ ずに、API通信を行うというコー ドを書くことができる

Slide 21

Slide 21 text

壁に当たる とりあえず手作業でymlをいくつか書いてみたが… 9年運用しているサーバはリクエスト/レスポンスの型情報が複雑 例えば… 要素数1万超え、ネスト深さ5以上のJSON 手作業でAPI定義のymlを書くのは難しい そもそも既存のAPI定義書は無いのか? -> ある

Slide 22

Slide 22 text

API定義書: Baal 甲子園ポケットにもAPI定義書はある 弊社独自のAPI定義書のフォーマット これを使ってクライアントアプリ( Unity C#)のコード生成 をしている サーバのコード生成はしていない これを使ってOpenAPIのymlを生成してみよう (API定義書の変換) https://techblog.kayac.com/unity_advent_calendar_2016_20

Slide 23

Slide 23 text

openapi.yml API定義 Goの 通信関連 コード openapi-generator Baal API定義 yaml-generator これを作ってみよう

Slide 24

Slide 24 text

Go製Baalパーサー

Slide 25

Slide 25 text

テンプレートエンジンを使ってymlを生成 Baalパーサーとテンプレートエンジンの 使い方の習得に苦戦 苦労して出来上がったymlのテンプレート→ 呪いの呪文のようだ

Slide 26

Slide 26 text

これでAPI通信基盤が完成!

Slide 27

Slide 27 text

とはならなかった! ダメです

Slide 28

Slide 28 text

API通信失敗 BaalによるAPI定義書 -> OpenAPIのAPI定義書 -> コード生成 によって生成したコードで通信を投げてみたが、 「型情報が違うのでJSONを解釈できない」というエラーが… API定義書に従ってコード生成したのに…?

Slide 29

Slide 29 text

サーバが返すJSONが型に厳密ではなかった ● 文字列として扱いたいのに、数値として送信してくる 場合がある ● 数値として扱いたいのに、文字列として送信してくる 場合がある ● 正しく送信してくる場合もある →文字/数値の扱いが不定のJSONを柔軟に  受け取れるようにする必要がある (サーバを直すというのは今回自身に課したレギュレーション的にナシ)

Slide 30

Slide 30 text

型を柔軟に受け取るには、JSON解析後の型当てはめを自分 で実装する必要がある Response JSON Go 構造体 型付き JSON解析&型当てはめ Response JSON Go 構造体 なんでも型 JSON解析 Go 構造体 型付き 型当てはめ この処理を今回のケースに合わせて自作する必要がある

Slide 31

Slide 31 text

OpenAPI、ダメかも openapi.yml API定義 Goの 通信関連 コード openapi-generator Baal API定義 yaml-generator Response JSON Go 構造体 型付き JSON解析&型当てはめ OpanAPIが生成したコードがブラックボッ クスで、生成物をカスタマイズできなかっ た Goであるがゆえに難しい

Slide 32

Slide 32 text

OpenAPIを使うのをやめる

Slide 33

Slide 33 text

そもそもなぜOpenAPIを使ったか? Goの構造体と通信を担うコードを生成するのは難しいと感じたから 既存の仕組みにはなるべく乗っかるべきだと思っていたから openapi.yml API定義 Goの 通信関連 コード openapi-generator Baal API定義 yaml-generator Baal API定義 Goの 通信関連 コード client-generator (自作) ここを自前で作るのは難しい(と思っていた) これを辞めて これをやることにした ツールを辞めて自前で作ることで、 JSONの型について 柔軟なしくみを作れるようになる

Slide 34

Slide 34 text

実は、知らない間に実力がついていた openapi.yml API定義 Goの 通信関連 コード openapi-generator Baal API定義 yaml-generator Baal API定義 Goの 通信関連 コード client-generator (自作) これを作るのに必要な要素 - Baalパーサを扱うこと - テンプレートエンジンを扱うこと これを作るのに必要な要素 - Baalパーサを扱うこと - テンプレートエンジンを扱うこと 難しいと思っていたことが もうできるようになっていた

Slide 35

Slide 35 text

コード生成を自前で作ることにした ● 結果として、Baal API定義書からコード生成するジェネレータを自前で 書けるようになった。 ● API通信の土台がやっと完成した AI開発のスタート地点に

Slide 36

Slide 36 text

教訓 ● 初心者意識はいつまでも持つものじゃない ● Goは既存のコードをカスタマイズするのが難しい ● 既存のツールの恩恵にあやかろうとしすぎず、 自分に必要な物だけを自前で用意する方が良い時もある ● がっつり失敗したほうが身につく物もある

Slide 37

Slide 37 text

なぜこんなことをしたのか ● 今現在の仕事で得られる経験がなくなってしまった -> 異動の希望? -> 転職? -> それ以外にもやりようはあるのではないか ● 数年かけて仕事を覚え、効率化し、余白を作った 余白を使い、今のプロジェクトのまま新しい経験が得られる題材を自分で 設定した

Slide 38

Slide 38 text

No content