Как динамически создавать конфигурацию маршрутов

В одном из моих вариантов использования у меня есть вся информация о моем маршруте в файле json, и я хочу прочитать файл и создать маршруты соответственно.

Например,

если я объявил такой маршрут в моем конфигурационном файле json

{
  "config": [
    {
      "routeSrcSystem": "System1",
      "routes": [
        {
          "fromRoute": {
            "type": "default",
            "typeValue": "direct:CMStart"
            },  
          "toRoute": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System1/inboundMessage"
            }
        }
      ]
    }
  ]
}

тогда я могу динамически создавать маршруты, как показано ниже. но здесь, несмотря на то, что он динамический, определение маршрута не является динамическим, потому что я использовал одно определение «от» и одно «до», но параметр для этого определения я передаю динамически.

public class GenerateRouter extends RouteBuilder {

        private RoutesMetadata routesMetadata;

        public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
            super(context);
            this.routesMetadata=routesMetadata;
        }

        @Override
        public void configure() throws Exception {
            from(routesMetadata.getFromRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue());
        }
    }

Но я хотел бы сделать определение маршрута динамически. например, у меня есть такая конфигурация маршрута,

{
  "config": [
    {
      "routeSrcSystem": "System1",
      "routes": [
        {
          "fromRoute": {
            "type": "default",
            "typeValue": "direct:CMStart"
            },  
          "toRoute1": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System1/inboundMessage"
            }
         "toRoute2": {
            "type": "http"
            "typeMethod": "POST",
            "typeContent": "application/json",
            "typeValue": "http://localhost:8080/v1/System2/inboundMessage"
            }
        }
      ]
    }
  ]
}

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

public class GenerateRouter extends RouteBuilder {

        private RoutesMetadata routesMetadata;

        public GenerateRouter(CamelContext context,RoutesMetadata routesMetadata) {
            super(context);
            this.routesMetadata=routesMetadata;
        }

        @Override
        public void configure() throws Exception {
            from(routesMetadata.getFromRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue())
            .setHeader(Exchange.HTTP_METHOD, simple(routesMetadata.getToRoute().getTypeMethod()))
            .setHeader(Exchange.CONTENT_TYPE, constant(routesMetadata.getToRoute().getTypeContent()))
            .to(routesMetadata.getToRoute().getTypeValue());
        }
    }

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

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

.to("класс:com.xxx.camel.layoutTransform?method=layout()")

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

Ниже приведен один из способов создания определения маршрутизатора из другого источника с использованием XML-файла. в XML у нас есть определенная информация о маршрутизаторе, и этот xml рассматривается как строка, и эта строка преобразуется как объект определения маршрутизатора и, наконец, добавляется в контекст.

<routes
  xmlns=\"http://camel.apache.org/schema/spring\">
  <route>
      <from uri='direct:c'/>
      <to uri='mock:d'/>
  </route>
</routes>
CamelContext context = new DefaultCamelContext(); 
context.setTracing(true); 
String xmlString = "<routes  xmlns=\"http://camel.apache.org/schema/spring\"><route><from uri='direct:c'/><to uri='mock:d'/></route></routes>"; 

InputStream is = new ByteArrayInputStream(xmlString.getBytes()); 
RoutesDefinition routes = context.loadRoutesDefinition(is); 
context.addRouteDefinitions(routes.getRoutes()); 

context.start(); 

ProducerTemplate template = null; 
template = context.createProducerTemplate(); 
template.start(); 
template.sendBody("direct:c", "HelloC"); 
Thread.sleep(10000); 
context.stop();

Я хотел бы сделать аналогичную концепцию, используя определение java dsl в виде строки.

например, если у меня есть строка, как показано ниже, можно ли ее преобразовать в определение маршрутизатора?

String dslString = "from("direct:starting").to("seda:end")";

Вот мой вариант использования. Иногда мы хотим вызвать 2 http-сервиса, как показано ниже.

