Remote Events migrated from Spring Bus to Spring Cloud Stream (#2563)

* Remote Events migrated from Spring Bus to Spring Cloud Stream

---------

Co-authored-by: vasilchev <vasil.ilchev@bosch.com>
This commit is contained in:
Vasil Ilchev
2025-07-30 16:58:00 +03:00
committed by GitHub
parent 10da0288d9
commit 4a8e60764f
49 changed files with 1147 additions and 461 deletions

View File

@@ -256,7 +256,7 @@ public class MgmtTargetTagResourceTest extends AbstractManagementApiIntegrationT
@Test
@ExpectEvents({
@Expect(type = TargetTagCreatedEvent.class, count = 1),
@Expect(type = TargetCreatedEvent.class, count = 5),
@Expect(type = TargetCreatedEvent.class, count = 5),
@Expect(type = TargetUpdatedEvent.class, count = 5) })
public void getAssignedTargetsWithPagingLimitRequestParameter() throws Exception {
final TargetTag tag = testdataFactory.createTargetTags(1, "").get(0);
@@ -280,7 +280,7 @@ public class MgmtTargetTagResourceTest extends AbstractManagementApiIntegrationT
@Test
@ExpectEvents({
@Expect(type = TargetTagCreatedEvent.class, count = 1),
@Expect(type = TargetCreatedEvent.class, count = 5),
@Expect(type = TargetCreatedEvent.class, count = 5),
@Expect(type = TargetUpdatedEvent.class, count = 5) })
public void getAssignedTargetsWithPagingLimitAndOffsetRequestParameter() throws Exception {
final TargetTag tag = testdataFactory.createTargetTags(1, "").get(0);

View File

@@ -11,6 +11,4 @@
# Logging START - activate to see request/response details
#logging.level.org.eclipse.hawkbit.rest.util.MockMvcResultPrinter=DEBUG
# Logging END
# disable spring cloud bus for tests
spring.cloud.bus.enabled=false
org.eclipse.hawkbit.events.remote-enabled=false

View File

@@ -24,17 +24,46 @@ run org.eclipse.hawkbit.app.mgmt.MgmtServerStart
The Management API can be accessed via http://localhost:8080/rest/v1
The root url http://localhost:8080 will redirect directly to the Swagger Management UI
### Clustering (Experimental!!!)
# Clustering (Experimental!!!)
## Events
The micro-service instances are configured to communicate via Spring Cloud Bus. You could run multiple instances of any
micro-service but hawkbit-mgmt-server. Management server run some schedulers which shall not run simultaneously - e.g.
auto assignment checker and rollouts executor. To run multiple management server instances you shall do some extensions
of hawkbit to ensure that they wont run schedulers simultaneously or you shall configure all instances but one to do not
run schedulers!
Event communication between nodes is based on [Spring Cloud Stream](http://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/).
There are different [binder implementations](http://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/#_binders)
available. The _hawkbit Update Server_ uses RabbitMQ binder.
## Optional Protostuff for Spring cloud bus
You can run multiple instances of any micro-service, including those consuming events.
However, the `hawkbit-mgmt-server` should typically be run as a single instance, as it schedules time-sensitive jobs such as auto-assignment checking and rollout execution.
If multiple management server instances are needed, you must extend hawkBit to ensure that scheduled tasks do not run concurrently.
Alternatively, configure all but one instance to disable scheduler execution.
The micro-service instances are configured to communicate via Spring Cloud Bus. Optionally, you could
## Event Channel Types in Spring Cloud Stream
Remote events in hawkBit are distributed through **two distinct types of channels**:
### 1. Fanout Event Channel
- Every service instance listening to `fanoutEventChannel` receives **a copy of every message**, regardless of instance count.
- Common for events that should be processed by each consumer independently
- In-memory cache updates
- Internal state propagation
- Logging or auditing
- Not recommended for scenarios where only one consumer should process an event (see `serviceEventChannel` for that).
**Note**: Every instance bound to this channel will get its own copy of the message.
### 2. Service Event Channel
The `serviceEventChannel` is used to **ensure exclusive consumption of events** across service instances.
Only **one instance per consumer group** receives and processes each message, which is critical for non-idempotent or resource-sensitive operations.
- Only one instance in a consumer group receives each message.
- Ideal for external integrations, third-party API calls, or any task that must not be duplicated.
- Load-balanced across instances within the same group.
### Optional Protostuff for Spring cloud stream
The micro-service instances are configured to communicate via Spring Cloud Stream. Optionally, you could
use [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance.
**Note**: If Protostuff is enabled it shall be enabled on all microservices!
@@ -42,19 +71,18 @@ use [Protostuff](https://github.com/protostuff/protostuff) based message payload
Add/Uncomment to/in your `application.properties` :
```properties
spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff
spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff
spring.cloud.stream.default.content-type=application/binary+protostuff
```
Add to your `pom.xml` :
```xml
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
</dependency>
```

View File

@@ -14,7 +14,6 @@ spring.main.allow-bean-definition-overriding=true
spring.port=8080
# Logging configuration
logging.level.org.eclipse.hawkbit.eventbus.DeadEventListener=WARN
logging.level.org.springframework.boot.actuate.audit.listener.AuditListener=WARN
logging.level.org.hibernate.validator.internal.util.Version=WARN
# security Log with hints on potential attacks
@@ -43,15 +42,6 @@ hawkbit.server.repository.publish-target-poll-event=false
# Disable discovery client of spring-cloud-commons
spring.cloud.discovery.enabled=false
# Configure communication between services
endpoints.spring.cloud.bus.refresh.enabled=false
endpoints.spring.cloud.bus.env.enabled=false
spring.cloud.stream.bindings.springCloudBusInput.group=mgmt-server
# To use protostuff (for instance fot improved performance) you shall uncomment
# the following two lines and add io.protostuff:protostuff-core and io.protostuff:protostuff-runtime to dependencies
#spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff
#spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff
# Swagger Configuration / https://springdoc.org/v2/#properties
springdoc.api-docs.version=openapi_3_0
@@ -61,4 +51,9 @@ springdoc.packages-to-scan=org.eclipse.hawkbit.mgmt
springdoc.paths-to-exclude=/system/**
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.csrf.enabled=true
springdoc.swagger-ui.doc-expansion=none
springdoc.swagger-ui.doc-expansion=none
# remote events configuration
spring.config.import=classpath:/hawkbit-events-defaults.properties
# Optional: Use protostuff (if enabled)
# spring.cloud.stream.default.content-type=application/binary+protostuff