Spring BootでアクティブなHTTPセッション数を取得する
Spring Bootのデフォルト組込サーバはTomcatなのですが、(pom.xml|build.gradle)に依存関係を設定する事でJettyも選択可能になっています。
(設定方法は マニュアル を参照してください)
Jettyもアプリケーションサーバとして十分な実績があり、早い時期からWebSocket対応やJava8対応がされているので、
TomcatではなくJettyを使いたい人も多いんじゃないでしょうか?
僕もその一人です :)
2014/09/07追記
ここに書いた内容は色々アレだったので、以下に改訂版のエントリーを改めて書きました。合わせてお読みください。
Spring BootでアクティブなHTTPセッション数を取得する (改訂版)
Spring Bootに限らず、Webアプリを運用時間中に本番環境にデプロイする場合、
ロードバランサからアプリケーションサーバを切り離しながら順番にデプロイしていくと思いますが、
Spring BootでJettyを選択した場合、デフォルトではアクティブなHTTPセッション数を確認する手段がないようです。
(Tomcatでは http://サーバ:ポート/manager/list/
で確認するおなじみのアレです)
Spring Bootは自分でメトリクスを追加出来るって事を@makingさんに教えていただきました。
ドキュメントのこの箇所 Recording your own metrics
@matsumana メトリクス追加できるでSessionListenerとからめてちょちょっと作れないですかね。
— Toshiaki Maki (@making) September 2, 2014
@matsumana http://t.co/e88wxJtHjI この辺です
— Toshiaki Maki (@making) September 2, 2014
以前、 @makingさんから Coda Hale Metrics (オフィシャルサイトは ここ) も教えて頂いてたのを思い出したので、
これで簡単に出来ないかなぁと調べていたら、 metrics-spring というのを見つけたので使ってみました。
まずは、pom.xmlに spring-boot-starter-actuator
と jolokia-core
と metrics-spring
を追加します。
Jolokia はJMXの値をHTTPで取得するためのライブラリです。(値はJSONで取れます)
HTTPではなく、JConsoleなどを使って確認するという方は、Jolokiaは不要です。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
</dependency>
<dependency>
<groupId>com.ryantenney.metrics</groupId>
<artifactId>metrics-spring</artifactId>
<version>3.0.1</version>
</dependency>
次に、MetricsConfigurerAdapter
を継承したクラスを作ります。
@Configuration
@EnableMetrics
public class MetricsConfig extends MetricsConfigurerAdapter {
@Override
public void configureReporters(MetricRegistry metricRegistry) {
JmxReporter
.forRegistry(metricRegistry)
.build()
.start();
}
}
JmxReporterを使うとメトリクスがJMXで取得出来るようになります。
次に、コントローラです。今回はこのように、単純な普通のSpringMVCのコントローラです。結果はTextで返すようにしています。
@RestController
@RequestMapping("/")
public class SampleController {
@RequestMapping(method = GET)
public String index() {
return "Hello World!";
}
}
次に、メトリクスの記録を行う部分です。
@ControllerAdvice("info.matsumana.controller")
public class ControllerAdvisor {
Logger logger = LoggerFactory.getLogger(getClass());
@Counted(name = "active-http-sessions", absolute = true)
@ModelAttribute("dummyModel")
public void dummyModel() {
logger.debug("dummyModel");
}
}
各リクエスト毎に自動で呼ばれるようにしたかったので、@ControllerAdviceを使ってみました。
@ModelAttributeを付けているメソッド(ControllerAdvisor#dummyModel)がまず呼ばれて、
次にコントローラの@RequestMappingを付けているメソッド(SampleController#index)が呼ばれます。
ControllerAdvisor#dummyModel()には、 @Counted(name = "active-http-sessions", absolute = true)
も付けているので、
アクティブなHTTPセッション数のカウンタが自動でインクリメント/デクリメントされます。
※@Counted
アノテーションは name
と absolute
の属性を必ず付けたほうが良いです。
付けない場合、JMXオブジェクト名がパッケージ名+クラス名になってしまいます。
こういう場合、@ControllerAdvice + @ModelAttributeではなく、@Aspect(AOP)でやるべきだと思いますが、
リクエスト毎に必ず1回だけ呼ばれるという処理が書きやすかったのでこういう書き方にしてしまいました。
@ControllerAdviceの使い方としては間違っていると思います。。。
もっと良いやり方があれば教えてください(>_<)
では次。
上の方で説明したように、アクティブセッション数をJMXに記録し、それをJolokiaを使ってHTTPで取得するのですが、
Spring Bootでは管理機能をアプリと別ポートにする事が出来るので設定しておいた方が良いでしょう。
Spring BootではYAMLで設定ファイルを記述する事が出来ます。
application.ymlというファイルを作っておけばOKです。
management:
port: 8081
デフォルトで準備されている設定項目一覧は、ドキュメントを見てください。
このサンプルアプリを起動して、以下のようなシェルスクリプトで負荷をかけながら、
ブラウザやcurlなどで localhost:8081/jolokia/read/metrics:name=active-http-sessions
にリクエストを投げると
アクティブなセッション数が確認できると思います。
#!/bin/bash
for ((i=0; i<1000; i++))
do
ab -n 200 -c 100 "http://localhost:8080/"
done
curlとjqを使うとこんな感じです。
$ curl -s "localhost:8081/jolokia/read/metrics:name=active-http-sessions" | jq .
{
"status": 200,
"timestamp": 1409886181,
"value": {
"Count": 56
},
"request": {
"type": "read",
"mbean": "metrics:name=active-http-sessions"
}
}
Countだけ取り出したい場合はこんな感じで。
$ curl -s "localhost:8081/jolokia/read/metrics:name=active-http-sessions" | jq .value.Count
56
JConsoleなどで見るとこんな感じで見えます。
今回のサンプルソースはここに置いてます。