回答編集履歴

2

補強情報を追記した。

2016/07/07 22:14

投稿

eripong
eripong

スコア1546

test CHANGED
@@ -94,4 +94,102 @@
94
94
 
95
95
 
96
96
 
97
+
97
98
 
99
+
100
+
101
+ ---
102
+
103
+ (2016/07/06 7:10追記)
104
+
105
+ 上に記述した内容を補強する情報がありました。
106
+
107
+
108
+
109
+ # Servlet 3.1でのノンブロッキングI/O対応
110
+
111
+ Servlet 3.1において、startAsyncをベースにして、リクエストやレスポンスのI/OをノンブロッキングI/OにするAPIが追加されています。
112
+
113
+
114
+
115
+ 以下が解説記事です。
116
+
117
+ [Oracle Blogs 日本語のまとめ: [Java] Non-blocking I/O using Servlet 3.1: Scalable applications using Java EE 7 (TOTD #188)](https://orablogs-jp.blogspot.jp/2012/11/non-blocking-io-using-servlet-31.html)
118
+
119
+
120
+
121
+ 以下が仕様の追記部分の一部です。
122
+
123
+ [Java Servlet Specification Version 3.1](https://java.net/downloads/servlet-spec/Final/servlet-3_1-final.pdf)
124
+
125
+ 3.7 Non Blocking IO
126
+
127
+ > Non-blocking request processing in the Web Container helps improve the ever increasing demand for improved Web Container scalability, increase the number of connections that can simultaneously be handled by the Web Container. Non-blocking IO in the Servlet container allows developers to read data as it becomes available or write data when possible to do so. Non-blocking IO only works with async request processing in Servlets and Filters (as defined in Section 2.3.3.3, “Asynchronous processing” on page 2-10), and upgrade processing (as defined in Section 2.3.3.5, “Upgrade Processing” on page 2-20).
128
+
129
+
130
+
131
+ # ノンブロッキングな外部サーバ呼び出しを行う例
132
+
133
+ 以下のサイトで、ノンブロッキングな外部サーバ呼び出しを行うコード例がありました。こちらで動作確認はしてませんが、処理実装のイメージは、私のイメージ通りです。
134
+
135
+
136
+
137
+ [Async Servlets - Jayway](https://www.jayway.com/2014/05/16/async-servlets/)
138
+
139
+
140
+
141
+ ```lang-java
142
+
143
+ protected void doGet(final HttpServletRequest req, HttpServletResponse resp) {
144
+
145
+ // Initialize async processing.
146
+
147
+ final AsyncContext context = req.startAsync();
148
+
149
+
150
+
151
+ // This call does not block.
152
+
153
+ client.callExternalService(
154
+
155
+ // This callback is invoked after the external service responds.
156
+
157
+ new Callback<string>() {
158
+
159
+ public void callback(String result) {
160
+
161
+ ServletResponse response = context.getResponse();
162
+
163
+ response.setContentType("text/plain");
164
+
165
+ response.setCharacterEncoding("UTF-8");
166
+
167
+ byte[] entity = ("Result: " + result + ".n").getBytes(Charset.forName("UTF-8"));
168
+
169
+ response.setContentLength(entity.length);
170
+
171
+ try {
172
+
173
+ response.getOutputStream().write(entity);
174
+
175
+ } catch (IOException e) {
176
+
177
+ // Ignored.
178
+
179
+ }
180
+
181
+ context.complete();
182
+
183
+ }
184
+
185
+ });
186
+
187
+ }
188
+
189
+ ```
190
+
191
+
192
+
193
+
194
+
195
+

1

もともと想定していた

2016/07/07 22:14

投稿

eripong
eripong

スコア1546

test CHANGED
@@ -31,3 +31,67 @@
31
31
  > 時にはフィルタ及び/あるいはサーブレットが応答発生前にあるリソースあるいはイベントを待たない と、ある要求処理を終了できないことがある。例えば、あるサーブレットは応答を発生させる前に、 利用可能な JDBC 接続、リモートのウェブ・サービスからの応答、JMS メッセージ、あるいはアプリ ケーションのあるイベント、などを待つ必要がある。そのサーブレット内での待機は非効率な使い方 である。何故ならそれはスレッドと他の限られたリソースを消費するブロッキング動作であるからであ る。しばしばデータベースのような遅いリソースが多くのスレッドをアクセス待ちの状態でブロックさ せ、ウェブ・コンテナ全体のスレッドの枯渇とサービス品質劣化をもたらす。
32
32
 
33
33
  サーブレット第 3 版では要求の非同期処理を導入しており、そのスレッドをコンテナに返して他のタ スクを実行できるようにしている。
34
+
35
+
36
+
37
+ ---
38
+
39
+ (2016/07/07 15:30 追記)
40
+
41
+ 上に書いた回答は不十分だったと思います。
42
+
43
+ (というより、仕様に書いてある以上のことを、私が勝手に期待した感じです。。)
44
+
45
+
46
+
47
+ AsyncContext.startAsync、AsyncContext.startするのは、目的としては
48
+
49
+ 上記のサーブレット3.0仕様書の2.3.3.3 非同期処理のところにある通りのようですが、その効果は
50
+
51
+ 「HTTP処理用のスレッドをつかみっぱなしにしないこと」の様です。
52
+
53
+ その結果として考えられるメリットは以下かと思います。
54
+
55
+
56
+
57
+ # 直接的なメリット(効果小)
58
+
59
+ HTTP処理用のスレッド数は通常なんらかの設定により上限があるため、
60
+
61
+ この制限とは別の管理のスレッドに処理が渡せることは、ある程度のメリットがあると思います。
62
+
63
+ とはいえ、実際の総スレッド数としては減るわけでもなくリソースの削減効果もないので、
64
+
65
+ 大したメリットとは思えません。
66
+
67
+
68
+
69
+ # 間接的なメリット(効果大だが想定される使い方か不明)
70
+
71
+ こちらは、私の考える実装の可能性で、検証したわけでもどこかに書いてあったわけでもないですが、
72
+
73
+ 処理が分離されることにより、ノンブロッキングI/Oを用いた通信を行うことによる
74
+
75
+ スレッド数の削減ができる前提が一つ満たされると思います。
76
+
77
+
78
+
79
+ 例えば、指定した外部のWeb APIを呼び出して結果を取得する処理をノンブロッキングI/Oを用いて
80
+
81
+ 複数のリクエストを1スレッドで同時に処理し、
82
+
83
+ 結果が取れた場合のみにAsyncContext.startを呼び出して結果を返すようにできれば、
84
+
85
+ 外部のWeb APIを呼び出して結果を待つ間は、複数のリクエストがあっても1スレッドしか使いません。
86
+
87
+
88
+
89
+ 今までは、もしこうした処理を実装したとしても、HTTP処理用のスレッドで
90
+
91
+ 処理を返さなければいけなかったので、使えませんでしたが、
92
+
93
+ AsyncContext.startAsyncの仕組みを使うことで、実装する余地は有るようになったと思います。
94
+
95
+
96
+
97
+