Серия Netty: используйте netty для реализации сервера, поддерживающего http2.

Java HTTP Netty

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность

Эта статья приняла участие"Проект "Звезда раскопок"", чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.

«Добро пожаловать для обсуждения в области комментариев, официальный представитель NuggetsПроект «Звезда раскопок»После мероприятия в комментариях будет разыграно 100 штук Наггетсов.Подробнее о лотерее читайте в статье о мероприятии».

Введение

В прошлой статье мы упоминали, как настроить TLS в netty для поддержки HTTP2. На самом деле TLS не является обязательным требованием для https, это всего лишь предлагаемый стандарт. Итак, в дополнение к TLS, как вам нужно настроить netty для поддержки http2? Давайте посмотрим вместе.

Основной процесс

Netty поддерживает http2 в двух случаях. В первом случае используется TLS. В этом случае необходимо добавить ProtocolNegotiationHandler для согласования протокола после рукопожатия. После согласования необходимо решить, какой протокол использовать.

В предыдущей статье мы представили подробности поддержки TLS для http2, и я не буду повторять их здесь, заинтересованные друзья могут ознакомиться с моими предыдущими статьями.

Если вы не используете TLS, есть два случая: один — напрямую использовать http1.1, нам нужно добавить ChannelInboundHandler для http1.1.

Другой случай — использовать открытый текст для обновления с HTTP1.1 до HTTP2.

HTTP/2 ClearText также называется h2c Давайте рассмотрим простой запрос на обновление, начиная с запроса клиента:

GET /index HTTP/1.1
Host: server.flydean.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c 
HTTP2-Settings: (SETTINGS payload) 

Затем идет ответ со стороны сервера, если серверная сторона не поддерживает обновления, он возвращает:


HTTP/1.1 200 OK 
Content-length: 100
Content-type: text/html

(... HTTP/1.1 response ...)

Возвращает, если сервер поддерживает обновления:

HTTP/1.1 101 Switching Protocols 
Connection: Upgrade
Upgrade: h2c

(... HTTP/2 response ...)

CleartextHttp2ServerUpgradeHandler

С помощью описанного выше базового процесса нам нужно только предоставить соответствующий класс обработчика в netty, чтобы решить проблему поддержки http2 в netty.

Однако описанный выше процесс обновления выглядит сложным, поэтому netty предоставляет нам упакованный класс: CleartextHttp2ServerUpgradeHandler для реализации функции h2c.

Этот класс должен передать три параметра, а именно HttpServerCodec, HttpServerUpgradeHandler и ChannelHandler.

HttpServerCodec — это класс кодирования, который обрабатывает http-сервер, обычно мы используем HttpServerCodec.

HttpServerUpgradeHandler — это класс обработки для обновления с http1.1 до http2.

Netty также предоставляет готовый класс: HttpServerUpgradeHandler для обработки кода обновления.

HttpServerUpgradeHandler требует два параметра: один — sourceCodec, который является исходным классом кодирования HTTP HttpServerCodec, а другой — фабричным классом, используемым для возврата UpgradeCodec, который возвращает Http2ServerUpgradeCodec, поставляемый с netty.

    public HttpServerUpgradeHandler(SourceCodec sourceCodec, UpgradeCodecFactory upgradeCodecFactory) {
        this(sourceCodec, upgradeCodecFactory, 0);
    }

ChannelHandler — это обработчик, который фактически обрабатывает HTTP2, и мы можем настроить этот обработчик по мере необходимости.

С помощью UpgradeHandler просто добавьте его в ChannelPipeline.

Http2ConnectionHandler

Будь то HttpServerUpgradeHandler или CleartextHttp2ServerUpgradeHandler, вам нужно передать обработчик, который действительно может обрабатывать http2. Этот обработчик — Http2ConnectionHandler.

Http2ConnectionHandler — это класс реализации, который реализовал события для обработки различных входящих событий кадра, а затем делегирует эти события Http2FrameListener.

Поэтому Http2ConnectionHandler необходимо использовать вместе с Http2FrameListener.

Вот подробное объяснение Http2FrameListener, который в основном обрабатывает различные события кадра HTTP2.

Давайте сначала посмотрим на метод триггера события, предоставленный в http2FrameListener:

Как видно из приведенного выше рисунка, в основном это способ срабатывания событий различных фреймов, среди которых в http2 есть несколько фреймов:

  • DATA frame
  • HEADERS frame
  • PRIORITY frame
  • RST_STREAM frame
  • SETTINGS acknowledgment frame
  • SETTINGS frame
  • PING frame
  • PING acknowledgment
  • PUSH_PROMISE frame
  • GO_AWAY frame
  • WINDOW_UPDATE frame
  • Unknown Frame

Эти типы фреймов в основном перечисляют все типы фреймов http2.

Все, что нам нужно сделать, это настроить класс обработчика, унаследовать Http2ConnectionHandler, а затем реализовать интерфейс Http2FrameListener.

    public final class CustHttp2Handler extends Http2ConnectionHandler implements Http2FrameListener

В процессе использования открытого текста для обновления с HTTP1.1 до HTTP2 нам нужно иметь дело с двумя вещами: во-первых, обрабатывать http1.1 и использовать заголовок http для обновления до http2.Вы можете переписать метод userEventTriggered, унаследованный от Http2ConnectionHandler.Определив, является ли тип события UpgradeEvent, чтобы вызвать метод в соответствующем интерфейсе Http2FrameListener, например, onHeadersRead здесь:


    /**
     * 处理HTTP upgrade事件
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof HttpServerUpgradeHandler.UpgradeEvent) {
            HttpServerUpgradeHandler.UpgradeEvent upgradeEvent =
                    (HttpServerUpgradeHandler.UpgradeEvent) evt;
            onHeadersRead(ctx, 1, upgradeToHttp2Headers(upgradeEvent.upgradeRequest()), 0 , true);
        }
        super.userEventTriggered(ctx, evt);
    }

Метод upgradeToHttp2Headers преобразует входящий FullHttpRequest в Http2Headers:

    private static Http2Headers upgradeToHttp2Headers(FullHttpRequest request) {
        CharSequence host = request.headers().get(HttpHeaderNames.HOST);
        Http2Headers http2Headers = new DefaultHttp2Headers()
                .method(HttpMethod.GET.asciiName())
                .path(request.uri())
                .scheme(HttpScheme.HTTP.name());
        if (host != null) {
            http2Headers.authority(host);
        }
        return http2Headers;
    }

Существует еще один метод, который необходимо реализовать, метод sendResponse, который записывает данные обратно клиенту. Обратная запись должна включать заголовки и данные, как показано ниже:

    /**
     * 发送响应数据到客户端
     */
    private void sendResponse(ChannelHandlerContext ctx, int streamId, ByteBuf payload) {
        Http2Headers headers = new DefaultHttp2Headers().status(OK.codeAsText());
        encoder().writeHeaders(ctx, streamId, headers, 0, false, ctx.newPromise());
        encoder().writeData(ctx, streamId, payload, 0, true, ctx.newPromise());
    }

Суммировать

На данный момент обработчик, который обрабатывает обновление открытого текста с HTTP1.1 до HTTP2, готов. В сочетании с поддержкой расширенного протокола TLS, описанного ранее, формируется полноценный сетевой сервер, поддерживающий http2.

Примеры этой статьи могут относиться к:learn-netty4

Эта статья была включена вWoohoo.Floyd Press.com/27-Netty-Contract…

Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!