From 46aa9993add6e426e7f247547d5c699c5720b326 Mon Sep 17 00:00:00 2001 From: Simon Hirtreiter <14137977+simonhir@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:12:09 +0200 Subject: [PATCH] Maint/hazelcast properties (#206) * :recycle: gateway refactor hazelcast properties * :memo: gateway document hazelcast properties * :memo: gateway document hazelcast module java properties * :memo: gateway document hazelcast kubernetes * :art: gateway sportless format * :recycle: gateway rm hazelcast kubernetes namespace as auto discovered * :recycle: gateway refactor properties load * :recycle: gateway refactor properties load --- refarch-gateway/README.md | 46 +++++++++++++++---- .../gateway/ApiGatewayApplication.java | 5 +- .../configuration/HazelcastProperties.java | 27 +++++++++++ ... => WebSessionHazelcastConfiguration.java} | 28 ++++------- 4 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/HazelcastProperties.java rename refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/{WebSessionConfiguration.java => WebSessionHazelcastConfiguration.java} (81%) diff --git a/refarch-gateway/README.md b/refarch-gateway/README.md index b93ed718..d15a0deb 100644 --- a/refarch-gateway/README.md +++ b/refarch-gateway/README.md @@ -41,16 +41,17 @@ Beside the default behaviour there are some special route prefixes which are han ## Configuration -| Var | Description | Example | -|----------------------------------------------------------|----------------------------------------------------|-------------------------------------------------------------------------| -| `SPRING_PROFILES_ACTIVE` | See profiles | `local,hazelcast-local` | -| `SPRING_CLOUD_GATEWAY_ROUTES__ID` | Id of a route definition. | `backend` | -| `SPRING_CLOUD_GATEWAY_ROUTES__URI` | The uri to route to if this route matches. | `http://backend-service:8080/` | -| `SPRING_CLOUD_GATEWAY_ROUTES__PREDICATES_` | Route predicates i.e. matcher. | `Path=/api/backend-service/**` | -| `SPRING_CLOUD_GATEWAY_ROUTES__FILTERS_` | List of filters applied to the route. | `RewritePath=/api/backend-service/(?.*), /$\{urlsegments}` | -| `ALLOWED_ORIGINS_PUBLIC` (optional) | List of urls allowed as origin for public routes. | `https://*.example.com,http://localhost:*` | -| `ALLOWED_ORIGINS_CLIENTS` (optional) | List of urls allowed as origin for clients routes. | `https://*.example.com,http://localhost:*` | -| `REFARCH_SECURITY_CSRFWHITELISTED_` (optional) | List of routes to disable csrf protection for. | `/example/**` | +| Var | Description | Example | +|----------------------------------------------------------|-------------------------------------------------------------------|-------------------------------------------------------------------------| +| `SPRING_PROFILES_ACTIVE` | See profiles | `local,hazelcast-local` | +| `SPRING_CLOUD_GATEWAY_ROUTES__ID` | Id of a route definition. | `backend` | +| `SPRING_CLOUD_GATEWAY_ROUTES__URI` | The uri to route to if this route matches. | `http://backend-service:8080/` | +| `SPRING_CLOUD_GATEWAY_ROUTES__PREDICATES_` | Route predicates i.e. matcher. | `Path=/api/backend-service/**` | +| `SPRING_CLOUD_GATEWAY_ROUTES__FILTERS_` | List of filters applied to the route. | `RewritePath=/api/backend-service/(?.*), /$\{urlsegments}` | +| `REFARCH_HAZELCAST_SERVICENAME` | Kubernetes service name for when using profile `hazelcast-k8s`. | | +| `ALLOWED_ORIGINS_PUBLIC` (optional) | List of urls allowed as origin for public routes. | `https://*.example.com,http://localhost:*` | +| `ALLOWED_ORIGINS_CLIENTS` (optional) | List of urls allowed as origin for clients routes. | `https://*.example.com,http://localhost:*` | +| `REFARCH_SECURITY_CSRFWHITELISTED_` (optional) | List of routes to disable csrf protection for. | `/example/**` | ### Security @@ -78,3 +79,28 @@ spring: # needed for userInfo endpoint scope: profile, openid ``` + +### Hazelcast + +Beside the already mentioned properties Hazelcast also has the following requirements. + +#### Modular java +See https://docs.hazelcast.com/hazelcast/5.5/getting-started/install-hazelcast#using-modular-java + +Following Java options need to be set. +For the gateway image this can be done with `JAVA_OPTS_APPEND`. +``` +--add-modules java.se \ + --add-exports java.base/jdk.internal.ref=ALL-UNNAMED \ + --add-opens java.base/java.lang=ALL-UNNAMED \ + --add-opens java.base/java.nio=ALL-UNNAMED \ + --add-opens java.base/sun.nio.ch=ALL-UNNAMED \ + --add-opens java.management/sun.management=ALL-UNNAMED \ + --add-opens jdk.management/com.ibm.lang.management.internal=ALL-UNNAMED \ + --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED +``` + +#### Kubernetes + +For running Hazelcast with profile `hazelcast-k8s` in Kubernetes port `5701` needs to be accessible. +This need to be configured for the Service and Deployment. diff --git a/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/ApiGatewayApplication.java b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/ApiGatewayApplication.java index ffc67c37..78ef74f0 100644 --- a/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/ApiGatewayApplication.java +++ b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/ApiGatewayApplication.java @@ -1,10 +1,9 @@ package de.muenchen.refarch.gateway; -import de.muenchen.refarch.gateway.configuration.SecurityProperties; import jakarta.annotation.PostConstruct; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import reactor.core.publisher.Hooks; /** @@ -30,7 +29,7 @@ * "https://cloud.spring.io/spring-cloud-gateway/reference/html/">https://cloud.spring.io/spring-cloud-gateway/reference/html/ */ @SpringBootApplication -@EnableConfigurationProperties(SecurityProperties.class) +@ConfigurationPropertiesScan public class ApiGatewayApplication { public static void main(final String[] args) { diff --git a/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/HazelcastProperties.java b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/HazelcastProperties.java new file mode 100644 index 00000000..55f00ba0 --- /dev/null +++ b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/HazelcastProperties.java @@ -0,0 +1,27 @@ +package de.muenchen.refarch.gateway.configuration; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@RequiredArgsConstructor +@AllArgsConstructor +@ConfigurationProperties("refarch.hazelcast") +@SuppressWarnings("PMD.ImmutableField") +public class HazelcastProperties { + /** + * Name of the hazelcast cluster. + */ + private String clusterName = "session_replication_group"; + /** + * Name of the hazelcast instance. + */ + private String instanceName = "hazl_instance"; + /** + * Kubernetes service name. + * Required for running hazelcast inside kubernetes. + */ + private String serviceName; +} diff --git a/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionConfiguration.java b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionHazelcastConfiguration.java similarity index 81% rename from refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionConfiguration.java rename to refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionHazelcastConfiguration.java index 8ab30818..b61afcac 100644 --- a/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionConfiguration.java +++ b/refarch-gateway/src/main/java/de/muenchen/refarch/gateway/configuration/WebSessionHazelcastConfiguration.java @@ -8,6 +8,7 @@ import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.map.IMap; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -28,19 +29,10 @@ @Configuration @EnableSpringWebSession @Profile({ "hazelcast-local", "hazelcast-k8s" }) -public class WebSessionConfiguration { +@RequiredArgsConstructor +public class WebSessionHazelcastConfiguration { - @Value("${hazelcast.instance:hazl_instance}") - public String hazelcastInstanceName; - - @Value("${hazelcast.group-name:session_replication_group}") - public String groupConfigName; - - @Value("${app.spring-session-hazelcast.namespace:my_namespace}") - public String openshiftNamespace; - - @Value("${hazelcast.openshift-service-name:apigateway}") - public String openshiftServiceName; + private final HazelcastProperties hazelcastProperties; @Bean public ServerOAuth2AuthorizedClientRepository authorizedClientRepository() { @@ -64,8 +56,8 @@ public Config localConfig(@Value( "${spring.session.timeout}" ) final int timeout) { final Config hazelcastConfig = new Config(); - hazelcastConfig.setInstanceName(hazelcastInstanceName); - hazelcastConfig.setClusterName(groupConfigName); + hazelcastConfig.setClusterName(hazelcastProperties.getClusterName()); + hazelcastConfig.setInstanceName(hazelcastProperties.getInstanceName()); addSessionTimeoutToHazelcastConfig(hazelcastConfig, timeout); @@ -84,17 +76,15 @@ public Config localConfig(@Value( @Profile({ "hazelcast-k8s" }) public Config config(@Value("${spring.session.timeout}") final int timeout) { final Config hazelcastConfig = new Config(); - hazelcastConfig.setInstanceName(hazelcastInstanceName); - hazelcastConfig.setClusterName(groupConfigName); + hazelcastConfig.setClusterName(hazelcastProperties.getClusterName()); + hazelcastConfig.setInstanceName(hazelcastProperties.getInstanceName()); addSessionTimeoutToHazelcastConfig(hazelcastConfig, timeout); hazelcastConfig.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); hazelcastConfig.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) - // explicitly configure namespace because default env lookup is not always correct - .setProperty("namespace", openshiftNamespace) //If we don't set a specific name, it would call -all- services within a namespace - .setProperty("service-name", openshiftServiceName); + .setProperty("service-name", hazelcastProperties.getServiceName()); return hazelcastConfig; }