|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 7
The onResponse() and onRequest() methods in Listing 10 will be performed immediately after the message header is received. (The xSocket-http module also supports an InvokeOn annotation to specify if the callback method should be performed after receiving the message header or after receiving the
complete message).
To reduce the required buffer sizes and to minimize call latency, the message body should be streamed. In Listing 10 this
will be done implicitly by the xSocket-http module. The environment detects that an incomplete received message should be forwarded and registers a non-blocking forward
handler on the incoming message-body channel.
Lower buffer sizes are required within the proxy because only parts of the message have to be buffered internally when it is transferred. Furthermore, the latency incurred by forwarding the message could be reduced significantly. If the message is forwarded in a non-streaming manner, first the whole message will be received and buffered before being forwarded. This adds the elapsed time between receiving the first and last message byte to the complete call latency.
Streaming is also supported by the current Servlet API, but only in a blocking way. When running the UploadServlet in Listing 11 in Tomcat (version 6.0.14, default configuration on Windows), the doPost() method will be called immediately after the request header is received. This allows you to stream the incoming message body.
The UploadServlet reads some message-header entries and streams the message body into a file. If not enough data is available, the HttpServletRequest's input stream read() method will block. This means the request-handling thread will be suspended until more data is received.
class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req.getRequestURI();
if (requestURI.startsWith("/upload")) {
String filename = requestURI.substring("/upload".length() + 1, requestURI.length());
File file = new File("files" + File.separator + filename);
file.createNewFile();
FileOutputStream os = new FileOutputStream(file);
InputStream is = req.getInputStream();
byte[] transferBytes = new byte[8196];
int len;
while ((len = is.read(transferBytes)) > 0) {
os.write(transferBytes, 0, len);
}
os.close();
is.close();
} else {
resp.sendError(404);
}
}
}
Outstanding threads can be avoided by using non-blocking streams. Listing 12 shows an UploadRequestHandler, which reads and transfers the incoming message body in a non-blocking way. Similar to the client-side non-blocking streaming
example in Listing 6, a non-blocking body channel will be retrieved and a body-data handler will be set. After this operation
the onRequest() method returns immediately, without sending a response message. If body data is received, the body-data handler will be called
to transfer the available body data into a file. If the complete body is received, the response message will be sent.
class UploadRequestHandler implements IHttpRequestHandler {
public void onRequest(HttpRequest req, final IHttpResponseContext respCtx) throws IOException {
String requestURI = req.getRequestURI();
if (requestURI.startsWith("/upload")) {
String filename = requestURI.substring("/upload".length() + 1, requestURI.length());
final File file = new File("files" + File.separator + filename);
file.createNewFile();
final FileChannel fc = new RandomAccessFile(file, "rw").getChannel();
IBodyDataHandler bodyToFileStreamer = new IBodyDataHandler() {
public boolean onData(NonBlockingBodyDataSource bodyDataSource) {
try {
int available = bodyDataSource.available();
if (available > 0) {
bodyDataSource.transferTo(fc, available);
} else if (available == -1) {
fc.close();
respCtx.send(200);
}
} catch (IOException ioe) {
file.delete();
respCtx.sendError(500);
}
return true;
}
//...
};
// set handler to stream the body into a file in a non-blocking manner
req.getNonBlockingBody().setDataHandler(bodyToFileStreamer);
} else {
respCtx.sendError(404);
}
}
}
IServer server = new HttpServer(80, new UploadRequestHandler());
server.run();
xSocket.
Archived Discussions (Read only)