KotlinとSpring Bootとか諸々を使ってMicroservicesを作ってみた

最近バックグラウンドで稼働する決済系のMicroservicesをKotlinで作ってめでたく運用開始したので、どんな感じでやったかを雑に共有。

Kotlin選択の理由

自分はScalaが好きなんですけど、周りに書ける人いないし、そんなに時間もないし、で素のJavaもダルいしってなって現実的な解となったのがKotlinだったに過ぎません。

Javaをバックグラウンドに持つ人が多い今のプロジェクトではなかなかよかった気がしてます。コンパイル速度もほどんど気にならなかったし満足(規模が大きくなったらどうなるだろうかというのはあるが)。

spring-boot-starter-web

手堅くSpring Bootを利用。もちろんKotlinでも利用できます。

これはヘルスチェック用のControllerですが、Kotlinではこんな風にかけます。個人的にはレスポンス用のdata classをController内部にサクッと書いて返せるのがいいですね。

@RestController
@EnableAutoConfiguration
open class HealthCheckController {

    data class HealthCheck(val result: Boolean)

    @RequestMapping(value = "/health_check", method = arrayOf(RequestMethod.GET))
    fun index(): HealthCheck {

        return HealthCheck(true)
    }
}

spring-boot-actuator

spring-boot-actuatorは簡単に言うとアプリケーションのメトリクスを返すための仕組みで、これを使うと**/metrics**のエンドポイントを追加できます。

あとspringbootのsensuプラグインもあるので、こいつをかましてMackrelでメトリクスを見れるようにしています。

springfox-swagger2

Springfoxを使えば、SpringMVCのAnnotationからSwaggerのページを出力してくれるので、SwaggerからAPIを実行できたりしてかなり便利。

ちなみに先程のヘルスチェックであればこんな感じにできる。

@RestController
@EnableAutoConfiguration
@Api(description = "ヘルスチェック用")
open class HealthCheckController {

    @ApiModel
    data class HealthCheck(
        @ApiModelProperty(required = true, value = "結果", example = "true") val result: Boolean
    )

    @ApiOperation(value = "ヘルスチェック用")
    @RequestMapping(value = "/health_check", method = arrayOf(RequestMethod.GET))
    fun index(): HealthCheck {

        return HealthCheck(true)
    }
}

この辺のアノテーションを駆使すれば良い感じになります。

moshi

Java界隈ではJacksonが有名でしたけどもうオワコンっぽかったので今回をmoshiを使ってみました。 

結構シンプルで良かった。Genericsの型を渡すために型定義オブジェクト作って渡すのはJavaなので相変わらずですけど。

※追記

先入観でオワコンっぽかったって書いてしまいましたが、JacksonにはKotlinのAdaptorがあるのをご指摘頂きました

全然オワコンじゃなかった、ごめんよJackson。

Doma

個人的には現時点で最強のORMじゃないかと思ってるDoma。

S2DaoやS2JDBCを使ったことがあればわかると思いますが、Daoのインタフェースを定義してそのメソッドに対応するSQLファイルを用意するというやつです。このSQLファイルはそのままクエリとして利用でき、コメントで変数をバインドすることができることから2Way-SQLと呼ばれているやつですね。

素のSQL書けるのが何が嬉しいかって言うと、今回集計系のクエリが多かったのでペロッとSQL書いてそれをメソッドに紐付ければいいだけなのでかなり生産性高かった。最近はJavaではJOOQとかもあるんですけど、個人的には流れるようにSQLチックに書けるインタフェースの使い方を習得するより、素のSQL書いてテスト書く方がお釣りが来ると思ってるので今のDomaは最高にマッチしてる。

logstash-logback-encoder

これはこの間のエントリで書いたやつと被りますが、ログをlogstash形式で出力するやつです。

Logbackでlogstash形式のログを出力し、fluentdでElasticsearchに転送する - tehepero note(・ω<)

とりあえず現状のログをJSONでlogstash化してElasticsearchに送りたいってケースでもすぐ使える。springbootにはlogback入ってるので特に新しく何かを習得する必要はないです。

aws-sdk-java

重めの処理はいったんSQSに投げて、別途メッセージを処理するWorkerに処理させています。Workerは基本的にSQSをロングポーリングして、ジョブをディスパッチする実装。

elastiquartz

SQSを運用すると悩みとして上がってくるのがスケジューリングした上でのジョブの実行があります。そこで、cron的にSQSにジョブメッセージを投げるものを作って運用しています(こいつは自作)

ちなみに1月から運用しててまったく問題ないので一応SLA100%。Dockerイメージも用意しているのですぐ使えます。こんな感じのYAMLファイルを用意してS3に置けばOKです。

sqs001:
  -
    cron: 0 0-5 14 * * ?
    # message to sqs
    message:
      job: job1
      params:
        param1: value1
        param2: value2
  -
    cron: 0 0/5 * * * ?
    # message to SQS
    message:
      job: job2
      params:
        param1: value1
        param2: value2

これはサンプルですが、メッセージの中身はもちろんどんなスキーマでも良いです。

感想

  • 当初考えていたよりも生産性は優れていた
  • Springfoxが良い。GoでGoa使ってた時期あったけど、DSL書くのがキツかったのでアノテーションで完結できるのよい
  • サーバサイドKotlin全然アリ