Implement high performance HTTP api for plugins with jetty.

This commit is contained in:
md_5 2013-03-20 18:52:26 +11:00
parent 692610cd7e
commit 8827feacfb
6 changed files with 65 additions and 11 deletions

View File

@ -25,6 +25,12 @@
<version>14.0</version> <version>14.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>9.0.0.v20130308</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>

View File

@ -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.connection.Server;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.scheduler.TaskScheduler; import net.md_5.bungee.api.scheduler.TaskScheduler;
import org.eclipse.jetty.client.HttpClient;
public abstract class ProxyServer public abstract class ProxyServer
{ {
@ -231,5 +232,19 @@ public abstract class ProxyServer
*/ */
public abstract File getPluginsFolder(); public abstract File getPluginsFolder();
/**
* Get the scheduler instance for this proxy.
*
* @return the in use scheduler
*/
public abstract TaskScheduler getScheduler(); 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();
} }

View File

@ -0,0 +1,9 @@
package net.md_5.bungee.api.http;
import java.net.URI;
public interface HttpRequest
{
URI getURI();
}

View File

@ -23,31 +23,37 @@
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId> <artifactId>netty-codec</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.netty</groupId> <groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId> <artifactId>netty-handler</artifactId>
<version>${netty.version}</version> <version>${netty.version}</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.sf.trove4j</groupId> <groupId>net.sf.trove4j</groupId>
<artifactId>trove4j</artifactId> <artifactId>trove4j</artifactId>
<version>3.0.3</version> <version>3.0.3</version>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<version>5.1.24</version> <version>5.1.24</version>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -11,7 +11,6 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.Configuration;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Calendar; import java.util.Calendar;
@ -22,6 +21,10 @@ import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap; 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.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; 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.netty.PipelineUtils;
import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.DefinedPacket;
import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFAPluginMessage;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/** /**
* Main BungeeCord proxy class. * Main BungeeCord proxy class.
@ -69,9 +74,10 @@ public class BungeeCord extends ProxyServer
*/ */
public final Configuration config = new Configuration(); 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. * locations.yml save thread.
*/ */
@ -106,6 +112,8 @@ public class BungeeCord extends ProxyServer
private final File pluginsFolder = new File( "plugins" ); private final File pluginsFolder = new File( "plugins" );
@Getter @Getter
private final TaskScheduler scheduler = new BungeeScheduler(); 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 * Start this proxy instance by loading the configuration, plugins and
* starting the connect thread. * starting the connect thread.
* *
* @throws IOException * @throws Exception
*/ */
@Override @Override
public void start() throws IOException public void start() throws Exception
{ {
httpClient.setExecutor( executors );
httpClient.start();
httpClient.GET( "http://isup.me/" );
pluginsFolder.mkdir(); pluginsFolder.mkdir();
pluginManager.loadPlugins( pluginsFolder ); pluginManager.loadPlugins( pluginsFolder );
config.load(); config.load();
@ -238,6 +249,16 @@ public class BungeeCord extends ProxyServer
{ {
this.isRunning = false; this.isRunning = false;
try
{
getLogger().info( "Stopping HTTP client" );
httpClient.stop();
} catch ( Exception ex )
{
getLogger().severe( "Could not stop HTTP client" );
}
executors.shutdown();
stopListeners(); stopListeners();
getLogger().info( "Closing pending connections" ); getLogger().info( "Closing pending connections" );

View File

@ -1,15 +1,13 @@
package net.md_5.bungee.scheduler; package net.md_5.bungee.scheduler;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import gnu.trove.TCollections; import gnu.trove.TCollections;
import gnu.trove.iterator.TIntObjectIterator; import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap; 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.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; 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.plugin.Plugin;
import net.md_5.bungee.api.scheduler.ScheduledTask; import net.md_5.bungee.api.scheduler.ScheduledTask;
import net.md_5.bungee.api.scheduler.TaskScheduler; 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 AtomicInteger taskCounter = new AtomicInteger();
private final TIntObjectMap<BungeeTask> tasks = TCollections.synchronizedMap( new TIntObjectHashMap<BungeeTask>() ); private final TIntObjectMap<BungeeTask> tasks = TCollections.synchronizedMap( new TIntObjectHashMap<BungeeTask>() );
private final ScheduledExecutorService executors = new ScheduledThreadPoolExecutor( 0, new ThreadFactoryBuilder().setNameFormat( "Bungee Scheduler Thread - %1$d" ).build() );
@Override @Override
public void cancel(int id) public void cancel(int id)
@ -60,13 +57,13 @@ public class BungeeScheduler implements TaskScheduler
@Override @Override
public ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit) 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 @Override
public ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit) 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) private BungeeTask prepare(Plugin owner, Runnable task)