From 8827feacfb04eb064ecec20fcc4cb736738fc9e9 Mon Sep 17 00:00:00 2001 From: md_5 Date: Wed, 20 Mar 2013 18:52:26 +1100 Subject: [PATCH] Implement high performance HTTP api for plugins with jetty. --- api/pom.xml | 6 ++++ .../java/net/md_5/bungee/api/ProxyServer.java | 15 +++++++++ .../net/md_5/bungee/api/http/HttpRequest.java | 9 ++++++ proxy/pom.xml | 6 ++++ .../main/java/net/md_5/bungee/BungeeCord.java | 31 ++++++++++++++++--- .../bungee/scheduler/BungeeScheduler.java | 9 ++---- 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 api/src/main/java/net/md_5/bungee/api/http/HttpRequest.java diff --git a/api/pom.xml b/api/pom.xml index 7cbb9671..2e2290d6 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -25,6 +25,12 @@ 14.0 compile + + org.eclipse.jetty + jetty-client + 9.0.0.v20130308 + compile + org.yaml snakeyaml diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java index 927e142b..464df38d 100644 --- a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java +++ b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java @@ -14,6 +14,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.Server; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.scheduler.TaskScheduler; +import org.eclipse.jetty.client.HttpClient; public abstract class ProxyServer { @@ -231,5 +232,19 @@ public abstract class ProxyServer */ public abstract File getPluginsFolder(); + /** + * Get the scheduler instance for this proxy. + * + * @return the in use scheduler + */ public abstract TaskScheduler getScheduler(); + + /** + * Gets the the web client used by this proxy to facilitate making web + * requests. Care should be taken to ensure that all operations are non + * blocking where applicable. + * + * @return + */ + public abstract HttpClient getHttpClient(); } diff --git a/api/src/main/java/net/md_5/bungee/api/http/HttpRequest.java b/api/src/main/java/net/md_5/bungee/api/http/HttpRequest.java new file mode 100644 index 00000000..9fd88c0f --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/http/HttpRequest.java @@ -0,0 +1,9 @@ +package net.md_5.bungee.api.http; + +import java.net.URI; + +public interface HttpRequest +{ + + URI getURI(); +} diff --git a/proxy/pom.xml b/proxy/pom.xml index 58e8b966..485570c5 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -23,31 +23,37 @@ io.netty netty-codec ${netty.version} + compile io.netty netty-handler ${netty.version} + compile net.md-5 bungeecord-protocol ${project.version} + compile net.md-5 bungeecord-api ${project.version} + compile net.sf.trove4j trove4j 3.0.3 + compile mysql mysql-connector-java 5.1.24 + compile diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index 58b8358e..682d1f0f 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -11,7 +11,6 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import net.md_5.bungee.config.Configuration; import java.io.BufferedReader; import java.io.File; -import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.util.Calendar; @@ -22,6 +21,10 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -45,6 +48,8 @@ import net.md_5.bungee.config.YamlConfig; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.thread.QueuedThreadPool; /** * Main BungeeCord proxy class. @@ -69,9 +74,10 @@ public class BungeeCord extends ProxyServer */ public final Configuration config = new Configuration(); /** - * Thread pool. + * Thread pools. */ - public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread - %1$d" ).build() ); + public final ScheduledExecutorService executors = new ScheduledThreadPoolExecutor( 8, new ThreadFactoryBuilder().setNameFormat( "Bungee Pool Thread #%1$d" ).build() ); + public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 8, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() ); /** * locations.yml save thread. */ @@ -106,6 +112,8 @@ public class BungeeCord extends ProxyServer private final File pluginsFolder = new File( "plugins" ); @Getter private final TaskScheduler scheduler = new BungeeScheduler(); + @Getter + private final HttpClient httpClient = new HttpClient(); { @@ -170,11 +178,14 @@ public class BungeeCord extends ProxyServer * Start this proxy instance by loading the configuration, plugins and * starting the connect thread. * - * @throws IOException + * @throws Exception */ @Override - public void start() throws IOException + public void start() throws Exception { + httpClient.setExecutor( executors ); + httpClient.start(); + httpClient.GET( "http://isup.me/" ); pluginsFolder.mkdir(); pluginManager.loadPlugins( pluginsFolder ); config.load(); @@ -238,6 +249,16 @@ public class BungeeCord extends ProxyServer { this.isRunning = false; + try + { + getLogger().info( "Stopping HTTP client" ); + httpClient.stop(); + } catch ( Exception ex ) + { + getLogger().severe( "Could not stop HTTP client" ); + } + executors.shutdown(); + stopListeners(); getLogger().info( "Closing pending connections" ); diff --git a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java index d05cb8c6..703b7731 100644 --- a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java +++ b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java @@ -1,15 +1,13 @@ package net.md_5.bungee.scheduler; import com.google.common.base.Preconditions; -import com.google.common.util.concurrent.ThreadFactoryBuilder; import gnu.trove.TCollections; import gnu.trove.iterator.TIntObjectIterator; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import net.md_5.bungee.BungeeCord; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.scheduler.ScheduledTask; import net.md_5.bungee.api.scheduler.TaskScheduler; @@ -19,7 +17,6 @@ public class BungeeScheduler implements TaskScheduler private final AtomicInteger taskCounter = new AtomicInteger(); private final TIntObjectMap tasks = TCollections.synchronizedMap( new TIntObjectHashMap() ); - private final ScheduledExecutorService executors = new ScheduledThreadPoolExecutor( 0, new ThreadFactoryBuilder().setNameFormat( "Bungee Scheduler Thread - %1$d" ).build() ); @Override public void cancel(int id) @@ -60,13 +57,13 @@ public class BungeeScheduler implements TaskScheduler @Override public ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit) { - return prepare( owner, task ).setFuture( executors.schedule( task, delay, unit ) ); + return prepare( owner, task ).setFuture( BungeeCord.getInstance().executors.schedule( task, delay, unit ) ); } @Override public ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit) { - return prepare( owner, task ).setFuture( executors.scheduleWithFixedDelay( task, delay, period, unit ) ); + return prepare( owner, task ).setFuture( BungeeCord.getInstance().executors.scheduleWithFixedDelay( task, delay, period, unit ) ); } private BungeeTask prepare(Plugin owner, Runnable task)