I am trying to set up the rate-limiting in a spring cloud gateway.
I tried to configure the filter in the application.yaml as below
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 5
I am getting the below error
java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name RequestRateLimiter
How to implement the rate limit in the spring cloud gateway?
One of the possibilities is not including the following dependency (the mistake which I did first time)
org.springframework.boot:spring-boot-starter-data-redis-reactive
Since the args contain redis-rate-limiter this dependency is must.
Below is a screenshot from the IDE showing RequestRateLimiterGatewayFilterFactory getting added when the above dependency is included.
Related
I have a spring boot (2.7.0) with spring-cloud-depependencies (2021.0.3) under GKE, where since I noticed Kubernetes api client is failing to connect but just few milliseconds later succeeding (And I can't figure out the reason why yet, although one detail is GKE cluster was upgraded, but that is another story), I rather on the meantime to fail fast the spring boot application and try to wait till the configmap is ready to be read.
In order to do so, I configured my bootstrap as follows:
profiles: some-profile
cloud:
kubernetes:
config:
retry:
initial-interval: 1000
max-attempts: 6
max-interval: 2000
multiplier: 1.1
fail-fast: true
enabled: true
enableApi: true
namespace: some-namespace
name: someConfigmapName
reload:
enabled: true
monitoring-config-maps: true
mode: event
strategy: refresh
I added the respective dependencies as well:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
As those are the steps declared here: https://docs.spring.io/spring-cloud-kubernetes/docs/current/reference/html/#configmap-propertysource
You can also make your application retry loading ConfigMap property sources on a failure. First, you need to set spring.cloud.kubernetes.config.fail-fast=true. Then you need to add spring-retry and spring-boot-starter-aop to your classpath. You can configure retry properties such as the maximum number of attempts, backoff options like initial interval, multiplier, max interval by setting the spring.cloud.kubernetes.config.retry.* properties.
But I'm getting as an error:
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'configServerRetryInterceptor' that could not be found.
Action:
Consider defining a bean named 'configServerRetryInterceptor' in your configuration.
Why should I add the configServerRetryInterceptor bean? shouldn't that one instantiated automatically based on the steps declared in the the documentation? Regardless if that, if I create such a #bean in a class annotated with #Configuration it doesn't work either.
What step am I missing?
Versions
Spring Parent: 2.7.4, Spring Cloud Version: 2021.0.4, Java Version: 11
Issue
My Spring service has been using Eureka to connect to the config server for a long time, but I want to upgrade to Spring 2.7.4. I understand that as of Spring 2.4, the bootstrap context has been deprecated (source) and I need to make some adjustments to the old bootstrap properties and move them over to application.properties.
The documentation for Spring Cloud specifies that in order for me to continue to use discovery-first config lookup, I need to define a spring.config.import property with an optional configserver entry (source). Since I'm also using Vault, I define the property as follows:
spring.config.import = optional:configserver:placeholder,vault://<my-generic-backend>/dev
Next, I need to define the following properties (source). These properties were already defined in my old bootstrap.properties, so all I need to do is copy and paste.
spring.cloud.config.discovery.enabled = true
spring.cloud.config.discovery.serviceId = config-server
eureka.client.serviceUrl.defaultZone = <my-eureka-url>
Unless I'm missing something, these are all the steps I need to take in order to upgrade to 2.7.4. However, when I run the Spring service, it complains that it can't find the config server (via Eureka, or via URL), then it registers successfully with Eureka, and then continues trying and failing to find the config server.
Here is some of the output of the program:
> Running with Spring Boot v2.7.4, Spring v5.3.23
> Could not locate configserver via discovery: No instances found of configserver (config-server)
> Could not locate PropertySource ([ConfigServerConfigDataResource#2aa6311a uris = array<String>['placeholder'], optional = true, profiles = list['local']]): Invalid URL: placeholder
...
> DiscoveryClient_<my-project-name>/local - registration status: 204
I understand why it's failing to find a config server at URL: placeholder since that's not a valid URL, but I don't understand how the service can successfully register with Eureka yet not be able to find the config server. I know the service is registered because the output of the program says it registered correctly (and I can see it in the registry), and I know that the config server has the correct entity ID (config-server) because it was copied and pasted from the old bootstrap (and I can see config-server in the registry).
Workaround with Hardcoded URL
When I hardcode the config server URL like this (and set spring.cloud.config.discovery.enabled to false), the config is loaded properly from the server:
spring.config.import=configserver:https://<my-hardcoded-config-url>.com,vault://<my-generic-backend>/dev
Workaround with Bootstrap
It's possible to return to using the bootstrap context and still use Spring 2.7.4 with discovery-first config lookup by adding the "spring-cloud-starter-bootstrap" dependency. So I added the dependency to my POM and moved these properties back to bootstrap.properties from application.properties.
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
I moved the Vault and Eureka properties back into bootstrap.properties as well. The new application.properties now contains no values relating to Eureka, Vault, and Cloud Config.
When I run the service, it does indeed find the address for the config server through Eureka, as expected (although it fails to connect because it's the internal address and I'm running locally).
Conclusion
While these are valid workarounds, it's frustrating to not be able to have a dynamic URL for the config server (as is the entire point of using Eureka). Right now, it looks like my choices are either to use a hard-coded URL and risk having to change every property file, or use a deprecated behavior that Spring documentation specifically disfavors (source).
I would appreciate any guidance you have on the issue, and I thank you in advance.
I am trying to run the Camel Salesforce Kafka Source Connector version 1.0.x (LTS) and following the documentation as described on https://camel.apache.org/camel-kafka-connector/1.0.x/reference/connectors/camel-salesforce-source-kafka-source-connector.html all I need to do is to configure a bunch of camel.kamelet.salesforce-source.xxx properties which is exactly what I did.
Let's just assume that camel.kamelet.salesforce-source.clientId=xyz
When trying to run the connector it fails to start complaining that clientId is an unknown parameter:
Failed to resolve endpoint: salesforce://event/Case__e?clientId=xyz due to:
There are 1 parameters that couldn't be set on the endpoint.
Check the uri if the parameters are spelt correctly and that they are properties of the endpoint.
Unknown parameters=[{clientId=xyz}]
Running out of ideas I tried to configure a camel route myself and specified the clientId part of the salesforce endpoint. The issue was exactly the same. Running out of ideas I asked this question Unable to create camel salesforce endpoint and got a valid explanation for that behaviour: This type of settings should be done at component level not at endpoint level.
Digging further I checked that version 0.11.x (LTS) allows us to configure camel.component.salesforce.xxx properties as opposed to 1.0.x (LTS) which only has camel.kamelet.salesforce-source.xxx. In fact I was able to start the 0.11.x (LTS) connector.
Now it is hard to believe the migration from 0.11.x to 1.0.x was not fully tested and I am tempted to say I am missing some basic setup.
Can anyone bring some light in here?
Thank you in advance for your inputs.
I am attempting to follow the answer here How to integrate AWS Secret Manager with Spring Boot Application also described https://cloud.spring.io/spring-cloud-aws/2.1.x/multi/multi__cloud_environment.html . It appears to be trying to read from secrets manager however when my service is starting up I am getting an error
java.lang.IllegalArgumentException: No region provided.
I have tried setting the region as an environment variable and relaunching intelliJ but I still face this issue. Any suggestions on how to set this region since I am not the one explicitly building the client? I'm out of ideas.
To add:
My application.yml file has the following setup:
cloud:
aws:
region:
static: us-east-1
secretsmanager:
prefix: /secret
defaultContext: application
profileSeparator: _
failFast: true
name: platform
enabled: true
I added the cloud section in an attempt to fix the error but it still does not boot
I added the region as part of the environment variables in the tomcat startup and it resolved the issue
I am extremely confused by Spring's Cloud module. I genuinely do not understand how to do the basic setup for it.
When I start my Spring Cloud application with the usual spring-boot parent, then I get this message: Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.
Alright, so no spring-boot-starter-web dependency. But then I am looking at the official "Getting Started" guide of Spring Cloud: Spring Cloud getting started. I copy the mentioned dependencies 1:1 and end up with the same message in the server(?) start output as previously. Which makes sense, because the code on that site also sets the typical spring-boot-starter-parent, which also uses the spring-boot-starter-web dependency. That already contradicts with each other??
But then there is also a section called "Building a Simple Gateway Using Spring MVC or Webflux" in the official Spring Cloud documentation: Spring Cloud reference
I am really confused. When I try to start Spring Cloud in the same way that the getting-started documentation suggests, I get the mentioned "not-compatible" output message and also this exception:
Error creating bean with name 'routeDefinitionRouteLocator' defined in
class path resource
[org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]:
Unsatisfied dependency expressed through method
'routeDefinitionRouteLocator' parameter 4;
Trying to define a RouteLocator-bean myself so that the auto-configuration doesn't trigger does not seem to work. That's why I am thinking this whole Spring Cloud <> Spring MVC thing is causing the issue. But the existing documentation on Spring Cloud keeps contradicting each other whether or not you can use these two together or not or what the consequences are or anything.