반응형

Camel에서 HTTP/2 클라이언트를 지원하는 라이브러리를 찾고 있었다.

 

camel-netty

- 프로젝트가 camel-netty 기반이라 가장 먼저 도전

- camel-netty에서는 자체적으로 http2를 지원하지 않음

- netty 예제에서 제공하는 http2 핸들러를 이용하여 이것저것 해보았으나, 실패

 

camel-jetty

 

camel-http

- httpclient 5.x 버전부터 지원하는 HTTP2를 사용하여 가능할 듯 함.

- 다만, 현재 프로젝트의 camel 3.x 버전이며, httpclient 5.x 버전은 camel 4.x 버전부터 지원

- camel 4.x 버전으로 상향하고 싶으나, 사용하고 있는 다른 camel 컴포넌트들이 4.x 부터 deprecated 되어 포기

 

camel-undertow

- camel-undertow에서 제공하는 UndertowHostOptions.http2Enabled이 존재. 다만 이건 서버 방식의 HTTP2만 지원

- 클라이언트 엔드포인트 url에 http2Enabled=true를 주어 테스트 해보려고 하였으나, 테스트 서버 인증서라, trust All을 해줘야 하지만, undertow에서는 따로 제공하는 옵션이 없음.

- 프로젝트 내의 인증서 모듈이 이미 존재하므로 해당 부분을 고쳐서 테스트하기가 어려워서 포기

 

camel-vertx-http

- netty 기반의 고수준 API vertx 

- camel-vertx-http에서는 자체적으로 http2를 지원하지는 않음

- vertx 옵션을 추가해서 해야하는데, 아주 쉽게 설정 가능

        WebClientOptions options = new WebClientOptions().setMaxRedirects(5)
            .setProtocolVersion(HttpVersion.HTTP_2)
            .setSsl(true)
            .setTrustAll(true)
            .setUseAlpn(true)
            .setVerifyHost(false);

        DataManager.getCamelContext().getRegistry().bind("options", options);

 

 

반응형

'Java > Camel' 카테고리의 다른 글

[Camel][Netty] NettyHttpComponent.bootstrapFactories  (0) 2024.07.01
반응형

Camel에서 제공하는 Netty Http 컴포넌트 클래스는 org.apache.camel.component.netty.http.NettyHttpComponent이다.

 

해당 컴포넌트를 이용하여 서버 모드를 기동할 때 org.apache.camel.component.netty.http.NettyHttpEndpoint createConsumer()가 호출된다.

    @Override
    public Consumer createConsumer(Processor processor) throws Exception {
        NettyHttpConsumer answer = new NettyHttpConsumer(this, processor, getConfiguration());
        configureConsumer(answer);

        if (nettySharedHttpServer != null) {
            answer.setNettyServerBootstrapFactory(nettySharedHttpServer.getServerBootstrapFactory());
            LOG.info("NettyHttpConsumer: {} is using NettySharedHttpServer on port: {}", answer,
                    nettySharedHttpServer.getPort());
        } else {
            // reuse pipeline factory for the same address
            HttpServerBootstrapFactory factory = getComponent().getOrCreateHttpNettyServerBootstrapFactory(answer);
            // force using our server bootstrap factory
            answer.setNettyServerBootstrapFactory(factory);
            LOG.debug("Created NettyHttpConsumer: {} using HttpServerBootstrapFactory: {}", answer, factory);
        }
        return answer;
    }

 

 

getComponent().getOrCreateHttpNettyServerBootstrapFactory(answer)를 호출하게 되는데, getComponent()가 NettyHttpComponent 이고 해당 코드는 아래와 같다.

    protected synchronized HttpServerBootstrapFactory getOrCreateHttpNettyServerBootstrapFactory(NettyHttpConsumer consumer) {
        String key = consumer.getConfiguration().getAddress();
        HttpServerBootstrapFactory answer = bootstrapFactories.get(key);
        if (answer == null) {
            HttpServerConsumerChannelFactory channelFactory = getMultiplexChannelHandler(consumer.getConfiguration().getPort());
            answer = new HttpServerBootstrapFactory(channelFactory);
            answer.init(getCamelContext(), consumer.getConfiguration(), new HttpServerInitializerFactory(consumer));
            bootstrapFactories.put(key, answer);
        }
        return answer;
    }

 

Address를 key로하여 Map 타입의 bootstrapFactories에 존재여부를 판단하여, 존재하지 않을 경우, 새로운 HttpServerBootstrapFactory 객체를 생성하고, 있을 경우, 그 설정을 그대로 사용.

 

따라서 초기에 설정하는 HttpServerBootstrapFactory의 NettyServerBootstrapConfiguration이 항상 로드된 채로 사용하게 됨. 

 

만약 로드된 상태에서, 새롭게 엔드포인트를 활성화할 경우, 기존 캐시에 저장되어 있던 HttpServerBootstrapFactory의 NettyServerBootstrapConfiguration과  새롭게 엔드포인트를 전달한 설정값을 확인하여, 다른 경우 에러 발생함. 코드는 아래와 같음

 

HttpServerBootstrapFactory.addConsumer

    @Override
    public void addConsumer(NettyConsumer consumer) {
        if (compatibleCheck) {
            // when adding additional consumers on the same port (eg to reuse port for multiple routes etc) then the Netty server bootstrap
            // configuration must match, as its the 1st consumer that calls the init method, which configuration is used for the Netty server bootstrap
            // we do this to avoid mis configuration, so people configure SSL and plain configuration on the same port etc.

            // first it may be the same instance, so only check for compatibility of different instance
            if (bootstrapConfiguration != consumer.getConfiguration()
                    && !bootstrapConfiguration.compatible(consumer.getConfiguration())) {
                throw new IllegalArgumentException(
                        "Bootstrap configuration must be identical when adding additional consumer: " + consumer.getEndpoint()
                                                   + " on same port: " + port
                                                   + ".\n  Existing " + bootstrapConfiguration.toStringBootstrapConfiguration()
                                                   + "\n       New "
                                                   + consumer.getConfiguration().toStringBootstrapConfiguration());
            }
        }

        if (LOG.isDebugEnabled()) {
            NettyHttpConsumer httpConsumer = (NettyHttpConsumer) consumer;
            LOG.debug("BootstrapFactory on port {} is adding consumer with context-path {}", port,
                    httpConsumer.getConfiguration().getPath());
        }

        channelFactory.addConsumer((NettyHttpConsumer) consumer);
    }

 

만약 새롭게 엔드포인트를 올릴때마다, 옵션이 바뀌는 경우 NettyHttpComponent를 stop하고, 새로운 NettyHttpComponent 객체를 만들던지, bootstrapFactories이 캐싱하는 로직을 제거.

 

필자는 bootstrapFactories에 캐싱하는 로직을 제거하였음. 다만, 제거하여 현재 어떠한 문제가 발생할지 의문.

반응형

'Java > Camel' 카테고리의 다른 글

[Camel] HTTP2 지원  (0) 2025.01.13

+ Recent posts