You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by or...@apache.org on 2024/02/08 14:22:32 UTC

(camel) branch main updated (d610743ccc9 -> 22151ef9e2a)

This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


    from d610743ccc9 CAMEL-20396: Enable KuduClient to be autowired
     new 4ecae317229 CAMEL-20355: refactor the throttle definition
     new 046c88ef95d CAMEL-20355: refactor the throttle tests
     new bbf8a54414d CAMEL-20355: refactor the throttler
     new 22151ef9e2a CAMEL-20355: enable multiple throttling modes

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/camel/catalog/models/throttle.json  |  12 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  24 ++
 .../spring/processor/SpringThrottlerTest.java      |   4 +-
 .../SpringThrottlerGroupingTest.java               |   4 +-
 .../SpringThrottlerMethodCallTest.java             |   4 +-
 .../SpringThrottlerThreadPoolProfileTest.java      |   4 +-
 .../SpringThrottlingInflightRoutePolicyTest.java   |   4 +-
 .../spring/processor/ThrottlerGroupingTest.xml     |   4 +-
 .../spring/processor/ThrottlerMethodCallTest.xml   |   2 +-
 .../main/docs/modules/eips/pages/throttle-eip.adoc |  74 ++++
 .../resources/org/apache/camel/model/jaxb.index    |   1 +
 .../resources/org/apache/camel/model/throttle.json |  12 +-
 .../apache/camel/model/ProcessorDefinition.java    |   1 -
 .../org/apache/camel/model/ThrottleDefinition.java | 165 +++++++-
 .../org/apache/camel/model/ThrottlingMode.java}    |  33 +-
 .../apache/camel/processor/AbstractThrottler.java  | 153 +++++++
 ...ttler.java => ConcurrentRequestsThrottler.java} | 121 +-----
 .../java/org/apache/camel/processor/Throttler.java | 459 +--------------------
 .../camel/processor/TotalRequestsThrottler.java    | 388 +++++++++++++++++
 .../org/apache/camel/reifier/ThrottleReifier.java  |  41 +-
 .../ThrottlerInvalidConfiguredTest.java            |   2 +-
 .../{ => throttle}/ThrottlerNullEvalTest.java      |   2 +-
 .../{ => throttle}/ThrottlerPermitTest.java        |   2 +-
 .../ThrottlerThreadPoolProfileTest.java            |   2 +-
 .../{ => throttle}/ThrottlingException.java        |   2 +-
 ...xceptionRoutePolicyHalfOpenHandlerSedaTest.java |   2 +-
 ...ingExceptionRoutePolicyHalfOpenHandlerTest.java |   2 +-
 ...ThrottlingExceptionRoutePolicyHalfOpenTest.java |   2 +-
 ...lingExceptionRoutePolicyKeepOpenOnInitTest.java |   2 +-
 ...tlingExceptionRoutePolicyOpenViaConfigTest.java |   2 +-
 .../ThrottlingExceptionRoutePolicyTest.java        |   2 +-
 .../ThrottlingInflightRoutePolicyTest.java         |   2 +-
 .../ConcurrentRequestsThrottlerTest.java}          |  16 +-
 .../ThrottlerAsyncDelayedCallerRunsTest.java       |   4 +-
 .../concurrent}/ThrottlerAsyncDelayedTest.java     |   8 +-
 .../concurrent}/ThrottlerMethodCallTest.java       |   5 +-
 .../concurrent}/ThrottlingGroupingTest.java        |  13 +-
 .../ThrottlerAsyncDelayedCallerRunsTest.java       |   4 +-
 .../requests}/ThrottlerAsyncDelayedTest.java       |   6 +-
 .../{ => throttle/requests}/ThrottlerDslTest.java  |  11 +-
 .../{ => throttle/requests}/ThrottlerTest.java     | 190 ++++-----
 .../requests}/ThrottlingGroupingTest.java          | 167 ++++----
 .../management/mbean/ManagedThrottlerMBean.java    |  13 +-
 .../camel/management/mbean/ManagedThrottler.java   |  35 +-
 ...Test.java => AbstractManagedThrottlerTest.java} |  83 +---
 .../management/ManagedConcurrentThrottlerTest.java | 107 +++++
 .../camel/management/ManagedThrottlerTest.java     | 228 +---------
 .../java/org/apache/camel/xml/in/ModelParser.java  |   2 +
 .../java/org/apache/camel/xml/out/ModelWriter.java |   2 +
 .../org/apache/camel/yaml/out/ModelWriter.java     |   2 +
 .../ROOT/pages/camel-4x-upgrade-guide-4_4.adoc     |  16 +
 .../dsl/yaml/deserializers/ModelDeserializers.java |  14 +-
 .../generated/resources/schema/camelYamlDsl.json   |  13 +
 53 files changed, 1334 insertions(+), 1139 deletions(-)
 rename components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/{ => throttle}/SpringThrottlerGroupingTest.java (94%)
 rename components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/{ => throttle}/SpringThrottlerMethodCallTest.java (90%)
 rename components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/{ => throttle}/SpringThrottlerThreadPoolProfileTest.java (90%)
 rename components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/{ => throttle}/SpringThrottlingInflightRoutePolicyTest.java (90%)
 copy core/{camel-core/src/test/java/org/apache/camel/processor/ThrottlingException.java => camel-core-model/src/main/java/org/apache/camel/model/ThrottlingMode.java} (53%)
 create mode 100644 core/camel-core-processor/src/main/java/org/apache/camel/processor/AbstractThrottler.java
 copy core/camel-core-processor/src/main/java/org/apache/camel/processor/{Throttler.java => ConcurrentRequestsThrottler.java} (78%)
 create mode 100644 core/camel-core-processor/src/main/java/org/apache/camel/processor/TotalRequestsThrottler.java
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlerInvalidConfiguredTest.java (97%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlerNullEvalTest.java (98%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlerPermitTest.java (98%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlerThreadPoolProfileTest.java (97%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingException.java (96%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java (99%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java (99%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyHalfOpenTest.java (99%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java (98%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java (98%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingExceptionRoutePolicyTest.java (99%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle}/ThrottlingInflightRoutePolicyTest.java (97%)
 copy core/camel-core/src/test/java/org/apache/camel/processor/{ThrottlerTest.java => throttle/concurrent/ConcurrentRequestsThrottlerTest.java} (93%)
 copy core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/concurrent}/ThrottlerAsyncDelayedCallerRunsTest.java (91%)
 copy core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/concurrent}/ThrottlerAsyncDelayedTest.java (87%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/concurrent}/ThrottlerMethodCallTest.java (95%)
 copy core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/concurrent}/ThrottlingGroupingTest.java (94%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/requests}/ThrottlerAsyncDelayedCallerRunsTest.java (92%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/requests}/ThrottlerAsyncDelayedTest.java (89%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/requests}/ThrottlerDslTest.java (88%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/requests}/ThrottlerTest.java (52%)
 rename core/camel-core/src/test/java/org/apache/camel/processor/{ => throttle/requests}/ThrottlingGroupingTest.java (55%)
 copy core/camel-management/src/test/java/org/apache/camel/management/{ManagedThrottlerTest.java => AbstractManagedThrottlerTest.java} (73%)
 create mode 100644 core/camel-management/src/test/java/org/apache/camel/management/ManagedConcurrentThrottlerTest.java


(camel) 02/04: CAMEL-20355: refactor the throttle tests

Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 046c88ef95d90b0f4a57fd65a12b88e800cafd87
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Feb 6 13:47:17 2024 +0100

    CAMEL-20355: refactor the throttle tests
    
    Adjust code to facilitate accommodating more tests for throttling
---
 .../spring/processor/{ => throttle}/SpringThrottlerGroupingTest.java  | 4 ++--
 .../processor/{ => throttle}/SpringThrottlerMethodCallTest.java       | 4 ++--
 .../{ => throttle}/SpringThrottlerThreadPoolProfileTest.java          | 4 ++--
 .../{ => throttle}/SpringThrottlingInflightRoutePolicyTest.java       | 4 ++--
 .../org/apache/camel/spring/processor/ThrottlerGroupingTest.xml       | 4 ++--
 .../org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml     | 2 +-
 .../processor/{ => throttle}/ThrottlerAsyncDelayedCallerRunsTest.java | 2 +-
 .../camel/processor/{ => throttle}/ThrottlerAsyncDelayedTest.java     | 2 +-
 .../org/apache/camel/processor/{ => throttle}/ThrottlerDslTest.java   | 2 +-
 .../processor/{ => throttle}/ThrottlerInvalidConfiguredTest.java      | 2 +-
 .../camel/processor/{ => throttle}/ThrottlerMethodCallTest.java       | 2 +-
 .../apache/camel/processor/{ => throttle}/ThrottlerNullEvalTest.java  | 2 +-
 .../apache/camel/processor/{ => throttle}/ThrottlerPermitTest.java    | 2 +-
 .../processor/{ => throttle}/ThrottlerThreadPoolProfileTest.java      | 2 +-
 .../apache/camel/processor/{ => throttle}/ThrottlingException.java    | 2 +-
 .../ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java        | 2 +-
 .../ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java            | 2 +-
 .../{ => throttle}/ThrottlingExceptionRoutePolicyHalfOpenTest.java    | 2 +-
 .../ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java             | 2 +-
 .../ThrottlingExceptionRoutePolicyOpenViaConfigTest.java              | 2 +-
 .../processor/{ => throttle}/ThrottlingExceptionRoutePolicyTest.java  | 2 +-
 .../apache/camel/processor/{ => throttle}/ThrottlingGroupingTest.java | 2 +-
 .../processor/{ => throttle}/ThrottlingInflightRoutePolicyTest.java   | 2 +-
 23 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerGroupingTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
similarity index 95%
rename from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerGroupingTest.java
rename to components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
index e0875bc6e0c..fe8364825b5 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerGroupingTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor;
+package org.apache.camel.spring.processor.throttle;
 
 import java.util.concurrent.Semaphore;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.ThrottlingGroupingTest;
+import org.apache.camel.processor.throttle.ThrottlingGroupingTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerMethodCallTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
similarity index 91%
rename from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerMethodCallTest.java
rename to components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
index ebb4e101edf..2b457f2dde5 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerMethodCallTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
@@ -14,10 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor;
+package org.apache.camel.spring.processor.throttle;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.processor.ThrottlerMethodCallTest;
+import org.apache.camel.processor.throttle.ThrottlerMethodCallTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerThreadPoolProfileTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerThreadPoolProfileTest.java
similarity index 90%
rename from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerThreadPoolProfileTest.java
rename to components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerThreadPoolProfileTest.java
index bc77223237b..0a441018148 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerThreadPoolProfileTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerThreadPoolProfileTest.java
@@ -14,10 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor;
+package org.apache.camel.spring.processor.throttle;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.processor.ThrottlerThreadPoolProfileTest;
+import org.apache.camel.processor.throttle.ThrottlerThreadPoolProfileTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlingInflightRoutePolicyTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlingInflightRoutePolicyTest.java
similarity index 90%
rename from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlingInflightRoutePolicyTest.java
rename to components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlingInflightRoutePolicyTest.java
index 97547b64d29..28c39cd8835 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlingInflightRoutePolicyTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlingInflightRoutePolicyTest.java
@@ -14,10 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor;
+package org.apache.camel.spring.processor.throttle;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.processor.ThrottlingInflightRoutePolicyTest;
+import org.apache.camel.processor.throttle.ThrottlingInflightRoutePolicyTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerGroupingTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerGroupingTest.xml
index 6d9c52eb36e..d8a28cec2b9 100644
--- a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerGroupingTest.xml
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerGroupingTest.xml
@@ -23,8 +23,8 @@
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
     ">
-  <bean id="incrementProcessor" class="org.apache.camel.spring.processor.SpringThrottlerGroupingTest$IncrementProcessor"/>
-  <bean id="decrementProcessor" class="org.apache.camel.spring.processor.SpringThrottlerGroupingTest$DecrementProcessor"/>
+  <bean id="incrementProcessor" class="org.apache.camel.spring.processor.throttle.SpringThrottlerGroupingTest$IncrementProcessor"/>
+  <bean id="decrementProcessor" class="org.apache.camel.spring.processor.throttle.SpringThrottlerGroupingTest$DecrementProcessor"/>
 
   <camelContext xmlns="http://camel.apache.org/schema/spring">
     <jmxAgent id="jmx" disabled="true"/>
diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml
index c65ea463e4a..d23d5a4bcd2 100644
--- a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml
+++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml
@@ -24,7 +24,7 @@
        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
     ">
 
-  <bean id="myBean" class="org.apache.camel.spring.processor.SpringThrottlerMethodCallTest"/>
+  <bean id="myBean" class="org.apache.camel.spring.processor.throttle.SpringThrottlerMethodCallTest"/>
 
   <camelContext xmlns="http://camel.apache.org/schema/spring">
     <jmxAgent id="jmx" disabled="true"/>
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedCallerRunsTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedCallerRunsTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
index 1af2943081c..c42e8fcac11 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedCallerRunsTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
index 71adf7ea555..28c0bb8ebc9 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerAsyncDelayedTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerDslTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerDslTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java
index f93f7cd7424..d92b36f0e64 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerDslTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerInvalidConfiguredTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerInvalidConfiguredTest.java
similarity index 97%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerInvalidConfiguredTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerInvalidConfiguredTest.java
index 6338d11b719..eeee8ef98ce 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerInvalidConfiguredTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerInvalidConfiguredTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerMethodCallTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerMethodCallTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java
index 14aa716a72f..b4b525a28b0 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerMethodCallTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerNullEvalTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerNullEvalTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerNullEvalTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerNullEvalTest.java
index c05a1c8813d..b085c95f0ae 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerNullEvalTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerNullEvalTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerPermitTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerPermitTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerPermitTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerPermitTest.java
index 74342e10f8f..42067e51a01 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerPermitTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerPermitTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.concurrent.Delayed;
 import java.util.concurrent.TimeUnit;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerThreadPoolProfileTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerThreadPoolProfileTest.java
similarity index 97%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerThreadPoolProfileTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerThreadPoolProfileTest.java
index 9aa0344488a..9c824f11231 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerThreadPoolProfileTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerThreadPoolProfileTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingException.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingException.java
similarity index 96%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingException.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingException.java
index 2cabd7bbb9e..e077469f91b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingException.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingException.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 public class ThrottlingException extends RuntimeException {
 
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java
index e716b0e0ee1..a4c31a09e9a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerSedaTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java
index 2ed4dbc8f68..9acfa165f8f 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenHandlerTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenTest.java
index 42b63b05d70..22b8895449b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyHalfOpenTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyHalfOpenTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java
index b556a00c8ab..a349547fc6a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyKeepOpenOnInitTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java
similarity index 98%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java
index 7651ce1088f..adec9dd4566 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyOpenViaConfigTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyTest.java
index 41ac371ab12..390c4852424 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingExceptionRoutePolicyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingExceptionRoutePolicyTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingGroupingTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingGroupingTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
index 8639310ecdf..461b88deb65 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingGroupingTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingInflightRoutePolicyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingInflightRoutePolicyTest.java
similarity index 97%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingInflightRoutePolicyTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingInflightRoutePolicyTest.java
index e5c7ed377b5..71deb5bc52c 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlingInflightRoutePolicyTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingInflightRoutePolicyTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;


(camel) 01/04: CAMEL-20355: refactor the throttle definition

Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 4ecae317229bcd9ce471adb1af9c7029b3c7c647
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Feb 6 13:15:13 2024 +0100

    CAMEL-20355: refactor the throttle definition
    
    Adjust code to facilitate accommodating more than one throttling behavior
---
 .../org/apache/camel/catalog/models/throttle.json  |   2 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  | 224 +++++++--------
 .../spring/processor/SpringThrottlerTest.java      |   4 +-
 .../resources/org/apache/camel/model/jaxb.index    |   2 +-
 .../resources/org/apache/camel/model/throttle.json |   2 +-
 ...a => ConcurrentRequestsThrottleDefinition.java} |  37 +--
 .../apache/camel/model/ProcessorDefinition.java    |  22 +-
 ...java => ConcurrentRequestsThrottleReifier.java} |   8 +-
 .../org/apache/camel/reifier/ProcessorReifier.java |   6 +-
 ...t.java => ConcurrentRequestsThrottlerTest.java} |   2 +-
 ...> ManagedConcurrentRequestsThrottlerMBean.java} |   2 +-
 .../DefaultManagementObjectStrategy.java           |   4 +-
 ...ava => ManagedConcurrentRequestsThrottler.java} |   6 +-
 .../java/org/apache/camel/xml/in/ModelParser.java  |  84 +++---
 .../java/org/apache/camel/xml/out/ModelWriter.java |  42 +--
 .../org/apache/camel/yaml/out/ModelWriter.java     |  42 +--
 .../dsl/yaml/deserializers/ModelDeserializers.java | 208 +++++++-------
 .../deserializers/ModelDeserializersResolver.java  |   4 +-
 .../generated/resources/schema/camelYamlDsl.json   | 302 ++++++++++-----------
 .../org/apache/camel/dsl/yaml/ThrottleTest.groovy  |   4 +-
 20 files changed, 504 insertions(+), 503 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
index 7e029afb431..2eafa8ecd27 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
@@ -6,7 +6,7 @@
     "description": "Controls the rate at which messages are passed to the next node in the route",
     "deprecated": false,
     "label": "eip,routing",
-    "javaType": "org.apache.camel.model.ThrottleDefinition",
+    "javaType": "org.apache.camel.model.ConcurrentRequestsThrottleDefinition",
     "abstract": false,
     "input": true,
     "output": false
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 62a224fc6ac..2aa9009d28d 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -1995,7 +1995,7 @@ Serialize and deserialize messages using Apache Thrift binary data format.
       </xs:documentation>
     </xs:annotation>
   </xs:element>
-  <xs:element name="throttle" type="tns:throttleDefinition">
+  <xs:element name="throttle" type="tns:concurrentRequestsThrottleDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en">
 <![CDATA[
@@ -3531,6 +3531,7 @@ will fallback to use the fixed value if the Expression result was null or 0.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -3581,7 +3582,6 @@ will fallback to use the fixed value if the Expression result was null or 0.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4095,6 +4095,7 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4145,7 +4146,6 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4204,6 +4204,7 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4254,7 +4255,6 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4304,6 +4304,7 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4354,7 +4355,6 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4387,6 +4387,7 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4437,7 +4438,6 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4837,6 +4837,7 @@ References to a custom thread pool to use when bulkhead is enabled.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4887,7 +4888,6 @@ References to a custom thread pool to use when bulkhead is enabled.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4973,6 +4973,91 @@ strategy and configure data at the same time.
             <xs:documentation xml:lang="en">
 <![CDATA[
 This option can be used to explicit declare the method name to use, when using POJOs as the AggregationStrategy.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="concurrentRequestsThrottleDefinition">
+    <xs:complexContent>
+      <xs:extension base="tns:processorDefinition">
+        <xs:sequence>
+          <xs:choice>
+            <xs:element ref="tns:expressionDefinition"/>
+            <xs:element ref="tns:csimple"/>
+            <xs:element ref="tns:constant"/>
+            <xs:element ref="tns:datasonnet"/>
+            <xs:element ref="tns:exchangeProperty"/>
+            <xs:element ref="tns:groovy"/>
+            <xs:element ref="tns:header"/>
+            <xs:element ref="tns:hl7terser"/>
+            <xs:element ref="tns:java"/>
+            <xs:element ref="tns:js"/>
+            <xs:element ref="tns:joor"/>
+            <xs:element ref="tns:jq"/>
+            <xs:element ref="tns:jsonpath"/>
+            <xs:element ref="tns:language"/>
+            <xs:element ref="tns:method"/>
+            <xs:element ref="tns:mvel"/>
+            <xs:element ref="tns:ognl"/>
+            <xs:element ref="tns:python"/>
+            <xs:element ref="tns:ref"/>
+            <xs:element ref="tns:simple"/>
+            <xs:element ref="tns:spel"/>
+            <xs:element ref="tns:tokenize"/>
+            <xs:element ref="tns:variable"/>
+            <xs:element ref="tns:wasm"/>
+            <xs:element ref="tns:xtokenize"/>
+            <xs:element ref="tns:xpath"/>
+            <xs:element ref="tns:xquery"/>
+          </xs:choice>
+          <xs:element minOccurs="0" name="correlationExpression" type="tns:expressionSubElementDefinition">
+            <xs:annotation>
+              <xs:documentation xml:lang="en">
+<![CDATA[
+The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same
+correlation key is throttled together.
+]]>
+              </xs:documentation>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+        <xs:attribute name="executorService" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+To use a custom thread pool (ScheduledExecutorService) by the throttler.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="asyncDelayed" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Enables asynchronous delay which means the thread will not block while delaying. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="callerRunsWhenRejected" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true. Default
+value: true
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="rejectExecution" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is
+by default false. Default value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -5988,6 +6073,7 @@ Sets the logging level to use for logging transactional rollback. This option is
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6038,7 +6124,6 @@ Sets the logging level to use for logging transactional rollback. This option is
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6078,6 +6163,7 @@ predicate evaluated as true or false.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6128,7 +6214,6 @@ predicate evaluated as true or false.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6239,6 +6324,7 @@ Global option value.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6289,7 +6375,6 @@ Global option value.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6399,6 +6484,7 @@ Whether if validation is required for this input type. Default value: false
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6449,7 +6535,6 @@ Whether if validation is required for this input type. Default value: false
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6496,6 +6581,7 @@ intercepted.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6546,7 +6632,6 @@ intercepted.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6604,6 +6689,7 @@ After sending to the endpoint then send the message to this uri which allows to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6654,7 +6740,6 @@ After sending to the endpoint then send the message to this uri which allows to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6703,6 +6788,7 @@ mynamecount=4&type=gold.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6753,7 +6839,6 @@ mynamecount=4&type=gold.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -7016,6 +7101,7 @@ To refer to a custom logger instance to lookup from the registry.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -7066,7 +7152,6 @@ To refer to a custom logger instance to lookup from the registry.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10423,6 +10508,7 @@ maximum decompressed size. Default value: 1073741824
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10473,7 +10559,6 @@ maximum decompressed size. Default value: 1073741824
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10646,6 +10731,7 @@ controlling whether a completion callback should be invoked or not.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10696,7 +10782,6 @@ controlling whether a completion callback should be invoked or not.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10844,6 +10929,7 @@ its considered handled as well.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10894,7 +10980,6 @@ its considered handled as well.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11102,6 +11187,7 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11152,7 +11238,6 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11182,6 +11267,7 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11232,7 +11318,6 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11810,6 +11895,7 @@ Name of variable to remove.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11860,7 +11946,6 @@ Name of variable to remove.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -12158,6 +12243,7 @@ Reference to the routes in the xml dsl.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -12208,7 +12294,6 @@ Reference to the routes in the xml dsl.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -12593,6 +12678,7 @@ actions. Option values will be transformed into input headers of the compensatio
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -12643,7 +12729,6 @@ actions. Option values will be transformed into input headers of the compensatio
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13041,6 +13126,7 @@ Sets the comparator to use for sorting.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13091,7 +13177,6 @@ Sets the comparator to use for sorting.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13271,6 +13356,7 @@ individual unit of work. Default value: false
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13321,7 +13407,6 @@ individual unit of work. Default value: false
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13603,91 +13688,6 @@ Sets the handler for tasks which cannot be executed by the thread pool.
 Whether or not to use as caller runs as fallback when a task is rejected being added to the thread pool (when its full).
 This is only used as fallback if no rejectedPolicy has been configured, or the thread pool has no configured rejection
 handler. Is by default true. Default value: true
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="throttleDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:processorDefinition">
-        <xs:sequence>
-          <xs:choice>
-            <xs:element ref="tns:expressionDefinition"/>
-            <xs:element ref="tns:csimple"/>
-            <xs:element ref="tns:constant"/>
-            <xs:element ref="tns:datasonnet"/>
-            <xs:element ref="tns:exchangeProperty"/>
-            <xs:element ref="tns:groovy"/>
-            <xs:element ref="tns:header"/>
-            <xs:element ref="tns:hl7terser"/>
-            <xs:element ref="tns:java"/>
-            <xs:element ref="tns:js"/>
-            <xs:element ref="tns:joor"/>
-            <xs:element ref="tns:jq"/>
-            <xs:element ref="tns:jsonpath"/>
-            <xs:element ref="tns:language"/>
-            <xs:element ref="tns:method"/>
-            <xs:element ref="tns:mvel"/>
-            <xs:element ref="tns:ognl"/>
-            <xs:element ref="tns:python"/>
-            <xs:element ref="tns:ref"/>
-            <xs:element ref="tns:simple"/>
-            <xs:element ref="tns:spel"/>
-            <xs:element ref="tns:tokenize"/>
-            <xs:element ref="tns:variable"/>
-            <xs:element ref="tns:wasm"/>
-            <xs:element ref="tns:xtokenize"/>
-            <xs:element ref="tns:xpath"/>
-            <xs:element ref="tns:xquery"/>
-          </xs:choice>
-          <xs:element minOccurs="0" name="correlationExpression" type="tns:expressionSubElementDefinition">
-            <xs:annotation>
-              <xs:documentation xml:lang="en">
-<![CDATA[
-The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same
-correlation key is throttled together.
-]]>
-              </xs:documentation>
-            </xs:annotation>
-          </xs:element>
-        </xs:sequence>
-        <xs:attribute name="executorService" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-To use a custom thread pool (ScheduledExecutorService) by the throttler.
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="asyncDelayed" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Enables asynchronous delay which means the thread will not block while delaying. Default value: false
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="callerRunsWhenRejected" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true. Default
-value: true
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="rejectExecution" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is
-by default false. Default value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -13875,6 +13875,7 @@ Whether to auto startup components when toD is starting up. Default value: true
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13925,7 +13926,6 @@ Whether to auto startup components when toD is starting up. Default value: true
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -14017,6 +14017,7 @@ To type used as a target data type in the transformation.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -14067,7 +14068,6 @@ To type used as a target data type in the transformation.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
index 2decf020277..a999e23fb27 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
@@ -19,12 +19,12 @@ package org.apache.camel.spring.processor;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.ThrottlerTest;
+import org.apache.camel.processor.ConcurrentRequestsThrottlerTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-public class SpringThrottlerTest extends ThrottlerTest {
+public class SpringThrottlerTest extends ConcurrentRequestsThrottlerTest {
 
     @Override
     protected CamelContext createCamelContext() throws Exception {
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
index 9c0bf809648..dde2e549f44 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
@@ -6,6 +6,7 @@ ChoiceDefinition
 CircuitBreakerDefinition
 ClaimCheckDefinition
 ClaimCheckOperation
+ConcurrentRequestsThrottleDefinition
 ContextScanDefinition
 ConvertBodyDefinition
 ConvertHeaderDefinition
@@ -98,7 +99,6 @@ TemplatedRouteParameterDefinition
 TemplatedRoutesDefinition
 ThreadPoolProfileDefinition
 ThreadsDefinition
-ThrottleDefinition
 ThrowExceptionDefinition
 ToDefinition
 ToDynamicDefinition
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
index 7e029afb431..2eafa8ecd27 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
@@ -6,7 +6,7 @@
     "description": "Controls the rate at which messages are passed to the next node in the route",
     "deprecated": false,
     "label": "eip,routing",
-    "javaType": "org.apache.camel.model.ThrottleDefinition",
+    "javaType": "org.apache.camel.model.ConcurrentRequestsThrottleDefinition",
     "abstract": false,
     "input": true,
     "output": false
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java
similarity index 84%
rename from core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java
rename to core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java
index 2a7611997b4..024a5f9b10e 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java
@@ -38,7 +38,8 @@ import org.apache.camel.spi.Metadata;
 @XmlRootElement(name = "throttle")
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(propOrder = { "expression", "correlationExpression" })
-public class ThrottleDefinition extends ExpressionNode implements ExecutorServiceAwareDefinition<ThrottleDefinition> {
+public class ConcurrentRequestsThrottleDefinition
+        extends ExpressionNode implements ExecutorServiceAwareDefinition<ConcurrentRequestsThrottleDefinition> {
 
     @XmlTransient
     private ExecutorService executorServiceBean;
@@ -58,18 +59,18 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
     @Metadata(label = "advanced", javaType = "java.lang.Boolean")
     private String rejectExecution;
 
-    public ThrottleDefinition() {
+    public ConcurrentRequestsThrottleDefinition() {
     }
 
-    public ThrottleDefinition(Expression maximumConcurrentRequests) {
+    public ConcurrentRequestsThrottleDefinition(Expression maximumConcurrentRequests) {
         super(maximumConcurrentRequests);
     }
 
-    public ThrottleDefinition(Expression maximumConcurrentRequests, Expression correlationExpression) {
+    public ConcurrentRequestsThrottleDefinition(Expression maximumConcurrentRequests, Expression correlationExpression) {
         this(ExpressionNodeHelper.toExpressionDefinition(maximumConcurrentRequests), correlationExpression);
     }
 
-    private ThrottleDefinition(ExpressionDefinition maximumConcurrentRequests, Expression correlationExpression) {
+    private ConcurrentRequestsThrottleDefinition(ExpressionDefinition maximumConcurrentRequests, Expression correlationExpression) {
         super(maximumConcurrentRequests);
 
         ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition();
@@ -100,7 +101,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  maximumConcurrentRequests the maximum number of concurrent requests
      * @return                           the builder
      */
-    public ThrottleDefinition maximumConcurrentRequests(long maximumConcurrentRequests) {
+    public ConcurrentRequestsThrottleDefinition maximumConcurrentRequests(long maximumConcurrentRequests) {
         setExpression(
                 ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.constantExpression(maximumConcurrentRequests)));
         return this;
@@ -112,7 +113,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  maximumConcurrentRequests the maximum number of concurrent requests
      * @return                           the builder
      */
-    public ThrottleDefinition maximumConcurrentRequests(String maximumConcurrentRequests) {
+    public ConcurrentRequestsThrottleDefinition maximumConcurrentRequests(String maximumConcurrentRequests) {
         setExpression(
                 ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.simpleExpression(maximumConcurrentRequests)));
         return this;
@@ -125,7 +126,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      *                               overall throttling
      * @return                       the builder
      */
-    public ThrottleDefinition correlationExpression(long correlationExpression) {
+    public ConcurrentRequestsThrottleDefinition correlationExpression(long correlationExpression) {
         return correlationExpression(ExpressionBuilder.constantExpression(correlationExpression));
     }
 
@@ -136,7 +137,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      *                               overall throttling
      * @return                       the builder
      */
-    public ThrottleDefinition correlationExpression(Expression correlationExpression) {
+    public ConcurrentRequestsThrottleDefinition correlationExpression(Expression correlationExpression) {
         ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition();
         cor.setExpressionType(ExpressionNodeHelper.toExpressionDefinition(correlationExpression));
         setCorrelationExpression(cor);
@@ -151,7 +152,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  callerRunsWhenRejected whether or not the caller should run
      * @return                        the builder
      */
-    public ThrottleDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) {
+    public ConcurrentRequestsThrottleDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) {
         return callerRunsWhenRejected(Boolean.toString(callerRunsWhenRejected));
     }
 
@@ -163,7 +164,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  callerRunsWhenRejected whether or not the caller should run
      * @return                        the builder
      */
-    public ThrottleDefinition callerRunsWhenRejected(String callerRunsWhenRejected) {
+    public ConcurrentRequestsThrottleDefinition callerRunsWhenRejected(String callerRunsWhenRejected) {
         setCallerRunsWhenRejected(callerRunsWhenRejected);
         return this;
     }
@@ -173,7 +174,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      *
      * @return the builder
      */
-    public ThrottleDefinition asyncDelayed() {
+    public ConcurrentRequestsThrottleDefinition asyncDelayed() {
         return asyncDelayed(true);
     }
 
@@ -182,7 +183,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      *
      * @return the builder
      */
-    public ThrottleDefinition asyncDelayed(boolean asyncDelayed) {
+    public ConcurrentRequestsThrottleDefinition asyncDelayed(boolean asyncDelayed) {
         return asyncDelayed(Boolean.toString(asyncDelayed));
     }
 
@@ -191,7 +192,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      *
      * @return the builder
      */
-    public ThrottleDefinition asyncDelayed(String asyncDelayed) {
+    public ConcurrentRequestsThrottleDefinition asyncDelayed(String asyncDelayed) {
         setAsyncDelayed(asyncDelayed);
         return this;
     }
@@ -205,7 +206,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  rejectExecution throw the RejectExecutionException if the exchange exceeds the request limit
      * @return                 the builder
      */
-    public ThrottleDefinition rejectExecution(boolean rejectExecution) {
+    public ConcurrentRequestsThrottleDefinition rejectExecution(boolean rejectExecution) {
         return rejectExecution(Boolean.toString(rejectExecution));
     }
 
@@ -218,7 +219,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @param  rejectExecution throw the RejectExecutionException if the exchange exceeds the request limit
      * @return                 the builder
      */
-    public ThrottleDefinition rejectExecution(String rejectExecution) {
+    public ConcurrentRequestsThrottleDefinition rejectExecution(String rejectExecution) {
         setRejectExecution(rejectExecution);
         return this;
     }
@@ -230,7 +231,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @return                 the builder
      */
     @Override
-    public ThrottleDefinition executorService(ExecutorService executorService) {
+    public ConcurrentRequestsThrottleDefinition executorService(ExecutorService executorService) {
         this.executorServiceBean = executorService;
         return this;
     }
@@ -242,7 +243,7 @@ public class ThrottleDefinition extends ExpressionNode implements ExecutorServic
      * @return                 the builder
      */
     @Override
-    public ThrottleDefinition executorService(String executorService) {
+    public ConcurrentRequestsThrottleDefinition executorService(String executorService) {
         setExecutorService(executorService);
         return this;
     }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index f6a584ce6c9..82632eb1590 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -23,7 +23,6 @@ import java.util.Comparator;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
 import java.util.function.Supplier;
@@ -1804,8 +1803,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *
      * @return the builder
      */
-    public ExpressionClause<ThrottleDefinition> throttle() {
-        ThrottleDefinition answer = new ThrottleDefinition();
+    public ExpressionClause<ConcurrentRequestsThrottleDefinition> throttle() {
+        ConcurrentRequestsThrottleDefinition answer = new ConcurrentRequestsThrottleDefinition();
         addOutput(answer);
         return createAndSetExpression(answer);
     }
@@ -1821,7 +1820,7 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      * @param  maximumConcurrentRequests the maximum number of concurrent messages
      * @return                           the builder
      */
-    public ThrottleDefinition throttle(long maximumConcurrentRequests) {
+    public ConcurrentRequestsThrottleDefinition throttle(long maximumConcurrentRequests) {
         return throttle(ExpressionBuilder.constantExpression(maximumConcurrentRequests));
     }
 
@@ -1836,8 +1835,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      * @param  maximumConcurrentRequests an expression to calculate the maximum concurrent request count
      * @return                           the builder
      */
-    public ThrottleDefinition throttle(Expression maximumConcurrentRequests) {
-        ThrottleDefinition answer = new ThrottleDefinition(maximumConcurrentRequests);
+    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests) {
+        ConcurrentRequestsThrottleDefinition answer = new ConcurrentRequestsThrottleDefinition(maximumConcurrentRequests);
         addOutput(answer);
         return answer;
     }
@@ -1857,9 +1856,9 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *                                   throttling
      * @return                           the builder
      */
-    public ThrottleDefinition throttle(Expression maximumConcurrentRequests, long correlationExpressionKey) {
-        ThrottleDefinition answer
-                = new ThrottleDefinition(
+    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests, long correlationExpressionKey) {
+        ConcurrentRequestsThrottleDefinition answer
+                = new ConcurrentRequestsThrottleDefinition(
                         maximumConcurrentRequests, ExpressionBuilder.constantExpression(correlationExpressionKey));
         addOutput(answer);
         return answer;
@@ -1880,8 +1879,9 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *                                   instead of overall throttling
      * @return                           the builder
      */
-    public ThrottleDefinition throttle(Expression maximumConcurrentRequests, Expression correlationExpressionKey) {
-        ThrottleDefinition answer = new ThrottleDefinition(maximumConcurrentRequests, correlationExpressionKey);
+    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests, Expression correlationExpressionKey) {
+        ConcurrentRequestsThrottleDefinition
+                answer = new ConcurrentRequestsThrottleDefinition(maximumConcurrentRequests, correlationExpressionKey);
         addOutput(answer);
         return answer;
     }
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
similarity index 87%
rename from core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
rename to core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
index a046d0bf1c4..1910baa21a5 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
@@ -22,13 +22,13 @@ import org.apache.camel.Expression;
 import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.ThrottleDefinition;
+import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
 import org.apache.camel.processor.Throttler;
 
-public class ThrottleReifier extends ExpressionReifier<ThrottleDefinition> {
+public class ConcurrentRequestsThrottleReifier extends ExpressionReifier<ConcurrentRequestsThrottleDefinition> {
 
-    public ThrottleReifier(Route route, ProcessorDefinition<?> definition) {
-        super(route, (ThrottleDefinition) definition);
+    public ConcurrentRequestsThrottleReifier(Route route, ProcessorDefinition<?> definition) {
+        super(route, (ConcurrentRequestsThrottleDefinition) definition);
     }
 
     @Override
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index 32bbdb1aacd..cffd3d29fc9 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -98,7 +98,7 @@ import org.apache.camel.model.SplitDefinition;
 import org.apache.camel.model.StepDefinition;
 import org.apache.camel.model.StopDefinition;
 import org.apache.camel.model.ThreadsDefinition;
-import org.apache.camel.model.ThrottleDefinition;
+import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
 import org.apache.camel.model.ThrowExceptionDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.apache.camel.model.ToDynamicDefinition;
@@ -316,8 +316,8 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> extends
             return new StopReifier(route, definition);
         } else if (definition instanceof ThreadsDefinition) {
             return new ThreadsReifier(route, definition);
-        } else if (definition instanceof ThrottleDefinition) {
-            return new ThrottleReifier(route, definition);
+        } else if (definition instanceof ConcurrentRequestsThrottleDefinition) {
+            return new ConcurrentRequestsThrottleReifier(route, definition);
         } else if (definition instanceof ThrowExceptionDefinition) {
             return new ThrowExceptionReifier(route, definition);
         } else if (definition instanceof ToDefinition) {
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
similarity index 99%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
index b49770d1f13..7e458c91a1f 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ThrottlerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
@@ -36,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 // time-bound that does not run well in shared environments
 @DisabledOnOs(OS.WINDOWS)
 @DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com", disabledReason = "Flaky on Github CI")
-public class ThrottlerTest extends ContextTestSupport {
+public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
     private static final int INTERVAL = 500;
     private static final int MESSAGE_COUNT = 9;
     private static final int CONCURRENT_REQUESTS = 2;
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java
similarity index 94%
rename from core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java
rename to core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java
index 95d5452693f..aa6d8129873 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java
@@ -18,7 +18,7 @@ package org.apache.camel.api.management.mbean;
 
 import org.apache.camel.api.management.ManagedAttribute;
 
-public interface ManagedThrottlerMBean extends ManagedProcessorMBean {
+public interface ManagedConcurrentRequestsThrottlerMBean extends ManagedProcessorMBean {
 
     @ManagedAttribute(description = "Maximum concurrent requests")
     long getMaximumConcurrentRequests();
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
index 6945ddacc43..c9854b97f6a 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
@@ -100,7 +100,7 @@ import org.apache.camel.management.mbean.ManagedSupervisingRouteController;
 import org.apache.camel.management.mbean.ManagedSuspendableRoute;
 import org.apache.camel.management.mbean.ManagedThreadPool;
 import org.apache.camel.management.mbean.ManagedThreads;
-import org.apache.camel.management.mbean.ManagedThrottler;
+import org.apache.camel.management.mbean.ManagedConcurrentRequestsThrottler;
 import org.apache.camel.management.mbean.ManagedThroughputLogger;
 import org.apache.camel.management.mbean.ManagedThrowException;
 import org.apache.camel.management.mbean.ManagedTopicLoadBalancer;
@@ -378,7 +378,7 @@ public class DefaultManagementObjectStrategy implements ManagementObjectStrategy
             } else if (target instanceof FinallyProcessor) {
                 answer = new ManagedDoFinally(context, (FinallyProcessor) target, (FinallyDefinition) definition);
             } else if (target instanceof Throttler) {
-                answer = new ManagedThrottler(context, (Throttler) target, definition);
+                answer = new ManagedConcurrentRequestsThrottler(context, (Throttler) target, definition);
             } else if (target instanceof DynamicRouter) {
                 answer = new ManagedDynamicRouter(context, (DynamicRouter) target, (DynamicRouterDefinition) definition);
             } else if (target instanceof RoutingSlip) {
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
similarity index 85%
rename from core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java
rename to core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
index 2abb6a14f16..e54766c3454 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
@@ -18,17 +18,17 @@ package org.apache.camel.management.mbean;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.ManagedThrottlerMBean;
+import org.apache.camel.api.management.mbean.ManagedConcurrentRequestsThrottlerMBean;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.processor.Throttler;
 
 import static org.apache.camel.builder.Builder.constant;
 
 @ManagedResource(description = "Managed Throttler")
-public class ManagedThrottler extends ManagedProcessor implements ManagedThrottlerMBean {
+public class ManagedConcurrentRequestsThrottler extends ManagedProcessor implements ManagedConcurrentRequestsThrottlerMBean {
     private final Throttler throttler;
 
-    public ManagedThrottler(CamelContext context, Throttler throttler, ProcessorDefinition<?> definition) {
+    public ManagedConcurrentRequestsThrottler(CamelContext context, Throttler throttler, ProcessorDefinition<?> definition) {
         super(context, throttler, definition);
         this.throttler = throttler;
     }
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 8c571ce7cf2..a3413fb4490 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -285,6 +285,47 @@ public class ModelParser extends BaseParser {
             return true;
         }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
     }
+    protected ConcurrentRequestsThrottleDefinition doParseConcurrentRequestsThrottleDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ConcurrentRequestsThrottleDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "asyncDelayed": def.setAsyncDelayed(val); break;
+                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+                case "executorService": def.setExecutorService(val); break;
+                case "rejectExecution": def.setRejectExecution(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("correlationExpression".equals(key)) {
+                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+                return true;
+            }
+            return expressionNodeElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
+    protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
+        return (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpression(v);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        };
+    }
+    protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "id": def.setId(val); break;
+                case "trim": def.setTrim(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(),  noElementHandler(), expressionDefinitionValueHandler());
+    }
     protected ContextScanDefinition doParseContextScanDefinition() throws IOException, XmlPullParserException {
         return doParse(new ContextScanDefinition(), (def, key, val) -> {
             if ("includeNonSingletons".equals(key)) {
@@ -362,29 +403,6 @@ public class ModelParser extends BaseParser {
             return true;
         }, expressionNodeElementHandler(), noValueHandler());
     }
-    protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
-        return (def, key) -> {
-            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
-            if (v != null) { 
-                def.setExpression(v);
-                return true;
-            }
-            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
-        };
-    }
-    protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
-        return (def, key, val) -> {
-            switch (key) {
-                case "id": def.setId(val); break;
-                case "trim": def.setTrim(val); break;
-                default: return false;
-            }
-            return true;
-        };
-    }
-    protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
-        return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(),  noElementHandler(), expressionDefinitionValueHandler());
-    }
     protected DynamicRouterDefinition doParseDynamicRouterDefinition() throws IOException, XmlPullParserException {
         return doParse(new DynamicRouterDefinition(), (def, key, val) -> {
             switch (key) {
@@ -1506,24 +1524,6 @@ public class ModelParser extends BaseParser {
             return true;
         }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
     }
-    protected ThrottleDefinition doParseThrottleDefinition() throws IOException, XmlPullParserException {
-        return doParse(new ThrottleDefinition(), (def, key, val) -> {
-            switch (key) {
-                case "asyncDelayed": def.setAsyncDelayed(val); break;
-                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
-                case "executorService": def.setExecutorService(val); break;
-                case "rejectExecution": def.setRejectExecution(val); break;
-                default: return processorDefinitionAttributeHandler().accept(def, key, val);
-            }
-            return true;
-        }, (def, key) -> {
-            if ("correlationExpression".equals(key)) {
-                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
-                return true;
-            }
-            return expressionNodeElementHandler().accept(def, key);
-        }, noValueHandler());
-    }
     protected ThrowExceptionDefinition doParseThrowExceptionDefinition() throws IOException, XmlPullParserException {
         return doParse(new ThrowExceptionDefinition(), (def, key, val) -> {
             switch (key) {
@@ -3506,6 +3506,7 @@ public class ModelParser extends BaseParser {
             case "circuitBreaker": return doParseCircuitBreakerDefinition();
             case "onFallback": return doParseOnFallbackDefinition();
             case "claimCheck": return doParseClaimCheckDefinition();
+            case "throttle": return doParseConcurrentRequestsThrottleDefinition();
             case "convertBodyTo": return doParseConvertBodyDefinition();
             case "convertHeaderTo": return doParseConvertHeaderDefinition();
             case "convertVariableTo": return doParseConvertVariableDefinition();
@@ -3556,7 +3557,6 @@ public class ModelParser extends BaseParser {
             case "step": return doParseStepDefinition();
             case "stop": return doParseStopDefinition();
             case "threads": return doParseThreadsDefinition();
-            case "throttle": return doParseThrottleDefinition();
             case "throwException": return doParseThrowExceptionDefinition();
             case "to": return doParseToDefinition();
             case "toD": return doParseToDynamicDefinition();
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index 709a3f77709..f35dd601a5c 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -73,6 +73,11 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         doWriteClaimCheckDefinition("claimCheck", def);
     }
+    public void writeConcurrentRequestsThrottleDefinition(
+            ConcurrentRequestsThrottleDefinition def)
+            throws IOException {
+        doWriteConcurrentRequestsThrottleDefinition("throttle", def);
+    }
     public void writeContextScanDefinition(
             ContextScanDefinition def)
             throws IOException {
@@ -451,11 +456,6 @@ public class ModelWriter extends BaseWriter {
     public void writeThreadsDefinition(ThreadsDefinition def) throws IOException {
         doWriteThreadsDefinition("threads", def);
     }
-    public void writeThrottleDefinition(
-            ThrottleDefinition def)
-            throws IOException {
-        doWriteThrottleDefinition("throttle", def);
-    }
     public void writeThrowExceptionDefinition(
             ThrowExceptionDefinition def)
             throws IOException {
@@ -1171,6 +1171,20 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("key", def.getKey());
         endElement(name);
     }
+    protected void doWriteConcurrentRequestsThrottleDefinition(
+            String name,
+            ConcurrentRequestsThrottleDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteProcessorDefinitionAttributes(def);
+        doWriteAttribute("rejectExecution", def.getRejectExecution());
+        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
+        doWriteAttribute("executorService", def.getExecutorService());
+        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
+        doWriteExpressionNodeElements(def);
+        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
+        endElement(name);
+    }
     protected void doWriteContextScanDefinition(
             String name,
             ContextScanDefinition def)
@@ -2414,20 +2428,6 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("timeUnit", def.getTimeUnit());
         endElement(name);
     }
-    protected void doWriteThrottleDefinition(
-            String name,
-            ThrottleDefinition def)
-            throws IOException {
-        startElement(name);
-        doWriteProcessorDefinitionAttributes(def);
-        doWriteAttribute("rejectExecution", def.getRejectExecution());
-        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
-        doWriteAttribute("executorService", def.getExecutorService());
-        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
-        doWriteExpressionNodeElements(def);
-        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
-        endElement(name);
-    }
     protected void doWriteThrowExceptionDefinition(
             String name,
             ThrowExceptionDefinition def)
@@ -4853,6 +4853,7 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
+                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -4915,7 +4916,6 @@ public class ModelWriter extends BaseWriter {
                 case "TemplatedRoutesDefinition" -> doWriteTemplatedRoutesDefinition("templatedRoutes", (TemplatedRoutesDefinition) v);
                 case "ThreadPoolProfileDefinition" -> doWriteThreadPoolProfileDefinition("threadPoolProfile", (ThreadPoolProfileDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
-                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
@@ -4961,6 +4961,7 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
+                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -5013,7 +5014,6 @@ public class ModelWriter extends BaseWriter {
                 case "StepDefinition" -> doWriteStepDefinition("step", (StepDefinition) v);
                 case "StopDefinition" -> doWriteStopDefinition("stop", (StopDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
-                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index ef72bc4447a..684ec6e965e 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -73,6 +73,11 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         doWriteClaimCheckDefinition("claimCheck", def);
     }
+    public void writeConcurrentRequestsThrottleDefinition(
+            ConcurrentRequestsThrottleDefinition def)
+            throws IOException {
+        doWriteConcurrentRequestsThrottleDefinition("throttle", def);
+    }
     public void writeContextScanDefinition(
             ContextScanDefinition def)
             throws IOException {
@@ -451,11 +456,6 @@ public class ModelWriter extends BaseWriter {
     public void writeThreadsDefinition(ThreadsDefinition def) throws IOException {
         doWriteThreadsDefinition("threads", def);
     }
-    public void writeThrottleDefinition(
-            ThrottleDefinition def)
-            throws IOException {
-        doWriteThrottleDefinition("throttle", def);
-    }
     public void writeThrowExceptionDefinition(
             ThrowExceptionDefinition def)
             throws IOException {
@@ -1171,6 +1171,20 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("key", def.getKey());
         endElement(name);
     }
+    protected void doWriteConcurrentRequestsThrottleDefinition(
+            String name,
+            ConcurrentRequestsThrottleDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteProcessorDefinitionAttributes(def);
+        doWriteAttribute("rejectExecution", def.getRejectExecution());
+        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
+        doWriteAttribute("executorService", def.getExecutorService());
+        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
+        doWriteExpressionNodeElements(def);
+        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
+        endElement(name);
+    }
     protected void doWriteContextScanDefinition(
             String name,
             ContextScanDefinition def)
@@ -2414,20 +2428,6 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("timeUnit", def.getTimeUnit());
         endElement(name);
     }
-    protected void doWriteThrottleDefinition(
-            String name,
-            ThrottleDefinition def)
-            throws IOException {
-        startElement(name);
-        doWriteProcessorDefinitionAttributes(def);
-        doWriteAttribute("rejectExecution", def.getRejectExecution());
-        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
-        doWriteAttribute("executorService", def.getExecutorService());
-        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
-        doWriteExpressionNodeElements(def);
-        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
-        endElement(name);
-    }
     protected void doWriteThrowExceptionDefinition(
             String name,
             ThrowExceptionDefinition def)
@@ -4853,6 +4853,7 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
+                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -4915,7 +4916,6 @@ public class ModelWriter extends BaseWriter {
                 case "TemplatedRoutesDefinition" -> doWriteTemplatedRoutesDefinition("templatedRoutes", (TemplatedRoutesDefinition) v);
                 case "ThreadPoolProfileDefinition" -> doWriteThreadPoolProfileDefinition("threadPoolProfile", (ThreadPoolProfileDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
-                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
@@ -4961,6 +4961,7 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
+                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -5013,7 +5014,6 @@ public class ModelWriter extends BaseWriter {
                 case "StepDefinition" -> doWriteStepDefinition("step", (StepDefinition) v);
                 case "StopDefinition" -> doWriteStopDefinition("stop", (StopDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
-                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index bba7f181965..c342c740ddc 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -16,6 +16,7 @@ import org.apache.camel.model.CatchDefinition;
 import org.apache.camel.model.ChoiceDefinition;
 import org.apache.camel.model.CircuitBreakerDefinition;
 import org.apache.camel.model.ClaimCheckDefinition;
+import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
 import org.apache.camel.model.ContextScanDefinition;
 import org.apache.camel.model.ConvertBodyDefinition;
 import org.apache.camel.model.ConvertHeaderDefinition;
@@ -90,7 +91,6 @@ import org.apache.camel.model.StopDefinition;
 import org.apache.camel.model.TemplatedRouteParameterDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
 import org.apache.camel.model.ThreadsDefinition;
-import org.apache.camel.model.ThrottleDefinition;
 import org.apache.camel.model.ThrowExceptionDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.apache.camel.model.ToDynamicDefinition;
@@ -2344,6 +2344,109 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
+    @YamlType(
+            nodes = "throttle",
+            types = org.apache.camel.model.ConcurrentRequestsThrottleDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            displayName = "Throttle",
+            description = "Controls the rate at which messages are passed to the next node in the route",
+            deprecated = false,
+            properties = {
+                    @YamlProperty(name = "__extends", type = "object:org.apache.camel.model.language.ExpressionDefinition", oneOf = "expression"),
+                    @YamlProperty(name = "asyncDelayed", type = "boolean", description = "Enables asynchronous delay which means the thread will not block while delaying.", displayName = "Async Delayed"),
+                    @YamlProperty(name = "callerRunsWhenRejected", type = "boolean", description = "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true", displayName = "Caller Runs When Rejected"),
+                    @YamlProperty(name = "correlationExpression", type = "object:org.apache.camel.model.ExpressionSubElementDefinition", description = "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.", displayName = "Correlation Expression"),
+                    @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
+                    @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
+                    @YamlProperty(name = "executorService", type = "string", description = "To use a custom thread pool (ScheduledExecutorService) by the throttler.", displayName = "Executor Service"),
+                    @YamlProperty(name = "expression", type = "object:org.apache.camel.model.language.ExpressionDefinition", description = "Expression to configure the maximum number of messages to throttle per request", displayName = "Expression", oneOf = "expression"),
+                    @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
+                    @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
+                    @YamlProperty(name = "rejectExecution", type = "boolean", description = "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false", displayName = "Reject Execution")
+            }
+    )
+    public static class ConcurrentRequestsThrottleDefinitionDeserializer extends YamlDeserializerBase<ConcurrentRequestsThrottleDefinition> {
+        public ConcurrentRequestsThrottleDefinitionDeserializer() {
+            super(ConcurrentRequestsThrottleDefinition.class);
+        }
+
+        @Override
+        protected ConcurrentRequestsThrottleDefinition newInstance() {
+            return new ConcurrentRequestsThrottleDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(ConcurrentRequestsThrottleDefinition target,
+                String propertyKey, String propertyName, Node node) {
+            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
+            switch(propertyKey) {
+                case "asyncDelayed": {
+                    String val = asText(node);
+                    target.setAsyncDelayed(val);
+                    break;
+                }
+                case "callerRunsWhenRejected": {
+                    String val = asText(node);
+                    target.setCallerRunsWhenRejected(val);
+                    break;
+                }
+                case "correlationExpression": {
+                    org.apache.camel.model.ExpressionSubElementDefinition val = asType(node, org.apache.camel.model.ExpressionSubElementDefinition.class);
+                    target.setCorrelationExpression(val);
+                    break;
+                }
+                case "disabled": {
+                    String val = asText(node);
+                    target.setDisabled(val);
+                    break;
+                }
+                case "executorService": {
+                    String val = asText(node);
+                    target.setExecutorService(val);
+                    break;
+                }
+                case "expression": {
+                    org.apache.camel.model.language.ExpressionDefinition val = asType(node, org.apache.camel.model.language.ExpressionDefinition.class);
+                    target.setExpression(val);
+                    break;
+                }
+                case "inheritErrorHandler": {
+                    String val = asText(node);
+                    target.setInheritErrorHandler(java.lang.Boolean.valueOf(val));
+                    break;
+                }
+                case "rejectExecution": {
+                    String val = asText(node);
+                    target.setRejectExecution(val);
+                    break;
+                }
+                case "id": {
+                    String val = asText(node);
+                    target.setId(val);
+                    break;
+                }
+                case "description": {
+                    String val = asText(node);
+                    target.setDescription(val);
+                    break;
+                }
+                default: {
+                    ExpressionDefinition ed = target.getExpressionType();
+                    if (ed != null) {
+                        throw new org.apache.camel.dsl.yaml.common.exception.DuplicateFieldException(node, propertyName, "as an expression");
+                    }
+                    ed = ExpressionDeserializers.constructExpressionType(propertyKey, node);
+                    if (ed != null) {
+                        target.setExpressionType(ed);
+                    } else {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
     @YamlType(
             nodes = "constant",
             inline = true,
@@ -17979,109 +18082,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
-    @YamlType(
-            nodes = "throttle",
-            types = org.apache.camel.model.ThrottleDefinition.class,
-            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
-            displayName = "Throttle",
-            description = "Controls the rate at which messages are passed to the next node in the route",
-            deprecated = false,
-            properties = {
-                    @YamlProperty(name = "__extends", type = "object:org.apache.camel.model.language.ExpressionDefinition", oneOf = "expression"),
-                    @YamlProperty(name = "asyncDelayed", type = "boolean", description = "Enables asynchronous delay which means the thread will not block while delaying.", displayName = "Async Delayed"),
-                    @YamlProperty(name = "callerRunsWhenRejected", type = "boolean", description = "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true", displayName = "Caller Runs When Rejected"),
-                    @YamlProperty(name = "correlationExpression", type = "object:org.apache.camel.model.ExpressionSubElementDefinition", description = "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.", displayName = "Correlation Expression"),
-                    @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
-                    @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
-                    @YamlProperty(name = "executorService", type = "string", description = "To use a custom thread pool (ScheduledExecutorService) by the throttler.", displayName = "Executor Service"),
-                    @YamlProperty(name = "expression", type = "object:org.apache.camel.model.language.ExpressionDefinition", description = "Expression to configure the maximum number of messages to throttle per request", displayName = "Expression", oneOf = "expression"),
-                    @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
-                    @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
-                    @YamlProperty(name = "rejectExecution", type = "boolean", description = "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false", displayName = "Reject Execution")
-            }
-    )
-    public static class ThrottleDefinitionDeserializer extends YamlDeserializerBase<ThrottleDefinition> {
-        public ThrottleDefinitionDeserializer() {
-            super(ThrottleDefinition.class);
-        }
-
-        @Override
-        protected ThrottleDefinition newInstance() {
-            return new ThrottleDefinition();
-        }
-
-        @Override
-        protected boolean setProperty(ThrottleDefinition target, String propertyKey,
-                String propertyName, Node node) {
-            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
-            switch(propertyKey) {
-                case "asyncDelayed": {
-                    String val = asText(node);
-                    target.setAsyncDelayed(val);
-                    break;
-                }
-                case "callerRunsWhenRejected": {
-                    String val = asText(node);
-                    target.setCallerRunsWhenRejected(val);
-                    break;
-                }
-                case "correlationExpression": {
-                    org.apache.camel.model.ExpressionSubElementDefinition val = asType(node, org.apache.camel.model.ExpressionSubElementDefinition.class);
-                    target.setCorrelationExpression(val);
-                    break;
-                }
-                case "disabled": {
-                    String val = asText(node);
-                    target.setDisabled(val);
-                    break;
-                }
-                case "executorService": {
-                    String val = asText(node);
-                    target.setExecutorService(val);
-                    break;
-                }
-                case "expression": {
-                    org.apache.camel.model.language.ExpressionDefinition val = asType(node, org.apache.camel.model.language.ExpressionDefinition.class);
-                    target.setExpression(val);
-                    break;
-                }
-                case "inheritErrorHandler": {
-                    String val = asText(node);
-                    target.setInheritErrorHandler(java.lang.Boolean.valueOf(val));
-                    break;
-                }
-                case "rejectExecution": {
-                    String val = asText(node);
-                    target.setRejectExecution(val);
-                    break;
-                }
-                case "id": {
-                    String val = asText(node);
-                    target.setId(val);
-                    break;
-                }
-                case "description": {
-                    String val = asText(node);
-                    target.setDescription(val);
-                    break;
-                }
-                default: {
-                    ExpressionDefinition ed = target.getExpressionType();
-                    if (ed != null) {
-                        throw new org.apache.camel.dsl.yaml.common.exception.DuplicateFieldException(node, propertyName, "as an expression");
-                    }
-                    ed = ExpressionDeserializers.constructExpressionType(propertyKey, node);
-                    if (ed != null) {
-                        target.setExpressionType(ed);
-                    } else {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
-    }
-
     @YamlType(
             nodes = {
                     "throw-exception",
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index bf7c90a66be..81568219098 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -75,6 +75,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "combinedServiceFilter": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer();
             case "org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer();
             case "org.apache.camel.model.app.ComponentScanDefinition": return new ModelDeserializers.ComponentScanDefinitionDeserializer();
+            case "throttle": return new ModelDeserializers.ConcurrentRequestsThrottleDefinitionDeserializer();
+            case "org.apache.camel.model.ConcurrentRequestsThrottleDefinition": return new ModelDeserializers.ConcurrentRequestsThrottleDefinitionDeserializer();
             case "constant": return new ModelDeserializers.ConstantExpressionDeserializer();
             case "org.apache.camel.model.language.ConstantExpression": return new ModelDeserializers.ConstantExpressionDeserializer();
             case "consul-service-discovery": return new ModelDeserializers.ConsulServiceCallServiceDiscoveryConfigurationDeserializer();
@@ -501,8 +503,6 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "org.apache.camel.model.ThreadsDefinition": return new ModelDeserializers.ThreadsDefinitionDeserializer();
             case "thrift": return new ModelDeserializers.ThriftDataFormatDeserializer();
             case "org.apache.camel.model.dataformat.ThriftDataFormat": return new ModelDeserializers.ThriftDataFormatDeserializer();
-            case "throttle": return new ModelDeserializers.ThrottleDefinitionDeserializer();
-            case "org.apache.camel.model.ThrottleDefinition": return new ModelDeserializers.ThrottleDefinitionDeserializer();
             case "throw-exception": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
             case "throwException": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
             case "org.apache.camel.model.ThrowExceptionDefinition": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index acc483a442a..edb9228f50a 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -28,6 +28,9 @@
           "claimCheck" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ClaimCheckDefinition"
           },
+          "throttle" : {
+            "$ref" : "#/items/definitions/org.apache.camel.model.ConcurrentRequestsThrottleDefinition"
+          },
           "convertBodyTo" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ConvertBodyDefinition"
           },
@@ -166,9 +169,6 @@
           "threads" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ThreadsDefinition"
           },
-          "throttle" : {
-            "$ref" : "#/items/definitions/org.apache.camel.model.ThrottleDefinition"
-          },
           "throwException" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ThrowExceptionDefinition"
           },
@@ -745,6 +745,154 @@
           }
         }
       },
+      "org.apache.camel.model.ConcurrentRequestsThrottleDefinition" : {
+        "title" : "Throttle",
+        "description" : "Controls the rate at which messages are passed to the next node in the route",
+        "type" : "object",
+        "additionalProperties" : false,
+        "anyOf" : [ {
+          "oneOf" : [ {
+            "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
+          }, {
+            "not" : {
+              "anyOf" : [ {
+                "required" : [ "expression" ]
+              }, {
+                "required" : [ "constant" ]
+              }, {
+                "required" : [ "csimple" ]
+              }, {
+                "required" : [ "datasonnet" ]
+              }, {
+                "required" : [ "exchangeProperty" ]
+              }, {
+                "required" : [ "groovy" ]
+              }, {
+                "required" : [ "header" ]
+              }, {
+                "required" : [ "hl7terser" ]
+              }, {
+                "required" : [ "java" ]
+              }, {
+                "required" : [ "joor" ]
+              }, {
+                "required" : [ "jq" ]
+              }, {
+                "required" : [ "js" ]
+              }, {
+                "required" : [ "jsonpath" ]
+              }, {
+                "required" : [ "language" ]
+              }, {
+                "required" : [ "method" ]
+              }, {
+                "required" : [ "mvel" ]
+              }, {
+                "required" : [ "ognl" ]
+              }, {
+                "required" : [ "python" ]
+              }, {
+                "required" : [ "ref" ]
+              }, {
+                "required" : [ "simple" ]
+              }, {
+                "required" : [ "spel" ]
+              }, {
+                "required" : [ "tokenize" ]
+              }, {
+                "required" : [ "variable" ]
+              }, {
+                "required" : [ "wasm" ]
+              }, {
+                "required" : [ "xpath" ]
+              }, {
+                "required" : [ "xquery" ]
+              }, {
+                "required" : [ "xtokenize" ]
+              } ]
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "expression" ],
+            "properties" : {
+              "expression" : {
+                "title" : "Expression",
+                "description" : "Expression to configure the maximum number of messages to throttle per request",
+                "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
+              }
+            }
+          } ]
+        } ],
+        "properties" : {
+          "asyncDelayed" : {
+            "type" : "boolean",
+            "title" : "Async Delayed",
+            "description" : "Enables asynchronous delay which means the thread will not block while delaying."
+          },
+          "callerRunsWhenRejected" : {
+            "type" : "boolean",
+            "title" : "Caller Runs When Rejected",
+            "description" : "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true"
+          },
+          "correlationExpression" : {
+            "title" : "Correlation Expression",
+            "description" : "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.",
+            "$ref" : "#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition"
+          },
+          "description" : {
+            "type" : "string",
+            "title" : "Description",
+            "description" : "Sets the description of this node"
+          },
+          "disabled" : {
+            "type" : "boolean",
+            "title" : "Disabled",
+            "description" : "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime."
+          },
+          "executorService" : {
+            "type" : "string",
+            "title" : "Executor Service",
+            "description" : "To use a custom thread pool (ScheduledExecutorService) by the throttler."
+          },
+          "id" : {
+            "type" : "string",
+            "title" : "Id",
+            "description" : "Sets the id of this node"
+          },
+          "rejectExecution" : {
+            "type" : "boolean",
+            "title" : "Reject Execution",
+            "description" : "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false"
+          },
+          "constant" : { },
+          "csimple" : { },
+          "datasonnet" : { },
+          "exchangeProperty" : { },
+          "groovy" : { },
+          "header" : { },
+          "hl7terser" : { },
+          "java" : { },
+          "joor" : { },
+          "jq" : { },
+          "js" : { },
+          "jsonpath" : { },
+          "language" : { },
+          "method" : { },
+          "mvel" : { },
+          "ognl" : { },
+          "python" : { },
+          "ref" : { },
+          "simple" : { },
+          "spel" : { },
+          "tokenize" : { },
+          "variable" : { },
+          "wasm" : { },
+          "xpath" : { },
+          "xquery" : { },
+          "xtokenize" : { },
+          "expression" : { }
+        }
+      },
       "org.apache.camel.model.ContextScanDefinition" : {
         "title" : "Context Scan",
         "description" : "Scans for Java org.apache.camel.builder.RouteBuilder instances in the context org.apache.camel.spi.Registry .",
@@ -6798,154 +6946,6 @@
           }
         }
       },
-      "org.apache.camel.model.ThrottleDefinition" : {
-        "title" : "Throttle",
-        "description" : "Controls the rate at which messages are passed to the next node in the route",
-        "type" : "object",
-        "additionalProperties" : false,
-        "anyOf" : [ {
-          "oneOf" : [ {
-            "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
-          }, {
-            "not" : {
-              "anyOf" : [ {
-                "required" : [ "expression" ]
-              }, {
-                "required" : [ "constant" ]
-              }, {
-                "required" : [ "csimple" ]
-              }, {
-                "required" : [ "datasonnet" ]
-              }, {
-                "required" : [ "exchangeProperty" ]
-              }, {
-                "required" : [ "groovy" ]
-              }, {
-                "required" : [ "header" ]
-              }, {
-                "required" : [ "hl7terser" ]
-              }, {
-                "required" : [ "java" ]
-              }, {
-                "required" : [ "joor" ]
-              }, {
-                "required" : [ "jq" ]
-              }, {
-                "required" : [ "js" ]
-              }, {
-                "required" : [ "jsonpath" ]
-              }, {
-                "required" : [ "language" ]
-              }, {
-                "required" : [ "method" ]
-              }, {
-                "required" : [ "mvel" ]
-              }, {
-                "required" : [ "ognl" ]
-              }, {
-                "required" : [ "python" ]
-              }, {
-                "required" : [ "ref" ]
-              }, {
-                "required" : [ "simple" ]
-              }, {
-                "required" : [ "spel" ]
-              }, {
-                "required" : [ "tokenize" ]
-              }, {
-                "required" : [ "variable" ]
-              }, {
-                "required" : [ "wasm" ]
-              }, {
-                "required" : [ "xpath" ]
-              }, {
-                "required" : [ "xquery" ]
-              }, {
-                "required" : [ "xtokenize" ]
-              } ]
-            }
-          }, {
-            "type" : "object",
-            "required" : [ "expression" ],
-            "properties" : {
-              "expression" : {
-                "title" : "Expression",
-                "description" : "Expression to configure the maximum number of messages to throttle per request",
-                "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
-              }
-            }
-          } ]
-        } ],
-        "properties" : {
-          "asyncDelayed" : {
-            "type" : "boolean",
-            "title" : "Async Delayed",
-            "description" : "Enables asynchronous delay which means the thread will not block while delaying."
-          },
-          "callerRunsWhenRejected" : {
-            "type" : "boolean",
-            "title" : "Caller Runs When Rejected",
-            "description" : "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true"
-          },
-          "correlationExpression" : {
-            "title" : "Correlation Expression",
-            "description" : "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.",
-            "$ref" : "#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition"
-          },
-          "description" : {
-            "type" : "string",
-            "title" : "Description",
-            "description" : "Sets the description of this node"
-          },
-          "disabled" : {
-            "type" : "boolean",
-            "title" : "Disabled",
-            "description" : "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime."
-          },
-          "executorService" : {
-            "type" : "string",
-            "title" : "Executor Service",
-            "description" : "To use a custom thread pool (ScheduledExecutorService) by the throttler."
-          },
-          "id" : {
-            "type" : "string",
-            "title" : "Id",
-            "description" : "Sets the id of this node"
-          },
-          "rejectExecution" : {
-            "type" : "boolean",
-            "title" : "Reject Execution",
-            "description" : "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false"
-          },
-          "constant" : { },
-          "csimple" : { },
-          "datasonnet" : { },
-          "exchangeProperty" : { },
-          "groovy" : { },
-          "header" : { },
-          "hl7terser" : { },
-          "java" : { },
-          "joor" : { },
-          "jq" : { },
-          "js" : { },
-          "jsonpath" : { },
-          "language" : { },
-          "method" : { },
-          "mvel" : { },
-          "ognl" : { },
-          "python" : { },
-          "ref" : { },
-          "simple" : { },
-          "spel" : { },
-          "tokenize" : { },
-          "variable" : { },
-          "wasm" : { },
-          "xpath" : { },
-          "xquery" : { },
-          "xtokenize" : { },
-          "expression" : { }
-        }
-      },
       "org.apache.camel.model.ThrowExceptionDefinition" : {
         "title" : "Throw Exception",
         "description" : "Throws an exception",
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
index 2b3ebddcc92..60d8b0f11fc 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
@@ -17,7 +17,7 @@
 package org.apache.camel.dsl.yaml
 
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
-import org.apache.camel.model.ThrottleDefinition
+import org.apache.camel.model.ConcurrentRequestsThrottleDefinition
 import org.apache.camel.model.language.ConstantExpression
 import org.apache.camel.spi.Resource
 import org.apache.camel.support.PluginHelper
@@ -28,7 +28,7 @@ class ThrottleTest extends YamlTestSupport {
         when:
             PluginHelper.getRoutesLoader(context).loadRoutes(resource)
         then:
-            with(context.routeDefinitions[0].outputs[0], ThrottleDefinition) {
+            with(context.routeDefinitions[0].outputs[0], ConcurrentRequestsThrottleDefinition) {
                 with (expression, ConstantExpression) {
                     language == 'constant'
                     expression == '5'


(camel) 03/04: CAMEL-20355: refactor the throttler

Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit bbf8a54414dd2dc6aaa4890c41066989cb83c84d
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Feb 6 14:18:00 2024 +0100

    CAMEL-20355: refactor the throttler
    
    Adjust code to facilitate accommodating more than one throttling behavior
---
 .../{Throttler.java => ConcurrentRequestsThrottler.java}          | 6 +++---
 .../apache/camel/reifier/ConcurrentRequestsThrottleReifier.java   | 4 ++--
 .../apache/camel/management/DefaultManagementObjectStrategy.java  | 6 +++---
 .../management/mbean/ManagedConcurrentRequestsThrottler.java      | 8 ++++----
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
similarity index 98%
rename from core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java
rename to core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
index 2a7df9052be..3c851b618ff 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
@@ -54,9 +54,9 @@ import org.slf4j.LoggerFactory;
  * The throttling mechanism is a Semaphore with maxConcurrentRequests permits on it. Callers trying to acquire a permit
  * will block if necessary when maxConcurrentRequests permits have been acquired.
  */
-public class Throttler extends AsyncProcessorSupport implements Traceable, IdAware, RouteIdAware {
+public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implements Traceable, IdAware, RouteIdAware {
 
-    private static final Logger LOG = LoggerFactory.getLogger(Throttler.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ConcurrentRequestsThrottler.class);
 
     private static final String DEFAULT_KEY = "CamelThrottlerDefaultKey";
 
@@ -82,7 +82,7 @@ public class Throttler extends AsyncProcessorSupport implements Traceable, IdAwa
     private final Expression correlationExpression;
     private final Map<String, ThrottlingState> states = new ConcurrentHashMap<>();
 
-    public Throttler(final CamelContext camelContext, final Expression maxConcurrentRequestsExpression,
+    public ConcurrentRequestsThrottler(final CamelContext camelContext, final Expression maxConcurrentRequestsExpression,
                      final ScheduledExecutorService asyncExecutor, final boolean shutdownAsyncExecutor,
                      final boolean rejectExecution, Expression correlation) {
         this.camelContext = camelContext;
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
index 1910baa21a5..baa1f1e8d1b 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
@@ -23,7 +23,7 @@ import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
-import org.apache.camel.processor.Throttler;
+import org.apache.camel.processor.ConcurrentRequestsThrottler;
 
 public class ConcurrentRequestsThrottleReifier extends ExpressionReifier<ConcurrentRequestsThrottleDefinition> {
 
@@ -49,7 +49,7 @@ public class ConcurrentRequestsThrottleReifier extends ExpressionReifier<Concurr
         }
 
         boolean reject = parseBoolean(definition.getRejectExecution(), false);
-        Throttler answer = new Throttler(
+        ConcurrentRequestsThrottler answer = new ConcurrentRequestsThrottler(
                 camelContext, maxRequestsExpression, threadPool, shutdownThreadPool, reject, correlation);
 
         answer.setAsyncDelayed(async);
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
index c9854b97f6a..4aa88918f13 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
@@ -172,7 +172,7 @@ import org.apache.camel.processor.StepProcessor;
 import org.apache.camel.processor.StopProcessor;
 import org.apache.camel.processor.StreamResequencer;
 import org.apache.camel.processor.ThreadsProcessor;
-import org.apache.camel.processor.Throttler;
+import org.apache.camel.processor.ConcurrentRequestsThrottler;
 import org.apache.camel.processor.ThrowExceptionProcessor;
 import org.apache.camel.processor.TransformProcessor;
 import org.apache.camel.processor.TryProcessor;
@@ -377,8 +377,8 @@ public class DefaultManagementObjectStrategy implements ManagementObjectStrategy
                 answer = new ManagedDoCatch(context, (CatchProcessor) target, (CatchDefinition) definition);
             } else if (target instanceof FinallyProcessor) {
                 answer = new ManagedDoFinally(context, (FinallyProcessor) target, (FinallyDefinition) definition);
-            } else if (target instanceof Throttler) {
-                answer = new ManagedConcurrentRequestsThrottler(context, (Throttler) target, definition);
+            } else if (target instanceof ConcurrentRequestsThrottler) {
+                answer = new ManagedConcurrentRequestsThrottler(context, (ConcurrentRequestsThrottler) target, definition);
             } else if (target instanceof DynamicRouter) {
                 answer = new ManagedDynamicRouter(context, (DynamicRouter) target, (DynamicRouterDefinition) definition);
             } else if (target instanceof RoutingSlip) {
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
index e54766c3454..655c718d114 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
@@ -20,20 +20,20 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.api.management.mbean.ManagedConcurrentRequestsThrottlerMBean;
 import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.processor.Throttler;
+import org.apache.camel.processor.ConcurrentRequestsThrottler;
 
 import static org.apache.camel.builder.Builder.constant;
 
 @ManagedResource(description = "Managed Throttler")
 public class ManagedConcurrentRequestsThrottler extends ManagedProcessor implements ManagedConcurrentRequestsThrottlerMBean {
-    private final Throttler throttler;
+    private final ConcurrentRequestsThrottler throttler;
 
-    public ManagedConcurrentRequestsThrottler(CamelContext context, Throttler throttler, ProcessorDefinition<?> definition) {
+    public ManagedConcurrentRequestsThrottler(CamelContext context, ConcurrentRequestsThrottler throttler, ProcessorDefinition<?> definition) {
         super(context, throttler, definition);
         this.throttler = throttler;
     }
 
-    public Throttler getThrottler() {
+    public ConcurrentRequestsThrottler getThrottler() {
         return throttler;
     }
 


(camel) 04/04: CAMEL-20355: enable multiple throttling modes

Posted by or...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

orpiske pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 22151ef9e2a55df723e4cce670004fea1538c960
Author: Otavio Rodolfo Piske <an...@gmail.com>
AuthorDate: Tue Feb 6 14:56:49 2024 +0100

    CAMEL-20355: enable multiple throttling modes
    
    Rework the throttler to allow different throttler implementations. This enables supporting both the current "leaky-bucket" throttler and the legacy "time-bound" throttler.
---
 .../org/apache/camel/catalog/models/throttle.json  |  14 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  | 248 +++++++------
 .../spring/processor/SpringThrottlerTest.java      |   2 +-
 .../throttle/SpringThrottlerGroupingTest.java      |   2 +-
 .../throttle/SpringThrottlerMethodCallTest.java    |   2 +-
 .../main/docs/modules/eips/pages/throttle-eip.adoc |  74 ++++
 .../resources/org/apache/camel/model/jaxb.index    |   3 +-
 .../resources/org/apache/camel/model/throttle.json |  14 +-
 .../apache/camel/model/ProcessorDefinition.java    |  21 +-
 ...ttleDefinition.java => ThrottleDefinition.java} | 192 ++++++++--
 .../org/apache/camel/model/ThrottlingMode.java     |  31 +-
 .../apache/camel/processor/AbstractThrottler.java  | 153 ++++++++
 .../processor/ConcurrentRequestsThrottler.java     | 119 +------
 .../java/org/apache/camel/processor/Throttler.java |  24 +-
 .../camel/processor/TotalRequestsThrottler.java    | 388 +++++++++++++++++++++
 .../org/apache/camel/reifier/ProcessorReifier.java |   6 +-
 ...tsThrottleReifier.java => ThrottleReifier.java} |  47 ++-
 .../ConcurrentRequestsThrottlerTest.java           |  14 +-
 .../ThrottlerAsyncDelayedCallerRunsTest.java       |   4 +-
 .../ThrottlerAsyncDelayedTest.java                 |   8 +-
 .../{ => concurrent}/ThrottlerMethodCallTest.java  |   5 +-
 .../{ => concurrent}/ThrottlingGroupingTest.java   |  13 +-
 .../ThrottlerAsyncDelayedCallerRunsTest.java       |   4 +-
 .../{ => requests}/ThrottlerAsyncDelayedTest.java  |   6 +-
 .../throttle/{ => requests}/ThrottlerDslTest.java  |  11 +-
 .../requests/ThrottlerTest.java}                   | 192 +++++-----
 .../{ => requests}/ThrottlingGroupingTest.java     | 167 +++++----
 ...ottlerMBean.java => ManagedThrottlerMBean.java} |  15 +-
 .../DefaultManagementObjectStrategy.java           |   8 +-
 ...equestsThrottler.java => ManagedThrottler.java} |  45 ++-
 ...Test.java => AbstractManagedThrottlerTest.java} |  83 +----
 .../management/ManagedConcurrentThrottlerTest.java | 107 ++++++
 .../camel/management/ManagedThrottlerTest.java     | 228 +-----------
 .../java/org/apache/camel/xml/in/ModelParser.java  |  86 ++---
 .../java/org/apache/camel/xml/out/ModelWriter.java |  44 +--
 .../org/apache/camel/yaml/out/ModelWriter.java     |  44 +--
 .../ROOT/pages/camel-4x-upgrade-guide-4_4.adoc     |  16 +
 .../dsl/yaml/deserializers/ModelDeserializers.java | 220 ++++++------
 .../deserializers/ModelDeserializersResolver.java  |   4 +-
 .../generated/resources/schema/camelYamlDsl.json   | 315 +++++++++--------
 .../org/apache/camel/dsl/yaml/ThrottleTest.groovy  |   4 +-
 41 files changed, 1814 insertions(+), 1169 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
index 2eafa8ecd27..fedfb362b6d 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/throttle.json
@@ -6,7 +6,7 @@
     "description": "Controls the rate at which messages are passed to the next node in the route",
     "deprecated": false,
     "label": "eip,routing",
-    "javaType": "org.apache.camel.model.ConcurrentRequestsThrottleDefinition",
+    "javaType": "org.apache.camel.model.ThrottleDefinition",
     "abstract": false,
     "input": true,
     "output": false
@@ -16,10 +16,12 @@
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
     "expression": { "index": 3, "kind": "expression", "displayName": "Expression", "required": true, "type": "object", "javaType": "org.apache.camel.model.language.ExpressionDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ], "deprecated": false, "aut [...]
-    "correlationExpression": { "index": 4, "kind": "expression", "displayName": "Correlation Expression", "required": false, "type": "object", "javaType": "org.apache.camel.model.ExpressionSubElementDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ],  [...]
-    "executorService": { "index": 5, "kind": "attribute", "displayName": "Executor Service", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom thread pool (ScheduledExecutorService) by the throttler." },
-    "asyncDelayed": { "index": 6, "kind": "attribute", "displayName": "Async Delayed", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables asynchronous delay which means the thread will not block while delaying." },
-    "callerRunsWhenRejected": { "index": 7, "kind": "attribute", "displayName": "Caller Runs When Rejected", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true" },
-    "rejectExecution": { "index": 8, "kind": "attribute", "displayName": "Reject Execution", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false" }
+    "mode": { "index": 4, "kind": "attribute", "displayName": "Mode", "required": false, "type": "enum", "javaType": "org.apache.camel.model.ThrottlingMode", "enum": [ "TotalRequests", "ConcurrentRequests" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TotalRequests", "description": "Sets the throttling mode to one of the available modes enumerated in ThrottlingMode" },
+    "correlationExpression": { "index": 5, "kind": "expression", "displayName": "Correlation Expression", "required": false, "type": "object", "javaType": "org.apache.camel.model.ExpressionSubElementDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ],  [...]
+    "executorService": { "index": 6, "kind": "attribute", "displayName": "Executor Service", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom thread pool (ScheduledExecutorService) by the throttler." },
+    "asyncDelayed": { "index": 7, "kind": "attribute", "displayName": "Async Delayed", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables asynchronous delay which means the thread will not block while delaying." },
+    "callerRunsWhenRejected": { "index": 8, "kind": "attribute", "displayName": "Caller Runs When Rejected", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true" },
+    "rejectExecution": { "index": 9, "kind": "attribute", "displayName": "Reject Execution", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false" },
+    "timePeriodMillis": { "index": 10, "kind": "attribute", "displayName": "Time Period Millis", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Sets the time period during which the maximum request count is valid for" }
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 2aa9009d28d..a70759e4269 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -1995,7 +1995,7 @@ Serialize and deserialize messages using Apache Thrift binary data format.
       </xs:documentation>
     </xs:annotation>
   </xs:element>
-  <xs:element name="throttle" type="tns:concurrentRequestsThrottleDefinition">
+  <xs:element name="throttle" type="tns:throttleDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en">
 <![CDATA[
@@ -3531,7 +3531,6 @@ will fallback to use the fixed value if the Expression result was null or 0.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -3582,6 +3581,7 @@ will fallback to use the fixed value if the Expression result was null or 0.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4095,7 +4095,6 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4146,6 +4145,7 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4204,7 +4204,6 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4255,6 +4254,7 @@ controlling whether a thrown exception should be intercepted by this exception t
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4304,7 +4304,6 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4355,6 +4354,7 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4387,7 +4387,6 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4438,6 +4437,7 @@ during startup to keep at runtime only the branch that matched. Default value: f
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4837,7 +4837,6 @@ References to a custom thread pool to use when bulkhead is enabled.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -4888,6 +4887,7 @@ References to a custom thread pool to use when bulkhead is enabled.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -4973,91 +4973,6 @@ strategy and configure data at the same time.
             <xs:documentation xml:lang="en">
 <![CDATA[
 This option can be used to explicit declare the method name to use, when using POJOs as the AggregationStrategy.
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-      </xs:extension>
-    </xs:complexContent>
-  </xs:complexType>
-  <xs:complexType name="concurrentRequestsThrottleDefinition">
-    <xs:complexContent>
-      <xs:extension base="tns:processorDefinition">
-        <xs:sequence>
-          <xs:choice>
-            <xs:element ref="tns:expressionDefinition"/>
-            <xs:element ref="tns:csimple"/>
-            <xs:element ref="tns:constant"/>
-            <xs:element ref="tns:datasonnet"/>
-            <xs:element ref="tns:exchangeProperty"/>
-            <xs:element ref="tns:groovy"/>
-            <xs:element ref="tns:header"/>
-            <xs:element ref="tns:hl7terser"/>
-            <xs:element ref="tns:java"/>
-            <xs:element ref="tns:js"/>
-            <xs:element ref="tns:joor"/>
-            <xs:element ref="tns:jq"/>
-            <xs:element ref="tns:jsonpath"/>
-            <xs:element ref="tns:language"/>
-            <xs:element ref="tns:method"/>
-            <xs:element ref="tns:mvel"/>
-            <xs:element ref="tns:ognl"/>
-            <xs:element ref="tns:python"/>
-            <xs:element ref="tns:ref"/>
-            <xs:element ref="tns:simple"/>
-            <xs:element ref="tns:spel"/>
-            <xs:element ref="tns:tokenize"/>
-            <xs:element ref="tns:variable"/>
-            <xs:element ref="tns:wasm"/>
-            <xs:element ref="tns:xtokenize"/>
-            <xs:element ref="tns:xpath"/>
-            <xs:element ref="tns:xquery"/>
-          </xs:choice>
-          <xs:element minOccurs="0" name="correlationExpression" type="tns:expressionSubElementDefinition">
-            <xs:annotation>
-              <xs:documentation xml:lang="en">
-<![CDATA[
-The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same
-correlation key is throttled together.
-]]>
-              </xs:documentation>
-            </xs:annotation>
-          </xs:element>
-        </xs:sequence>
-        <xs:attribute name="executorService" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-To use a custom thread pool (ScheduledExecutorService) by the throttler.
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="asyncDelayed" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Enables asynchronous delay which means the thread will not block while delaying. Default value: false
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="callerRunsWhenRejected" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true. Default
-value: true
-]]>
-            </xs:documentation>
-          </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="rejectExecution" type="xs:string">
-          <xs:annotation>
-            <xs:documentation xml:lang="en">
-<![CDATA[
-Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is
-by default false. Default value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -6073,7 +5988,6 @@ Sets the logging level to use for logging transactional rollback. This option is
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6124,6 +6038,7 @@ Sets the logging level to use for logging transactional rollback. This option is
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6163,7 +6078,6 @@ predicate evaluated as true or false.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6214,6 +6128,7 @@ predicate evaluated as true or false.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6324,7 +6239,6 @@ Global option value.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6375,6 +6289,7 @@ Global option value.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6484,7 +6399,6 @@ Whether if validation is required for this input type. Default value: false
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6535,6 +6449,7 @@ Whether if validation is required for this input type. Default value: false
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6581,7 +6496,6 @@ intercepted.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6632,6 +6546,7 @@ intercepted.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6689,7 +6604,6 @@ After sending to the endpoint then send the message to this uri which allows to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6740,6 +6654,7 @@ After sending to the endpoint then send the message to this uri which allows to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -6788,7 +6703,6 @@ mynamecount=4&type=gold.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -6839,6 +6753,7 @@ mynamecount=4&type=gold.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -7101,7 +7016,6 @@ To refer to a custom logger instance to lookup from the registry.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -7152,6 +7066,7 @@ To refer to a custom logger instance to lookup from the registry.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10508,7 +10423,6 @@ maximum decompressed size. Default value: 1073741824
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10559,6 +10473,7 @@ maximum decompressed size. Default value: 1073741824
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10731,7 +10646,6 @@ controlling whether a completion callback should be invoked or not.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10782,6 +10696,7 @@ controlling whether a completion callback should be invoked or not.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -10929,7 +10844,6 @@ its considered handled as well.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -10980,6 +10894,7 @@ its considered handled as well.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11187,7 +11102,6 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11238,6 +11152,7 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11267,7 +11182,6 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11318,6 +11232,7 @@ one of the available events. Implementations should not assume the predicate to
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -11895,7 +11810,6 @@ Name of variable to remove.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -11946,6 +11860,7 @@ Name of variable to remove.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -12243,7 +12158,6 @@ Reference to the routes in the xml dsl.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -12294,6 +12208,7 @@ Reference to the routes in the xml dsl.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -12678,7 +12593,6 @@ actions. Option values will be transformed into input headers of the compensatio
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -12729,6 +12643,7 @@ actions. Option values will be transformed into input headers of the compensatio
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13126,7 +13041,6 @@ Sets the comparator to use for sorting.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13177,6 +13091,7 @@ Sets the comparator to use for sorting.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13356,7 +13271,6 @@ individual unit of work. Default value: false
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13407,6 +13321,7 @@ individual unit of work. Default value: false
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -13688,6 +13603,109 @@ Sets the handler for tasks which cannot be executed by the thread pool.
 Whether or not to use as caller runs as fallback when a task is rejected being added to the thread pool (when its full).
 This is only used as fallback if no rejectedPolicy has been configured, or the thread pool has no configured rejection
 handler. Is by default true. Default value: true
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="throttleDefinition">
+    <xs:complexContent>
+      <xs:extension base="tns:processorDefinition">
+        <xs:sequence>
+          <xs:choice>
+            <xs:element ref="tns:expressionDefinition"/>
+            <xs:element ref="tns:csimple"/>
+            <xs:element ref="tns:constant"/>
+            <xs:element ref="tns:datasonnet"/>
+            <xs:element ref="tns:exchangeProperty"/>
+            <xs:element ref="tns:groovy"/>
+            <xs:element ref="tns:header"/>
+            <xs:element ref="tns:hl7terser"/>
+            <xs:element ref="tns:java"/>
+            <xs:element ref="tns:js"/>
+            <xs:element ref="tns:joor"/>
+            <xs:element ref="tns:jq"/>
+            <xs:element ref="tns:jsonpath"/>
+            <xs:element ref="tns:language"/>
+            <xs:element ref="tns:method"/>
+            <xs:element ref="tns:mvel"/>
+            <xs:element ref="tns:ognl"/>
+            <xs:element ref="tns:python"/>
+            <xs:element ref="tns:ref"/>
+            <xs:element ref="tns:simple"/>
+            <xs:element ref="tns:spel"/>
+            <xs:element ref="tns:tokenize"/>
+            <xs:element ref="tns:variable"/>
+            <xs:element ref="tns:wasm"/>
+            <xs:element ref="tns:xtokenize"/>
+            <xs:element ref="tns:xpath"/>
+            <xs:element ref="tns:xquery"/>
+          </xs:choice>
+          <xs:element minOccurs="0" name="correlationExpression" type="tns:expressionSubElementDefinition">
+            <xs:annotation>
+              <xs:documentation xml:lang="en">
+<![CDATA[
+The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same
+correlation key is throttled together.
+]]>
+              </xs:documentation>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+        <xs:attribute name="mode" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Sets the throttling mode to one of the available modes enumerated in ThrottlingMode. Default value: TotalRequests
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="executorService" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+To use a custom thread pool (ScheduledExecutorService) by the throttler.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="asyncDelayed" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Enables asynchronous delay which means the thread will not block while delaying. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="callerRunsWhenRejected" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true. Default
+value: true
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="rejectExecution" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is
+by default false. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="timePeriodMillis" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Sets the time period during which the maximum request count is valid for. Default value: 1000
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -13875,7 +13893,6 @@ Whether to auto startup components when toD is starting up. Default value: true
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -13926,6 +13943,7 @@ Whether to auto startup components when toD is starting up. Default value: true
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -14017,7 +14035,6 @@ To type used as a target data type in the transformation.
             <xs:element ref="tns:circuitBreaker"/>
             <xs:element ref="tns:onFallback"/>
             <xs:element ref="tns:claimCheck"/>
-            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:convertBodyTo"/>
             <xs:element ref="tns:convertHeaderTo"/>
             <xs:element ref="tns:convertVariableTo"/>
@@ -14068,6 +14085,7 @@ To type used as a target data type in the transformation.
             <xs:element ref="tns:step"/>
             <xs:element ref="tns:stop"/>
             <xs:element ref="tns:threads"/>
+            <xs:element ref="tns:throttle"/>
             <xs:element ref="tns:throwException"/>
             <xs:element ref="tns:to"/>
             <xs:element ref="tns:toD"/>
@@ -17926,6 +17944,12 @@ An optional certificate alias to use. This is useful when the keystore has multi
       <xs:enumeration value="NEVER"/>
     </xs:restriction>
   </xs:simpleType>
+  <xs:simpleType name="throttlingMode">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="TotalRequests"/>
+      <xs:enumeration value="ConcurrentRequests"/>
+    </xs:restriction>
+  </xs:simpleType>
   <xs:simpleType name="bindyType">
     <xs:restriction base="xs:string">
       <xs:enumeration value="Csv"/>
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
index a999e23fb27..631313c2c5e 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringThrottlerTest.java
@@ -19,7 +19,7 @@ package org.apache.camel.spring.processor;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.ConcurrentRequestsThrottlerTest;
+import org.apache.camel.processor.throttle.concurrent.ConcurrentRequestsThrottlerTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
index fe8364825b5..8a83c3a80d8 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerGroupingTest.java
@@ -21,7 +21,7 @@ import java.util.concurrent.Semaphore;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
-import org.apache.camel.processor.throttle.ThrottlingGroupingTest;
+import org.apache.camel.processor.throttle.concurrent.ThrottlingGroupingTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
index 2b457f2dde5..ebe18789828 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
@@ -17,7 +17,7 @@
 package org.apache.camel.spring.processor.throttle;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.processor.throttle.ThrottlerMethodCallTest;
+import org.apache.camel.processor.throttle.concurrent.ThrottlerMethodCallTest;
 
 import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
 
diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/throttle-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/throttle-eip.adoc
index ceeaec370b0..51077de5be7 100644
--- a/core/camel-core-engine/src/main/docs/modules/eips/pages/throttle-eip.adoc
+++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/throttle-eip.adoc
@@ -311,3 +311,77 @@ YAML::
 In the example above messages are throttled by the header with name region.
 So suppose there are regions for US, EMEA, and ASIA, then we have three different groups, that each
 are throttled by 100 messages per second.
+
+== Throttling Modes
+
+Apache Camel comes with two distinct throttling modes to control and manage the flow of requests in their applications.
+
+These modes address different aspects of request handling:
+
+*Total Requests Mode*:: Throttles requests based on the total number of requests made within a defined unit of time. It regulates the overall traffic flow to prevent overwhelming the system with an excessive number of requests.
+
+*Concurrent Connections Mode*:: Throttles requests by managing concurrent connections using a https://en.wikipedia.org/wiki/Leaky_bucket[leaky bucket algorithm.] This algorithm controls the rate at which requests are processed simultaneously, preventing system overload.
+
+=== Default Mode
+
+By default, Camel uses the *Total Requests Mode* as the default throttling mechanism.
+
+This means that, unless specified otherwise, the framework regulates the flow of requests based on the total number of requests per unit of time.
+
+=== Choosing Throttling Mode
+
+Users can choose their preferred throttling mode using different approaches:
+
+*DSL Methods*::
+
+- `totalRequestsMode()`: Sets the total requests mode.
+- `concurrentRequestsMode()`: Sets the concurrent connections mode.
+
+*Mode DSL Method*::
+
+- `mode(String)`: Users can specify the throttling mode by passing either `TotalRequests` or `ConcurrentRequests` as an argument.
+
+For example, `mode("ConcurrentRequests")` sets the throttling mode based on concurrent connections.
+
+These options provide users with fine-grained control over how Camel manages the flow of requests, allowing them to choose the mode that best aligns with their specific application requirements.
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+from("seda:a")
+  .throttle(3).mode("ConcurrentRequests")
+  .to("mock:result");
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+  <from uri="seda:a"/>
+  <throttle mode="ConcurrentRequests">
+    <constant>3</constant>
+  </throttle>
+  <to uri="mock:result"/>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- from:
+    uri: seda:a
+    steps:
+      - throttle:
+          expression:
+            constant: 3
+          mode: ConcurrentRequests
+          timePeriodMillis: 10000
+      - to:
+          uri: mock:result
+----
+====
\ No newline at end of file
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
index dde2e549f44..e4f78c9dd9d 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/jaxb.index
@@ -6,7 +6,6 @@ ChoiceDefinition
 CircuitBreakerDefinition
 ClaimCheckDefinition
 ClaimCheckOperation
-ConcurrentRequestsThrottleDefinition
 ContextScanDefinition
 ConvertBodyDefinition
 ConvertHeaderDefinition
@@ -99,6 +98,8 @@ TemplatedRouteParameterDefinition
 TemplatedRoutesDefinition
 ThreadPoolProfileDefinition
 ThreadsDefinition
+ThrottleDefinition
+ThrottlingMode
 ThrowExceptionDefinition
 ToDefinition
 ToDynamicDefinition
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
index 2eafa8ecd27..fedfb362b6d 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/throttle.json
@@ -6,7 +6,7 @@
     "description": "Controls the rate at which messages are passed to the next node in the route",
     "deprecated": false,
     "label": "eip,routing",
-    "javaType": "org.apache.camel.model.ConcurrentRequestsThrottleDefinition",
+    "javaType": "org.apache.camel.model.ThrottleDefinition",
     "abstract": false,
     "input": true,
     "output": false
@@ -16,10 +16,12 @@
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
     "expression": { "index": 3, "kind": "expression", "displayName": "Expression", "required": true, "type": "object", "javaType": "org.apache.camel.model.language.ExpressionDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ], "deprecated": false, "aut [...]
-    "correlationExpression": { "index": 4, "kind": "expression", "displayName": "Correlation Expression", "required": false, "type": "object", "javaType": "org.apache.camel.model.ExpressionSubElementDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ],  [...]
-    "executorService": { "index": 5, "kind": "attribute", "displayName": "Executor Service", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom thread pool (ScheduledExecutorService) by the throttler." },
-    "asyncDelayed": { "index": 6, "kind": "attribute", "displayName": "Async Delayed", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables asynchronous delay which means the thread will not block while delaying." },
-    "callerRunsWhenRejected": { "index": 7, "kind": "attribute", "displayName": "Caller Runs When Rejected", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true" },
-    "rejectExecution": { "index": 8, "kind": "attribute", "displayName": "Reject Execution", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false" }
+    "mode": { "index": 4, "kind": "attribute", "displayName": "Mode", "required": false, "type": "enum", "javaType": "org.apache.camel.model.ThrottlingMode", "enum": [ "TotalRequests", "ConcurrentRequests" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TotalRequests", "description": "Sets the throttling mode to one of the available modes enumerated in ThrottlingMode" },
+    "correlationExpression": { "index": 5, "kind": "expression", "displayName": "Correlation Expression", "required": false, "type": "object", "javaType": "org.apache.camel.model.ExpressionSubElementDefinition", "oneOf": [ "constant", "csimple", "datasonnet", "exchangeProperty", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "language", "method", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "variable", "wasm", "xpath", "xquery", "xtokenize" ],  [...]
+    "executorService": { "index": 6, "kind": "attribute", "displayName": "Executor Service", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom thread pool (ScheduledExecutorService) by the throttler." },
+    "asyncDelayed": { "index": 7, "kind": "attribute", "displayName": "Async Delayed", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enables asynchronous delay which means the thread will not block while delaying." },
+    "callerRunsWhenRejected": { "index": 8, "kind": "attribute", "displayName": "Caller Runs When Rejected", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true" },
+    "rejectExecution": { "index": 9, "kind": "attribute", "displayName": "Reject Execution", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false" },
+    "timePeriodMillis": { "index": 10, "kind": "attribute", "displayName": "Time Period Millis", "required": false, "type": "duration", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "Sets the time period during which the maximum request count is valid for" }
   }
 }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 82632eb1590..8adb212460b 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -1803,8 +1803,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *
      * @return the builder
      */
-    public ExpressionClause<ConcurrentRequestsThrottleDefinition> throttle() {
-        ConcurrentRequestsThrottleDefinition answer = new ConcurrentRequestsThrottleDefinition();
+    public ExpressionClause<ThrottleDefinition> throttle() {
+        ThrottleDefinition answer = new ThrottleDefinition();
         addOutput(answer);
         return createAndSetExpression(answer);
     }
@@ -1820,7 +1820,7 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      * @param  maximumConcurrentRequests the maximum number of concurrent messages
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition throttle(long maximumConcurrentRequests) {
+    public ThrottleDefinition throttle(long maximumConcurrentRequests) {
         return throttle(ExpressionBuilder.constantExpression(maximumConcurrentRequests));
     }
 
@@ -1835,8 +1835,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      * @param  maximumConcurrentRequests an expression to calculate the maximum concurrent request count
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests) {
-        ConcurrentRequestsThrottleDefinition answer = new ConcurrentRequestsThrottleDefinition(maximumConcurrentRequests);
+    public ThrottleDefinition throttle(Expression maximumConcurrentRequests) {
+        ThrottleDefinition answer = new ThrottleDefinition(maximumConcurrentRequests);
         addOutput(answer);
         return answer;
     }
@@ -1856,9 +1856,9 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *                                   throttling
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests, long correlationExpressionKey) {
-        ConcurrentRequestsThrottleDefinition answer
-                = new ConcurrentRequestsThrottleDefinition(
+    public ThrottleDefinition throttle(Expression maximumConcurrentRequests, long correlationExpressionKey) {
+        ThrottleDefinition answer
+                = new ThrottleDefinition(
                         maximumConcurrentRequests, ExpressionBuilder.constantExpression(correlationExpressionKey));
         addOutput(answer);
         return answer;
@@ -1879,9 +1879,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
      *                                   instead of overall throttling
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition throttle(Expression maximumConcurrentRequests, Expression correlationExpressionKey) {
-        ConcurrentRequestsThrottleDefinition
-                answer = new ConcurrentRequestsThrottleDefinition(maximumConcurrentRequests, correlationExpressionKey);
+    public ThrottleDefinition throttle(Expression maximumConcurrentRequests, Expression correlationExpressionKey) {
+        ThrottleDefinition answer = new ThrottleDefinition(maximumConcurrentRequests, correlationExpressionKey);
         addOutput(answer);
         return answer;
     }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java
similarity index 56%
rename from core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java
rename to core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java
index 024a5f9b10e..60e1551a3f1 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/ConcurrentRequestsThrottleDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottleDefinition.java
@@ -38,12 +38,15 @@ import org.apache.camel.spi.Metadata;
 @XmlRootElement(name = "throttle")
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(propOrder = { "expression", "correlationExpression" })
-public class ConcurrentRequestsThrottleDefinition
-        extends ExpressionNode implements ExecutorServiceAwareDefinition<ConcurrentRequestsThrottleDefinition> {
+public class ThrottleDefinition extends ExpressionNode implements ExecutorServiceAwareDefinition<ThrottleDefinition> {
 
     @XmlTransient
     private ExecutorService executorServiceBean;
 
+    @XmlAttribute
+    @Metadata(javaType = "org.apache.camel.model.ThrottlingMode", defaultValue = "TotalRequests",
+              enums = "TotalRequests,ConcurrentRequests")
+    private String mode;
     @XmlElement(name = "correlationExpression")
     private ExpressionSubElementDefinition correlationExpression;
     @XmlAttribute
@@ -58,29 +61,55 @@ public class ConcurrentRequestsThrottleDefinition
     @XmlAttribute
     @Metadata(label = "advanced", javaType = "java.lang.Boolean")
     private String rejectExecution;
+    @XmlAttribute
+    @Metadata(defaultValue = "1000", javaType = "java.time.Duration")
+    private String timePeriodMillis;
 
-    public ConcurrentRequestsThrottleDefinition() {
+    public ThrottleDefinition() {
+        totalRequestsMode();
     }
 
-    public ConcurrentRequestsThrottleDefinition(Expression maximumConcurrentRequests) {
-        super(maximumConcurrentRequests);
+    public ThrottleDefinition(Expression maximumRequestsPerPeriod) {
+        super(maximumRequestsPerPeriod);
+
+        totalRequestsMode();
     }
 
-    public ConcurrentRequestsThrottleDefinition(Expression maximumConcurrentRequests, Expression correlationExpression) {
-        this(ExpressionNodeHelper.toExpressionDefinition(maximumConcurrentRequests), correlationExpression);
+    public ThrottleDefinition(Expression maximumRequestsPerPeriod, Expression correlationExpression) {
+        this(ExpressionNodeHelper.toExpressionDefinition(maximumRequestsPerPeriod), correlationExpression);
     }
 
-    private ConcurrentRequestsThrottleDefinition(ExpressionDefinition maximumConcurrentRequests, Expression correlationExpression) {
-        super(maximumConcurrentRequests);
+    private ThrottleDefinition(ExpressionDefinition maximumRequestsPerPeriod, Expression correlationExpression) {
+        super(maximumRequestsPerPeriod);
 
         ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition();
         cor.setExpressionType(ExpressionNodeHelper.toExpressionDefinition(correlationExpression));
         setCorrelationExpression(cor);
+
+        totalRequestsMode();
+    }
+
+    public ThrottleDefinition totalRequestsMode() {
+        this.mode = ThrottlingMode.TotalRequests.name();
+        return this;
+    }
+
+    public ThrottleDefinition concurrentRequestsMode() {
+        this.mode = ThrottlingMode.ConcurrentRequests.name();
+        return this;
     }
 
     @Override
     public String toString() {
-        return "Throttle[" + getExpression() + "]";
+        return "Throttle[" + description() + "]";
+    }
+
+    protected String description() {
+        if (mode.equals(ThrottlingMode.TotalRequests.name())) {
+            return getExpression() + " request per " + getTimePeriodMillis() + " millis";
+        } else {
+            return getExpression() + " maximum concurrent requests";
+        }
     }
 
     @Override
@@ -90,35 +119,95 @@ public class ConcurrentRequestsThrottleDefinition
 
     @Override
     public String getLabel() {
-        return "throttle[" + getExpression() + "]";
+        return "throttle[" + description() + "]";
     }
 
     // Fluent API
     // -------------------------------------------------------------------------
     /**
-     * Sets the maximum number of concurrent requests
+     * Sets the time period during which the maximum request count is valid for
      *
-     * @param  maximumConcurrentRequests the maximum number of concurrent requests
+     * @param  timePeriodMillis period in millis
+     * @return                  the builder
+     */
+    public ThrottleDefinition timePeriodMillis(long timePeriodMillis) {
+        return timePeriodMillis(Long.toString(timePeriodMillis));
+    }
+
+    /**
+     * Sets the time period during which the maximum request count is valid for
+     *
+     * @param  timePeriodMillis period in millis
+     * @return                  the builder
+     */
+    public ThrottleDefinition timePeriodMillis(String timePeriodMillis) {
+        setTimePeriodMillis(timePeriodMillis);
+        return this;
+    }
+
+    /**
+     * Sets the maximum number of requests
+     *
+     * @param  maximumConcurrentRequests the maximum number of requests (according to the mode in use - either
+     *                                   concurrent or by time period)
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition maximumConcurrentRequests(long maximumConcurrentRequests) {
+    public ThrottleDefinition maximumRequests(long maximumConcurrentRequests) {
         setExpression(
                 ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.constantExpression(maximumConcurrentRequests)));
         return this;
     }
 
     /**
-     * Sets the number of concurrent requests
+     * Sets the maximum number of requests
      *
-     * @param  maximumConcurrentRequests the maximum number of concurrent requests
+     * @param  maximumConcurrentRequests the maximum number of requests (according to the mode in use - either
+     *                                   concurrent or by time period)
      * @return                           the builder
      */
-    public ConcurrentRequestsThrottleDefinition maximumConcurrentRequests(String maximumConcurrentRequests) {
+    public ThrottleDefinition maximumRequests(String maximumConcurrentRequests) {
         setExpression(
-                ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.simpleExpression(maximumConcurrentRequests)));
+                ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.constantExpression(maximumConcurrentRequests)));
         return this;
     }
 
+    /**
+     * Sets the time period during which the maximum request count per period
+     *
+     * @param      maximumRequestsPerPeriod the maximum request count number per time period
+     * @deprecated                          Use {@link #maximumRequests(long)}
+     * @return                              the builder
+     */
+    @Deprecated(since = "4.4.0")
+    public ThrottleDefinition maximumRequestsPerPeriod(long maximumRequestsPerPeriod) {
+        if (ThrottlingMode.toMode(mode) == ThrottlingMode.TotalRequests) {
+            setExpression(
+                    ExpressionNodeHelper.toExpressionDefinition(
+                            ExpressionBuilder.constantExpression(maximumRequestsPerPeriod)));
+            return this;
+        } else {
+            throw new IllegalArgumentException("Maximum requests per period can only be set when using total requests mode");
+        }
+    }
+
+    /**
+     * Sets the time period during which the maximum request count per period
+     *
+     * @param      maximumRequestsPerPeriod the maximum request count number per time period
+     * @deprecated                          Use {@link #maximumRequests(long)}
+     * @return                              the builder
+     */
+    @Deprecated(since = "4.4.0")
+    public ThrottleDefinition maximumRequestsPerPeriod(String maximumRequestsPerPeriod) {
+        if (ThrottlingMode.toMode(mode) == ThrottlingMode.TotalRequests) {
+            setExpression(
+                    ExpressionNodeHelper.toExpressionDefinition(ExpressionBuilder.simpleExpression(maximumRequestsPerPeriod)));
+            return this;
+        } else {
+            throw new IllegalArgumentException("Maximum requests per period can only be set when using total requests mode");
+        }
+    }
+
     /**
      * To use a correlation expression that can throttle by the given key instead of overall throttling
      *
@@ -126,7 +215,7 @@ public class ConcurrentRequestsThrottleDefinition
      *                               overall throttling
      * @return                       the builder
      */
-    public ConcurrentRequestsThrottleDefinition correlationExpression(long correlationExpression) {
+    public ThrottleDefinition correlationExpression(long correlationExpression) {
         return correlationExpression(ExpressionBuilder.constantExpression(correlationExpression));
     }
 
@@ -137,7 +226,7 @@ public class ConcurrentRequestsThrottleDefinition
      *                               overall throttling
      * @return                       the builder
      */
-    public ConcurrentRequestsThrottleDefinition correlationExpression(Expression correlationExpression) {
+    public ThrottleDefinition correlationExpression(Expression correlationExpression) {
         ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition();
         cor.setExpressionType(ExpressionNodeHelper.toExpressionDefinition(correlationExpression));
         setCorrelationExpression(cor);
@@ -152,7 +241,7 @@ public class ConcurrentRequestsThrottleDefinition
      * @param  callerRunsWhenRejected whether or not the caller should run
      * @return                        the builder
      */
-    public ConcurrentRequestsThrottleDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) {
+    public ThrottleDefinition callerRunsWhenRejected(boolean callerRunsWhenRejected) {
         return callerRunsWhenRejected(Boolean.toString(callerRunsWhenRejected));
     }
 
@@ -164,7 +253,7 @@ public class ConcurrentRequestsThrottleDefinition
      * @param  callerRunsWhenRejected whether or not the caller should run
      * @return                        the builder
      */
-    public ConcurrentRequestsThrottleDefinition callerRunsWhenRejected(String callerRunsWhenRejected) {
+    public ThrottleDefinition callerRunsWhenRejected(String callerRunsWhenRejected) {
         setCallerRunsWhenRejected(callerRunsWhenRejected);
         return this;
     }
@@ -174,7 +263,7 @@ public class ConcurrentRequestsThrottleDefinition
      *
      * @return the builder
      */
-    public ConcurrentRequestsThrottleDefinition asyncDelayed() {
+    public ThrottleDefinition asyncDelayed() {
         return asyncDelayed(true);
     }
 
@@ -183,7 +272,7 @@ public class ConcurrentRequestsThrottleDefinition
      *
      * @return the builder
      */
-    public ConcurrentRequestsThrottleDefinition asyncDelayed(boolean asyncDelayed) {
+    public ThrottleDefinition asyncDelayed(boolean asyncDelayed) {
         return asyncDelayed(Boolean.toString(asyncDelayed));
     }
 
@@ -192,7 +281,7 @@ public class ConcurrentRequestsThrottleDefinition
      *
      * @return the builder
      */
-    public ConcurrentRequestsThrottleDefinition asyncDelayed(String asyncDelayed) {
+    public ThrottleDefinition asyncDelayed(String asyncDelayed) {
         setAsyncDelayed(asyncDelayed);
         return this;
     }
@@ -206,7 +295,7 @@ public class ConcurrentRequestsThrottleDefinition
      * @param  rejectExecution throw the RejectExecutionException if the exchange exceeds the request limit
      * @return                 the builder
      */
-    public ConcurrentRequestsThrottleDefinition rejectExecution(boolean rejectExecution) {
+    public ThrottleDefinition rejectExecution(boolean rejectExecution) {
         return rejectExecution(Boolean.toString(rejectExecution));
     }
 
@@ -219,7 +308,7 @@ public class ConcurrentRequestsThrottleDefinition
      * @param  rejectExecution throw the RejectExecutionException if the exchange exceeds the request limit
      * @return                 the builder
      */
-    public ConcurrentRequestsThrottleDefinition rejectExecution(String rejectExecution) {
+    public ThrottleDefinition rejectExecution(String rejectExecution) {
         setRejectExecution(rejectExecution);
         return this;
     }
@@ -231,7 +320,7 @@ public class ConcurrentRequestsThrottleDefinition
      * @return                 the builder
      */
     @Override
-    public ConcurrentRequestsThrottleDefinition executorService(ExecutorService executorService) {
+    public ThrottleDefinition executorService(ExecutorService executorService) {
         this.executorServiceBean = executorService;
         return this;
     }
@@ -243,11 +332,25 @@ public class ConcurrentRequestsThrottleDefinition
      * @return                 the builder
      */
     @Override
-    public ConcurrentRequestsThrottleDefinition executorService(String executorService) {
+    public ThrottleDefinition executorService(String executorService) {
         setExecutorService(executorService);
         return this;
     }
 
+    /**
+     * Sets the throttling mode to one of the available modes enumerated in ThrottlingMode
+     *
+     * @param  mode The throttling mode as a string parameter. It currently accepts one of 'TotalRequests' or
+     *              `ConcurrentRequests`
+     * @see         ThrottlingMode
+     * @return      the builder
+     */
+    public ThrottleDefinition mode(String mode) {
+        setMode(mode);
+
+        return this;
+    }
+
     // Properties
     // -------------------------------------------------------------------------
 
@@ -270,6 +373,22 @@ public class ConcurrentRequestsThrottleDefinition
         super.setExpression(expression);
     }
 
+    public String getTimePeriodMillis() {
+        if (ThrottlingMode.toMode(mode) == ThrottlingMode.TotalRequests) {
+            return timePeriodMillis;
+        }
+
+        throw new IllegalArgumentException("Time period in millis can only be obtained when using total requests mode");
+    }
+
+    public void setTimePeriodMillis(String timePeriodMillis) {
+        if (ThrottlingMode.toMode(mode) == ThrottlingMode.TotalRequests) {
+            this.timePeriodMillis = timePeriodMillis;
+        } else {
+            throw new IllegalArgumentException("Time period in millis can only be set when using total requests mode");
+        }
+    }
+
     public String getAsyncDelayed() {
         return asyncDelayed;
     }
@@ -313,4 +432,19 @@ public class ConcurrentRequestsThrottleDefinition
     public void setExecutorService(String executorService) {
         this.executorService = executorService;
     }
+
+    public String getMode() {
+        return mode;
+    }
+
+    /**
+     * Sets the throttling mode to one of the available modes enumerated in ThrottlingMode
+     *
+     * @param mode The throttling mode as a string parameter. It currently accepts one of 'TotalRequests' or
+     *             `ConcurrentRequests`
+     * @see        ThrottlingMode
+     */
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
 }
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottlingMode.java
similarity index 53%
copy from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
copy to core/camel-core-model/src/main/java/org/apache/camel/model/ThrottlingMode.java
index 2b457f2dde5..daba0fb465a 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ThrottlingMode.java
@@ -14,18 +14,31 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor.throttle;
 
-import org.apache.camel.CamelContext;
-import org.apache.camel.processor.throttle.ThrottlerMethodCallTest;
+package org.apache.camel.model;
 
-import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+import jakarta.xml.bind.annotation.XmlEnum;
+import jakarta.xml.bind.annotation.XmlType;
 
-public class SpringThrottlerMethodCallTest extends ThrottlerMethodCallTest {
+@XmlType
+@XmlEnum
+public enum ThrottlingMode {
+    /**
+     * Uses a throttling mode that considers the total number of requests over defined period of time
+     */
+    TotalRequests,
 
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        return createSpringCamelContext(this,
-                "org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml");
+    /**
+     * Uses a throttling mode that uses a leaky-bucket algorithm to limit the outflow based on a maximum number of
+     * concurrent requests
+     */
+    ConcurrentRequests;
+
+    public static ThrottlingMode toMode(String mode) {
+        if (mode.equals(ThrottlingMode.TotalRequests.name())) {
+            return ThrottlingMode.TotalRequests;
+        }
+
+        return ThrottlingMode.ConcurrentRequests;
     }
 }
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/AbstractThrottler.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/AbstractThrottler.java
new file mode 100644
index 00000000000..7970554e746
--- /dev/null
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/AbstractThrottler.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.processor;
+
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.Traceable;
+import org.apache.camel.spi.IdAware;
+import org.apache.camel.spi.RouteIdAware;
+import org.apache.camel.support.AsyncProcessorSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractThrottler extends AsyncProcessorSupport implements Traceable, IdAware, RouteIdAware, Throttler {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractThrottler.class);
+
+    protected static final String DEFAULT_KEY = "CamelThrottlerDefaultKey";
+    protected static final String PROPERTY_EXCHANGE_QUEUED_TIMESTAMP = "CamelThrottlerExchangeQueuedTimestamp";
+    protected static final String PROPERTY_EXCHANGE_STATE = "CamelThrottlerExchangeState";
+    protected final ScheduledExecutorService asyncExecutor;
+    protected final boolean shutdownAsyncExecutor;
+    protected final CamelContext camelContext;
+    protected final Expression correlationExpression;
+    protected String id;
+    protected String routeId;
+    protected boolean rejectExecution;
+    protected boolean asyncDelayed;
+    protected boolean callerRunsWhenRejected = true;
+    protected Expression maxRequestsExpression;
+
+    AbstractThrottler(final ScheduledExecutorService asyncExecutor, final boolean shutdownAsyncExecutor,
+                      final CamelContext camelContext, final boolean rejectExecution, Expression correlation,
+                      final Expression maxRequestsExpression) {
+        this.asyncExecutor = asyncExecutor;
+        this.shutdownAsyncExecutor = shutdownAsyncExecutor;
+        this.camelContext = camelContext;
+        this.rejectExecution = rejectExecution;
+        this.correlationExpression = correlation;
+        this.maxRequestsExpression = ObjectHelper.notNull(maxRequestsExpression, "maxConcurrentRequestsExpression");
+        ;
+    }
+
+    protected static boolean handleInterrupt(
+            Exchange exchange, AsyncCallback callback, InterruptedException e, boolean doneSync) {
+        // determine if we can still run, or the camel context is forcing a shutdown
+        boolean forceShutdown = exchange.getContext().getShutdownStrategy().isForceShutdown();
+        if (forceShutdown) {
+            String msg = "Run not allowed as ShutdownStrategy is forcing shutting down, will reject executing exchange: "
+                         + exchange;
+            LOG.debug(msg);
+            exchange.setException(new RejectedExecutionException(msg, e));
+        } else {
+            exchange.setException(e);
+        }
+        callback.done(doneSync);
+        return doneSync;
+    }
+
+    protected static boolean handleException(Exchange exchange, AsyncCallback callback, Exception t, boolean doneSync) {
+        exchange.setException(t);
+        callback.done(doneSync);
+        return doneSync;
+    }
+
+    @Override
+    public boolean isRejectExecution() {
+        return rejectExecution;
+    }
+
+    public void setRejectExecution(boolean rejectExecution) {
+        this.rejectExecution = rejectExecution;
+    }
+
+    @Override
+    public boolean isAsyncDelayed() {
+        return asyncDelayed;
+    }
+
+    public void setAsyncDelayed(boolean asyncDelayed) {
+        this.asyncDelayed = asyncDelayed;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    @Override
+    public String getRouteId() {
+        return routeId;
+    }
+
+    @Override
+    public void setRouteId(String routeId) {
+        this.routeId = routeId;
+    }
+
+    @Override
+    public boolean isCallerRunsWhenRejected() {
+        return callerRunsWhenRejected;
+    }
+
+    public void setCallerRunsWhenRejected(boolean callerRunsWhenRejected) {
+        this.callerRunsWhenRejected = callerRunsWhenRejected;
+    }
+
+    /**
+     * Sets the maximum number of concurrent requests.
+     */
+    @Override
+    public void setMaximumRequestsExpression(Expression maxConcurrentRequestsExpression) {
+        this.maxRequestsExpression = maxConcurrentRequestsExpression;
+    }
+
+    public Expression getMaximumRequestsExpression() {
+        return maxRequestsExpression;
+    }
+
+    protected enum State {
+        SYNC,
+        ASYNC,
+        ASYNC_REJECTED
+    }
+
+    @Override
+    public abstract String getMode();
+}
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
index 3c851b618ff..c4630109516 100644
--- a/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/ConcurrentRequestsThrottler.java
@@ -31,11 +31,7 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
 import org.apache.camel.RuntimeExchangeException;
-import org.apache.camel.Traceable;
-import org.apache.camel.spi.IdAware;
-import org.apache.camel.spi.RouteIdAware;
 import org.apache.camel.spi.Synchronization;
-import org.apache.camel.support.AsyncProcessorSupport;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -54,7 +50,7 @@ import org.slf4j.LoggerFactory;
  * The throttling mechanism is a Semaphore with maxConcurrentRequests permits on it. Callers trying to acquire a permit
  * will block if necessary when maxConcurrentRequests permits have been acquired.
  */
-public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implements Traceable, IdAware, RouteIdAware {
+public class ConcurrentRequestsThrottler extends AbstractThrottler {
 
     private static final Logger LOG = LoggerFactory.getLogger(ConcurrentRequestsThrottler.class);
 
@@ -70,29 +66,12 @@ public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implement
         ASYNC_REJECTED
     }
 
-    private final CamelContext camelContext;
-    private final ScheduledExecutorService asyncExecutor;
-    private final boolean shutdownAsyncExecutor;
-    private String id;
-    private String routeId;
-    private Expression maxConcurrentRequestsExpression;
-    private boolean rejectExecution;
-    private boolean asyncDelayed;
-    private boolean callerRunsWhenRejected = true;
-    private final Expression correlationExpression;
     private final Map<String, ThrottlingState> states = new ConcurrentHashMap<>();
 
-    public ConcurrentRequestsThrottler(final CamelContext camelContext, final Expression maxConcurrentRequestsExpression,
-                     final ScheduledExecutorService asyncExecutor, final boolean shutdownAsyncExecutor,
-                     final boolean rejectExecution, Expression correlation) {
-        this.camelContext = camelContext;
-        this.rejectExecution = rejectExecution;
-        this.shutdownAsyncExecutor = shutdownAsyncExecutor;
-
-        ObjectHelper.notNull(maxConcurrentRequestsExpression, "maxConcurrentRequestsExpression");
-        this.maxConcurrentRequestsExpression = maxConcurrentRequestsExpression;
-        this.asyncExecutor = asyncExecutor;
-        this.correlationExpression = correlation;
+    public ConcurrentRequestsThrottler(final CamelContext camelContext, final Expression maxRequestsExpression,
+                                       final ScheduledExecutorService asyncExecutor, final boolean shutdownAsyncExecutor,
+                                       final boolean rejectExecution, Expression correlation) {
+        super(asyncExecutor, shutdownAsyncExecutor, camelContext, rejectExecution, correlation, maxRequestsExpression);
     }
 
     @Override
@@ -165,29 +144,6 @@ public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implement
         return doneSync;
     }
 
-    private static boolean handleException(Exchange exchange, AsyncCallback callback, Exception t, boolean doneSync) {
-        exchange.setException(t);
-        callback.done(doneSync);
-        return doneSync;
-    }
-
-    private static boolean handleInterrupt(
-            Exchange exchange, AsyncCallback callback, InterruptedException e, boolean doneSync) {
-        Thread.currentThread().interrupt();
-        // determine if we can still run, or the camel context is forcing a shutdown
-        boolean forceShutdown = exchange.getContext().getShutdownStrategy().isForceShutdown();
-        if (forceShutdown) {
-            String msg = "Run not allowed as ShutdownStrategy is forcing shutting down, will reject executing exchange: "
-                         + exchange;
-            LOG.debug(msg);
-            exchange.setException(new RejectedExecutionException(msg, e));
-        } else {
-            exchange.setException(e);
-        }
-        callback.done(doneSync);
-        return doneSync;
-    }
-
     private static void doThrottle(Exchange exchange, ThrottlingState throttlingState, State state, long queuedStart)
             throws InterruptedException {
         // block waiting for a permit
@@ -327,7 +283,7 @@ public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implement
          * Evaluates the maxConcurrentRequestsExpression and adjusts the throttle rate up or down.
          */
         public synchronized void calculateAndSetMaxConcurrentRequestsExpression(final Exchange exchange) throws Exception {
-            Integer newThrottle = maxConcurrentRequestsExpression.evaluate(exchange, Integer.class);
+            Integer newThrottle = getMaximumRequestsExpression().evaluate(exchange, Integer.class);
 
             if (newThrottle != null && newThrottle < 0) {
                 throw new IllegalStateException("The maximumConcurrentRequests must be a positive number, was: " + newThrottle);
@@ -335,7 +291,7 @@ public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implement
 
             if (newThrottle == null && throttleRate == 0) {
                 throw new RuntimeExchangeException(
-                        "The maxConcurrentRequestsExpression was evaluated as null: " + maxConcurrentRequestsExpression,
+                        "The maxConcurrentRequestsExpression was evaluated as null: " + getMaximumRequestsExpression(),
                         exchange);
             }
 
@@ -401,76 +357,27 @@ public class ConcurrentRequestsThrottler extends AsyncProcessorSupport implement
         }
     }
 
-    public boolean isRejectExecution() {
-        return rejectExecution;
-    }
-
-    public void setRejectExecution(boolean rejectExecution) {
-        this.rejectExecution = rejectExecution;
-    }
-
-    public boolean isAsyncDelayed() {
-        return asyncDelayed;
-    }
-
-    public void setAsyncDelayed(boolean asyncDelayed) {
-        this.asyncDelayed = asyncDelayed;
-    }
-
-    public boolean isCallerRunsWhenRejected() {
-        return callerRunsWhenRejected;
-    }
-
-    public void setCallerRunsWhenRejected(boolean callerRunsWhenRejected) {
-        this.callerRunsWhenRejected = callerRunsWhenRejected;
-    }
-
-    @Override
-    public String getId() {
-        return id;
-    }
-
     @Override
-    public void setId(final String id) {
-        this.id = id;
-    }
-
-    @Override
-    public String getRouteId() {
-        return routeId;
-    }
-
-    @Override
-    public void setRouteId(String routeId) {
-        this.routeId = routeId;
-    }
-
-    /**
-     * Sets the maximum number of concurrent requests.
-     */
-    public void setMaximumConcurrentRequestsExpression(Expression maxConcurrentRequestsExpression) {
-        this.maxConcurrentRequestsExpression = maxConcurrentRequestsExpression;
-    }
-
-    public Expression getMaximumConcurrentRequests() {
-        return maxConcurrentRequestsExpression;
+    public String getMode() {
+        return "ConcurrentRequests";
     }
 
     /**
      * Gets the current maximum request. If it is grouped throttling applied with correlationExpression then the max
      * within the group will return
      */
-    public int getCurrentMaximumConcurrentRequests() {
+    @Override
+    public int getCurrentMaximumRequests() {
         return states.values().stream().mapToInt(ThrottlingState::getThrottleRate).max().orElse(0);
     }
 
     @Override
     public String getTraceLabel() {
-        return "throttle[" + maxConcurrentRequestsExpression + "]";
+        return "throttle[" + getMaximumRequestsExpression() + "]";
     }
 
     @Override
     public String toString() {
-        return id;
+        return getId();
     }
 }
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java
similarity index 59%
copy from components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
copy to core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java
index 2b457f2dde5..4c21269bd79 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/throttle/SpringThrottlerMethodCallTest.java
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/Throttler.java
@@ -14,18 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.processor.throttle;
 
-import org.apache.camel.CamelContext;
-import org.apache.camel.processor.throttle.ThrottlerMethodCallTest;
+package org.apache.camel.processor;
 
-import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.Processor;
 
-public class SpringThrottlerMethodCallTest extends ThrottlerMethodCallTest {
+public interface Throttler extends Processor {
+    boolean isRejectExecution();
 
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        return createSpringCamelContext(this,
-                "org/apache/camel/spring/processor/ThrottlerMethodCallTest.xml");
-    }
+    boolean isAsyncDelayed();
+
+    boolean isCallerRunsWhenRejected();
+
+    void setMaximumRequestsExpression(Expression maxConcurrentRequestsExpression);
+
+    int getCurrentMaximumRequests();
+
+    String getMode();
 }
diff --git a/core/camel-core-processor/src/main/java/org/apache/camel/processor/TotalRequestsThrottler.java b/core/camel-core-processor/src/main/java/org/apache/camel/processor/TotalRequestsThrottler.java
new file mode 100644
index 00000000000..7ce539b0356
--- /dev/null
+++ b/core/camel-core-processor/src/main/java/org/apache/camel/processor/TotalRequestsThrottler.java
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.DelayQueue;
+import java.util.concurrent.Delayed;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.RuntimeExchangeException;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A <a href="http://camel.apache.org/throttler.html">Throttler</a> will set a limit on the maximum number of message
+ * exchanges which can be sent to a processor within a specific time period.
+ * <p/>
+ * This pattern can be extremely useful if you have some external system which meters access; such as only allowing 100
+ * requests per second; or if huge load can cause a particular system to malfunction or to reduce its throughput you
+ * might want to introduce some throttling.
+ *
+ * This throttle implementation is thread-safe and is therefore safe to be used by multiple concurrent threads in a
+ * single route.
+ *
+ * The throttling mechanism is a DelayQueue with maxRequestsPerPeriod permits on it. Each permit is set to be delayed by
+ * timePeriodMillis (except when the throttler is initialized or the throttle rate increased, then there is no delay for
+ * those permits). Callers trying to acquire a permit from the DelayQueue will block if necessary. The end result is a
+ * rolling window of time. Where from the callers point of view in the last timePeriodMillis no more than
+ * maxRequestsPerPeriod have been allowed to be acquired.
+ */
+public class TotalRequestsThrottler extends AbstractThrottler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TotalRequestsThrottler.class);
+
+    private long timePeriodMillis;
+    private final long cleanPeriodMillis;
+    private final Expression correlationExpression;
+    private final Map<String, ThrottlingState> states = new ConcurrentHashMap<>();
+
+    public TotalRequestsThrottler(final CamelContext camelContext, final Expression maxRequestsExpression,
+                                  final long timePeriodMillis,
+                                  final ScheduledExecutorService asyncExecutor, final boolean shutdownAsyncExecutor,
+                                  final boolean rejectExecution, Expression correlation) {
+        super(asyncExecutor, shutdownAsyncExecutor, camelContext, rejectExecution, correlation, maxRequestsExpression);
+
+        if (timePeriodMillis <= 0) {
+            throw new IllegalArgumentException("TimePeriodMillis should be a positive number, was: " + timePeriodMillis);
+        }
+        this.timePeriodMillis = timePeriodMillis;
+        this.cleanPeriodMillis = timePeriodMillis * 10;
+        this.correlationExpression = correlation;
+    }
+
+    @Override
+    public boolean process(final Exchange exchange, final AsyncCallback callback) {
+        long queuedStart = 0;
+        if (LOG.isTraceEnabled()) {
+            queuedStart = exchange.getProperty(PROPERTY_EXCHANGE_QUEUED_TIMESTAMP, 0L, Long.class);
+            exchange.removeProperty(PROPERTY_EXCHANGE_QUEUED_TIMESTAMP);
+        }
+        State state = exchange.getProperty(PROPERTY_EXCHANGE_STATE, State.SYNC, State.class);
+        exchange.removeProperty(PROPERTY_EXCHANGE_STATE);
+        boolean doneSync = state == State.SYNC || state == State.ASYNC_REJECTED;
+
+        try {
+            if (!isRunAllowed()) {
+                throw new RejectedExecutionException("Run is not allowed");
+            }
+
+            String key = DEFAULT_KEY;
+            if (correlationExpression != null) {
+                key = correlationExpression.evaluate(exchange, String.class);
+            }
+            ThrottlingState throttlingState = states.computeIfAbsent(key, ThrottlingState::new);
+            throttlingState.calculateAndSetMaxRequestsPerPeriod(exchange);
+
+            ThrottlePermit permit = throttlingState.poll();
+
+            if (permit == null) {
+                if (isRejectExecution()) {
+                    throw new ThrottlerRejectedExecutionException(
+                            "Exceeded the max throttle rate of "
+                                                                  + throttlingState.getThrottleRate() + " within "
+                                                                  + timePeriodMillis + "ms");
+                } else {
+                    // delegate to async pool
+                    if (isAsyncDelayed() && !exchange.isTransacted() && state == State.SYNC) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug(
+                                    "Throttle rate exceeded but AsyncDelayed enabled, so queueing for async processing, exchangeId: {}",
+                                    exchange.getExchangeId());
+                        }
+                        return processAsynchronously(exchange, callback, throttlingState);
+                    }
+
+                    // block waiting for a permit
+                    long start = 0;
+                    long elapsed = 0;
+                    if (LOG.isTraceEnabled()) {
+                        start = System.currentTimeMillis();
+                    }
+                    permit = throttlingState.take();
+                    if (LOG.isTraceEnabled()) {
+                        elapsed = System.currentTimeMillis() - start;
+                    }
+                    throttlingState.enqueue(permit, exchange);
+
+                    if (state == State.ASYNC) {
+                        if (LOG.isTraceEnabled()) {
+                            long queuedTime = start - queuedStart;
+                            if (LOG.isTraceEnabled()) {
+                                LOG.trace("Queued for {}ms, Throttled for {}ms, exchangeId: {}", queuedTime, elapsed,
+                                        exchange.getExchangeId());
+                            }
+                        }
+                    } else {
+                        if (LOG.isTraceEnabled()) {
+                            LOG.trace("Throttled for {}ms, exchangeId: {}", elapsed, exchange.getExchangeId());
+                        }
+                    }
+                }
+            } else {
+                throttlingState.enqueue(permit, exchange);
+
+                if (state == State.ASYNC) {
+                    if (LOG.isTraceEnabled()) {
+                        long queuedTime = System.currentTimeMillis() - queuedStart;
+                        LOG.trace("Queued for {}ms, No throttling applied (throttle cleared while queued), for exchangeId: {}",
+                                queuedTime, exchange.getExchangeId());
+                    }
+                } else {
+                    if (LOG.isTraceEnabled()) {
+                        LOG.trace("No throttling applied to exchangeId: {}", exchange.getExchangeId());
+                    }
+                }
+            }
+
+            callback.done(doneSync);
+            return doneSync;
+
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            return handleInterrupt(exchange, callback, e, doneSync);
+        } catch (Exception e) {
+            return handleException(exchange, callback, e, doneSync);
+        }
+    }
+
+    /**
+     * Delegate blocking on the DelayQueue to an asyncExecutor. Except if the executor rejects the submission and
+     * isCallerRunsWhenRejected() is enabled, then this method will delegate back to process(), but not before changing
+     * the exchange state to stop any recursion.
+     */
+    protected boolean processAsynchronously(
+            final Exchange exchange, final AsyncCallback callback, ThrottlingState throttlingState) {
+        try {
+            if (LOG.isTraceEnabled()) {
+                exchange.setProperty(PROPERTY_EXCHANGE_QUEUED_TIMESTAMP, System.nanoTime());
+            }
+            exchange.setProperty(PROPERTY_EXCHANGE_STATE, State.ASYNC);
+            long delay = throttlingState.peek().getDelay(TimeUnit.NANOSECONDS);
+            asyncExecutor.schedule(() -> process(exchange, callback), delay, TimeUnit.NANOSECONDS);
+            return false;
+        } catch (final RejectedExecutionException e) {
+            if (isCallerRunsWhenRejected()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("AsyncExecutor is full, rejected exchange will run in the current thread, exchangeId: {}",
+                            exchange.getExchangeId());
+                }
+                exchange.setProperty(PROPERTY_EXCHANGE_STATE, State.ASYNC_REJECTED);
+                return process(exchange, callback);
+            }
+            throw e;
+        }
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        if (isAsyncDelayed()) {
+            ObjectHelper.notNull(asyncExecutor, "executorService", this);
+        }
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        if (shutdownAsyncExecutor && asyncExecutor != null) {
+            camelContext.getExecutorServiceManager().shutdownNow(asyncExecutor);
+        }
+        states.clear();
+        super.doShutdown();
+    }
+
+    private class ThrottlingState {
+        private final String key;
+        private final DelayQueue<ThrottlePermit> delayQueue = new DelayQueue<>();
+        private final AtomicReference<ScheduledFuture<?>> cleanFuture = new AtomicReference<>();
+        private volatile int throttleRate;
+
+        ThrottlingState(String key) {
+            this.key = key;
+        }
+
+        public int getThrottleRate() {
+            return throttleRate;
+        }
+
+        public ThrottlePermit poll() {
+            return delayQueue.poll();
+        }
+
+        public ThrottlePermit peek() {
+            return delayQueue.peek();
+        }
+
+        public ThrottlePermit take() throws InterruptedException {
+            return delayQueue.take();
+        }
+
+        public void clean() {
+            states.remove(key);
+        }
+
+        /**
+         * Returns a permit to the DelayQueue, first resetting it's delay to be relative to now.
+         */
+        public void enqueue(final ThrottlePermit permit, final Exchange exchange) {
+            permit.setDelayMs(getTimePeriodMillis());
+            delayQueue.put(permit);
+            try {
+                ScheduledFuture<?> next = asyncExecutor.schedule(this::clean, cleanPeriodMillis, TimeUnit.MILLISECONDS);
+                ScheduledFuture<?> prev = cleanFuture.getAndSet(next);
+                if (prev != null) {
+                    prev.cancel(false);
+                }
+                // try and incur the least amount of overhead while releasing permits back to the queue
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Permit released, for exchangeId: {}", exchange.getExchangeId());
+                }
+            } catch (RejectedExecutionException e) {
+                LOG.debug("Throttling queue cleaning rejected", e);
+            }
+        }
+
+        /**
+         * Evaluates the maxRequestsPerPeriodExpression and adjusts the throttle rate up or down.
+         */
+        public synchronized void calculateAndSetMaxRequestsPerPeriod(final Exchange exchange) throws Exception {
+            Integer newThrottle = TotalRequestsThrottler.this.getMaximumRequestsExpression().evaluate(exchange, Integer.class);
+
+            if (newThrottle != null && newThrottle < 0) {
+                throw new IllegalStateException("The maximumRequestsPerPeriod must be a positive number, was: " + newThrottle);
+            }
+
+            if (newThrottle == null && throttleRate == 0) {
+                throw new RuntimeExchangeException(
+                        "The maxRequestsPerPeriodExpression was evaluated as null: "
+                                                   + TotalRequestsThrottler.this.getMaximumRequestsExpression(),
+                        exchange);
+            }
+
+            if (newThrottle != null) {
+                if (newThrottle != throttleRate) {
+                    // decrease
+                    if (throttleRate > newThrottle) {
+                        int delta = throttleRate - newThrottle;
+
+                        // discard any permits that are needed to decrease throttling
+                        while (delta > 0) {
+                            delayQueue.take();
+                            delta--;
+                            if (LOG.isTraceEnabled()) {
+                                LOG.trace("Permit discarded due to throttling rate decrease, triggered by ExchangeId: {}",
+                                        exchange.getExchangeId());
+                            }
+                        }
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Throttle rate decreased from {} to {}, triggered by ExchangeId: {}", throttleRate,
+                                    newThrottle, exchange.getExchangeId());
+                        }
+
+                        // increase
+                    } else if (newThrottle > throttleRate) {
+                        int delta = newThrottle - throttleRate;
+                        for (int i = 0; i < delta; i++) {
+                            delayQueue.put(new ThrottlePermit(-1));
+                        }
+                        if (throttleRate == 0) {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("Initial throttle rate set to {}, triggered by ExchangeId: {}", newThrottle,
+                                        exchange.getExchangeId());
+                            }
+                        } else {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("Throttle rate increase from {} to {}, triggered by ExchangeId: {}", throttleRate,
+                                        newThrottle, exchange.getExchangeId());
+                            }
+                        }
+                    }
+                    throttleRate = newThrottle;
+                }
+            }
+        }
+    }
+
+    /**
+     * Permit that implements the Delayed interface needed by DelayQueue.
+     */
+    private static class ThrottlePermit implements Delayed {
+        private volatile long scheduledTime;
+
+        ThrottlePermit(final long delayMs) {
+            setDelayMs(delayMs);
+        }
+
+        public void setDelayMs(final long delayMs) {
+            this.scheduledTime = System.currentTimeMillis() + delayMs;
+        }
+
+        @Override
+        public long getDelay(final TimeUnit unit) {
+            return unit.convert(scheduledTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+        }
+
+        @Override
+        public int compareTo(final Delayed o) {
+            return Long.compare(getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Override
+    public String getMode() {
+        return "TotalRequests";
+    }
+
+    /**
+     * Gets the current maximum request per period value. If it is grouped throttling applied with correlationExpression
+     * than the max per period within the group will return
+     */
+    @Override
+    public int getCurrentMaximumRequests() {
+        return states.values().stream().mapToInt(ThrottlingState::getThrottleRate).max().orElse(0);
+    }
+
+    /**
+     * Sets the time period during which the maximum number of requests apply
+     */
+    public void setTimePeriodMillis(final long timePeriodMillis) {
+        this.timePeriodMillis = timePeriodMillis;
+    }
+
+    public long getTimePeriodMillis() {
+        return timePeriodMillis;
+    }
+
+    @Override
+    public String getTraceLabel() {
+        return "throttle[" + this.getMaximumRequestsExpression() + " per: " + timePeriodMillis + "]";
+    }
+
+    @Override
+    public String toString() {
+        return id;
+    }
+}
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
index cffd3d29fc9..32bbdb1aacd 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ProcessorReifier.java
@@ -98,7 +98,7 @@ import org.apache.camel.model.SplitDefinition;
 import org.apache.camel.model.StepDefinition;
 import org.apache.camel.model.StopDefinition;
 import org.apache.camel.model.ThreadsDefinition;
-import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
+import org.apache.camel.model.ThrottleDefinition;
 import org.apache.camel.model.ThrowExceptionDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.apache.camel.model.ToDynamicDefinition;
@@ -316,8 +316,8 @@ public abstract class ProcessorReifier<T extends ProcessorDefinition<?>> extends
             return new StopReifier(route, definition);
         } else if (definition instanceof ThreadsDefinition) {
             return new ThreadsReifier(route, definition);
-        } else if (definition instanceof ConcurrentRequestsThrottleDefinition) {
-            return new ConcurrentRequestsThrottleReifier(route, definition);
+        } else if (definition instanceof ThrottleDefinition) {
+            return new ThrottleReifier(route, definition);
         } else if (definition instanceof ThrowExceptionDefinition) {
             return new ThrowExceptionReifier(route, definition);
         } else if (definition instanceof ToDefinition) {
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
similarity index 61%
rename from core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
rename to core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
index baa1f1e8d1b..f88d1e8ab14 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ConcurrentRequestsThrottleReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/ThrottleReifier.java
@@ -22,41 +22,58 @@ import org.apache.camel.Expression;
 import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
+import org.apache.camel.model.ThrottleDefinition;
+import org.apache.camel.model.ThrottlingMode;
 import org.apache.camel.processor.ConcurrentRequestsThrottler;
+import org.apache.camel.processor.TotalRequestsThrottler;
 
-public class ConcurrentRequestsThrottleReifier extends ExpressionReifier<ConcurrentRequestsThrottleDefinition> {
+public class ThrottleReifier extends ExpressionReifier<ThrottleDefinition> {
 
-    public ConcurrentRequestsThrottleReifier(Route route, ProcessorDefinition<?> definition) {
-        super(route, (ConcurrentRequestsThrottleDefinition) definition);
+    public ThrottleReifier(Route route, ProcessorDefinition<?> definition) {
+        super(route, (ThrottleDefinition) definition);
     }
 
     @Override
     public Processor createProcessor() throws Exception {
+
         boolean async = parseBoolean(definition.getAsyncDelayed(), false);
         boolean shutdownThreadPool = willCreateNewThreadPool(definition, true);
         ScheduledExecutorService threadPool = getConfiguredScheduledExecutorService("Throttle", definition, true);
 
+        Expression correlation = null;
+        if (definition.getCorrelationExpression() != null) {
+            correlation = createExpression(definition.getCorrelationExpression());
+        }
+
+        boolean reject = parseBoolean(definition.getRejectExecution(), false);
         // max requests per period is mandatory
         Expression maxRequestsExpression = createMaxRequestsPerPeriodExpression();
         if (maxRequestsExpression == null) {
             throw new IllegalArgumentException("MaxRequestsPerPeriod expression must be provided on " + this);
         }
 
-        Expression correlation = null;
-        if (definition.getCorrelationExpression() != null) {
-            correlation = createExpression(definition.getCorrelationExpression());
-        }
+        if (ThrottlingMode.toMode(parseString(definition.getMode())) == ThrottlingMode.ConcurrentRequests) {
+            ConcurrentRequestsThrottler answer = new ConcurrentRequestsThrottler(
+                    camelContext, maxRequestsExpression, threadPool, shutdownThreadPool, reject, correlation);
 
-        boolean reject = parseBoolean(definition.getRejectExecution(), false);
-        ConcurrentRequestsThrottler answer = new ConcurrentRequestsThrottler(
-                camelContext, maxRequestsExpression, threadPool, shutdownThreadPool, reject, correlation);
+            answer.setAsyncDelayed(async);
+            // should be true by default
+            answer.setCallerRunsWhenRejected(parseBoolean(definition.getCallerRunsWhenRejected(), true));
 
-        answer.setAsyncDelayed(async);
-        // should be true by default
-        answer.setCallerRunsWhenRejected(parseBoolean(definition.getCallerRunsWhenRejected(), true));
+            return answer;
+        } else {
+            long period = parseDuration(definition.getTimePeriodMillis(), 1000L);
+
+            TotalRequestsThrottler answer = new TotalRequestsThrottler(
+                    camelContext, maxRequestsExpression, period, threadPool, shutdownThreadPool, reject, correlation);
+
+            answer.setAsyncDelayed(async);
+            // should be true by default
+            answer.setCallerRunsWhenRejected(parseBoolean(definition.getCallerRunsWhenRejected(), true));
+
+            return answer;
+        }
 
-        return answer;
     }
 
     private Expression createMaxRequestsPerPeriodExpression() {
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ConcurrentRequestsThrottlerTest.java
similarity index 94%
copy from core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
copy to core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ConcurrentRequestsThrottlerTest.java
index 7e458c91a1f..c43da30952a 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ConcurrentRequestsThrottlerTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle.concurrent;
 
 import java.util.Arrays;
 import java.util.concurrent.ExecutorService;
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.ThrottlerRejectedExecutionException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
 import org.junit.jupiter.api.condition.DisabledOnOs;
@@ -199,7 +200,7 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
 
                 onException(ThrottlerRejectedExecutionException.class).handled(true).to("mock:error");
 
-                from("direct:a").throttle(CONCURRENT_REQUESTS)
+                from("direct:a").throttle(CONCURRENT_REQUESTS).concurrentRequestsMode()
                         .process(exchange -> {
                             assertTrue(semaphore.tryAcquire(), "'direct:a' too many requests");
                         })
@@ -209,7 +210,7 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
                         })
                         .to("log:result", "mock:result");
 
-                from("direct:expressionConstant").throttle(constant(CONCURRENT_REQUESTS))
+                from("direct:expressionConstant").throttle(constant(CONCURRENT_REQUESTS)).concurrentRequestsMode()
                         .process(exchange -> {
                             assertTrue(semaphore.tryAcquire(), "'direct:expressionConstant' too many requests");
                         })
@@ -219,7 +220,7 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
                         })
                         .to("log:result", "mock:result");
 
-                from("direct:expressionHeader").throttle(header("throttleValue"))
+                from("direct:expressionHeader").throttle(header("throttleValue")).concurrentRequestsMode()
                         .process(exchange -> {
                             assertTrue(semaphore.tryAcquire(), "'direct:expressionHeader' too many requests");
                         })
@@ -229,9 +230,10 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
                         })
                         .to("log:result", "mock:result");
 
-                from("direct:start").throttle(2).rejectExecution(true).delay(1000).to("log:result", "mock:result");
+                from("direct:start").throttle(2).concurrentRequestsMode().rejectExecution(true).delay(1000).to("log:result",
+                        "mock:result");
 
-                from("direct:fifo").throttle(1).delay(100).to("mock:result");
+                from("direct:fifo").throttle(1).concurrentRequestsMode().delay(100).to("mock:result");
 
                 from("direct:release").errorHandler(deadLetterChannel("mock:error")).throttle(1).delay(100)
                         .process(exchange -> {
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedCallerRunsTest.java
similarity index 91%
copy from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
copy to core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedCallerRunsTest.java
index c42e8fcac11..03df96c2e44 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedCallerRunsTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.concurrent;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
@@ -50,7 +50,7 @@ public class ThrottlerAsyncDelayedCallerRunsTest extends ContextTestSupport {
                 builder.maxQueueSize(2);
                 context.getExecutorServiceManager().registerThreadPoolProfile(builder.build());
 
-                from("seda:start").throttle(1).delay(100).asyncDelayed().executorService("myThrottler")
+                from("seda:start").throttle(1).concurrentRequestsMode().delay(100).asyncDelayed().executorService("myThrottler")
                         .callerRunsWhenRejected(true).to("mock:result");
             }
         };
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedTest.java
similarity index 87%
copy from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
copy to core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedTest.java
index 28c0bb8ebc9..dd909d9e02f 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerAsyncDelayedTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.concurrent;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -67,10 +67,12 @@ public class ThrottlerAsyncDelayedTest extends ContextTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 // START SNIPPET: ex
-                from("seda:a").throttle(3).delay(INTERVAL).asyncDelayed().to("log:result", "mock:result");
+                from("seda:a").throttle(3).concurrentRequestsMode().delay(INTERVAL).asyncDelayed().to("log:result",
+                        "mock:result");
                 // END SNIPPET: ex
 
-                from("direct:a").throttle(3).delay(INTERVAL).asyncDelayed().to("log:result", "mock:result");
+                from("direct:a").throttle(3).concurrentRequestsMode().delay(INTERVAL).asyncDelayed().to("log:result",
+                        "mock:result");
             }
         };
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerMethodCallTest.java
similarity index 95%
rename from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerMethodCallTest.java
index b4b525a28b0..e7c719b501e 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerMethodCallTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlerMethodCallTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.concurrent;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -87,7 +87,8 @@ public class ThrottlerMethodCallTest extends ContextTestSupport {
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
             public void configure() {
-                from("direct:expressionMethod").throttle(method("myBean", "getConcurrentMessages")).delay(INTERVAL)
+                from("direct:expressionMethod").throttle(method("myBean", "getConcurrentMessages")).concurrentRequestsMode()
+                        .delay(INTERVAL)
                         .to("log:result", "mock:result");
             }
         };
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlingGroupingTest.java
similarity index 94%
copy from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
copy to core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlingGroupingTest.java
index 461b88deb65..e2c1dc6db17 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/concurrent/ThrottlingGroupingTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.concurrent;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -168,11 +168,12 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
             public void configure() throws Exception {
                 errorHandler(deadLetterChannel("mock:dead"));
 
-                from("seda:a").throttle(header("max"), 1).to("mock:result");
-                from("seda:b").throttle(header("max"), 2).to("mock:result2");
-                from("seda:c").throttle(header("max")).correlationExpression(header("key")).to("mock:resultdynamic");
+                from("seda:a").throttle(header("max"), 1).concurrentRequestsMode().to("mock:result");
+                from("seda:b").throttle(header("max"), 2).concurrentRequestsMode().to("mock:result2");
+                from("seda:c").throttle(header("max")).concurrentRequestsMode().correlationExpression(header("key"))
+                        .to("mock:resultdynamic");
 
-                from("direct:ga").throttle(constant(CONCURRENT_REQUESTS), header("key"))
+                from("direct:ga").throttle(constant(CONCURRENT_REQUESTS), header("key")).concurrentRequestsMode()
                         .process(exchange -> {
                             String key = (String) exchange.getMessage().getHeader("key");
                             // should be no more in-flight exchanges than set on the throttle
@@ -185,7 +186,7 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
                         })
                         .to("log:gresult", "mock:gresult");
 
-                from("direct:gexpressionHeader").throttle(header("throttleValue"), header("key"))
+                from("direct:gexpressionHeader").throttle(header("throttleValue"), header("key")).concurrentRequestsMode()
                         .process(exchange -> {
                             String key = (String) exchange.getMessage().getHeader("key");
                             // should be no more in-flight exchanges than set on the throttle via the 'throttleValue' header
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedCallerRunsTest.java
similarity index 92%
rename from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedCallerRunsTest.java
index c42e8fcac11..04a781988f8 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedCallerRunsTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedCallerRunsTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.requests;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
@@ -50,7 +50,7 @@ public class ThrottlerAsyncDelayedCallerRunsTest extends ContextTestSupport {
                 builder.maxQueueSize(2);
                 context.getExecutorServiceManager().registerThreadPoolProfile(builder.build());
 
-                from("seda:start").throttle(1).delay(100).asyncDelayed().executorService("myThrottler")
+                from("seda:start").throttle(1).timePeriodMillis(100).asyncDelayed().executorService("myThrottler")
                         .callerRunsWhenRejected(true).to("mock:result");
             }
         };
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedTest.java
similarity index 89%
rename from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedTest.java
index 28c0bb8ebc9..996417dbe1c 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerAsyncDelayedTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerAsyncDelayedTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.requests;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -67,10 +67,10 @@ public class ThrottlerAsyncDelayedTest extends ContextTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 // START SNIPPET: ex
-                from("seda:a").throttle(3).delay(INTERVAL).asyncDelayed().to("log:result", "mock:result");
+                from("seda:a").throttle(3).timePeriodMillis(INTERVAL).asyncDelayed().to("log:result", "mock:result");
                 // END SNIPPET: ex
 
-                from("direct:a").throttle(3).delay(INTERVAL).asyncDelayed().to("log:result", "mock:result");
+                from("direct:a").throttle(3).timePeriodMillis(INTERVAL).asyncDelayed().to("log:result", "mock:result");
             }
         };
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerDslTest.java
similarity index 88%
rename from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerDslTest.java
index d92b36f0e64..70737f051ff 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlerDslTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerDslTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.requests;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -22,7 +22,6 @@ import java.util.concurrent.Executors;
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.util.StopWatch;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
@@ -41,7 +40,7 @@ public class ThrottlerDslTest extends ContextTestSupport {
 
         ExecutorService executor = Executors.newFixedThreadPool(messageCount);
 
-        StopWatch watch = new StopWatch();
+        long start = System.currentTimeMillis();
         for (int i = 0; i < messageCount; i++) {
             executor.execute(() -> template.sendBodyAndHeader("direct:start", "payload", "ThrottleCount", 1));
         }
@@ -50,9 +49,9 @@ public class ThrottlerDslTest extends ContextTestSupport {
         resultEndpoint.assertIsSatisfied();
 
         // now assert that they have actually been throttled
-        long minimumTime = messageCount * INTERVAL;
+        long minimumTime = (messageCount - 1) * INTERVAL;
         // add a little slack
-        long delta = watch.taken() + 200;
+        long delta = System.currentTimeMillis() - start + 200;
         assertTrue(delta >= minimumTime, "Should take at least " + minimumTime + "ms, was: " + delta);
         executor.shutdownNow();
     }
@@ -62,7 +61,7 @@ public class ThrottlerDslTest extends ContextTestSupport {
         return new RouteBuilder() {
             public void configure() {
                 from("direct:start").throttle().message(m -> m.getHeader("ThrottleCount", Integer.class))
-                        .delay(INTERVAL).to("log:result", "mock:result");
+                        .timePeriodMillis(INTERVAL).to("log:result", "mock:result");
             }
         };
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerTest.java
similarity index 52%
rename from core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerTest.java
index 7e458c91a1f..ebe0a6ff46e 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/ConcurrentRequestsThrottlerTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlerTest.java
@@ -14,33 +14,45 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor;
+package org.apache.camel.processor.throttle.requests;
 
-import java.util.Arrays;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.processor.ThrottlerRejectedExecutionException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
 
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
 
 // time-bound that does not run well in shared environments
 @DisabledOnOs(OS.WINDOWS)
 @DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com", disabledReason = "Flaky on Github CI")
-public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
+public class ThrottlerTest extends ContextTestSupport {
     private static final int INTERVAL = 500;
+    private static final int TOLERANCE = 50;
     private static final int MESSAGE_COUNT = 9;
-    private static final int CONCURRENT_REQUESTS = 2;
-    protected static Semaphore semaphore;
+
+    @Test
+    public void testSendLotsOfMessagesButOnly3GetThroughWithin2Seconds() throws Exception {
+        MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:result", MockEndpoint.class);
+        resultEndpoint.expectedMessageCount(3);
+        resultEndpoint.setResultWaitTime(2000);
+
+        for (int i = 0; i < MESSAGE_COUNT; i++) {
+            template.sendBody("seda:a", "<message>" + i + "</message>");
+        }
+
+        // lets pause to give the requests time to be processed
+        // to check that the throttle really does kick in
+        resultEndpoint.assertIsSatisfied();
+    }
 
     @Test
     public void testSendLotsOfMessagesWithRejectExecution() throws Exception {
@@ -50,29 +62,27 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
         MockEndpoint errorEndpoint = resolveMandatoryEndpoint("mock:error", MockEndpoint.class);
         errorEndpoint.expectedMessageCount(4);
 
-        ExecutorService executor = Executors.newFixedThreadPool(6);
-        try {
-            for (int i = 0; i < 6; i++) {
-                executor.execute(() -> template.sendBody("direct:start", "<message>payload</message>"));
-            }
-            assertMockEndpointsSatisfied();
-        } finally {
-            shutdownAndAwait(executor);
+        for (int i = 0; i < 6; i++) {
+            template.sendBody("direct:start", "<message>" + i + "</message>");
         }
+
+        // lets pause to give the requests time to be processed
+        // to check that the throttle really does kick in
+        assertMockEndpointsSatisfied();
     }
 
     @Test
     public void testSendLotsOfMessagesSimultaneouslyButOnly3GetThrough() throws Exception {
-        semaphore = new Semaphore(CONCURRENT_REQUESTS);
         MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:result", MockEndpoint.class);
-        sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:a", MESSAGE_COUNT, resultEndpoint);
+        long elapsed = sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:a", MESSAGE_COUNT, resultEndpoint);
+        assertThrottlerTiming(elapsed, 5, INTERVAL, MESSAGE_COUNT);
     }
 
     @Test
     public void testConfigurationWithConstantExpression() throws Exception {
-        semaphore = new Semaphore(CONCURRENT_REQUESTS);
         MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:result", MockEndpoint.class);
-        sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:expressionConstant", MESSAGE_COUNT, resultEndpoint);
+        long elapsed = sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:expressionConstant", MESSAGE_COUNT, resultEndpoint);
+        assertThrottlerTiming(elapsed, 5, INTERVAL, MESSAGE_COUNT);
     }
 
     @Test
@@ -82,9 +92,9 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
 
         ExecutorService executor = Executors.newFixedThreadPool(MESSAGE_COUNT);
         try {
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, CONCURRENT_REQUESTS, MESSAGE_COUNT);
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 5, INTERVAL, MESSAGE_COUNT);
         } finally {
-            shutdownAndAwait(executor);
+            executor.shutdownNow();
         }
     }
 
@@ -93,46 +103,47 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
         ExecutorService executor = Executors.newFixedThreadPool(5);
         try {
             MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:result", MockEndpoint.class);
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, 2, MESSAGE_COUNT);
-            Thread.sleep(INTERVAL); // sleep here to ensure the
-                                   // first throttle rate does not
-                                   // influence the next one.
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 5, INTERVAL, MESSAGE_COUNT);
+            Thread.sleep(INTERVAL + TOLERANCE); // sleep here to ensure the
+                                               // first throttle rate does not
+                                               // influence the next one.
 
             resultEndpoint.reset();
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, 4, MESSAGE_COUNT);
-            Thread.sleep(INTERVAL); // sleep here to ensure the
-                                   // first throttle rate does not
-                                   // influence the next one.
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 10, INTERVAL, MESSAGE_COUNT);
+            Thread.sleep(INTERVAL + TOLERANCE); // sleep here to ensure the
+                                               // first throttle rate does not
+                                               // influence the next one.
 
             resultEndpoint.reset();
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, 2, MESSAGE_COUNT);
-            Thread.sleep(INTERVAL); // sleep here to ensure the
-                                   // first throttle rate does not
-                                   // influence the next one.
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 5, INTERVAL, MESSAGE_COUNT);
+            Thread.sleep(INTERVAL + TOLERANCE); // sleep here to ensure the
+                                               // first throttle rate does not
+                                               // influence the next one.
 
             resultEndpoint.reset();
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, 4, MESSAGE_COUNT);
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 10, INTERVAL, MESSAGE_COUNT);
         } finally {
-            shutdownAndAwait(executor);
+            executor.shutdownNow();
         }
     }
 
-    @Test
-    public void testFifo() throws Exception {
-        getMockEndpoint("mock:result").expectedBodiesReceived("A", "B", "C", "D", "E", "F", "G", "H");
-        sendBody("direct:fifo");
-        assertMockEndpointsSatisfied();
+    private void assertThrottlerTiming(
+            final long elapsedTimeMs, final int throttle, final int intervalMs, final int messageCount) {
+        // now assert that they have actually been throttled (use +/- 50 as
+        // slack)
+        long minimum = calculateMinimum(intervalMs, throttle, messageCount) - 50;
+        long maximum = calculateMaximum(intervalMs, throttle, messageCount) + 50;
+        // add 500 in case running on slow CI boxes
+        maximum += 500;
+        log.info("Sent {} exchanges in {}ms, with throttle rate of {} per {}ms. Calculated min {}ms and max {}ms", messageCount,
+                elapsedTimeMs, throttle, intervalMs, minimum,
+                maximum);
+
+        assertTrue(elapsedTimeMs >= minimum, "Should take at least " + minimum + "ms, was: " + elapsedTimeMs);
+        assertTrue(elapsedTimeMs <= maximum + TOLERANCE, "Should take at most " + maximum + "ms, was: " + elapsedTimeMs);
     }
 
-    @Test
-    public void testPermitReleaseOnException() throws Exception {
-        // verify that failed processing releases throttle permit
-        getMockEndpoint("mock:error").expectedBodiesReceived("A", "B", "C", "D", "E", "F", "G", "H");
-        sendBody("direct:release");
-        assertMockEndpointsSatisfied();
-    }
-
-    private void sendMessagesAndAwaitDelivery(
+    private long sendMessagesAndAwaitDelivery(
             final int messageCount, final String endpointUri, final int threadPoolSize, final MockEndpoint receivingEndpoint)
             throws InterruptedException {
         ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
@@ -141,6 +152,7 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
                 receivingEndpoint.expectedMessageCount(messageCount);
             }
 
+            long start = System.nanoTime();
             for (int i = 0; i < messageCount; i++) {
                 executor.execute(new Runnable() {
                     public void run() {
@@ -153,17 +165,19 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
             if (receivingEndpoint != null) {
                 receivingEndpoint.assertIsSatisfied();
             }
+            return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
         } finally {
-            shutdownAndAwait(executor);
+            executor.shutdownNow();
         }
     }
 
     private void sendMessagesWithHeaderExpression(
-            final ExecutorService executor, final MockEndpoint resultEndpoint, final int throttle, final int messageCount)
+            final ExecutorService executor, final MockEndpoint resultEndpoint, final int throttle, final int intervalMs,
+            final int messageCount)
             throws InterruptedException {
         resultEndpoint.expectedMessageCount(messageCount);
-        semaphore = new Semaphore(throttle);
 
+        long start = System.nanoTime();
         for (int i = 0; i < messageCount; i++) {
             executor.execute(new Runnable() {
                 public void run() {
@@ -175,21 +189,20 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
 
         // let's wait for the exchanges to arrive
         resultEndpoint.assertIsSatisfied();
+        long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
+        assertThrottlerTiming(elapsed, throttle, intervalMs, messageCount);
     }
 
-    private void sendBody(String endpoint) {
-        Arrays.stream(new String[] { "A", "B", "C", "D", "E", "F", "G", "H" })
-                .forEach(b -> template.sendBody(endpoint, b));
+    private long calculateMinimum(final long periodMs, final long throttleRate, final long messageCount) {
+        if (messageCount % throttleRate > 0) {
+            return (long) Math.floor((double) messageCount / (double) throttleRate) * periodMs;
+        } else {
+            return (long) (Math.floor((double) messageCount / (double) throttleRate) * periodMs) - periodMs;
+        }
     }
 
-    private void shutdownAndAwait(final ExecutorService executorService) {
-        executorService.shutdown();
-        try {
-            assertTrue(executorService.awaitTermination(10, TimeUnit.SECONDS),
-                    "Test ExecutorService shutdown is not expected to take longer than 10 seconds.");
-        } catch (InterruptedException e) {
-            fail("Test ExecutorService shutdown is not expected to be interrupted.");
-        }
+    private long calculateMaximum(final long periodMs, final long throttleRate, final long messageCount) {
+        return ((long) Math.ceil((double) messageCount / (double) throttleRate)) * periodMs;
     }
 
     @Override
@@ -199,44 +212,21 @@ public class ConcurrentRequestsThrottlerTest extends ContextTestSupport {
 
                 onException(ThrottlerRejectedExecutionException.class).handled(true).to("mock:error");
 
-                from("direct:a").throttle(CONCURRENT_REQUESTS)
-                        .process(exchange -> {
-                            assertTrue(semaphore.tryAcquire(), "'direct:a' too many requests");
-                        })
-                        .delay(100)
-                        .process(exchange -> {
-                            semaphore.release();
-                        })
-                        .to("log:result", "mock:result");
-
-                from("direct:expressionConstant").throttle(constant(CONCURRENT_REQUESTS))
-                        .process(exchange -> {
-                            assertTrue(semaphore.tryAcquire(), "'direct:expressionConstant' too many requests");
-                        })
-                        .delay(100)
-                        .process(exchange -> {
-                            semaphore.release();
-                        })
-                        .to("log:result", "mock:result");
-
-                from("direct:expressionHeader").throttle(header("throttleValue"))
-                        .process(exchange -> {
-                            assertTrue(semaphore.tryAcquire(), "'direct:expressionHeader' too many requests");
-                        })
-                        .delay(100)
-                        .process(exchange -> {
-                            semaphore.release();
-                        })
-                        .to("log:result", "mock:result");
-
-                from("direct:start").throttle(2).rejectExecution(true).delay(1000).to("log:result", "mock:result");
-
-                from("direct:fifo").throttle(1).delay(100).to("mock:result");
-
-                from("direct:release").errorHandler(deadLetterChannel("mock:error")).throttle(1).delay(100)
-                        .process(exchange -> {
-                            throw new RuntimeException();
-                        }).to("mock:result");
+                // START SNIPPET: ex
+                from("seda:a").throttle(3).timePeriodMillis(1000).to("log:result", "mock:result");
+                // END SNIPPET: ex
+
+                from("direct:a").throttle(5).timePeriodMillis(INTERVAL).to("log:result", "mock:result");
+
+                from("direct:expressionConstant").throttle(constant(5)).timePeriodMillis(INTERVAL).to("log:result",
+                        "mock:result");
+
+                from("direct:expressionHeader").throttle(header("throttleValue")).timePeriodMillis(INTERVAL).to("log:result",
+                        "mock:result");
+
+                from("direct:start").throttle(2).timePeriodMillis(1000).rejectExecution(true).to("log:result", "mock:result");
+
+                from("direct:highThrottleRate").throttle(10000).timePeriodMillis(INTERVAL).to("mock:result");
             }
         };
     }
diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlingGroupingTest.java
similarity index 55%
rename from core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
rename to core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlingGroupingTest.java
index 461b88deb65..ec12a687a7d 100644
--- a/core/camel-core/src/test/java/org/apache/camel/processor/throttle/ThrottlingGroupingTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/processor/throttle/requests/ThrottlingGroupingTest.java
@@ -14,14 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.processor.throttle;
+package org.apache.camel.processor.throttle.requests;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.ContextTestSupport;
@@ -31,13 +29,12 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.parallel.Isolated;
 
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
 
 @Isolated
 public class ThrottlingGroupingTest extends ContextTestSupport {
-    private static final int MESSAGE_COUNT = 20;
-    protected static final int CONCURRENT_REQUESTS = 2;
-    protected static Map<String, Semaphore> semaphores;
+    private static final int INTERVAL = 500;
+    private static final int MESSAGE_COUNT = 9;
+    private static final int TOLERANCE = 50;
 
     @Test
     public void testGroupingWithSingleConstant() throws Exception {
@@ -76,32 +73,64 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
     }
 
     @Test
-    public void testSendLotsOfMessagesSimultaneouslyButOnlyGetThroughAsConstantThrottleValue() throws Exception {
+    public void testSendLotsOfMessagesButOnly3GetThroughWithin2Seconds() throws Exception {
+
         MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:gresult", MockEndpoint.class);
-        sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:ga", resultEndpoint);
+        resultEndpoint.expectedMessageCount(3);
+        resultEndpoint.setResultWaitTime(2000);
+
+        Map<String, Object> headers = new HashMap<>();
+        for (int i = 0; i < 9; i++) {
+            if (i % 2 == 0) {
+                headers.put("key", "1");
+            } else {
+                headers.put("key", "2");
+            }
+            template.sendBodyAndHeaders("seda:ga", "<message>" + i + "</message>", headers);
+        }
+
+        // lets pause to give the requests time to be processed
+        // to check that the throttle really does kick in
+        resultEndpoint.assertIsSatisfied();
     }
 
-    private void sendMessagesAndAwaitDelivery(
-            final int messageCount, final String endpointUri, final MockEndpoint receivingEndpoint)
-            throws InterruptedException {
+    private void assertThrottlerTiming(
+            final long elapsedTimeMs, final int throttle, final int intervalMs, final int messageCount) {
+        // now assert that they have actually been throttled (use +/- 50 as
+        // slack)
+        long minimum = calculateMinimum(intervalMs, throttle, messageCount) - 50;
+        long maximum = calculateMaximum(intervalMs, throttle, messageCount) + 50;
+        // add 500 in case running on slow CI boxes
+        maximum += 500;
+        log.info("Sent {} exchanges in {}ms, with throttle rate of {} per {}ms. Calculated min {}ms and max {}ms", messageCount,
+                elapsedTimeMs, throttle, intervalMs, minimum,
+                maximum);
+
+        assertTrue(elapsedTimeMs >= minimum, "Should take at least " + minimum + "ms, was: " + elapsedTimeMs);
+        assertTrue(elapsedTimeMs <= maximum + TOLERANCE, "Should take at most " + maximum + "ms, was: " + elapsedTimeMs);
+    }
 
-        semaphores = new ConcurrentHashMap<>();
-        ExecutorService executor = Executors.newFixedThreadPool(messageCount);
+    private long sendMessagesAndAwaitDelivery(
+            final int messageCount, final String endpointUri, final int threadPoolSize, final MockEndpoint receivingEndpoint)
+            throws InterruptedException {
+        ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
         try {
             if (receivingEndpoint != null) {
                 receivingEndpoint.expectedMessageCount(messageCount);
             }
 
+            long start = System.nanoTime();
             for (int i = 0; i < messageCount; i++) {
-                int finalI = i;
-                executor.execute(() -> {
-                    Map<String, Object> headers = new HashMap<>();
-                    if (finalI % 2 == 0) {
-                        headers.put("key", "1");
-                    } else {
-                        headers.put("key", "2");
+                executor.execute(new Runnable() {
+                    public void run() {
+                        Map<String, Object> headers = new HashMap<>();
+                        if (messageCount % 2 == 0) {
+                            headers.put("key", "1");
+                        } else {
+                            headers.put("key", "2");
+                        }
+                        template.sendBodyAndHeaders(endpointUri, "<message>payload</message>", headers);
                     }
-                    template.sendBodyAndHeaders(endpointUri, "<message>payload</message>", headers);
                 });
             }
 
@@ -109,11 +138,19 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
             if (receivingEndpoint != null) {
                 receivingEndpoint.assertIsSatisfied();
             }
+            return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
         } finally {
-            shutdownAndAwait(executor);
+            executor.shutdownNow();
         }
     }
 
+    @Test
+    public void testSendLotsOfMessagesSimultaneouslyButOnlyGetThroughAsConstantThrottleValue() throws Exception {
+        MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:gresult", MockEndpoint.class);
+        long elapsed = sendMessagesAndAwaitDelivery(MESSAGE_COUNT, "direct:ga", MESSAGE_COUNT, resultEndpoint);
+        assertThrottlerTiming(elapsed, 5, INTERVAL, MESSAGE_COUNT);
+    }
+
     @Test
     public void testConfigurationWithHeaderExpression() throws Exception {
         MockEndpoint resultEndpoint = resolveMandatoryEndpoint("mock:gresult", MockEndpoint.class);
@@ -121,44 +158,50 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
 
         ExecutorService executor = Executors.newFixedThreadPool(MESSAGE_COUNT);
         try {
-            sendMessagesWithHeaderExpression(executor, resultEndpoint, CONCURRENT_REQUESTS, MESSAGE_COUNT);
+            sendMessagesWithHeaderExpression(executor, resultEndpoint, 5, INTERVAL, MESSAGE_COUNT);
         } finally {
-            shutdownAndAwait(executor);
+            executor.shutdownNow();
+        }
+    }
+
+    private long calculateMinimum(final long periodMs, final long throttleRate, final long messageCount) {
+        if (messageCount % throttleRate > 0) {
+            return (long) Math.floor((double) messageCount / (double) throttleRate) * periodMs;
+        } else {
+            return (long) (Math.floor((double) messageCount / (double) throttleRate) * periodMs) - periodMs;
         }
     }
 
+    private long calculateMaximum(final long periodMs, final long throttleRate, final long messageCount) {
+        return ((long) Math.ceil((double) messageCount / (double) throttleRate)) * periodMs;
+    }
+
     private void sendMessagesWithHeaderExpression(
-            final ExecutorService executor, final MockEndpoint resultEndpoint, final int throttle, final int messageCount)
+            final ExecutorService executor, final MockEndpoint resultEndpoint, final int throttle, final int intervalMs,
+            final int messageCount)
             throws InterruptedException {
         resultEndpoint.expectedMessageCount(messageCount);
 
-        semaphores = new ConcurrentHashMap<>();
+        long start = System.nanoTime();
         for (int i = 0; i < messageCount; i++) {
-            int finalI = i;
-            executor.execute(() -> {
-                Map<String, Object> headers = new HashMap<>();
-                headers.put("throttleValue", throttle);
-                if (finalI % 2 == 0) {
-                    headers.put("key", "1");
-                } else {
-                    headers.put("key", "2");
+            executor.execute(new Runnable() {
+                public void run() {
+                    Map<String, Object> headers = new HashMap<>();
+                    headers.put("throttleValue", throttle);
+                    if (messageCount % 2 == 0) {
+                        headers.put("key", "1");
+                    } else {
+                        headers.put("key", "2");
+                    }
+                    template.sendBodyAndHeaders("direct:gexpressionHeader", "<message>payload</message>", headers);
                 }
-                template.sendBodyAndHeaders("direct:gexpressionHeader", "<message>payload</message>", headers);
             });
         }
 
         // let's wait for the exchanges to arrive
         resultEndpoint.assertIsSatisfied();
-    }
-
-    private void shutdownAndAwait(final ExecutorService executorService) {
-        executorService.shutdown();
-        try {
-            assertTrue(executorService.awaitTermination(10, TimeUnit.SECONDS),
-                    "Test ExecutorService shutdown is not expected to take longer than 10 seconds.");
-        } catch (InterruptedException e) {
-            fail("Test ExecutorService shutdown is not expected to be interrupted.");
-        }
+        long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
+        assertThrottlerTiming(elapsed, throttle, intervalMs, messageCount);
     }
 
     @Override
@@ -172,34 +215,12 @@ public class ThrottlingGroupingTest extends ContextTestSupport {
                 from("seda:b").throttle(header("max"), 2).to("mock:result2");
                 from("seda:c").throttle(header("max")).correlationExpression(header("key")).to("mock:resultdynamic");
 
-                from("direct:ga").throttle(constant(CONCURRENT_REQUESTS), header("key"))
-                        .process(exchange -> {
-                            String key = (String) exchange.getMessage().getHeader("key");
-                            // should be no more in-flight exchanges than set on the throttle
-                            assertTrue(semaphores.computeIfAbsent(key, k -> new Semaphore(CONCURRENT_REQUESTS)).tryAcquire(),
-                                    "'direct:ga' too many requests for key " + key);
-                        })
-                        .delay(100)
-                        .process(exchange -> {
-                            semaphores.get(exchange.getMessage().getHeader("key")).release();
-                        })
-                        .to("log:gresult", "mock:gresult");
+                from("seda:ga").throttle(constant(3), header("key")).timePeriodMillis(1000).to("log:gresult", "mock:gresult");
+
+                from("direct:ga").throttle(constant(5), header("key")).timePeriodMillis(INTERVAL).to("log:gresult",
+                        "mock:gresult");
 
-                from("direct:gexpressionHeader").throttle(header("throttleValue"), header("key"))
-                        .process(exchange -> {
-                            String key = (String) exchange.getMessage().getHeader("key");
-                            // should be no more in-flight exchanges than set on the throttle via the 'throttleValue' header
-                            assertTrue(
-                                    semaphores.computeIfAbsent(key,
-                                            k -> new Semaphore(
-                                                    (Integer) exchange.getMessage().getHeader("throttleValue")))
-                                            .tryAcquire(),
-                                    "'direct:gexpressionHeader' too many requests for key " + key);
-                        })
-                        .delay(100)
-                        .process(exchange -> {
-                            semaphores.get(exchange.getMessage().getHeader("key")).release();
-                        })
+                from("direct:gexpressionHeader").throttle(header("throttleValue"), header("key")).timePeriodMillis(INTERVAL)
                         .to("log:gresult", "mock:gresult");
             }
         };
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java
similarity index 77%
rename from core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java
rename to core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java
index aa6d8129873..71533713a55 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedConcurrentRequestsThrottlerMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedThrottlerMBean.java
@@ -18,13 +18,22 @@ package org.apache.camel.api.management.mbean;
 
 import org.apache.camel.api.management.ManagedAttribute;
 
-public interface ManagedConcurrentRequestsThrottlerMBean extends ManagedProcessorMBean {
+public interface ManagedThrottlerMBean extends ManagedProcessorMBean {
 
     @ManagedAttribute(description = "Maximum concurrent requests")
-    long getMaximumConcurrentRequests();
+    long getMaximumRequests();
 
     @ManagedAttribute(description = "Maximum concurrent requests")
-    void setMaximumConcurrentRequests(long maximumConcurrentRequests);
+    void setMaximumRequests(long maximumConcurrentRequests);
+
+    @ManagedAttribute(description = "Time period in millis")
+    long getTimePeriodMillis();
+
+    @ManagedAttribute(description = "Time period in millis")
+    void setTimePeriodMillis(long timePeriodMillis);
+
+    @ManagedAttribute(description = "The throttler mode in use")
+    String getMode();
 
     @ManagedAttribute(description = "Enables asynchronous delay which means the thread will not block while delaying")
     Boolean isAsyncDelayed();
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
index 4aa88918f13..6945ddacc43 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/DefaultManagementObjectStrategy.java
@@ -100,7 +100,7 @@ import org.apache.camel.management.mbean.ManagedSupervisingRouteController;
 import org.apache.camel.management.mbean.ManagedSuspendableRoute;
 import org.apache.camel.management.mbean.ManagedThreadPool;
 import org.apache.camel.management.mbean.ManagedThreads;
-import org.apache.camel.management.mbean.ManagedConcurrentRequestsThrottler;
+import org.apache.camel.management.mbean.ManagedThrottler;
 import org.apache.camel.management.mbean.ManagedThroughputLogger;
 import org.apache.camel.management.mbean.ManagedThrowException;
 import org.apache.camel.management.mbean.ManagedTopicLoadBalancer;
@@ -172,7 +172,7 @@ import org.apache.camel.processor.StepProcessor;
 import org.apache.camel.processor.StopProcessor;
 import org.apache.camel.processor.StreamResequencer;
 import org.apache.camel.processor.ThreadsProcessor;
-import org.apache.camel.processor.ConcurrentRequestsThrottler;
+import org.apache.camel.processor.Throttler;
 import org.apache.camel.processor.ThrowExceptionProcessor;
 import org.apache.camel.processor.TransformProcessor;
 import org.apache.camel.processor.TryProcessor;
@@ -377,8 +377,8 @@ public class DefaultManagementObjectStrategy implements ManagementObjectStrategy
                 answer = new ManagedDoCatch(context, (CatchProcessor) target, (CatchDefinition) definition);
             } else if (target instanceof FinallyProcessor) {
                 answer = new ManagedDoFinally(context, (FinallyProcessor) target, (FinallyDefinition) definition);
-            } else if (target instanceof ConcurrentRequestsThrottler) {
-                answer = new ManagedConcurrentRequestsThrottler(context, (ConcurrentRequestsThrottler) target, definition);
+            } else if (target instanceof Throttler) {
+                answer = new ManagedThrottler(context, (Throttler) target, definition);
             } else if (target instanceof DynamicRouter) {
                 answer = new ManagedDynamicRouter(context, (DynamicRouter) target, (DynamicRouterDefinition) definition);
             } else if (target instanceof RoutingSlip) {
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java
similarity index 54%
rename from core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
rename to core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java
index 655c718d114..90dd38e8d55 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedConcurrentRequestsThrottler.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedThrottler.java
@@ -18,33 +18,56 @@ package org.apache.camel.management.mbean;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.api.management.ManagedResource;
-import org.apache.camel.api.management.mbean.ManagedConcurrentRequestsThrottlerMBean;
+import org.apache.camel.api.management.mbean.ManagedThrottlerMBean;
 import org.apache.camel.model.ProcessorDefinition;
-import org.apache.camel.processor.ConcurrentRequestsThrottler;
+import org.apache.camel.processor.Throttler;
+import org.apache.camel.processor.TotalRequestsThrottler;
 
 import static org.apache.camel.builder.Builder.constant;
 
-@ManagedResource(description = "Managed Throttler")
-public class ManagedConcurrentRequestsThrottler extends ManagedProcessor implements ManagedConcurrentRequestsThrottlerMBean {
-    private final ConcurrentRequestsThrottler throttler;
+@ManagedResource(description = "Managed Concurrent Requests Throttler")
+public class ManagedThrottler extends ManagedProcessor implements ManagedThrottlerMBean {
+    private final Throttler throttler;
 
-    public ManagedConcurrentRequestsThrottler(CamelContext context, ConcurrentRequestsThrottler throttler, ProcessorDefinition<?> definition) {
+    public ManagedThrottler(CamelContext context, Throttler throttler,
+                            ProcessorDefinition<?> definition) {
         super(context, throttler, definition);
         this.throttler = throttler;
     }
 
-    public ConcurrentRequestsThrottler getThrottler() {
+    public Throttler getThrottler() {
         return throttler;
     }
 
     @Override
-    public long getMaximumConcurrentRequests() {
-        return throttler.getCurrentMaximumConcurrentRequests();
+    public long getMaximumRequests() {
+        return throttler.getCurrentMaximumRequests();
     }
 
     @Override
-    public void setMaximumConcurrentRequests(long maximumConcurrentRequests) {
-        throttler.setMaximumConcurrentRequestsExpression(constant(maximumConcurrentRequests));
+    public void setMaximumRequests(long maximumConcurrentRequests) {
+        throttler.setMaximumRequestsExpression(constant(maximumConcurrentRequests));
+    }
+
+    @Override
+    public long getTimePeriodMillis() {
+        if (throttler instanceof TotalRequestsThrottler t) {
+            return t.getTimePeriodMillis();
+        }
+
+        return 0;
+    }
+
+    @Override
+    public void setTimePeriodMillis(long timePeriodMillis) {
+        if (throttler instanceof TotalRequestsThrottler t) {
+            t.setTimePeriodMillis(timePeriodMillis);
+        }
+    }
+
+    @Override
+    public String getMode() {
+        return throttler.getMode();
     }
 
     @Override
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java b/core/camel-management/src/test/java/org/apache/camel/management/AbstractManagedThrottlerTest.java
similarity index 73%
copy from core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java
copy to core/camel-management/src/test/java/org/apache/camel/management/AbstractManagedThrottlerTest.java
index d1be4aeaeb0..be788c41761 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/AbstractManagedThrottlerTest.java
@@ -16,11 +16,6 @@
  */
 package org.apache.camel.management;
 
-import java.util.concurrent.Callable;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 import javax.management.Attribute;
@@ -28,7 +23,6 @@ import javax.management.MBeanServer;
 import javax.management.ObjectName;
 
 import org.apache.camel.builder.NotifyBuilder;
-import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
@@ -43,10 +37,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @DisabledOnOs(OS.AIX)
 @DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com", disabledReason = "Flaky on GitHub Actions")
-public class ManagedThrottlerTest extends ManagementTestSupport {
+public abstract class AbstractManagedThrottlerTest extends ManagementTestSupport {
 
-    @Test
-    public void testManageThrottler() throws Exception {
+    protected Long runTestManageThrottler() throws Exception {
         getMockEndpoint("mock:result").expectedMessageCount(10);
 
         // Send in a first batch of 10 messages and check that the endpoint
@@ -87,7 +80,7 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
         assertTrue(total < 1200, "Should take at most 1.2 sec: was " + total);
 
         // change the throttler using JMX
-        mbeanServer.setAttribute(throttlerName, new Attribute("MaximumConcurrentRequests", (long) 2));
+        mbeanServer.setAttribute(throttlerName, new Attribute("MaximumRequests", (long) 2));
 
         // reset the counters
         mbeanServer.invoke(routeName, "reset", null, null);
@@ -97,21 +90,17 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
             template.sendBody("direct:start", "Message " + i);
         }
 
-        Long requests = (Long) mbeanServer.getAttribute(throttlerName, "MaximumConcurrentRequests");
+        Long requests = (Long) mbeanServer.getAttribute(throttlerName, "MaximumRequests");
         assertNotNull(requests);
         assertEquals(2, requests.longValue());
 
         completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
         assertEquals(10, completed.longValue());
-        total = (Long) mbeanServer.getAttribute(routeName, "TotalProcessingTime");
+        return (Long) mbeanServer.getAttribute(routeName, "TotalProcessingTime");
 
-        // 10 * delay (100) + tolerance (200)
-        assertTrue(total < 1200, "Should take at most 1.2 sec: was " + total);
     }
 
-    @DisabledOnOs(OS.WINDOWS)
-    @Test
-    public void testThrottleVisableViaJmx() throws Exception {
+    protected void runTestThrottleVisibleViaJmx() throws Exception {
         // get the stats for the route
         MBeanServer mbeanServer = getMBeanServer();
 
@@ -136,9 +125,7 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
         assertEquals(10, completed.longValue());
     }
 
-    @DisabledOnOs(OS.WINDOWS)
-    @Test
-    public void testThrottleAsyncVisableViaJmx() throws Exception {
+    public void runTestThrottleAsyncVisibleViaJmx() throws Exception {
         // get the stats for the route
         MBeanServer mbeanServer = getMBeanServer();
 
@@ -253,60 +240,4 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
 
         assertMockEndpointsSatisfied();
     }
-
-    @Override
-    protected RouteBuilder createRouteBuilder() throws Exception {
-        final ScheduledExecutorService badService = new ScheduledThreadPoolExecutor(1) {
-            @Override
-            public <V> ScheduledFuture<V> schedule(Callable<V> command, long delay, TimeUnit unit) {
-                throw new RejectedExecutionException();
-            }
-        };
-
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start").id("route1")
-                        .to("log:foo")
-                        .throttle(10).id("mythrottler")
-                        .delay(100)
-                        .to("mock:result");
-
-                from("seda:throttleCount").id("route2")
-                        .throttle(1).id("mythrottler2").delay(250)
-                        .to("mock:end");
-
-                from("seda:throttleCountAsync").id("route3")
-                        .throttle(1).asyncDelayed().id("mythrottler3").delay(250)
-                        .to("mock:endAsync");
-
-                from("seda:throttleCountAsyncException").id("route4")
-                        .throttle(1).asyncDelayed().id("mythrottler4").delay(250)
-                        .to("mock:endAsyncException")
-                        .process(exchange -> {
-                            throw new RuntimeException("Fail me");
-                        });
-                from("seda:throttleCountRejectExecutionCallerRuns").id("route5")
-                        .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
-                        .throttle(1)
-                        .asyncDelayed()
-                        .executorService(badService)
-                        .callerRunsWhenRejected(true)
-                        .id("mythrottler5")
-                        .delay(250)
-                        .to("mock:endAsyncRejectCallerRuns");
-
-                from("seda:throttleCountRejectExecution").id("route6")
-                        .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
-                        .throttle(1)
-                        .asyncDelayed()
-                        .executorService(badService)
-                        .callerRunsWhenRejected(false)
-                        .id("mythrottler6")
-                        .delay(250)
-                        .to("mock:endAsyncReject");
-            }
-        };
-    }
-
 }
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedConcurrentThrottlerTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedConcurrentThrottlerTest.java
new file mode 100644
index 00000000000..bda6f2aa891
--- /dev/null
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedConcurrentThrottlerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.management;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DisabledOnOs(OS.AIX)
+@DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com", disabledReason = "Flaky on GitHub Actions")
+public class ManagedConcurrentThrottlerTest extends AbstractManagedThrottlerTest {
+
+    @Test
+    public void testManageThrottler() throws Exception {
+        final Long total = super.runTestManageThrottler();
+
+        // 10 * delay (100) + tolerance (200)
+        assertTrue(total < 1200, "Should take at most 1.2 sec: was " + total);
+    }
+
+    @DisabledOnOs(OS.WINDOWS)
+    @Test
+    public void testThrottleVisibleViaJmx() throws Exception {
+        super.runTestThrottleAsyncVisibleViaJmx();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final ScheduledExecutorService badService = new ScheduledThreadPoolExecutor(1) {
+            @Override
+            public <V> ScheduledFuture<V> schedule(Callable<V> command, long delay, TimeUnit unit) {
+                throw new RejectedExecutionException();
+            }
+        };
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").id("route1")
+                        .to("log:foo")
+                        .throttle(10).mode("ConcurrentRequests").id("mythrottler")
+                        .delay(100)
+                        .to("mock:result");
+
+                from("seda:throttleCount").id("route2")
+                        .throttle(1).concurrentRequestsMode().id("mythrottler2").delay(250)
+                        .to("mock:end");
+
+                from("seda:throttleCountAsync").id("route3")
+                        .throttle(1).concurrentRequestsMode().asyncDelayed().id("mythrottler3").delay(250)
+                        .to("mock:endAsync");
+
+                from("seda:throttleCountAsyncException").id("route4")
+                        .throttle(1).concurrentRequestsMode().asyncDelayed().id("mythrottler4").delay(250)
+                        .to("mock:endAsyncException")
+                        .process(exchange -> {
+                            throw new RuntimeException("Fail me");
+                        });
+                from("seda:throttleCountRejectExecutionCallerRuns").id("route5")
+                        .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
+                        .throttle(1).concurrentRequestsMode()
+                        .asyncDelayed()
+                        .executorService(badService)
+                        .callerRunsWhenRejected(true)
+                        .id("mythrottler5")
+                        .delay(250)
+                        .to("mock:endAsyncRejectCallerRuns");
+
+                from("seda:throttleCountRejectExecution").id("route6")
+                        .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
+                        .throttle(1).concurrentRequestsMode()
+                        .asyncDelayed()
+                        .executorService(badService)
+                        .callerRunsWhenRejected(false)
+                        .id("mythrottler6")
+                        .delay(250)
+                        .to("mock:endAsyncReject");
+            }
+        };
+    }
+
+}
diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java
index d1be4aeaeb0..709a3706a85 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedThrottlerTest.java
@@ -23,235 +23,29 @@ import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
-import javax.management.Attribute;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.camel.builder.NotifyBuilder;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
 
-import static org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_PROCESSOR;
-import static org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_ROUTE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @DisabledOnOs(OS.AIX)
 @DisabledIfSystemProperty(named = "ci.env.name", matches = "github.com", disabledReason = "Flaky on GitHub Actions")
-public class ManagedThrottlerTest extends ManagementTestSupport {
+public class ManagedThrottlerTest extends AbstractManagedThrottlerTest {
 
     @Test
     public void testManageThrottler() throws Exception {
-        getMockEndpoint("mock:result").expectedMessageCount(10);
-
-        // Send in a first batch of 10 messages and check that the endpoint
-        // gets them.  We'll check the total time of the second and third
-        // batches as it seems that there is some time required to prime
-        // things, which can vary significantly... particularly on slower
-        // machines.
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("direct:start", "Message " + i);
-        }
-
-        assertMockEndpointsSatisfied();
-
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // get the object name for the delayer
-        ObjectName throttlerName
-                = getCamelObjectName(TYPE_PROCESSOR, "mythrottler");
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route1");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        // send in 10 messages
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("direct:start", "Message " + i);
-        }
-
-        Long completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
-        assertEquals(10, completed.longValue());
-
-        Long total = (Long) mbeanServer.getAttribute(routeName, "TotalProcessingTime");
-
-        // 10 * delay (100) + tolerance (200)
-        assertTrue(total < 1200, "Should take at most 1.2 sec: was " + total);
-
-        // change the throttler using JMX
-        mbeanServer.setAttribute(throttlerName, new Attribute("MaximumConcurrentRequests", (long) 2));
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        // send in another 10 messages
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("direct:start", "Message " + i);
-        }
-
-        Long requests = (Long) mbeanServer.getAttribute(throttlerName, "MaximumConcurrentRequests");
-        assertNotNull(requests);
-        assertEquals(2, requests.longValue());
-
-        completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
-        assertEquals(10, completed.longValue());
-        total = (Long) mbeanServer.getAttribute(routeName, "TotalProcessingTime");
+        final Long total = super.runTestManageThrottler();
 
         // 10 * delay (100) + tolerance (200)
-        assertTrue(total < 1200, "Should take at most 1.2 sec: was " + total);
+        assertTrue(total > 1000, "Should be around 1 sec now: was " + total);
     }
 
-    @DisabledOnOs(OS.WINDOWS)
     @Test
-    public void testThrottleVisableViaJmx() throws Exception {
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route2");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        getMockEndpoint("mock:end").expectedMessageCount(10);
-
-        NotifyBuilder notifier = new NotifyBuilder(context).from("seda:throttleCount").whenReceived(5).create();
-
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("seda:throttleCount", "Message " + i);
-        }
-
-        assertTrue(notifier.matches(2, TimeUnit.SECONDS));
-        assertMockEndpointsSatisfied();
-
-        Long completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
-        assertEquals(10, completed.longValue());
-    }
-
-    @DisabledOnOs(OS.WINDOWS)
-    @Test
-    public void testThrottleAsyncVisableViaJmx() throws Exception {
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route3");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        getMockEndpoint("mock:endAsync").expectedMessageCount(10);
-
-        // we pick '5' because we are right in the middle of the number of messages
-        // that have been and reduces any race conditions to minimal...
-        NotifyBuilder notifier = new NotifyBuilder(context).from("seda:throttleCountAsync").whenReceived(5).create();
-
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("seda:throttleCountAsync", "Message " + i);
-        }
-
-        assertTrue(notifier.matches(2, TimeUnit.SECONDS));
-        assertMockEndpointsSatisfied();
-
-        Long completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
-        assertEquals(10, completed.longValue());
-    }
-
-    @DisabledOnOs(OS.WINDOWS)
-    @Test
-    public void testThrottleAsyncExceptionVisableViaJmx() throws Exception {
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route4");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        getMockEndpoint("mock:endAsyncException").expectedMessageCount(10);
-
-        NotifyBuilder notifier = new NotifyBuilder(context).from("seda:throttleCountAsyncException").whenReceived(5).create();
-
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("seda:throttleCountAsyncException", "Message " + i);
-        }
-
-        assertTrue(notifier.matches(2, TimeUnit.SECONDS));
-        assertMockEndpointsSatisfied();
-
-        // give a sec for exception handling to finish..
-        Thread.sleep(500);
-
-        // since all exchanges ended w/ exception, they are not completed
-        Long completed = (Long) mbeanServer.getAttribute(routeName, "ExchangesCompleted");
-        assertEquals(0, completed.longValue());
-    }
-
-    @Test
-    public void testRejectedExecution() throws Exception {
-        // when delaying async, we can possibly fill up the execution queue
-        //. which would through a RejectedExecutionException.. we need to make
-        // sure that the delayedCount/throttledCount doesn't leak
-
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route2");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        MockEndpoint mock = getMockEndpoint("mock:endAsyncReject");
-        // only one message (the first one) should get through because the rest should get delayed
-        mock.expectedMessageCount(1);
-
-        MockEndpoint exceptionMock = getMockEndpoint("mock:rejectedExceptionEndpoint1");
-        exceptionMock.expectedMessageCount(9);
-
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("seda:throttleCountRejectExecution", "Message " + i);
-        }
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Test
-    public void testRejectedExecutionCallerRuns() throws Exception {
-        // when delaying async, we can possibly fill up the execution queue
-        //. which would through a RejectedExecutionException.. we need to make
-        // sure that the delayedCount/throttledCount doesn't leak
-
-        // get the stats for the route
-        MBeanServer mbeanServer = getMBeanServer();
-
-        // use route to get the total time
-        ObjectName routeName = getCamelObjectName(TYPE_ROUTE, "route2");
-
-        // reset the counters
-        mbeanServer.invoke(routeName, "reset", null, null);
-
-        MockEndpoint mock = getMockEndpoint("mock:endAsyncRejectCallerRuns");
-        // only one message (the first one) should get through because the rest should get delayed
-        mock.expectedMessageCount(10);
-
-        MockEndpoint exceptionMock = getMockEndpoint("mock:rejectedExceptionEndpoint");
-        exceptionMock.expectedMessageCount(0);
-
-        for (int i = 0; i < 10; i++) {
-            template.sendBody("seda:throttleCountRejectExecutionCallerRuns", "Message " + i);
-        }
-
-        assertMockEndpointsSatisfied();
+    public void testThrottleAsyncVisibleViaJmx() throws Exception {
+        super.runTestThrottleAsyncVisibleViaJmx();
     }
 
     @Override
@@ -268,27 +62,27 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
             public void configure() throws Exception {
                 from("direct:start").id("route1")
                         .to("log:foo")
-                        .throttle(10).id("mythrottler")
+                        .throttle(10).totalRequestsMode().id("mythrottler")
                         .delay(100)
                         .to("mock:result");
 
                 from("seda:throttleCount").id("route2")
-                        .throttle(1).id("mythrottler2").delay(250)
+                        .throttle(1).totalRequestsMode().id("mythrottler2").delay(250)
                         .to("mock:end");
 
                 from("seda:throttleCountAsync").id("route3")
-                        .throttle(1).asyncDelayed().id("mythrottler3").delay(250)
+                        .throttle(1).totalRequestsMode().asyncDelayed().id("mythrottler3").delay(250)
                         .to("mock:endAsync");
 
                 from("seda:throttleCountAsyncException").id("route4")
-                        .throttle(1).asyncDelayed().id("mythrottler4").delay(250)
+                        .throttle(1).totalRequestsMode().asyncDelayed().id("mythrottler4").delay(250)
                         .to("mock:endAsyncException")
                         .process(exchange -> {
                             throw new RuntimeException("Fail me");
                         });
                 from("seda:throttleCountRejectExecutionCallerRuns").id("route5")
                         .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
-                        .throttle(1)
+                        .throttle(1).totalRequestsMode()
                         .asyncDelayed()
                         .executorService(badService)
                         .callerRunsWhenRejected(true)
@@ -298,7 +92,7 @@ public class ManagedThrottlerTest extends ManagementTestSupport {
 
                 from("seda:throttleCountRejectExecution").id("route6")
                         .onException(RejectedExecutionException.class).to("mock:rejectedExceptionEndpoint1").end()
-                        .throttle(1)
+                        .throttle(1).totalRequestsMode()
                         .asyncDelayed()
                         .executorService(badService)
                         .callerRunsWhenRejected(false)
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index a3413fb4490..147fa513081 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -285,47 +285,6 @@ public class ModelParser extends BaseParser {
             return true;
         }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
     }
-    protected ConcurrentRequestsThrottleDefinition doParseConcurrentRequestsThrottleDefinition() throws IOException, XmlPullParserException {
-        return doParse(new ConcurrentRequestsThrottleDefinition(), (def, key, val) -> {
-            switch (key) {
-                case "asyncDelayed": def.setAsyncDelayed(val); break;
-                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
-                case "executorService": def.setExecutorService(val); break;
-                case "rejectExecution": def.setRejectExecution(val); break;
-                default: return processorDefinitionAttributeHandler().accept(def, key, val);
-            }
-            return true;
-        }, (def, key) -> {
-            if ("correlationExpression".equals(key)) {
-                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
-                return true;
-            }
-            return expressionNodeElementHandler().accept(def, key);
-        }, noValueHandler());
-    }
-    protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
-        return (def, key) -> {
-            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
-            if (v != null) { 
-                def.setExpression(v);
-                return true;
-            }
-            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
-        };
-    }
-    protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
-        return (def, key, val) -> {
-            switch (key) {
-                case "id": def.setId(val); break;
-                case "trim": def.setTrim(val); break;
-                default: return false;
-            }
-            return true;
-        };
-    }
-    protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
-        return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(),  noElementHandler(), expressionDefinitionValueHandler());
-    }
     protected ContextScanDefinition doParseContextScanDefinition() throws IOException, XmlPullParserException {
         return doParse(new ContextScanDefinition(), (def, key, val) -> {
             if ("includeNonSingletons".equals(key)) {
@@ -403,6 +362,29 @@ public class ModelParser extends BaseParser {
             return true;
         }, expressionNodeElementHandler(), noValueHandler());
     }
+    protected <T extends ExpressionNode> ElementHandler<T> expressionNodeElementHandler() {
+        return (def, key) -> {
+            ExpressionDefinition v = doParseExpressionDefinitionRef(key);
+            if (v != null) { 
+                def.setExpression(v);
+                return true;
+            }
+            return optionalIdentifiedDefinitionElementHandler().accept(def, key);
+        };
+    }
+    protected <T extends ExpressionDefinition> AttributeHandler<T> expressionDefinitionAttributeHandler() {
+        return (def, key, val) -> {
+            switch (key) {
+                case "id": def.setId(val); break;
+                case "trim": def.setTrim(val); break;
+                default: return false;
+            }
+            return true;
+        };
+    }
+    protected ExpressionDefinition doParseExpressionDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ExpressionDefinition(), expressionDefinitionAttributeHandler(),  noElementHandler(), expressionDefinitionValueHandler());
+    }
     protected DynamicRouterDefinition doParseDynamicRouterDefinition() throws IOException, XmlPullParserException {
         return doParse(new DynamicRouterDefinition(), (def, key, val) -> {
             switch (key) {
@@ -1524,6 +1506,26 @@ public class ModelParser extends BaseParser {
             return true;
         }, optionalIdentifiedDefinitionElementHandler(), noValueHandler());
     }
+    protected ThrottleDefinition doParseThrottleDefinition() throws IOException, XmlPullParserException {
+        return doParse(new ThrottleDefinition(), (def, key, val) -> {
+            switch (key) {
+                case "asyncDelayed": def.setAsyncDelayed(val); break;
+                case "callerRunsWhenRejected": def.setCallerRunsWhenRejected(val); break;
+                case "executorService": def.setExecutorService(val); break;
+                case "mode": def.setMode(val); break;
+                case "rejectExecution": def.setRejectExecution(val); break;
+                case "timePeriodMillis": def.setTimePeriodMillis(val); break;
+                default: return processorDefinitionAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, (def, key) -> {
+            if ("correlationExpression".equals(key)) {
+                def.setCorrelationExpression(doParseExpressionSubElementDefinition());
+                return true;
+            }
+            return expressionNodeElementHandler().accept(def, key);
+        }, noValueHandler());
+    }
     protected ThrowExceptionDefinition doParseThrowExceptionDefinition() throws IOException, XmlPullParserException {
         return doParse(new ThrowExceptionDefinition(), (def, key, val) -> {
             switch (key) {
@@ -3506,7 +3508,6 @@ public class ModelParser extends BaseParser {
             case "circuitBreaker": return doParseCircuitBreakerDefinition();
             case "onFallback": return doParseOnFallbackDefinition();
             case "claimCheck": return doParseClaimCheckDefinition();
-            case "throttle": return doParseConcurrentRequestsThrottleDefinition();
             case "convertBodyTo": return doParseConvertBodyDefinition();
             case "convertHeaderTo": return doParseConvertHeaderDefinition();
             case "convertVariableTo": return doParseConvertVariableDefinition();
@@ -3557,6 +3558,7 @@ public class ModelParser extends BaseParser {
             case "step": return doParseStepDefinition();
             case "stop": return doParseStopDefinition();
             case "threads": return doParseThreadsDefinition();
+            case "throttle": return doParseThrottleDefinition();
             case "throwException": return doParseThrowExceptionDefinition();
             case "to": return doParseToDefinition();
             case "toD": return doParseToDynamicDefinition();
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index f35dd601a5c..39304c0c88e 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -73,11 +73,6 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         doWriteClaimCheckDefinition("claimCheck", def);
     }
-    public void writeConcurrentRequestsThrottleDefinition(
-            ConcurrentRequestsThrottleDefinition def)
-            throws IOException {
-        doWriteConcurrentRequestsThrottleDefinition("throttle", def);
-    }
     public void writeContextScanDefinition(
             ContextScanDefinition def)
             throws IOException {
@@ -456,6 +451,11 @@ public class ModelWriter extends BaseWriter {
     public void writeThreadsDefinition(ThreadsDefinition def) throws IOException {
         doWriteThreadsDefinition("threads", def);
     }
+    public void writeThrottleDefinition(
+            ThrottleDefinition def)
+            throws IOException {
+        doWriteThrottleDefinition("throttle", def);
+    }
     public void writeThrowExceptionDefinition(
             ThrowExceptionDefinition def)
             throws IOException {
@@ -1171,20 +1171,6 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("key", def.getKey());
         endElement(name);
     }
-    protected void doWriteConcurrentRequestsThrottleDefinition(
-            String name,
-            ConcurrentRequestsThrottleDefinition def)
-            throws IOException {
-        startElement(name);
-        doWriteProcessorDefinitionAttributes(def);
-        doWriteAttribute("rejectExecution", def.getRejectExecution());
-        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
-        doWriteAttribute("executorService", def.getExecutorService());
-        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
-        doWriteExpressionNodeElements(def);
-        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
-        endElement(name);
-    }
     protected void doWriteContextScanDefinition(
             String name,
             ContextScanDefinition def)
@@ -2428,6 +2414,22 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("timeUnit", def.getTimeUnit());
         endElement(name);
     }
+    protected void doWriteThrottleDefinition(
+            String name,
+            ThrottleDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteProcessorDefinitionAttributes(def);
+        doWriteAttribute("mode", def.getMode());
+        doWriteAttribute("timePeriodMillis", def.getTimePeriodMillis());
+        doWriteAttribute("rejectExecution", def.getRejectExecution());
+        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
+        doWriteAttribute("executorService", def.getExecutorService());
+        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
+        doWriteExpressionNodeElements(def);
+        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
+        endElement(name);
+    }
     protected void doWriteThrowExceptionDefinition(
             String name,
             ThrowExceptionDefinition def)
@@ -4853,7 +4855,6 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
-                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -4916,6 +4917,7 @@ public class ModelWriter extends BaseWriter {
                 case "TemplatedRoutesDefinition" -> doWriteTemplatedRoutesDefinition("templatedRoutes", (TemplatedRoutesDefinition) v);
                 case "ThreadPoolProfileDefinition" -> doWriteThreadPoolProfileDefinition("threadPoolProfile", (ThreadPoolProfileDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
+                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
@@ -4961,7 +4963,6 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
-                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -5014,6 +5015,7 @@ public class ModelWriter extends BaseWriter {
                 case "StepDefinition" -> doWriteStepDefinition("step", (StepDefinition) v);
                 case "StopDefinition" -> doWriteStopDefinition("stop", (StopDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
+                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 684ec6e965e..e70ae9cdf21 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -73,11 +73,6 @@ public class ModelWriter extends BaseWriter {
             throws IOException {
         doWriteClaimCheckDefinition("claimCheck", def);
     }
-    public void writeConcurrentRequestsThrottleDefinition(
-            ConcurrentRequestsThrottleDefinition def)
-            throws IOException {
-        doWriteConcurrentRequestsThrottleDefinition("throttle", def);
-    }
     public void writeContextScanDefinition(
             ContextScanDefinition def)
             throws IOException {
@@ -456,6 +451,11 @@ public class ModelWriter extends BaseWriter {
     public void writeThreadsDefinition(ThreadsDefinition def) throws IOException {
         doWriteThreadsDefinition("threads", def);
     }
+    public void writeThrottleDefinition(
+            ThrottleDefinition def)
+            throws IOException {
+        doWriteThrottleDefinition("throttle", def);
+    }
     public void writeThrowExceptionDefinition(
             ThrowExceptionDefinition def)
             throws IOException {
@@ -1171,20 +1171,6 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("key", def.getKey());
         endElement(name);
     }
-    protected void doWriteConcurrentRequestsThrottleDefinition(
-            String name,
-            ConcurrentRequestsThrottleDefinition def)
-            throws IOException {
-        startElement(name);
-        doWriteProcessorDefinitionAttributes(def);
-        doWriteAttribute("rejectExecution", def.getRejectExecution());
-        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
-        doWriteAttribute("executorService", def.getExecutorService());
-        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
-        doWriteExpressionNodeElements(def);
-        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
-        endElement(name);
-    }
     protected void doWriteContextScanDefinition(
             String name,
             ContextScanDefinition def)
@@ -2428,6 +2414,22 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("timeUnit", def.getTimeUnit());
         endElement(name);
     }
+    protected void doWriteThrottleDefinition(
+            String name,
+            ThrottleDefinition def)
+            throws IOException {
+        startElement(name);
+        doWriteProcessorDefinitionAttributes(def);
+        doWriteAttribute("mode", def.getMode());
+        doWriteAttribute("timePeriodMillis", def.getTimePeriodMillis());
+        doWriteAttribute("rejectExecution", def.getRejectExecution());
+        doWriteAttribute("callerRunsWhenRejected", def.getCallerRunsWhenRejected());
+        doWriteAttribute("executorService", def.getExecutorService());
+        doWriteAttribute("asyncDelayed", def.getAsyncDelayed());
+        doWriteExpressionNodeElements(def);
+        doWriteElement("correlationExpression", def.getCorrelationExpression(), this::doWriteExpressionSubElementDefinition);
+        endElement(name);
+    }
     protected void doWriteThrowExceptionDefinition(
             String name,
             ThrowExceptionDefinition def)
@@ -4853,7 +4855,6 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
-                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -4916,6 +4917,7 @@ public class ModelWriter extends BaseWriter {
                 case "TemplatedRoutesDefinition" -> doWriteTemplatedRoutesDefinition("templatedRoutes", (TemplatedRoutesDefinition) v);
                 case "ThreadPoolProfileDefinition" -> doWriteThreadPoolProfileDefinition("threadPoolProfile", (ThreadPoolProfileDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
+                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
@@ -4961,7 +4963,6 @@ public class ModelWriter extends BaseWriter {
                 case "ChoiceDefinition" -> doWriteChoiceDefinition("choice", (ChoiceDefinition) v);
                 case "CircuitBreakerDefinition" -> doWriteCircuitBreakerDefinition("circuitBreaker", (CircuitBreakerDefinition) v);
                 case "ClaimCheckDefinition" -> doWriteClaimCheckDefinition("claimCheck", (ClaimCheckDefinition) v);
-                case "ConcurrentRequestsThrottleDefinition" -> doWriteConcurrentRequestsThrottleDefinition("throttle", (ConcurrentRequestsThrottleDefinition) v);
                 case "ConvertBodyDefinition" -> doWriteConvertBodyDefinition("convertBodyTo", (ConvertBodyDefinition) v);
                 case "ConvertHeaderDefinition" -> doWriteConvertHeaderDefinition("convertHeaderTo", (ConvertHeaderDefinition) v);
                 case "ConvertVariableDefinition" -> doWriteConvertVariableDefinition("convertVariableTo", (ConvertVariableDefinition) v);
@@ -5014,6 +5015,7 @@ public class ModelWriter extends BaseWriter {
                 case "StepDefinition" -> doWriteStepDefinition("step", (StepDefinition) v);
                 case "StopDefinition" -> doWriteStopDefinition("stop", (StopDefinition) v);
                 case "ThreadsDefinition" -> doWriteThreadsDefinition("threads", (ThreadsDefinition) v);
+                case "ThrottleDefinition" -> doWriteThrottleDefinition("throttle", (ThrottleDefinition) v);
                 case "ThrowExceptionDefinition" -> doWriteThrowExceptionDefinition("throwException", (ThrowExceptionDefinition) v);
                 case "ToDefinition" -> doWriteToDefinition("to", (ToDefinition) v);
                 case "ToDynamicDefinition" -> doWriteToDynamicDefinition("toD", (ToDynamicDefinition) v);
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc
index 546b325a473..92bd507382c 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_4.adoc
@@ -33,6 +33,22 @@ In XML and YAML DSL the `type` option in `<xquery>` has been renamed to `resultT
 The copied exchange is no longer having exchange property CORRELATION_ID set that links to the original exchange.
 The reason is that this link should only be for EIPs with sub exchanges such as Splitter and Multicast.
 
+==== Throttle EIP
+
+// We refactored the Throttle EIP implementation so that Camel can support two different modes of throttling.
+//
+// One based on the total number of requests over a period of time ("TotalRequests" mode), that was the default on Camel up to
+// version 4.2.0. On Camel 4.3.0 we introduced a new one based on the number of concurrent requests and replaced the former.
+
+
+Previously Camel used a throttler based on the total number of requests over a period of time ("TotalRequests" mode). That was
+the default on Camel up to version 4.2.0. On Camel 4.3.0 we introduced a new one based on the number of concurrent requests and
+replaced the former.
+
+With Camel 4.4.0 we refactored the xref:next@components:eips:throttle-eip.adoc[Throttle EIP] implementation so that Camel can support two different modes of throttling.
+
+Check the component documentation for details about how to use each mode.
+
 ==== MDC logging
 
 When using custom MDC keys (need to configure `MDCLoggingKeysPattern`) then these custom keys are cleared at the end of routing.
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index c342c740ddc..0ef2905807e 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -16,7 +16,6 @@ import org.apache.camel.model.CatchDefinition;
 import org.apache.camel.model.ChoiceDefinition;
 import org.apache.camel.model.CircuitBreakerDefinition;
 import org.apache.camel.model.ClaimCheckDefinition;
-import org.apache.camel.model.ConcurrentRequestsThrottleDefinition;
 import org.apache.camel.model.ContextScanDefinition;
 import org.apache.camel.model.ConvertBodyDefinition;
 import org.apache.camel.model.ConvertHeaderDefinition;
@@ -91,6 +90,7 @@ import org.apache.camel.model.StopDefinition;
 import org.apache.camel.model.TemplatedRouteParameterDefinition;
 import org.apache.camel.model.ThreadPoolProfileDefinition;
 import org.apache.camel.model.ThreadsDefinition;
+import org.apache.camel.model.ThrottleDefinition;
 import org.apache.camel.model.ThrowExceptionDefinition;
 import org.apache.camel.model.ToDefinition;
 import org.apache.camel.model.ToDynamicDefinition;
@@ -2344,109 +2344,6 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
-    @YamlType(
-            nodes = "throttle",
-            types = org.apache.camel.model.ConcurrentRequestsThrottleDefinition.class,
-            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
-            displayName = "Throttle",
-            description = "Controls the rate at which messages are passed to the next node in the route",
-            deprecated = false,
-            properties = {
-                    @YamlProperty(name = "__extends", type = "object:org.apache.camel.model.language.ExpressionDefinition", oneOf = "expression"),
-                    @YamlProperty(name = "asyncDelayed", type = "boolean", description = "Enables asynchronous delay which means the thread will not block while delaying.", displayName = "Async Delayed"),
-                    @YamlProperty(name = "callerRunsWhenRejected", type = "boolean", description = "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true", displayName = "Caller Runs When Rejected"),
-                    @YamlProperty(name = "correlationExpression", type = "object:org.apache.camel.model.ExpressionSubElementDefinition", description = "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.", displayName = "Correlation Expression"),
-                    @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
-                    @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
-                    @YamlProperty(name = "executorService", type = "string", description = "To use a custom thread pool (ScheduledExecutorService) by the throttler.", displayName = "Executor Service"),
-                    @YamlProperty(name = "expression", type = "object:org.apache.camel.model.language.ExpressionDefinition", description = "Expression to configure the maximum number of messages to throttle per request", displayName = "Expression", oneOf = "expression"),
-                    @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
-                    @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
-                    @YamlProperty(name = "rejectExecution", type = "boolean", description = "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false", displayName = "Reject Execution")
-            }
-    )
-    public static class ConcurrentRequestsThrottleDefinitionDeserializer extends YamlDeserializerBase<ConcurrentRequestsThrottleDefinition> {
-        public ConcurrentRequestsThrottleDefinitionDeserializer() {
-            super(ConcurrentRequestsThrottleDefinition.class);
-        }
-
-        @Override
-        protected ConcurrentRequestsThrottleDefinition newInstance() {
-            return new ConcurrentRequestsThrottleDefinition();
-        }
-
-        @Override
-        protected boolean setProperty(ConcurrentRequestsThrottleDefinition target,
-                String propertyKey, String propertyName, Node node) {
-            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
-            switch(propertyKey) {
-                case "asyncDelayed": {
-                    String val = asText(node);
-                    target.setAsyncDelayed(val);
-                    break;
-                }
-                case "callerRunsWhenRejected": {
-                    String val = asText(node);
-                    target.setCallerRunsWhenRejected(val);
-                    break;
-                }
-                case "correlationExpression": {
-                    org.apache.camel.model.ExpressionSubElementDefinition val = asType(node, org.apache.camel.model.ExpressionSubElementDefinition.class);
-                    target.setCorrelationExpression(val);
-                    break;
-                }
-                case "disabled": {
-                    String val = asText(node);
-                    target.setDisabled(val);
-                    break;
-                }
-                case "executorService": {
-                    String val = asText(node);
-                    target.setExecutorService(val);
-                    break;
-                }
-                case "expression": {
-                    org.apache.camel.model.language.ExpressionDefinition val = asType(node, org.apache.camel.model.language.ExpressionDefinition.class);
-                    target.setExpression(val);
-                    break;
-                }
-                case "inheritErrorHandler": {
-                    String val = asText(node);
-                    target.setInheritErrorHandler(java.lang.Boolean.valueOf(val));
-                    break;
-                }
-                case "rejectExecution": {
-                    String val = asText(node);
-                    target.setRejectExecution(val);
-                    break;
-                }
-                case "id": {
-                    String val = asText(node);
-                    target.setId(val);
-                    break;
-                }
-                case "description": {
-                    String val = asText(node);
-                    target.setDescription(val);
-                    break;
-                }
-                default: {
-                    ExpressionDefinition ed = target.getExpressionType();
-                    if (ed != null) {
-                        throw new org.apache.camel.dsl.yaml.common.exception.DuplicateFieldException(node, propertyName, "as an expression");
-                    }
-                    ed = ExpressionDeserializers.constructExpressionType(propertyKey, node);
-                    if (ed != null) {
-                        target.setExpressionType(ed);
-                    } else {
-                        return false;
-                    }
-                }
-            }
-            return true;
-        }
-    }
-
     @YamlType(
             nodes = "constant",
             inline = true,
@@ -18082,6 +17979,121 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
+    @YamlType(
+            nodes = "throttle",
+            types = org.apache.camel.model.ThrottleDefinition.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            displayName = "Throttle",
+            description = "Controls the rate at which messages are passed to the next node in the route",
+            deprecated = false,
+            properties = {
+                    @YamlProperty(name = "__extends", type = "object:org.apache.camel.model.language.ExpressionDefinition", oneOf = "expression"),
+                    @YamlProperty(name = "asyncDelayed", type = "boolean", description = "Enables asynchronous delay which means the thread will not block while delaying.", displayName = "Async Delayed"),
+                    @YamlProperty(name = "callerRunsWhenRejected", type = "boolean", description = "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true", displayName = "Caller Runs When Rejected"),
+                    @YamlProperty(name = "correlationExpression", type = "object:org.apache.camel.model.ExpressionSubElementDefinition", description = "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.", displayName = "Correlation Expression"),
+                    @YamlProperty(name = "description", type = "string", description = "Sets the description of this node", displayName = "Description"),
+                    @YamlProperty(name = "disabled", type = "boolean", description = "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime.", displayName = "Disabled"),
+                    @YamlProperty(name = "executorService", type = "string", description = "To use a custom thread pool (ScheduledExecutorService) by the throttler.", displayName = "Executor Service"),
+                    @YamlProperty(name = "expression", type = "object:org.apache.camel.model.language.ExpressionDefinition", description = "Expression to configure the maximum number of messages to throttle per request", displayName = "Expression", oneOf = "expression"),
+                    @YamlProperty(name = "id", type = "string", description = "Sets the id of this node", displayName = "Id"),
+                    @YamlProperty(name = "inheritErrorHandler", type = "boolean"),
+                    @YamlProperty(name = "mode", type = "enum:TotalRequests,ConcurrentRequests", defaultValue = "TotalRequests", description = "Sets the throttling mode to one of the available modes enumerated in ThrottlingMode", displayName = "Mode"),
+                    @YamlProperty(name = "rejectExecution", type = "boolean", description = "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false", displayName = "Reject Execution"),
+                    @YamlProperty(name = "timePeriodMillis", type = "string", defaultValue = "1000", description = "Sets the time period during which the maximum request count is valid for", displayName = "Time Period Millis")
+            }
+    )
+    public static class ThrottleDefinitionDeserializer extends YamlDeserializerBase<ThrottleDefinition> {
+        public ThrottleDefinitionDeserializer() {
+            super(ThrottleDefinition.class);
+        }
+
+        @Override
+        protected ThrottleDefinition newInstance() {
+            return new ThrottleDefinition();
+        }
+
+        @Override
+        protected boolean setProperty(ThrottleDefinition target, String propertyKey,
+                String propertyName, Node node) {
+            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
+            switch(propertyKey) {
+                case "asyncDelayed": {
+                    String val = asText(node);
+                    target.setAsyncDelayed(val);
+                    break;
+                }
+                case "callerRunsWhenRejected": {
+                    String val = asText(node);
+                    target.setCallerRunsWhenRejected(val);
+                    break;
+                }
+                case "correlationExpression": {
+                    org.apache.camel.model.ExpressionSubElementDefinition val = asType(node, org.apache.camel.model.ExpressionSubElementDefinition.class);
+                    target.setCorrelationExpression(val);
+                    break;
+                }
+                case "disabled": {
+                    String val = asText(node);
+                    target.setDisabled(val);
+                    break;
+                }
+                case "executorService": {
+                    String val = asText(node);
+                    target.setExecutorService(val);
+                    break;
+                }
+                case "expression": {
+                    org.apache.camel.model.language.ExpressionDefinition val = asType(node, org.apache.camel.model.language.ExpressionDefinition.class);
+                    target.setExpression(val);
+                    break;
+                }
+                case "inheritErrorHandler": {
+                    String val = asText(node);
+                    target.setInheritErrorHandler(java.lang.Boolean.valueOf(val));
+                    break;
+                }
+                case "mode": {
+                    String val = asText(node);
+                    target.setMode(val);
+                    break;
+                }
+                case "rejectExecution": {
+                    String val = asText(node);
+                    target.setRejectExecution(val);
+                    break;
+                }
+                case "timePeriodMillis": {
+                    String val = asText(node);
+                    target.setTimePeriodMillis(val);
+                    break;
+                }
+                case "id": {
+                    String val = asText(node);
+                    target.setId(val);
+                    break;
+                }
+                case "description": {
+                    String val = asText(node);
+                    target.setDescription(val);
+                    break;
+                }
+                default: {
+                    ExpressionDefinition ed = target.getExpressionType();
+                    if (ed != null) {
+                        throw new org.apache.camel.dsl.yaml.common.exception.DuplicateFieldException(node, propertyName, "as an expression");
+                    }
+                    ed = ExpressionDeserializers.constructExpressionType(propertyKey, node);
+                    if (ed != null) {
+                        target.setExpressionType(ed);
+                    } else {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
     @YamlType(
             nodes = {
                     "throw-exception",
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index 81568219098..bf7c90a66be 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -75,8 +75,6 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "combinedServiceFilter": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer();
             case "org.apache.camel.model.cloud.CombinedServiceCallServiceFilterConfiguration": return new ModelDeserializers.CombinedServiceCallServiceFilterConfigurationDeserializer();
             case "org.apache.camel.model.app.ComponentScanDefinition": return new ModelDeserializers.ComponentScanDefinitionDeserializer();
-            case "throttle": return new ModelDeserializers.ConcurrentRequestsThrottleDefinitionDeserializer();
-            case "org.apache.camel.model.ConcurrentRequestsThrottleDefinition": return new ModelDeserializers.ConcurrentRequestsThrottleDefinitionDeserializer();
             case "constant": return new ModelDeserializers.ConstantExpressionDeserializer();
             case "org.apache.camel.model.language.ConstantExpression": return new ModelDeserializers.ConstantExpressionDeserializer();
             case "consul-service-discovery": return new ModelDeserializers.ConsulServiceCallServiceDiscoveryConfigurationDeserializer();
@@ -503,6 +501,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "org.apache.camel.model.ThreadsDefinition": return new ModelDeserializers.ThreadsDefinitionDeserializer();
             case "thrift": return new ModelDeserializers.ThriftDataFormatDeserializer();
             case "org.apache.camel.model.dataformat.ThriftDataFormat": return new ModelDeserializers.ThriftDataFormatDeserializer();
+            case "throttle": return new ModelDeserializers.ThrottleDefinitionDeserializer();
+            case "org.apache.camel.model.ThrottleDefinition": return new ModelDeserializers.ThrottleDefinitionDeserializer();
             case "throw-exception": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
             case "throwException": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
             case "org.apache.camel.model.ThrowExceptionDefinition": return new ModelDeserializers.ThrowExceptionDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index edb9228f50a..b82aca255dc 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -28,9 +28,6 @@
           "claimCheck" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ClaimCheckDefinition"
           },
-          "throttle" : {
-            "$ref" : "#/items/definitions/org.apache.camel.model.ConcurrentRequestsThrottleDefinition"
-          },
           "convertBodyTo" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ConvertBodyDefinition"
           },
@@ -169,6 +166,9 @@
           "threads" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ThreadsDefinition"
           },
+          "throttle" : {
+            "$ref" : "#/items/definitions/org.apache.camel.model.ThrottleDefinition"
+          },
           "throwException" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.ThrowExceptionDefinition"
           },
@@ -745,154 +745,6 @@
           }
         }
       },
-      "org.apache.camel.model.ConcurrentRequestsThrottleDefinition" : {
-        "title" : "Throttle",
-        "description" : "Controls the rate at which messages are passed to the next node in the route",
-        "type" : "object",
-        "additionalProperties" : false,
-        "anyOf" : [ {
-          "oneOf" : [ {
-            "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
-          }, {
-            "not" : {
-              "anyOf" : [ {
-                "required" : [ "expression" ]
-              }, {
-                "required" : [ "constant" ]
-              }, {
-                "required" : [ "csimple" ]
-              }, {
-                "required" : [ "datasonnet" ]
-              }, {
-                "required" : [ "exchangeProperty" ]
-              }, {
-                "required" : [ "groovy" ]
-              }, {
-                "required" : [ "header" ]
-              }, {
-                "required" : [ "hl7terser" ]
-              }, {
-                "required" : [ "java" ]
-              }, {
-                "required" : [ "joor" ]
-              }, {
-                "required" : [ "jq" ]
-              }, {
-                "required" : [ "js" ]
-              }, {
-                "required" : [ "jsonpath" ]
-              }, {
-                "required" : [ "language" ]
-              }, {
-                "required" : [ "method" ]
-              }, {
-                "required" : [ "mvel" ]
-              }, {
-                "required" : [ "ognl" ]
-              }, {
-                "required" : [ "python" ]
-              }, {
-                "required" : [ "ref" ]
-              }, {
-                "required" : [ "simple" ]
-              }, {
-                "required" : [ "spel" ]
-              }, {
-                "required" : [ "tokenize" ]
-              }, {
-                "required" : [ "variable" ]
-              }, {
-                "required" : [ "wasm" ]
-              }, {
-                "required" : [ "xpath" ]
-              }, {
-                "required" : [ "xquery" ]
-              }, {
-                "required" : [ "xtokenize" ]
-              } ]
-            }
-          }, {
-            "type" : "object",
-            "required" : [ "expression" ],
-            "properties" : {
-              "expression" : {
-                "title" : "Expression",
-                "description" : "Expression to configure the maximum number of messages to throttle per request",
-                "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
-              }
-            }
-          } ]
-        } ],
-        "properties" : {
-          "asyncDelayed" : {
-            "type" : "boolean",
-            "title" : "Async Delayed",
-            "description" : "Enables asynchronous delay which means the thread will not block while delaying."
-          },
-          "callerRunsWhenRejected" : {
-            "type" : "boolean",
-            "title" : "Caller Runs When Rejected",
-            "description" : "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true"
-          },
-          "correlationExpression" : {
-            "title" : "Correlation Expression",
-            "description" : "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.",
-            "$ref" : "#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition"
-          },
-          "description" : {
-            "type" : "string",
-            "title" : "Description",
-            "description" : "Sets the description of this node"
-          },
-          "disabled" : {
-            "type" : "boolean",
-            "title" : "Disabled",
-            "description" : "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime."
-          },
-          "executorService" : {
-            "type" : "string",
-            "title" : "Executor Service",
-            "description" : "To use a custom thread pool (ScheduledExecutorService) by the throttler."
-          },
-          "id" : {
-            "type" : "string",
-            "title" : "Id",
-            "description" : "Sets the id of this node"
-          },
-          "rejectExecution" : {
-            "type" : "boolean",
-            "title" : "Reject Execution",
-            "description" : "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false"
-          },
-          "constant" : { },
-          "csimple" : { },
-          "datasonnet" : { },
-          "exchangeProperty" : { },
-          "groovy" : { },
-          "header" : { },
-          "hl7terser" : { },
-          "java" : { },
-          "joor" : { },
-          "jq" : { },
-          "js" : { },
-          "jsonpath" : { },
-          "language" : { },
-          "method" : { },
-          "mvel" : { },
-          "ognl" : { },
-          "python" : { },
-          "ref" : { },
-          "simple" : { },
-          "spel" : { },
-          "tokenize" : { },
-          "variable" : { },
-          "wasm" : { },
-          "xpath" : { },
-          "xquery" : { },
-          "xtokenize" : { },
-          "expression" : { }
-        }
-      },
       "org.apache.camel.model.ContextScanDefinition" : {
         "title" : "Context Scan",
         "description" : "Scans for Java org.apache.camel.builder.RouteBuilder instances in the context org.apache.camel.spi.Registry .",
@@ -6946,6 +6798,167 @@
           }
         }
       },
+      "org.apache.camel.model.ThrottleDefinition" : {
+        "title" : "Throttle",
+        "description" : "Controls the rate at which messages are passed to the next node in the route",
+        "type" : "object",
+        "additionalProperties" : false,
+        "anyOf" : [ {
+          "oneOf" : [ {
+            "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
+          }, {
+            "not" : {
+              "anyOf" : [ {
+                "required" : [ "expression" ]
+              }, {
+                "required" : [ "constant" ]
+              }, {
+                "required" : [ "csimple" ]
+              }, {
+                "required" : [ "datasonnet" ]
+              }, {
+                "required" : [ "exchangeProperty" ]
+              }, {
+                "required" : [ "groovy" ]
+              }, {
+                "required" : [ "header" ]
+              }, {
+                "required" : [ "hl7terser" ]
+              }, {
+                "required" : [ "java" ]
+              }, {
+                "required" : [ "joor" ]
+              }, {
+                "required" : [ "jq" ]
+              }, {
+                "required" : [ "js" ]
+              }, {
+                "required" : [ "jsonpath" ]
+              }, {
+                "required" : [ "language" ]
+              }, {
+                "required" : [ "method" ]
+              }, {
+                "required" : [ "mvel" ]
+              }, {
+                "required" : [ "ognl" ]
+              }, {
+                "required" : [ "python" ]
+              }, {
+                "required" : [ "ref" ]
+              }, {
+                "required" : [ "simple" ]
+              }, {
+                "required" : [ "spel" ]
+              }, {
+                "required" : [ "tokenize" ]
+              }, {
+                "required" : [ "variable" ]
+              }, {
+                "required" : [ "wasm" ]
+              }, {
+                "required" : [ "xpath" ]
+              }, {
+                "required" : [ "xquery" ]
+              }, {
+                "required" : [ "xtokenize" ]
+              } ]
+            }
+          }, {
+            "type" : "object",
+            "required" : [ "expression" ],
+            "properties" : {
+              "expression" : {
+                "title" : "Expression",
+                "description" : "Expression to configure the maximum number of messages to throttle per request",
+                "$ref" : "#/items/definitions/org.apache.camel.model.language.ExpressionDefinition"
+              }
+            }
+          } ]
+        } ],
+        "properties" : {
+          "asyncDelayed" : {
+            "type" : "boolean",
+            "title" : "Async Delayed",
+            "description" : "Enables asynchronous delay which means the thread will not block while delaying."
+          },
+          "callerRunsWhenRejected" : {
+            "type" : "boolean",
+            "title" : "Caller Runs When Rejected",
+            "description" : "Whether or not the caller should run the task when it was rejected by the thread pool. Is by default true"
+          },
+          "correlationExpression" : {
+            "title" : "Correlation Expression",
+            "description" : "The expression used to calculate the correlation key to use for throttle grouping. The Exchange which has the same correlation key is throttled together.",
+            "$ref" : "#/items/definitions/org.apache.camel.model.ExpressionSubElementDefinition"
+          },
+          "description" : {
+            "type" : "string",
+            "title" : "Description",
+            "description" : "Sets the description of this node"
+          },
+          "disabled" : {
+            "type" : "boolean",
+            "title" : "Disabled",
+            "description" : "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime."
+          },
+          "executorService" : {
+            "type" : "string",
+            "title" : "Executor Service",
+            "description" : "To use a custom thread pool (ScheduledExecutorService) by the throttler."
+          },
+          "id" : {
+            "type" : "string",
+            "title" : "Id",
+            "description" : "Sets the id of this node"
+          },
+          "mode" : {
+            "type" : "string",
+            "title" : "Mode",
+            "description" : "Sets the throttling mode to one of the available modes enumerated in ThrottlingMode",
+            "default" : "TotalRequests",
+            "enum" : [ "TotalRequests", "ConcurrentRequests" ]
+          },
+          "rejectExecution" : {
+            "type" : "boolean",
+            "title" : "Reject Execution",
+            "description" : "Whether or not throttler throws the ThrottlerRejectedExecutionException when the exchange exceeds the request limit Is by default false"
+          },
+          "timePeriodMillis" : {
+            "type" : "string",
+            "title" : "Time Period Millis",
+            "description" : "Sets the time period during which the maximum request count is valid for",
+            "default" : "1000"
+          },
+          "constant" : { },
+          "csimple" : { },
+          "datasonnet" : { },
+          "exchangeProperty" : { },
+          "groovy" : { },
+          "header" : { },
+          "hl7terser" : { },
+          "java" : { },
+          "joor" : { },
+          "jq" : { },
+          "js" : { },
+          "jsonpath" : { },
+          "language" : { },
+          "method" : { },
+          "mvel" : { },
+          "ognl" : { },
+          "python" : { },
+          "ref" : { },
+          "simple" : { },
+          "spel" : { },
+          "tokenize" : { },
+          "variable" : { },
+          "wasm" : { },
+          "xpath" : { },
+          "xquery" : { },
+          "xtokenize" : { },
+          "expression" : { }
+        }
+      },
       "org.apache.camel.model.ThrowExceptionDefinition" : {
         "title" : "Throw Exception",
         "description" : "Throws an exception",
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
index 60d8b0f11fc..2b3ebddcc92 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/ThrottleTest.groovy
@@ -17,7 +17,7 @@
 package org.apache.camel.dsl.yaml
 
 import org.apache.camel.dsl.yaml.support.YamlTestSupport
-import org.apache.camel.model.ConcurrentRequestsThrottleDefinition
+import org.apache.camel.model.ThrottleDefinition
 import org.apache.camel.model.language.ConstantExpression
 import org.apache.camel.spi.Resource
 import org.apache.camel.support.PluginHelper
@@ -28,7 +28,7 @@ class ThrottleTest extends YamlTestSupport {
         when:
             PluginHelper.getRoutesLoader(context).loadRoutes(resource)
         then:
-            with(context.routeDefinitions[0].outputs[0], ConcurrentRequestsThrottleDefinition) {
+            with(context.routeDefinitions[0].outputs[0], ThrottleDefinition) {
                 with (expression, ConstantExpression) {
                     language == 'constant'
                     expression == '5'