Статьи

Запуск OkHttpClient из WildFly 9 (подсистема)

Несколько дней назад был выпущен WildFly 9, и одним из основных моментов наверняка является поддержка HTTP / 2.0 в веб-подсистеме Undertow. Поскольку Hawkular недавно перешел на использование WildFly 9 (из 8.2) в качестве базового сервера, было естественным попытаться использовать http2 для подключения клиента Hawkular-Wildfly-Monitor к серверу.

Одна особенность здесь заключается в том, что в моем случае клиент монитора работает внутри сервера Hawkular, но в конце не имеет значения, работает ли он внутри автономного сервера WildFly или внутри сервера Hawkular.

Настройка

Грег Аутрик написал пост в блоге, в котором показано, как настроить Http2 в WildFly с помощью автономного интерфейса командной строки , что также хорошо работает в случае с Hawkular.

Единственное, что немного проблематично в этом посте, это то, что установка JAVA_OPTS перед запуском сервера будет игнорировать все настройки из standalone.conf, что в текущей версии Hawkular помешает корректному запуску брокера шины (поскольку флаг IPv4Only потерял).

Поэтому, по моему мнению, лучше изменить standalone.conf чтобы * добавить * эти параметры к другим, которые уже есть:

1
2
3
JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true"
  JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/p:/opt/hawkular-1.0.0.Alpha3-SNAPSHOT/alpn-boot-8.1.3.v20150130.jar"
  JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"

Теперь, когда я запускаю сервер Hawkular и пытаюсь соединиться с FireFox через порт https, я получаю предупреждение о самозаверяющем сертификате, но могу подключиться и получить пользовательский интерфейс через соединение Http2, как описано в посте Грега.

Запуск OkHttpClient

Как было сказано ранее, клиент монитора WildFly является подсистемой внутри сервера WildFly. Я написал немного клиентского кода, который работает в подсистеме (сокращенно):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
OkHttpClient httpClient;
   httpClient = new OkHttpClient();
 
   // DO NOT USE IN PRODUCTION, allow all hostnames
   httpClient.setHostnameVerifier(new NullHostNameVerifier());
 
   setKeystore(httpClient); // Use custom ssl factory
 
   String uri = "https://...:8443/";
 
   Request request = new Request.Builder()
            .url(uri)
            .addHeader("Accept", "application/json")
            .get()
            .build();
 
   // sync execution just for the post
   Response resp = httpClient.newCall(request).execute();
   System.out.println(resp.toString());

Потерпеть неудачу?

Этот код работает хорошо, за исключением того факта, что он всегда использует Http (s) /1.1 и никогда не Http2, как вы можете видеть из выходных данных последнего оператора println :

1
Response{protocol=http/1.1, code=204, message=....}

Я играл с различными опциями до того момента, когда подумал, что мне нужно извлечь код в автономный класс Java SE, чтобы лучше отладить его в изоляции.

Я написал класс, установил загрузочный путь, запустил его, и он работал отлично:

1
Response{protocol=h2, code=204, message=....}

Так в чем же разница? Я удалил настройку bootclasspath для ALPN, повторно подключился и соединение вернулось к http / 1.1.

Что довольно странно, поскольку моя клиентская подсистема работает на том же самом сервере WilFly, на котором работает Undertow и который может обслуживать запросы http2, и где я ранее добавил классы JAVA_OPTS через JAVA_OPTS .

Теперь помните, что WildFly использует свою собственную систему загрузчика классов (jboss-modules), которая довольно мощна для изоляции развертываний и классов и ограничения их видимости и / или утечки в области, где они должны (не) быть видны.

И это на самом деле то, что здесь произошло.

Успех!

Поэтому мне пришлось явно добавить классы ALPN в мой файл module.xml для клиентской подсистемы мониторинга:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<module xmlns="urn:jboss:module:1.3" name="${moduleName}">
    <resources>
      <resource-root path="clients-common.jar"/>
      [...]
      <resource-root path="okhttp.jar"/>
      <resource-root path="okio.jar"/>
    </resources>
    <dependencies>
      <!-- modules required by any subsystem -->
      <module name="javax.api"/>
      [...]
      <system export="true">
        <paths>
          <!-- Needed for HTTP2 and SPDY support-->
          <path name="org/eclipse/jetty/alpn"/>
        </paths>
      </system>
    </dependencies>
  </module>

Из приведенного выше фрагмента видно, что okhttp okio okhttp и okio упакованы в модуле и доступны для моего клиентского кода.

Теперь, когда модуль.xml настроен, и моя подсистема использует Http2 🙂