/*
* Copyright (C) 2015 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.http;
import io.datakernel.async.IgnoreCompletionCallback;
import io.datakernel.async.ResultCallback;
import io.datakernel.bytebuf.ByteBufPool;
import io.datakernel.bytebuf.ByteBufStrings;
import io.datakernel.eventloop.Eventloop;
import io.datakernel.eventloop.ThrottlingController;
import io.datakernel.jmx.DynamicMBeanFactory;
import io.datakernel.jmx.JmxMBeans;
import io.datakernel.jmx.MBeanSettings;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
import java.util.Random;
import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError;
import static io.datakernel.util.Preconditions.checkArgument;
import static java.util.Arrays.asList;
public class HttpThrottlingServer {
private static final Random rand = new Random();
private static final int defaultLoadBusinessLogic = 0; // without load on the business logic
private static final String TEST_RESPONSE = "Hello, World!";
public static final int SERVER_PORT = 45566;
static class ServerOptions {
private int loadBusinessLogic;
public ServerOptions(int loadBusinessLogic) {
checkArgument(loadBusinessLogic >= 0);
this.loadBusinessLogic = loadBusinessLogic;
}
public int getLoadBusinessLogic() {
return loadBusinessLogic;
}
public static ServerOptions parseCommandLine(String[] args) {
int loadBusinessLogic = defaultLoadBusinessLogic;
for (int i = defaultLoadBusinessLogic; i < args.length; i++) {
switch (args[i]) {
case "-l":
loadBusinessLogic = Integer.parseInt(args[++i]);
break;
case "-?":
case "-h":
usage();
return null;
}
}
return new ServerOptions(loadBusinessLogic);
}
public static void usage() {
System.err.println(HttpThrottlingServer.class.getSimpleName() + " [options]\n" +
"\t-l - value of load server\n" +
"\t-h/-? - this help.");
}
@Override
public String toString() {
return "Load business logic : " + getLoadBusinessLogic();
}
}
private final AsyncHttpServer server;
public HttpThrottlingServer(Eventloop eventloop, ServerOptions options) {
this.server = buildHttpServer(eventloop, options.getLoadBusinessLogic());
}
private static AsyncHttpServer buildHttpServer(Eventloop eventloop, final int loadBusinessLogic) {
// final ByteBufPool byteBufferPool = new ByteBufPool(16, 65536);
AsyncServlet servlet = new AsyncServlet() {
@Override
public void serve(HttpRequest request, ResultCallback<HttpResponse> callback) {
callback.setResult(longBusinessLogic(TEST_RESPONSE, loadBusinessLogic));
}
};
return AsyncHttpServer.create(eventloop, servlet).withListenPort(SERVER_PORT);
}
protected static HttpResponse longBusinessLogic(String response, int loadBusinessLogic) {
long result = 0;
for (int i = 0; i < loadBusinessLogic; ++i) {
for (int j = 0; j < 200; ++j) {
int index = Math.abs(rand.nextInt()) % response.length();
result += response.charAt(index) * rand.nextLong();
}
}
if (result % 3 != 0) {
response += "!";
}
return HttpResponse.ok200().withBody(ByteBufStrings.encodeAscii(response));
}
public void start() throws Exception {
server.listen();
}
public void stop() {
server.close(IgnoreCompletionCallback.create());
}
public static void info(ServerOptions options) {
System.out.println("<" + HttpThrottlingServer.class.getSimpleName() + ">\n" + options.toString());
}
public static void main(String[] args) throws Exception {
ServerOptions options = ServerOptions.parseCommandLine(args);
if (options == null)
return;
info(options);
ThrottlingController throttlingController = ThrottlingController.create();
final Eventloop eventloop = Eventloop.create().withThrottlingController(throttlingController).withFatalErrorHandler(rethrowOnAnyError());
final HttpThrottlingServer server = new HttpThrottlingServer(eventloop, options);
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
DynamicMBeanFactory mBeanFactory = JmxMBeans.factory();
mbeanServer.registerMBean(mBeanFactory.createFor(asList(eventloop), MBeanSettings.defaultSettings(), true),
new ObjectName(Eventloop.class.getPackage().getName() + ":type=Eventloop"));
mbeanServer.registerMBean(ByteBufPool.getStats(),
new ObjectName(ByteBufPool.class.getPackage().getName() + ":type=ByteBufPool"));
mbeanServer.registerMBean(mBeanFactory.createFor(asList(throttlingController), MBeanSettings.defaultSettings(), true),
new ObjectName(ThrottlingController.class.getPackage().getName() + ":type=ThrottlingController"));
server.start();
eventloop.run();
}
}