1. Как использовать и примеры
Введение. Когда вводится пакет зависимостей стороннего производителя или пакет зависимостей стороннего производителя, может возникнуть конфликт между внешним пакетом jar зависимостей и собственными потребностями проекта, или несколько сторонних и сторонних пакетов зависимостей конфликтуют друг с другом. разное. В настоящее время для их изоляции необходим изолирующий контейнер.Принцип зависимости заключается в том, что JVM считает, что классы, загруженные разными загрузчиками классов, различны, даже если имя пакета и имя класса совпадают. диван-арк упаковывает пакеты jar, которые необходимо изолировать, в плагины и использует независимый загрузчик классов для загрузки каждого плагина.
(Напоминание: если вы мало знаете о диван-ковчеге, вам лучше сначала пойти и посмотреть егоофициальная документация, Легко понять)
Основные шаги для использования:
- Добавьте плагин maven, предоставленный диваном-арком, в файл POM пакета jar, который будет конфликтовать, и отформатируйте его в пакет jar (плагин) в определенном формате.
- Пакет jar импортируется во внешний проект в соответствии с соглашением. Если внешний проект нужно упаковать в исполняемый файл jar (fat-jar), необходимо добавить специальный плагин maven.
- запустить напрямую.
Глоссарий:
- Контейнер Ark: Контейнер Ark является ядром компонента SOFAArk.При запуске пакета Ark контейнер Ark запускается первым и отвечает за управление средой выполнения приложения.В основном это включает в себя создание таблицы отношений импорта и экспорта классов Ark Plugin и Ark Biz., запускать и инициализировать Ark Plugin и Ark Biz, управлять публикацией и ссылками на сервисы Ark Plugin и многое другое.
- Biz: бизнес-проект, который ссылается на один или несколько внешних пакетов jar.
- плагин: пакет fat-jar конфликтующего пакета jar внешней зависимости создается с помощью предоставленного плагина Maven. Во время выполнения он загружается независимым загрузчиком классов, поэтому пакеты Jar с требованиями к изоляции рекомендуется упаковывать как подключаемый модуль Ark для зависимостей приложений.
1.0 Принцип дивана-ковчега
В диване-арк контейнер-контейнер используется для запуска внешнего проекта (Biz) и конфликтующего пакета jar (плагина). может ссылаться только на классы, экспортируемые плагином, и этот класс сделан независимым отPluginClassLoader
загружен, тем самым решив проблему конфликта пакетов jar.
1.1 Пример конфликта
1.2 Устанавливаем мыльный ковчег
отофициальный сайт диван-ковчегаЗагрузите весь проект и выполните его по пути, где находится самый внешний файл pom.xml.mvn package
иmvn install
Установите пакет JAR зависимостей дивана-арка локально.
1.3 Создайте пакет Jar с базовой зависимостью (конфликтующий пакет)
Создайте проект myjar самостоятельно, упакуйте две версии в обычном режиме и установите их на локальном складе maven.
Например: версия v1
версия v2
1.4 Создать пакет услуг (плагин)
Создайте два проекта, как показано на рисунке:
существуетmyJarservice-v1
иmyJarservice-v2
Два базовых пакета зависимостей, написанные ранее, упоминаются в pom соответственно. затем вMyJarService1
иMyJarService2
См. методы в соответствующей версии пакета myjar соответственно.
Например, MyJarService1.java:
MyJarService2.java
Примечание. Две службы здесь относятся к разным версиям myjar.
Далее нужно запаковать два проекта.Чем отличается от обычной упаковки, так это плагином maven, который нужно добавить в диван-арк-плагин. Необходимо добавить pom.xml в оба проекта:
<build>
<plugins>
<plugin>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-plugin-maven-plugin</artifactId>
<version>0.4.0-SNAPSHOT</version>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>ark-plugin</goal>
</goals>
<configuration>
<!-- configure exported class -->
<exported>
<!-- configure class-level exported class -->
<classes>
<class>com.netease.sofaservice.MyJar1Service</class>
</classes>
</exported>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
существуетexported
Методы, которые должны быть предоставлены извне, написаны в метке, и все методы, на которые нужно ссылаться извне, должны быть записаны здесь, что может быть записано в классе (<classes>
) для единиц и пакетов (packages
) экспортируются в единицах.
Перейти к родительскому пути проектаmvn package
иmvn install
Вот и все.
1.5 Внешняя ссылка на проект (Biz)
Создайте новый проект и введите следующие зависимости в pom.xml:
<dependencies>
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-support-starter</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.netease</groupId>
<artifactId>myjarservice-v1</artifactId>
<classifier>ark-plugin</classifier>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.netease</groupId>
<artifactId>myjarservice-v2</artifactId>
<classifier>ark-plugin</classifier>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.netease</groupId>
<artifactId>myjarservice-v1</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netease</groupId>
<artifactId>myjarservice-v2</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Примечание для добавления<classifier>
Этикетка, так как среда IDE не может распознать jar-пакет ark-plugin, ей необходимо ввести другую область видимости.provided
баночный пакет.
Затем pom.xml также добавляет плагин maven:
<build>
<plugins>
<plugin>
<groupId>com.alipay.sofa</groupId>
<artifactId>sofa-ark-maven-plugin</artifactId>
<version>0.4.0-SNAPSHOT</version>
<executions>
<execution>
<id>default-cli</id>
<!--goal executed to generate executable-ark-jar -->
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<!--specify destination where executable-ark-jar will be saved, default saved to ${project.build.directory}-->
<outputDirectory>./</outputDirectory>
<!--default none-->
<arkClassifier>executable-ark</arkClassifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Затем просто напишите класс, чтобы представить классы двух версий пакета услуг для использования.Вам нужно добавить предложение при входе в основную функцию:
SofaArkBootstrap.launch(args);
Вы можете увидеть результат печати:
2. Принципиальный анализ плагина Sofa-ark-plugin-maven-plugin
2.1 Просмотр содержимого пакета jar плагина
использоватьsofa-ark-plugin-maven-plugin
Подключаемый модуль Maven может упаковать пакет jar в пакет jar, который можно изолировать и загрузить в контейнер (например, myjarservice-v1-1.0-ark-plugin.jarr и myjarservice-v2-1.0-ark-plugin.jar). Введя расположение локального репозитория maven проекта myJarservice-v1, вы увидите, что у maven есть два пакета: один — это общий пакет, созданный подключаемым модулем, который поставляется с maven:myjarservice-v1-1.0.jar
, другой — это пакет, созданный плагином maven, предоставленным диваном-арком.myjarservice-v1-1.0-ark-plugin.jar
,Открытымmyjarservice-v1-1.0-ark-plugin.jar
Вы можете увидеть следующие каталоги:
Соответствующее описание каталога:
-
com/alipay/sofa/ark/plugin/mark
: пометить файл, пометить пакет Jarsofa-ark-plugin-maven-plugin
упакованный сгенерированныйArk Plugin
документ. -
META-INF/MANIFEST.MF
: запись метаинформации плагина,который содержит классы для экспорта и импорта.
Manifest-Version: 1.0
groupId: com.netease
artifactId: myjarservice-v1
version: 1.0
priority: 100
pluginName: myjarservice-v1
activator:
import-packages:
import-classes:
import-resources:
export-packages:
export-classes: com.netease.sofaservice.MyJar1Service
export-resources:
-
conf/export.index
: Плагин экспортирует файл индекса класса, чтобы избежать его вычисления во время выполнения.MANIFEST.MF
серединаexport-packages
В пакете создаются следующие специальные классы экспортаArk Plugin
При , индексный файл всех экспортированных классов плагина будет сгенерирован, сокращаяArk Container
Время настройки разбора. -
lib/
: В каталоге lib хранятся общие пакеты Jar, от которых зависят проекты подключаемых модулей, обычно включая пакеты Jar, которые необходимо изолировать подключаемым модулям от других подключаемых модулей или предприятий; экспортированные классы, настроенные подключаемыми модулями, включаются в эти пакеты Jar.
2.2 Анализ исходного кода диван-арк-плагин-мавен-плагин
Введите загруженный исходный код дивана-аркаark-plugin-maven-plugin
Project, вы можете видеть, что ArkPluginMojo унаследовал
@Mojo(name = "ark-plugin", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME)
public class ArkPluginMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.artifactId}")
public String pluginName;
@Parameter(defaultValue = "100", property = "sofa.ark.plugin.priority")
protected Integer priority;
@Parameter
protected String activator;
@Parameter
protected ExportConfig exported;
@Parameter
protected ImportConfig imported;
...
@Mojo
цель, которая может быть привязана кphase
(Вот пакет) выполнение, @Parameter — это параметр, переданный извне, вы можете напрямую получить параметры, настроенные в xml. Стандартные требования к плагину Maven должны быть переписаныexecute()
метод, когда подключаемый модуль выполняется, он в основном выполняетсяexecute()
.
@Override
public void execute() throws MojoExecutionException
{
Archiver archiver;//zip归档
archiver = getArchiver();
outputDirectory.mkdirs();
String fileName = getFileName();
File destination = new File(outputDirectory, fileName);
archiver.setDestFile(destination);
Set<Artifact> artifacts = project.getArtifacts();
artifacts = filterExcludeArtifacts(artifacts);
Set<Artifact> conflictArtifacts = filterConflictArtifacts(artifacts);
addArkPluginArtifact(archiver, artifacts, conflictArtifacts);
addArkPluginConfig(archiver);
archiver.createArchive();
projectHelper.attachArtifact(project, destination, getClassifier());
}
здесь будетexecute()
Этот метод упрощен, он в основном делает следующее:
- Создайте архив в формате zip, чтобы сохранить импортированный пакет jar и другие файлы, и укажите выходной путь.
- Получите все введенные зависимости (артефакты) и исключите пакеты, которые необходимо исключить.
- Запишите все зависимости в каталог lib в zip-архиве.
- Запишите информацию о конфигурации в zip-архив, включая ранее упомянутые
export.index
,MANIFEST.MF
,mark
После вышеуказанных шагов зависимые зависимости и файлы конфигурации записываются в zip, а затем преобразуются в суффикс jar.
3. Анализ принципа дивана-ковчега
3.1 Инициализировать ArkContainer
В предыдущем разделе объяснялось, как работает подключаемый модуль, а в этом разделе описывается, как внешний проект обращается к пакету jar подключаемого модуля, упакованному с подключаемым модулем, для разрешения конфликта изоляции. можно добавить из основного методаSofaArkBootstrap.launch(args)
Для пошагового отслеживания этот код в основномЗапустите контейнер, а затем дайте контейнеру загрузить Plugin и Biz. существуетlaunch
Метод вызывается отражениемSofaArkBootstrap
изremain
метод, вremain
Метод в основном делает две вещи:
private static void remain(String[] args) throws Exception {// NOPMD
URL[] urls = getURLClassPath();
new ClasspathLauncher(new ClassPathArchive(urls)).launch(args, getClasspath(urls),
entryMethod.getMethod());
}
- Получите все пакеты jar в пути к классам, включая собственные пакеты jar JDK и пакеты jar, представленные maven.
- положить всеЗависит от пакета jar и класса запуска, а его основная функция написана сама по себеПередать как URL
ClasspathLauncher
,ClasspathLauncher
вызов отраженияArkContainer
изmain
метод и использованиеContainerClassLoader
нагрузкаArkContainer
. В этот момент запустите ArkContainer.
3.2 Запустить АркКонтейнер
Затем он работаетArkContainer
В основном методе входящий параметр args является предыдущимClasspathLauncher
входящий URL
public static Object main(String[] args) throws ArkException
{
//使用LaunchCommand将传入的参数按类型分类
LaunchCommand launchCommand = LaunchCommand.parse(args[ARK_COMMAND_ARG_INDEX], Arrays.copyOfRange(args, MINIMUM_ARGS_SIZE, args.length));
//ClassPathArchive将传入依赖的Jar包分类,并提供获得plugin和biz的filter方法
ClassPathArchive classPathArchive = new ClassPathArchive(launchCommand.getEntryClassName(), launchCommand.getEntryMethodName(), launchCommand.getEntryMethodDescriptor(), launchCommand.getClasspath());
return new ArkContainer(classPathArchive, launchCommand).start();
}
}
Этот метод в основном выполняет следующие действия:
- использовать
LaunchCommand
Классифицируйте входящие параметры, извлеките URL пути к классам и основной метод класса запуска, написанный вами - будет
LaunchCommand
входящийArkContainer
и начните:
существуетArkContainer.start()
середина:
public Object start() throws ArkException
{
if (started.compareAndSet(false, true))
{
arkServiceContainer.start();
Pipeline pipeline = arkServiceContainer.getService(Pipeline.class);
pipeline.process(pipelineContext);
}
return this;
}
arkServiceContainer
Он содержит некоторые сервисы, которые необходимо запустить до запуска Контейнера, и эти сервисы инкапсулированы в один за другим.PipelineStage
в этихPipelineStage
Он снова инкапсулируется в список вpipeline
середина. В основном включают в себя этиPipelineStage
, выполнить последовательно:
-
HandleArchiveStage
Отфильтруйте все сторонние пакеты jar, которые содержат отмеченные меткой jar-файлы плагинов, указав, что эти jar-файлы упакованы плагином дивана ark maven и должны быть изолированы. Извлеките классы, которые необходимо изолировать, из файла export.index в банке и добавьте их вPluginList
, а каждому плагину назначить отдельныйPluginClassLoader
. В то же время назначьте Biz с той же операцией.BizClassLoader
-
DeployPluginStage
Создайте карту, ключ — это класс, который необходимо изолировать, а значение — это экземпляр PluginClassLoader, используемый для загрузки этого класса. -
DeployBizStage
Вызовите основной метод Biz, используя отражение BizClassLoader.
В этот момент Контейнер запускается. При вызове класса, который необходимо изолировать позже, поскольку поток, запустивший Biz, был заменен BizClassLoader, BizClassLoader сначала просматриваетDeployPluginStage
Есть ли в созданной карте PluginClassLoader, который может загрузить этот класс, и если да, делегируйте PluginClassLoader для загрузки. Достигается, что разные классы загружаются с помощью разных загрузчиков классов.