Статьи

Fatjars, Thinwars и почему OpenLiberty это круто

Fatjars

Создание Fatjar (или Uberjar), содержащего все, что вам нужно для запуска вашего приложения, хорошо упаковано вместе, значит вы можете просто сделать:

1
java -jar myapp.jar

и уходи. Нет сервера приложений. Нет пути к классам.

Этот подход популяризировался архитектурным стилем и фреймворками микросервисов, такими как Springboot .

«Короче говоря, архитектурный стиль микросервисов — это подход к разработке отдельного приложения в виде набора небольших сервисов , каждый из которых работает в своем собственном процессе и обменивается данными с облегченными механизмами, часто API-интерфейсом для HTTP-ресурсов. Эти сервисы построены на бизнес-возможностях и могут быть развернуты независимо с помощью полностью автоматизированного механизма развертывания » .

Имея кучу исполняемых jar-файлов, отметьте все поля выше.

Java EE

Концепция FATJAR также была доступна в Java EE уже некоторое время. Все легкие серверы приложений имеют опцию «Micro»:

У фатжара есть много плюсов. Однако есть и минусы.

  • Вы делаете этот выбор во время разработки (и на самом деле это выбор времени развертывания). Мне нравится отделять мою модель разработки от моей модели развертывания.
  • Это дает вам неоптимальный цикл разработки. Вам нужно собрать фаджар, затем остановить предыдущую версию, скорее всего, с помощью kill, а затем снова начать. Переход от «изменения кода» к «запуску кода» через некоторое время становится раздражающим. Одним из преимуществ развертывания «тонкой войны» на работающем сервере приложений является быстрое решение проблемы.
  • Отсутствие classpath на самом деле за и против. Несмотря на то, что одним из рекламируемых преимуществ fatjars является отсутствие сервера приложений, у вас фактически есть сервер приложений, он просто встроен. Наличие только одного файла JAR означает, что ваше приложение и встроенный сервер приложений имеют одинаковые зависимости. Вы можете столкнуться с проблемами, когда ваше приложение использует другую версию зависимости, чем встроенный сервер. Это может вызвать некоторые приятные скрытые ошибки. Возможность изолировать classpath сервера приложений от вашего приложения на самом деле хорошая вещь. Java 9 может решить эту проблему, однако большинство серверов приложений все еще работают на Java 8.

докер

Докер поднял уровень микросервисов на более глубокий уровень и позволил вам изолировать на уровне ОС. Это означает, что создание отдельных файлов JAR становится менее актуальным, так как вы будете создавать отдельные образы Docker.

Создание толстой банки для развертывания в качестве образа Docker на самом деле медленнее и тяжелее, чем тонкая война. Вы обычно накладываете свои изображения Docker:

(выше: ваш последний уровень в опции fatjar намного тяжелее, чем в режиме thinwar, поскольку он включает встроенный сервер приложений)

OpenLiberty это круто!

Традиционная Websphere большая, медленная, дорогая и сложная в установке. Не то, что вы бы использовали для создания микросервисов. IBM — довольно поздний выход на облегченные серверные решения для приложений с Websphere Liberty , ядро ​​которого недавно было открыто с открытым исходным кодом в рамках OpenLiberty .

Но эта поздняя запись может быть причиной того, что они сделали некоторые вещи правильно и очень чисто. Способ, которым вы можете загружать только те части, которые вам нужны, с функциями и как вы можете расширить сервер своими собственными функциями, удивителен. Несмотря на то, что другие серверы приложений также выполняют некоторую модульность с OSGi (или с модулями JBoss), с Liberty все проще. Для Liberty в том числе Microprofile — это просто еще одна особенность. Другие серверы приложений добавили MicroProfile к своим дистрибутивам FATJAR («Micro»), и хотя я считаю, что его можно добавить и к полной версии сервера приложений, это сделать нелегко.

Еще одна интересная вещь — это то, как вы можете очень легко определить модель развертывания только во время развертывания. Таким образом, вы можете иметь лучшее из всех миров. Вы можете разработать полноценный сервер приложений с тонкой моделью, чтобы получить быстрый оборот. При сборке вы можете собрать образ фиджара, тонкавара, докера или их всех. То, против чего вы развиваетесь, остается прежним.

Пример OpenLiberty с MicroProfile

Я создал простое приложение, чтобы продемонстрировать эти варианты развертывания. (Код доступен в GitHub )

Я не хотел создавать простой «Hello world», поскольку хотел включить некоторые функции MicroProfile, так что это приложение «Цитата дня». Он использует фабрику для загрузки провайдера котировок (пока только один). Текущий поставщик получает и кеширует цитату с сайта forismatic.com . Я использую MicroProfile Configuration API для настройки таких вещей, как HTTP-прокси, URL-адрес и поставщик для загрузки. Я использую MicroProfile Fault Tolerance API, чтобы убедиться, что мы выживем, когда источник поставщика недоступен.

