This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 7eefb33 CAMEL-16861: Cleanup and update EIP docs 7eefb33 is described below commit 7eefb339a19ecec41f93793df0770342e6178cdd Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Sep 23 20:00:27 2021 +0200 CAMEL-16861: Cleanup and update EIP docs --- .../docs/modules/eips/pages/loadBalance-eip.adoc | 233 +-------------------- .../src/main/docs/modules/eips/pages/log-eip.adoc | 122 +++++++---- .../src/main/docs/modules/eips/pages/loop-eip.adoc | 84 ++++---- 3 files changed, 130 insertions(+), 309 deletions(-) diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/loadBalance-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/loadBalance-eip.adoc index d9edd11..517abe3 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/loadBalance-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/loadBalance-eip.adoc @@ -14,231 +14,12 @@ Camel provides the following policies out-of-the-box: [width="100%",cols="3,6",options="header"] |======================================================================= | Policy | Description -| Round Robin | The exchanges are selected in a round robin fashion. This is a well known and classic policy, which spreads the load evenly. -| Random | A random endpoint is selected for each exchange. -| Sticky | Sticky load balancing using an Expression to calculate a correlation key to perform the sticky load balancing; rather like jsessionid in the web or JMSXGroupID in JMS. -| Topic | Topic which sends to all destinations (rather like JMS Topics) -| Failover | In case of failures the exchange will be tried on the next endpoint. -| Weighted Round-Robin |The weighted load balancing policy allows you to specify a processing load distribution ratio for each server with respect to the others. In addition to the weight, endpoint selection is then further refined using *round-robin* distribution based on weight. -| Weighted Random |The weighted load balancing policy allows you to specify a processing load distribution ratio for each server with respect to others.In addition to the weight, endpoint selection is then further refined using *random* distribution based on weight. -| Custom |The preferred way of using a custom Load Balancer is to use this policy, as the ref attribute is not supported anymore. +| xref:customLoadBalancer-eip.adoc[Custom Load Balancer] |To use a custom load balancer implementation. +| xref:failover-eip.adoc[Failover Load Balancer] | In case of failures the exchange will be tried on the next endpoint. +| xref:roundRobin-eip.adoc[Round Robin Load Balancer] | The exchanges are selected in a round robin fashion. This is a well known and classic policy, which spreads the load evenly. +| xref:random-eip.adoc[Random Load Balancer] | A random endpoint is selected for each exchange. +| xref:sticky-eip.adoc[Sticky Load Balancer] | Sticky load balancing using an xref:latest@manual:ROOT:expression.adoc[Expression] to calculate a correlation key to perform the sticky load balancing. +| xref:topic-eip.adoc[Topic Load Balancer] | Topic which sends to all destinations. +| xref:weighted-eip.adoc[Weighted Loader Balancer] |Uses a weighted load distribution ratio for each server with respect to others. |======================================================================= -== Options - -// eip options: START -include::partial$eip-options.adoc[] -// eip options: END - - -== Round Robin - -The round robin load balancer is not meant to work with failover, for that you should use the dedicated *failover* load balancer. The round robin load balancer will only change to next endpoint per message. -The round robin load balancer is stateful as it keeps state of which endpoint to use next time. - -Here is a little example: - -[source,java] ----- -from("direct:start") - .loadBalance().roundRobin() - .to("mock:x") - .to("mock:y") - .to("mock:z") - .end() // end load balancer ----- - -And in XML: -[source,xml] ----- -<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> - <route> - <from uri="direct:start"/> - <loadBalance> - <roundRobin/> - <to uri="mock:x"/> - <to uri="mock:y"/> - <to uri="mock:z"/> - </loadBalance> - </route> -</camelContext> ----- - -The above example loads balance requests from *direct:start* to one of the available *mock endpoint* instances, in this case using a round robin policy. - -== Failover - -The failover load balancer is capable of trying the next processor in case an Exchange failed with an exception during processing. -You can constrain the failover to activate only when one exception of a list you specify occurs. If you do not specify a list any exception will cause fail over to occur. This balancer uses the same strategy for matching exceptions as the Exception Clause does for the `onException`. - -[TIP] -==== -**Enable stream caching if using streams:** - -If you use streaming then you should enable Stream caching when using the failover load balancer. This is needed so the stream can be re-read after failing over to the next processor. -==== - -Here is a sample to failover only if a IOException related exception was thrown: -[source,java] ----- -from("direct:start") - // here we will load balance if IOException was thrown - // any other kind of exception will result in the Exchange as failed - // to failover over any kind of exception we can just omit the exception - // in the failOver DSL - .loadBalance().failover(IOException.class) - .to("mock:x") - .to("mock:y") - .to("mock:z"); ----- -You can specify multiple exceptions to failover as the option is varargs, for instance: - -[source,java] ----- -// enable maximum redelivery so failover can react -errorHandler(defaultErrorHandler().maximumRedeliveries(5)); - -from("direct:foo"). - loadBalance().failover(IOException.class, MyOtherException.class) - .to("direct:a") - .to("direct:b"); ----- - -And in XML: - -Failover can also be used from Spring DSL and you configure it as: -[source,xml] ----- -<route errorHandlerRef="myErrorHandler"> - <from uri="direct:foo"/> - <loadBalance> - <failover> - <exception>java.io.IOException</exception> - <exception>com.mycompany.MyOtherException</exception> - </failover> - <to uri="direct:a"/> - <to uri="direct:b"/> - </loadBalance> - </route> ----- - -== Using failover in round robin mode - -An example using Java DSL: -[source,java] ----- -from("direct:start") - // Use failover load balancer in stateful round robin mode - // which mean it will failover immediately in case of an exception - // as it does NOT inherit error handler. It will also keep retrying as - // its configured to newer exhaust. - .loadBalance().failover(-1, false, true) - .to("direct:bad") - .to("direct:bad2") - .to("direct:good") - .to("direct:good2"); ----- - -And the same example using Spring XML: -[source,xml] ----- -<route> - <from uri="direct:start"/> - <loadBalance> - <!-- failover using stateful round robin, - which will keep retrying forever those 4 endpoints until success. - You can set the maximumFailoverAttempt to break out after X attempts --> - <failover roundRobin="true"/> - <to uri="direct:bad"/> - <to uri="direct:bad2"/> - <to uri="direct:good"/> - <to uri="direct:good2"/> - </loadBalance> -</route> ----- - -[TIP] -==== -*Disabled inheritErrorHandler* - -You can configure `inheritErrorHandler=false` if you want to failover to the next endpoint as fast as possible. -By disabling the Error Handler you ensure it does not _intervene_ which allows the `failover` load balancer to handle failover asap. -By also enabling `roundRobin` mode, then it will keep retrying until it success. You can then configure the `maximumFailoverAttempts` option to a high value to let it eventually exhaust (give up) and fail. -==== - -== Weighted Round-Robin and Random Load Balancing - -In many enterprise environments where server nodes of unequal processing power & performance characteristics are utilized to host services and processing endpoints, it is frequently necessary to distribute processing load based on their individual server capabilities so that some endpoints are not unfairly burdened with requests. Obviously simple round-robin or random load balancing do not alleviate problems of this nature. A Weighted Round-Robin and/or Weighted Random load balancer can [...] -The weighted load balancing policy allows you to specify a processing load distribution ratio for each server with respect to others. You can specify this as a positive processing weight for each server. A larger number indicates that the server can handle a larger load. The weight is utilized to determine the payload distribution ratio to different processing endpoints with respect to others. - -The parameters that can be used are - -[width="100%",cols="3,1,2,6",options="header"] -|======================================================================= -| Option | Type | Default | Description -| roundRobin | boolean | false | The default value for round-robin is false. In the absence of this setting or parameter the load balancing algorithm used is random. -| distributionRatio | String | none | The distributionRatio is a delimited String consisting on integer weights separated by delimiters for example "2,3,5". The distributionRatio must match the number of endpoints and/or processors specified in the load balancer list. -| distributionRatioDelimiter | String | , | The distributionRatioDelimiter is the delimiter used to specify the distributionRatio. If this attribute is not specified a default delimiter "," is expected as the delimiter used for specifying the distributionRatio. -|======================================================================= - -== Using Weighted round-robin & random load balancing - -An example using Java DSL: -[source,java] ----- -String distributionRatio = "4,2,1" - -// round-robin -from("direct:start") - .loadBalance().weighted(true, distributionRatio) - .to("mock:x", "mock:y", "mock:z"); - -//random -from("direct:start") - .loadBalance().weighted(false, distributionRatio) - .to("mock:x", "mock:y", "mock:z"); ----- - -And the same example using Spring XML: -[source,xml] ----- -<route> - <from uri="direct:start"/> - <loadBalance> - <weighted roundRobin="false" - distributionRatio="4 2 1"/> - <to uri="mock:x"/> - <to uri="mock:y"/> - <to uri="mock:z"/> - </loadBalance> -</route> ----- - -An example using Java DSL: -[source,java] ----- -// round-robin -from("direct:start") - .loadBalance().weighted(true, "4:2:1" distributionRatioDelimiter=":") - .to("mock:x", "mock:y", "mock:z"); - -//random -from("direct:start") - .loadBalance().weighted(false, "4,2,1") - .to("mock:x", "mock:y", "mock:z"); ----- - -And the same example using Spring XML: -[source,xml] ----- -<route> - <from uri="direct:start"/> - <loadBalance> - <weighted roundRobin="false" - distributionRatio="4-2-1" distributionRatioDelimiter="-" /> - <to uri="mock:x"/> - <to uri="mock:y"/> - <to uri="mock:z"/> - </loadBalance> -</route> ----- diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/log-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/log-eip.adoc index f73147b..a9c5351 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/log-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/log-eip.adoc @@ -8,10 +8,11 @@ How can I log the processing of a xref:message.adoc[Message]? Camel provides many ways to log the fact that you are processing a message. Here are just a few examples: + * You can use the xref:components::log-component.adoc[Log] component which logs the Message content. * You can use the xref:latest@manual:ROOT:tracer.adoc[Tracer] which trace logs message flow. * You can also use a xref:latest@manual:ROOT:processor.adoc[Processor] or xref:latest@manual:ROOT:bean-binding.adoc[Bean] and log from Java code. -* You can use the log DSL. +* You can use this log EIP. == Options @@ -19,17 +20,17 @@ Camel provides many ways to log the fact that you are processing a message. Here include::partial$eip-options.adoc[] // eip options: END +=== Difference between Log EIP and Log component -=== Difference between log in the DSL and Log component - -The log DSL is much lighter and meant for logging human logs such as Starting to do ... etc. -It can only log a message based on the Simple language. +This log EIP is much lighter and meant for logging human logs such as `Starting to do ...` etc. +It can only log a message based on the xref:components:languages:simple-language.adoc[Simple] language. -The Log component is meant for logging the `Message` itself, and you have many URI options to control what you would like to be logged. +The xref:components::log-component.adoc[log] component is meant for logging the message content (body, headers, etc.). +There are many options on the log component to configure what content to log. -== Examples +== Example -You can use the log DSL which allows you to use xref:components:languages:simple-language.adoc[Simple] language to construct a dynamic message which gets logged. +You can use the log EIP which allows you to use xref:components:languages:simple-language.adoc[Simple] language to construct a dynamic message which gets logged. For example, you can do @@ -40,14 +41,23 @@ from("direct:start") .to("bean:foo"); ---- -This will construct a String message at runtime using the Simple language. The log message will by logged at INFO level using the route id as the log name. By default a route is named route-1, route-2 etc. But you can use the routeId("myCoolRoute") to set a route name of choice. +And in XML: + +[source,xml] +---- +<route> + <from uri="direct:start"/> + <log message="Processing ${id}"/> + <to uri="bean:foo"/> +</route> +---- + +This will be evaluated using the xref:components:languages:simple-language.adoc[Simple] +to construct the `String` containg the message to be logged. -[TIP] -==== -*Logging message body with streamed messages:* +=== Logging message body with streaming If the message body is stream based, then logging the message body, may cause the message body to be empty afterwards. See this xref:manual:faq:why-is-my-message-body-empty.adoc[FAQ]. For streamed messages you can use Stream caching to allow logging the message body and be able to read the message body afterwards again. -==== The log DSL have overloaded methods to set the logging level and/or name as well. [source,java] @@ -101,84 +111,103 @@ The log tag has attributes to set the message, loggingLevel and logName. For exa </route> ---- -=== Using custom logger +== Using custom logger -It is possible to reference logger instance. For example: +It is possible to reference an existing logger instance. For example: [source,xml] ---- -<bean id="myLogger" class="org.slf4j.LoggerFactory" factory-method="getLogger" xmlns="http://www.springframework.org/schema/beans"> +<bean id="myLogger" class="org.slf4j.LoggerFactory" factory-method="getLogger"> <constructor-arg value="com.mycompany.mylogger" /> </bean> -<route id="moo" xmlns="http://camel.apache.org/schema/spring"> +<route id="moo"> <from uri="direct:moo"/> - <log message="Me Got ${body}" loggingLevel="INFO" loggerRef="myLogger"/> + <log message="Me Got ${body}" loggerRef="myLogger"/> <to uri="mock:baz"/> </route> ---- -=== Using Logger instance from the Registry +=== Configuring logging name + +The log message will be logged at `INFO` level using the route id as the logger name. +So for example if you have not assigned an id to the route, then Camel will use `route-1`, `route-2` as the logger name. + +For example to use "fooRoute" as the route id, you can do: + +[source,java] +---- +from("direct:start").routeId("fooRoute") + .log("Processing ${id}") + .to("bean:foo"); +---- + +And in XML: + +[source,xml] +---- +<route id="fooRoute"> + <from uri="direct:start"/> + <log message="Processing ${id}"/> + <to uri="bean:foo"/> +</route> +---- + +==== Using custom logger from the Registry + +If the Log EIP has not been configured with a specific logger to use, +then Camel will will lookup in the xref:latest@manual:ROOT:registry.adoc[Registry] +if there is a single instance of `org.slf4j.Logger`. + +If such an instance exists then this logger is used, +if not the behavior defaults to creating a new instance of logger. -If no logger name or logger instance is passed to log DSL, -there is a Registry lookup performed to find single instance of org.slf4j.Logger. -If such an instance is found, it is used instead of creating a new logger instance. -If more instances are found, the behavior defaults to creating a new instance of logger. +=== Configuring logging name globally -== Configuring log name globally +You can configure a global log name that is used instead of the route id, +by setting the global option on the `CamelContext`. -By default, the log name is the route id. If you want to use a different log name, you would need to configure the logName option. However if you have many logs and you want all of them to use the same log name, then you would need to set that logName option on all of them. +In Java you can do: -You can configure a global log name that is used instead of the route id, eg [source,java] ---- camelContext.getGlobalOptions().put(Exchange.LOG_EIP_NAME, "com.foo.myapp"); ---- -And in XML +And in XML: [source,xml] ---- -<camelContext ...> +<camelContext> <properties> <property key="CamelLogEipName" value="com.foo.myapp"/> </properties> </camelContext> ---- -== Using slf4j Marker - -You can specify a marker name in the DSL -[source,xml] ----- -<route id="baz"> - <from uri="direct:baz"/> - <log loggingLevel="FATAL" logName="com.mycompany.MyCoolRoute" marker="myMarker" - message="Me Got ${body}"/> - <to uri="mock:baz"/> -</route> ----- - == Masking sensitive information like password You can enable security masking for logging by setting `logMask` flag to `true`. Note that this option also affects xref:components::log-component.adoc[Log] component. To enable mask in Java DSL at CamelContext level: + [source,java] ---- camelContext.setLogMask(true); ---- -And in XML: -[source,java] +And in XML you set the option on `<camelContext>`: + +[source,xml] ---- <camelContext logMask="true"> -... + </camelContext> ---- You can also turn it on|off at route level. To enable mask in Java DSL at route level: + [source,java] ---- from("direct:start").logMask() @@ -187,10 +216,11 @@ from("direct:start").logMask() ---- And in XML: -[source,java] + +[source,xml] ---- <route logMask="true"> -... + </route> ---- diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/loop-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/loop-eip.adoc index f758b4b..6c57e5a 100644 --- a/core/camel-core-engine/src/main/docs/modules/eips/pages/loop-eip.adoc +++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/loop-eip.adoc @@ -5,13 +5,7 @@ :since: :supportlevel: Stable -The Loop allows for processing a message a number of times, possibly in a different way for each iteration. Useful mostly during testing. - -[NOTE] -.Default mode -=== -Notice by default the loop uses the same exchange throughout the looping. So the result from the previous iteration will be used for the next (eg Pipes and Filters). You can enable copy mode instead. See the options table for more details. -=== +The Loop EIP allows for processing a message a number of times, possibly in a different way for each iteration. Useful mostly during testing. == Options @@ -19,22 +13,43 @@ Notice by default the loop uses the same exchange throughout the looping. So the include::partial$eip-options.adoc[] // eip options: END - == Exchange properties -For each iteration two properties are set on the Exchange. Processors can rely on these properties to process the Message in different ways. +For each iteration two properties are set on the `Exchange`. +Processors can rely on these properties to process the message in different ways. -[width="100%",cols="3,6",options="header"] +[width="100%",cols="3m,6",options="header"] |=== | Property | Description -| CamelLoopSize | Total number of loops. This is not available if running the loop in while loop mode. -| CamelLoopIndex | Index of the current iteration (0 based) +| Exchange.LOOP_SIZE | Total number of loops. This is not available if running the loop in while loop mode. +| Exchange.LOOP_INDEX | Index of the current iteration (0 based) |=== -== Samples -The following example shows how to take a request from the *direct:x* endpoint, then send the message repetitively to *mock:result*. The number of times the message is sent is either passed as an argument to `loop()`, or determined at runtime by evaluating an expression. The expression *must* evaluate to an int, otherwise a `RuntimeCamelException` is thrown. +== Looping modes + +The Loop EIP can run in three modes: default, or copy. + +In default mode the Loop EIP uses the same `Exchange` instance throughout the looping. +So the result from the previous iteration will be used for the next iteration. + +In the copy mode, then the Loop EIP uses a copy of the original `Exchange` in each iteration. +So the result from the previous iteration will *not* be used for the next iteration. + +In the doWhile mode, the Loop EIP + +== Example + +The following example shows how to take a request from the direct:x endpoint, +then send the message repetitively to mock:result. + +The number of times the message is sent is either passed as an argument to `loop`, +or determined at runtime by evaluating an expression. + +The xref:latest@manual:ROOT:expression.adoc[Expression] *must* evaluate to an `int`, +otherwise a `RuntimeCamelException` is thrown. + +Pass loop count as an argument: -Pass loop count as an argument [source,java] ---- from("direct:a") @@ -42,7 +57,8 @@ from("direct:a") .to("mock:result"); ---- -Use expression to determine loop count +Use expression to determine loop count: + [source,java] ---- from("direct:b") @@ -50,7 +66,8 @@ from("direct:b") .to("mock:result"); ---- -Use expression to determine loop count +And with the xref:components:languages:xpath-language.adoc[XPath] language: + [source,java] ---- from("direct:c") @@ -58,9 +75,10 @@ from("direct:c") .to("mock:result"); ---- -And examples in XML: +And in XML: Pass loop count as an argument + [source,xml] ---- <route> @@ -73,6 +91,7 @@ Pass loop count as an argument ---- Use expression to determine loop count + [source,xml] ---- <route> @@ -86,8 +105,8 @@ Use expression to determine loop count == Using copy mode -Now suppose we send a message to "direct:start" endpoint containing the letter A. + -The output of processing this route will be that, each "mock:loop" endpoint will receive "AB" as message. +Now suppose we send a message to direct:start endpoint containing the letter A. +The output of processing this route will be that, each mock:loop endpoint will receive AB as message. [source,java] ---- @@ -101,19 +120,7 @@ from("direct:start") .to("mock:result"); ---- -However if we do *not* enable copy mode then "mock:loop" will receive "AB", "ABB", "ABBB", etc. messages. - -[source,java] ----- -from("direct:start") - // by default loop will keep using the same exchange so on the 2nd and 3rd iteration its - // the same exchange that was previous used that are being looped all over - .loop(3) - .transform(body().append("B")) - .to("mock:loop") - .end() // end loop - .to("mock:result"); ----- +However, if we do *not* enable copy mode then mock:loop will receive "AB", "ABB", "ABBB", etc. messages. The equivalent example in XML DSL in copy mode is as follows: @@ -133,10 +140,12 @@ The equivalent example in XML DSL in copy mode is as follows: </route> ---- -== Using while mode +== Looping using while + +The loop can act like a while loop that loops until the expression evaluates to `false` or `null`. -The loop can act like a while loop that loops until the expression evaluates to false or null. + -For example the route below loops while the length of the message body is 5 or less characters. Notice that the DSL uses *loopDoWhile*. +For example the route below loops while the length of the message body is 5 or fewer characters. +Notice that the DSL uses `loopDoWhile`. [source,java] ---- @@ -149,6 +158,7 @@ from("direct:start") ---- And the same example in XML: + [source,xml] ---- <route> @@ -164,4 +174,4 @@ And the same example in XML: </route> ---- -Notice in XML that the while loop is turned on using the *doWhile* attribute. +Notice in XML that the while loop is turned on using the `doWhile` attribute.