ラベル tomcat の投稿を表示しています。 すべての投稿を表示
ラベル tomcat の投稿を表示しています。 すべての投稿を表示

2018年3月21日水曜日

Tomcatでポストサイズの上限を設定する

HTTP ConnectorにmaxPostSizeを設定するとポストサイズの上限を設定できるようなので動きを確認してみた。

確認用Servlet

確認用のServletではpostされた内容を標準出力にだしています。
override fun doPost(req: HttpServletRequest, resp: HttpServletResponse) {
    println("Content-Length: ${req.contentLengthLong}")
    println("parameter count: ${req.parameterMap.size}")
    req.parameterMap.forEach {
        println("${it.key}: ${it.value.joinToString(", ")}")
    }
    doGet(req, resp)
}

デフォルト設定で実行

デフォルト設定だと上限が2MBとなるのでエラーなどは発生しないでうまく処理が行われる。
➜  ~ curl http://localhost:8080/sample/hello --data-urlencode "param_key=値" -X POST -i     
HTTP/1.1 200 

サーバの標準出力の内容
Content-Length: 19
parameter count: 1
param_key: 値

maxPoolSizeを指定して実行

conf/server.xmlのConnector部分にmaxPostSizeの設定を追加する。簡単に上限を超えるように設定値は1バイトに。
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           maxPostSize="1"
           redirectPort="8443" />

デフォルトの設定だと、クライアントには200が返ってくる。
➜  ~ curl http://localhost:8080/sample/hello --data-urlencode "param_key=値" -X POST -i 
HTTP/1.1 200 

サーバのログを見ると、パラメータが存在しない状態でServletが呼び出されている。
このような場合、リクエストスコープのorg.apache.catalina.parameter_parse_failed_reasonの値(org.apache.tomcat.util.http.Parameters.FailReason)を見ると何が起きたかがわかるらしい。
Content-Length: 19
parameter count: 0

FailedRequestFilterを適用して実行

web.xmlにFailedRequestFilterを追加する。
<filter>
  <filter-name>failedRequestFilter</filter-name>
  <filter-class>org.apache.catalina.filters.FailedRequestFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>failedRequestFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Filterで指定サイズを超えた場合は処理を中断し、413 Request Entity Too Largeが返されるようになる。
➜  ~ curl http://localhost:8080/sample/hello --data-urlencode "param_key=値" -X POST -i 
HTTP/1.1 413 


ちなみにこのフィルターはapplication/x-www-form-urlencoded以外には影響を与えないようです。例えば、application/jsonの場合には下のように正常に処理が終わります。
➜  ~ curl http://localhost:8080/sample/hello -H "Content-Type: application/json" -d "{}"  -i   
HTTP/1.1 200 

2017年7月15日土曜日

Tomcat EmbeddedでAccessLogValveを適用してアクセスログを出力する

Tomcat EmbeddedでTomcatのアクセスログを出力する方法

META-INF/context.xmlを作成してAccessLogValveを適用する

context.xmlを用いて、下のようにAccessLogValveを適用する
<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
      prefix="access" suffix=".log" pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Context>

Tomcat Embeddedを使ってTomcatを起動する

final Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);

final String docBase = new File("src/main/webapp").getAbsolutePath();
final StandardContext context = (StandardContext) tomcat.addWebapp("/", docBase);

final File additionWebInfClasses = new File("build/classes/main");
final StandardRoot resources = new StandardRoot(context);
resources.addPreResources(
        new DirResourceSet(resources, "/WEB-INF/classes",
                additionWebInfClasses.getAbsolutePath(), "/"));
context.setResources(resources);

tomcat.start();
tomcat.getServer().await();

結果

カレントディレクトリ配下のtomcat.8080/logs配下にアクセスログが出力されるようになる。

➜  tomcat-embedded-example cat tomcat.8080/logs/access.2017-07-15.log 
127.0.0.1 - - [15/Jul/2017:15:36:39 +0900] "GET / HTTP/1.1" 200 89
127.0.0.1 - - [15/Jul/2017:15:36:43 +0900] "GET /hoge HTTP/1.1" 404 1002

2017年6月16日金曜日

[Tomcat]StuckThreadDetectionValveを使って遅延した処理の情報をログに出力する

StuckThreadDetectionValveを使うことで、処理遅延が発生したスレッドを検知することができる。

使い方は下の通り

設定を追加する

conf/server.xmlにStuckThreadDetectionValveを使用するように設定をする。

thresholdを使って、どれぐらい遅延したら検知するかを設定する。
デフォルトは600秒となっている。下のように60と設定すると60秒となる。

  


ログの結果

単純に一定時間スリープするServletで試すと下のようなログが出力される。

16-Jun-2017 21:14:37.445 警告 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.valves.StuckThreadDetectionValve.notifyStuckThreadDetected Thread [http-nio-8080-exec-6] (id=[29]) has been active for [62,731] milliseconds (since [17/06/16 21:13]) to serve the same request for [http://localhost:8080/hoge] and may be stuck (configured threshold for this StuckThreadDetectionValve is [60] seconds). There is/are [1] thread(s) in total that are monitored by this Valve and may be stuck.
java.lang.Throwable
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at hoge.HogeServlet.doGet(HogeServlet.kt:11)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)

その後処理が完了すると、下のようなログも出力される

16-Jun-2017 21:15:37.465 警告 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.valves.StuckThreadDetectionValve.notifyStuckThreadCompleted Thread [http-nio-8080-exec-6] (id=[29]) was previously reported to be stuck but has completed. It was active for approximately [120,031] milliseconds.

これで、処理遅延などが発生した場合に自動的にスレッドダンプが取得できる。
障害時にスレッドダンプとってません問題も回避できそうな気もする。