Настройка OpenLiberty

Конфигурация на OpenLiberty также очень чистая. Это позволяет легко включить конфигурацию в ваш проект. Используя фильтрацию ресурсов maven, вы также можете извлечь определенные переменные в свою сборку. Ниже приведены важные части моего server.xml (вы можете увидеть полную в github )

SRC / основная / свобода / конфигурации / server.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<server description="${project.build.finalName}">
 
    <featureManager>
        <feature>javaee-7.0</feature>
        <feature>microProfile-1.2</feature>
    </featureManager>
 
    <httpEndpoint id="defaultHttpEndpoint"
        httpPort="${httpPort}"
        httpsPort="${httpsPort}"/>
 
    <application location="${project.build.directory}/${project.build.finalName}.war"/>
 
    <logging traceSpecification="${log.name}.*=${log.level}"/>
 
</server>

На данный момент мы просто включили функции зонтика для Java EE и Microprofile. Чуть позже мы можем настроить это, чтобы уменьшить объем памяти.

${httpPort} и ${httpsPort} фактически ${httpsPort} из bootstrap.properties, которые мы создаем с помощью плагина liberty maven .

Все переменные в server.xml , включая ${project.build.directory} и ${project.build.finalName} будут заменены при сборке с помощью этой фильтрации ресурсов в файле pom.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
<build>
    <finalName>${project.artifactId}</finalName>
    <resources>
        <resource>
            <directory>${basedir}/src/main/liberty/config</directory>
            <targetPath>${project.build.directory}</targetPath>
            <filtering>true</filtering>
            <includes>
                <include>server.xml</include>
            </includes>
        </resource>
    </resources>
</build>

(Вы можете увидеть полный pom.xml в github )

Поэтому, когда мы выполняем mvn clean install server.xml будет скопирован в целевой каталог с замененными переменными.

Варианты развертывания

Я использую профили maven, чтобы во время сборки я мог выбрать, какой вариант развертывания мне нужен:

В <build> файла pom.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<plugins>
    <plugin>
        <groupId>net.wasdev.wlp.maven.plugins</groupId>
        <artifactId>liberty-maven-plugin</artifactId>
        <version>${openliberty.maven.version}</version>
 
        <configuration>
            <assemblyArtifact>
                <groupId>io.openliberty</groupId>
                <artifactId>openliberty-runtime</artifactId>
                <version>${openliberty.version}</version>
                <type>zip</type>
            </assemblyArtifact>
        </configuration>
    </plugin>
</plugins>

На лету вариант

Этот параметр следует тому же циклу разработки, что и цикл FATJAR (хотя он не создает файл JAR). Если вы выполните mvn clean install -Pfatjar , он установит, настроит (из server.xml ) и запустит сервер на переднем плане. Другими словами, процесс mvn не завершается, так как запуск сервера является частью процесса mvn. Чтобы остановить сервер вам нужно ctrl-c процесс.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<profile>
        <id>fatjar</id>
        <activation>
            <property>
                <name>fatjar</name>
            </property>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>net.wasdev.wlp.maven.plugins</groupId>
                    <artifactId>liberty-maven-plugin</artifactId>
 
                    <executions>
                        <execution>
                            <phase>install</phase>
                            <goals>
                                <goal>install-server</goal>
                                <goal>create-server</goal>
                                <goal>run-server</goal>   
                            </goals>
 
                            <configuration>
                                <configFile>${project.build.directory}/server.xml</configFile>
                                <bootstrapProperties>
                                    <httpPort>${openliberty.http.port}</httpPort>
                                    <httpsPort>${openliberty.https.port}</httpsPort>
                                </bootstrapProperties>
                                <jvmOptions>
                                    <param>-Xmx${openliberty.Xmx}</param>
                                </jvmOptions>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
 
            </plugins>
        </build>
    </profile>

Конечно, используя IDE, например Netbeans (или любую другую IDE), это всего лишь кнопка, которую вы нажимаете:

Полная опция сервера приложений:

С помощью этой опции мы хотим установить, настроить и запустить сервер, а затем непрерывно развертывать тонкую войну, пока мы пишем код. Мы по-прежнему устанавливаем и настраиваем сервер с нуля при каждом его запуске, но не при каждом развертывании.