from("direct:start").to(http://localhost:8080/service1).to("http://localhost:8080/service2")

Иногда нам может понадобиться вызвать 3 службы, как показано ниже.

from("direct:start").to(http://localhost:8080/service1).to("http://localhost:8080/service2").to("http://localhost:8080/service3")

иногда нам нужно выполнить преобразование, прежде чем мы вызовем service2, как показано ниже.

from("direct:start").to(http://localhost:8080/service1).to("class:com.xxx.yyy").to("http://localhost:8080/service2").to("http://localhost:8080/service3")

В архитектуре с четным управлением у нас будет набор маршрутов, которые должны быть определены для каждого типа событий. Итак, идея в том, что если мы определим эти маршруты в таблице для каждого типа событий, то во время запуска службы все маршруты будут загружены в контексте и будут запущены. Я могу сделать то же самое в XML DSL, но пытаюсь сделать то же самое в java DSL.

Заранее спасибо!


person James Mark    schedule 16.05.2019    source источник


Ответы (1)


Camel поддерживает определение всех сведений о маршрутах в определенном формате на основе XML. Эта страница содержит ссылки на этот (и другие) DSL.

Вы определенно можете придумать свой собственный DSL и динамически строить маршруты, но это много работы, если вы хотите поддерживать все, что поддерживает полноценный Camel DSL. Я подозреваю, что это не правильное решение для любого вашего варианта использования.

Если у вас есть определенные шаблоны для ваших маршрутов, вы можете создать довольно динамичные построители маршрутов Camel, которые управляются некоторой конфигурацией. Чтобы сделать это конкретным, предположим, что у вас есть много вариантов использования, которые следуют очень похожей схеме... скажем, данные о потребителе из файлов в папке, выполните несколько преобразований из меню (скажем) 10-15 преобразований, а затем отправьте вывод в одну из множества очередей.

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

По сути, вы все равно будете создавать DSL или сортировки, но более близкие к вашему варианту использования.

person Darius X.    schedule 17.05.2019
comment
Спасибо за быстрый ответ!. Я нашел способ динамически создавать определение маршрутизатора с помощью XML-файла, но я хотел бы сделать то же самое с помощью java DSL. я обновил эту информацию в своем посте для получения дополнительной информации - person James Mark; 17.05.2019
comment
Я полностью согласен с тем, что сказал Дарий X. OP примерно реализует JSON DSL для Camel, и, скорее всего, это приведет к эффекту внутренней платформы< /а> - person ShellDragon; 18.05.2019
comment
@ShellDragon, спасибо за ваши предложения!.. Я все еще пытаюсь динамически загрузить определение маршрута, если моя информация о маршруте определена в формате DSL, но хранится в строковой переменной, потому что я хотел бы выполнять все определения в формате DSL, а не XML-способ. Мой вопрос: если у меня есть строка, как показано ниже, могу ли я загрузить ее как определение маршрута? Строка dslString = from(\direct:starting\).to(\seda:end\); Заранее спасибо!. - person James Mark; 20.05.2019
comment
Итак, Джеймс... вы говорите, что хотите написать DSL так же, как если бы вы кодировали DSL на Java, но вы хотите сохранить это в каком-то файле, который вы читаете. По сути... как динамический код Java, скомпилированный в время выполнения? - person Darius X.; 20.05.2019
comment
Привет, Дариус. Еще раз спасибо за ответ!.. да, вы правы. у нас есть возможность сделать это? - person James Mark; 26.05.2019
comment
Я не уверен, что есть простой способ. В основном вам нужен интерпретируемый код Java... может быть, что-то вроде Groovy. Честно говоря, мне трудно с этим справиться: я не могу представить вариант использования, в котором это было бы хорошим решением. - person Darius X.; 26.05.2019
comment
@DariusX.- Теперь я добавил дополнительную информацию в основной пост, чтобы более подробно объяснить вариант использования. Пожалуйста, просмотрите его. - person James Mark; 26.05.2019
comment
@James Mark: Спасибо за дополнительную информацию. Я не знаю ничего, что могло бы динамически создавать Java DSL для работающего маршрута или RouteBuilder. Читая ваши примеры, если все эти определения маршрутов известны в зависимости от типа события, у вас могут быть другие варианты в Camel для реализации того, что вы хотите. Например, 1. три разные конечные точки для каждого из этих событий. 2. Использование решений о маршрутизации во время полета с использованием условных выражений в Camel (например, .choice() + .when()). Они могут помочь вам решить, использовать ли некоторые процессоры или нет, на основе выбранных вами значений заголовков. - person ShellDragon; 27.05.2019
comment
@JamesMark Я не знаю, как это сделать. Но я до сих пор не понимаю реальной мотивации. По сути, вы будете добавлять код в базу данных. Как это будет отлаживаться, контролироваться версиями и т. д. Более простой подход, по-видимому, состоит в том, чтобы хранить маршруты в файлах классов, позволять людям тестировать их и т. д. И, когда вы хотите развернуть, добавьте их в развернутое приложение. База данных может выполнять сопоставление: какой маршрут вызывать для какого события. Возможно, вы даже захотите запустить несколько приложений, каждое из которых будет обрабатывать корзину событий. Я думаю, что, уйдя из IDE, вы потеряете ценность. - person Darius X.; 28.05.2019