Skip to content

Latest commit

 

History

History
84 lines (74 loc) · 3.65 KB

3.1-使用Undertow.md

File metadata and controls

84 lines (74 loc) · 3.65 KB

使用undertow

有2种主要的方式使用undertow,一种是直接在你的代码中嵌入undertow,另外一种是使用Wildfly应用服务器,我们主要关注于嵌入式的方式。

获取undertow

使用maven获取undertow,如下所示:

<dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-core</artifactId>
        <version>${undertow.version}</version>
</dependency>
<dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-servlet</artifactId>
        <version>${undertow.version}</version>
</dependency>
<dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-websockets-jsr</artifactId>
        <version>${undertow.version}</version>
</dependency>

undertow提供3个独立的应用包,分别是:

  • core,undertow的核心包,提供非阻塞IO机制和web socket,这个包可以单独使用
  • servlet,servlet4.0支持,依赖core包
  • Websockets JSR,websocket的Java API包

启动Undertow

官方提供2种方式启动undertow,分别是:

  1. 使用undertow builder API
public class HelloWorldServer {
    public static void main(final String[] args) {
        Undertow server = Undertow.builder()
                .addHttpListener(8080, "localhost")
                .setHandler(new HttpHandler() {
                    @Override
                    public void handleRequest(final HttpServerExchange exchange) throws Exception {
                        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
                        exchange.getResponseSender().send("Hello World");
                    }
                }).build();
        server.start();
    }
}

上面示例启动一个服务器处理所有HTTP请求并返回"Hello World"字符串,这种方式的优点是简单,是最通用的一种方式。

  1. 手动装载服务 手动装载服务需要用到XNIO的API,undertow就是基于XNIO实现的高性能服务器,下面示例代码实现HTTP监听器:
Xnio xnio = Xnio.getInstance();
XnioWorker worker = xnio.createWorker(OptionMap.builder()
        .set(Options.WORKER_IO_THREADS, ioThreads)
        .set(Options.WORKER_TASK_CORE_THREADS, workerThreads)
        .set(Options.WORKER_TASK_MAX_THREADS, workerThreads)
        .set(Options.TCP_NODELAY, true)
        .getMap());

OptionMap socketOptions = OptionMap.builder()
        .set(Options.WORKER_IO_THREADS, ioThreads)
        .set(Options.TCP_NODELAY, true)
        .set(Options.REUSE_ADDRESSES, true)
        .getMap();

Pool<ByteBuffer> buffers = new ByteBufferSlicePool(BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR,bufferSize, bufferSize * buffersPerRegion);

HttpOpenListener openListener = new HttpOpenListener(buffers, OptionMap.builder().set(UndertowOptions.BUFFER_PIPELINED_DATA, true).addAll(serverOptions).getMap(), bufferSize);
openListener.setRootHandler(rootHandler);
ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions);
server.resumeAccepts();

这种方式需要更多的代码,也有一定的复杂度,但更具灵活度:

  • 所有步骤完全控制
  • 对不同listerns使用不同buffer pools和workers
  • 不同server实例可以使用同一个XnioWorker实例
  • 不同server实例可以使用同一个buffer pools
  • Listerns可以使用不同root handlers

对于大部分场景,这种级别的控制其实是不必要的,所以更好的方式是使用Buidler API。