mvn clean install -Pstart-liberty установит, настроит (из server.xml ) и запустит liberty-сервер в папке /tmp :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<profile>
        <id>start-liberty</id>
        <activation>
            <property>
                <name>start-liberty</name>
            </property>
        </activation>
        <build>
 
            <plugins>
                <plugin>
                    <groupId>net.wasdev.wlp.maven.plugins</groupId>
                    <artifactId>liberty-maven-plugin</artifactId>
 
                    <executions>
 
                        <execution>
                            <id>1</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>install-server</goal>
                            </goals>
                            <configuration>
                                <assemblyInstallDirectory>${openliberty.installDir}</assemblyInstallDirectory>
                            </configuration>
                        </execution>
 
                        <execution>
                            <id>2</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>create-server</goal>
                                <goal>start-server</goal>
                            </goals>
                            <configuration>
                                <installDirectory>${openliberty.installDir}/wlp</installDirectory>
                                <serverName>${project.artifactId}</serverName>
                                <configFile>${project.build.directory}/server.xml</configFile>
                                <bootstrapProperties>
                                    <httpPort>${openliberty.http.port}</httpPort>
                                    <httpsPort>${openliberty.https.port}</httpsPort>
                                </bootstrapProperties>
                                <jvmOptions>
                                    <param>-Xmx${openliberty.Xmx}</param>
                                </jvmOptions>
                            </configuration>
                        </execution>
 
                    </executions>
                </plugin>
 
            </plugins>
        </build>
    </profile>

Теперь вы можете использовать тонкий воин непрерывно:

mvn clean install -Pdeploy

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<profile>
    <id>deploy</id>
    <activation>
        <property>
            <name>deploy</name>
        </property>
    </activation>
    <build>
        <plugins>
            <plugin>
                <groupId>net.wasdev.wlp.maven.plugins</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>deploy</goal>
                        </goals>
                        <configuration>
                            <appArchive>${project.build.directory}/${project.artifactId}.war</appArchive>
                            <serverName>${project.artifactId}</serverName>
                            <installDirectory>${openliberty.installDir}/wlp</installDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Остановить сервер тоже очень просто:

mvn clean install -Pstop-liberty

Fatjar распределение

Создать очень простой дистрибутив с помощью mvn clean install -Ppackage-liberty очень просто:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<profile>
    <id>package-liberty</id>
    <activation>
        <property>
            <name>package-liberty</name>
        </property>
    </activation>
    <build>
        <plugins>
            <plugin>
                <groupId>net.wasdev.wlp.maven.plugins</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>package-server</goal>
                        </goals>
                        <configuration>
                            <packageFile>${project.build.directory}/${project.artifactId}.jar</packageFile>
                            <include>runnable</include>
                            <serverName>${project.artifactId}</serverName>
                            <installDirectory>${openliberty.installDir}/wlp</installDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
 
</profile>

В моей целевой директории у меня теперь есть исполняемый (толстый) файл jar, с которого я могу начать: java -jar quote-service.jar

Во всех вышеупомянутых profiles вы можете протестировать пример приложения с:

mvn -Dtest=com.github.phillipkruger.quoteservice.QuoteApiIT surefire:test

И это должно дать вам цитату дня:

1
2
3
4
{
    "author":"Naguib Mahfouz",
    "text":"You can tell whether a man is clever by his answers. You can tell whether a man is wise by his questions."
}

Тонкая настройка памяти.

Для начала я использовал функции зонтика javaee-7.0 и microProfile-1.2 , хотя мое приложение использует только часть этих спецификаций.

Используя jconsole я измерил объем памяти (после GC) работающего сервера:

50 691 кбайт

В моем примере вы можете изменить server.xml чтобы включить только те функции, которые использует ваше приложение:

1
2
3
4
5
6
7
<feature>jaxrs-2.0</feature>
<feature>ejb-3.2</feature>
<feature>cdi-1.2</feature>
<feature>jsonp-1.0</feature>
<feature>jaxrsClient-2.0</feature>
<feature>mpConfig-1.1</feature>
<feature>mpFaultTolerance-1.0</feature>

Снова используя jconsole я измерил объем памяти (после GC) работающего сервера:

30 198 кбайт

В идеале вы также должны настроить pom.xml чтобы он включал только те спецификации, которые вы используете.

Вывод

Мы можем спорить о том, лучше ли делать «фатжарс», а не «тонких войн», а также плюсы и минусы наличия сервера приложений или нет. Тем не менее, не нужно принимать это решение, когда мы начинаем разработку (т. Е. Загружать микро-дистрибутив или полный дистрибутив), а только когда мы строим, предоставляет больше возможностей. Может быть, это возможно сделать с другими серверами приложений, но OpenLiberty сделал это легко.

Больше информации

Также читайте это отличные блоги от Павла Пшеидля

и смотреть это видео от Адама Бина

Опубликовано на Java Code Geeks с разрешения Филиппа Крюгера, партнера нашей программы JCG . Смотрите оригинальную статью здесь: Fatjars, Thinwars и почему OpenLiberty — это круто.

Мнения, высказанные участниками Java Code Geeks, являются их собственными.