Как подключиться к сокету домена UNIX с HTTP-сервером через Netty? - PullRequest
1 голос
/ 18 октября 2019

Я пытаюсь подключиться к сокету домена Docker UNIX, используя Netty. Вот моя попытка.

@PostConstruct
public void init() throws Exception {
    io.netty.bootstrap.Bootstrap bootstrap = new io.netty.bootstrap.Bootstrap();
    bootstrap
            .group(new NioEventLoopGroup())
            .channel(NioSocketChannel.class)
            .option(ChannelOption.SO_KEEPALIVE, true)
            .remoteAddress(new DomainSocketAddress("/var/run/docker.sock"))
    .handler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            socketChannel
                    .pipeline()
                    .addLast(new SimpleChannelInboundHandler<HttpObject>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
                            System.out.println(httpObject);
                        }
                    });
        }
    });
    final Channel channel = bootstrap.connect().sync().channel();

    final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/services", Unpooled.EMPTY_BUFFER);
    request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
    channel.writeAndFlush(request);
    channel.closeFuture().sync();
    System.out.println("DONE");
}

В настоящий момент я получаю

. Причина: java.nio.channels.UnsupportedAddressTypeException: null

Есть ли пример, как сделать HTTP-соединения с UDS, используя Netty? До сих пор я нашел только сырые UDS и TCP HTTP, но не объединенные.

1 Ответ

1 голос
/ 19 октября 2019

Вот рабочая реализация.

        io.netty.bootstrap.Bootstrap bootstrap = new io.netty.bootstrap.Bootstrap();
        final EpollEventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup();
        try {
            bootstrap
                    .group(epollEventLoopGroup)
                    .channel(EpollDomainSocketChannel.class)
                    .handler(new ChannelInitializer<UnixChannel>() {
                        @Override
                        public void initChannel(UnixChannel ch) throws Exception {
                            ch
                                    .pipeline()
                                    .addLast(new HttpClientCodec())
                                    .addLast(new HttpContentDecompressor())
                                    .addLast(new SimpleChannelInboundHandler<HttpObject>() {
                                        private StringBuilder messageBuilder = new StringBuilder();
                                        @Override
                                        public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
                                            if (msg instanceof HttpContent) {
                                                HttpContent content = (HttpContent) msg;
                                                messageBuilder.append(content.content().toString(StandardCharsets.UTF_8));
                                                if (msg instanceof LastHttpContent) {
                                                    System.out.println(messageBuilder);
                                                }
                                            } else {
                                                System.out.println(msg.getClass());
                                            }
                                        }
                                    });
                        }
                    });
            final Channel channel = bootstrap.connect(new DomainSocketAddress("/var/run/docker.sock")).sync().channel();

            final FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/services", Unpooled.EMPTY_BUFFER);
            request.headers().set(HttpHeaderNames.HOST, "daemon");
            channel.writeAndFlush(request);
            channel.closeFuture().sync();
        } finally {
            epollEventLoopGroup.shutdownGracefully();
        }

Несколько замечаний:

  • Используйте EpollEventLoopGroup и EpollDomainSocketChannel с ChannelInitializer<UnixChannel>.
  • HTTP требует new HttpCodec() в конвейере для использования объектов Netty HTTP.
  • Данные могут быть разделены на части, поэтому вам нужно собрать их и дождаться LastHttpContent объекта

https://github.com/trajano/netty-docker-daemon-socket

...