Spring cloud gateway hystrix not working - spring-cloud

I am having issues getting hystrix to work with my route. things like re-write paths and load balancing are working but for some reason hystrix never trips. I am setting my timeouts very low and have a delay in a downstream service. Is there anything special you need to do to get hystrix working?
I am using spring-cloud-gateway with eureka and spring-cloud-config. Also, is there a way to debug when a route is not working? Like a log setting to see what is happening?
Here is my route:
spring:
cloud:
gateway:
routes:
# =====================================
- id: main-service
uri: lbl://main-service
predicates:
- Path=/main-service**
filters:
- Hystrix=mainservice
Here is my pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>2.0.0.M2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Here is my Application class:
#EnableDiscoveryClient
#EnableHystrix
#SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
The only other class in the jar is this:
#Configuration
public class GatewayConfiguration {
#Bean
public DiscoveryClientRouteDefinitionLocator
discoveryClientRouteLocator(DiscoveryClient discoveryClient) {
return new DiscoveryClientRouteDefinitionLocator(discoveryClient);
}
}

I figured out the issue. It seems that if you add eureka discovery then it automatically add routes that match all the spring.application.names returned by your eureka server and these have the same order as the ones I defined using application name as the predicate. I was able to fix this by setting the order for my route to -1.
Not sure if there is a better way to do this but at least I know hystrix is working.
Thanks

Maybe you should use this dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

Related

Combine REST connection with embedded Mongo integration in test

I'm using SpringBoot 2.6.2 together with flapdoodle 3.2.3 for test.
If I just want to test DB stuff, then #DataMongoTest works finde, because for tests I want to test it with an in-memory database. If I want to test RestConnections I'm using #SpringBootTest and also everything is fine.
Now I just want to use both, I need to test to send something to an rest connection and at the method on the other side it needs to check the database if the data is already there or not.
My problem now is, that I cannot use both #DataMongoTest and #SpringBootTest, they are not combinable, but I still need the autowired of all my Services, Components, etc. why I need SpringBootTest and also I need my embedded database, because I don't want to prerequisite an installed mongoDB with service.
I already tried #AutoConfigureDataMongo together with #SpringBootTest, like it is mentioned here: enter link description here but it will not work.
Any suggestions how I can combine both?
Thanks and Best,
Lobo
PS: Here is my pom provide which libraries I'm using in which version
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.github.openjson</groupId>
<artifactId>openjson</artifactId>
<version>1.0.11</version>
</dependency>
<dependency>
<groupId>com.github.erosb</groupId>
<artifactId>everit-json-schema</artifactId>
<version>1.14.0</version>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>3.2.3</version><!--$NO-MVN-MAN-VER$-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.process</artifactId>
<version>3.1.4</version>
<scope>test</scope>
</dependency>
</dependencies>
OK I created just my own database in a #beforeAll like it is described here:
https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo
MongodStarter starter = MongodStarter.getDefaultInstance();
int port = Network.getFreeServerPort();
MongodConfig mongodConfig = MongodConfig.builder()
.version(Version.Main.PRODUCTION)
.net(new Net(port, Network.localhostIsIPv6()))
.build();
MongodExecutable mongodExecutable = null;
try {
mongodExecutable = starter.prepare(mongodConfig);
MongodProcess mongod = mongodExecutable.start();
try (MongoClient mongo = new MongoClient("localhost", port)) {
DB db = mongo.getDB("test");
DBCollection col = db.createCollection("testCol", new BasicDBObject());
col.save(new BasicDBObject("testDoc", new Date()));
}
} finally {
if (mongodExecutable != null)
mongodExecutable.stop();
}
with this I can use #SpringBootTest and still have the connection to the embedded database.

Springboot app works on embbeded tomcat but in external tomcat get 404

I have a project on spring and when i run it on the embbeded tomcat it works so good
But the idea is put the project in a external server but when i create the war
and i deploy it in tomcat 8 i get 404 even if it is running
I have seen that the problem could be in the maven but i tried a lot of things that i saw
in other posts and i cant fix it
i dont knot what else i can do.
here is some of my code
#SpringBootApplication
public class RD extends SpringBootServletInitializer implements CommandLineRunner {
#Resource
// FileStorageService storageService;
FileStorageService storageService;
public static void main(String[] args) {
SpringApplication.run(RD.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(RD.class);
}
#Override
public void run(String... arg) throws Exception {
storageService.deleteAll();
storageService.init();
}
}
my main class already has the serverlet extends i think that its not the problem
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.r</groupId>
<artifactId>RD</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>RDrone</name>
<description>Portal Web</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery-validation</artifactId>
<version>1.19.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>font-awesome</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.5.0</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>popper.js</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.40</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>ROOT</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
And here is my pom where i think that could be the problem
I tried to make some exlusion on the springgboot starter web dependecy but it doesnt work
Thats what i see that fix it in other project but not in mine
I dont know if could be something on my tomcat but i have tomcat 8 with java 1.8
I deployee spring boot restful app on wildfly what I do is create the class ServletInitializer .
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(FikerApplication.class);
}
}
I hope this will give you the solution, if not comment me I will try to figure out .

Hazelcast member discovery with PCF Registry Service and hazelcast-eureka-plugin

Running several instances of application with embedded hazelcast on PCF. My goal is to chain hazelcast members into cluster. For purpose of member discovery I am using hazelcast-eureka plugin. I am able to achieve member discovery using simple Eureka Server app, passing eureka URL to hazelcast-eureka plugin, using this example.
Now I want to use PCF Registry Service instead of Eureka Server app. For that purpose I am using EurekaOneDiscoveryStrategyFactory with EurekaClient autowired which is configured with PCF Registry Service properies.
Issue is - my hazelcast members do net get registered by PCF Registry Service, hence can not discover each other. Though I can see my application instances get registered by PCF Registry Service.
Instance config:
#Autowired
private EurekaClient eurekaClient;
#Bean
public HazelcastInstance hazelcastInstance() {
return Hazelcast.newHazelcastInstance(cloudConfig());
}
#Bean
public Config cloudConfig(){
Config config = new Config();
config.getGroupConfig().setName( "hazelcast-test" );
config.setProperty("hazelcast.discovery.enabled", Boolean.TRUE.toString());
JoinConfig join = config.getNetworkConfig().getJoin();
join.getMulticastConfig().setEnabled(false);
EurekaOneDiscoveryStrategyFactory.setEurekaClient(eurekaClient);
final EurekaOneDiscoveryStrategyFactory eurekaOneDiscoveryStrategyFactory = new EurekaOneDiscoveryStrategyFactory();
DiscoveryStrategyConfig discoveryStrategyConfig =new DiscoveryStrategyConfig(eurekaOneDiscoveryStrategyFactory);
discoveryStrategyConfig.addProperty("self-registration", true);
discoveryStrategyConfig.addProperty("namespace", "hazelcast-test");
discoveryStrategyConfig.addProperty("use-classpath-eureka-client-props", false);
discoveryStrategyConfig.addProperty("shouldUseDns", false);
discoveryStrategyConfig.addProperty("datacenter", "cloud");
discoveryStrategyConfig.addProperty("name", "hazelcast-test");
discoveryStrategyConfig.addProperty("use-metadata-for-host-and-port", false);
discoveryStrategyConfig.addProperty("skip-eureka-registration-verification", false);
DiscoveryConfig discoveryConfig = new DiscoveryConfig();
discoveryConfig.addDiscoveryStrategyConfig( discoveryStrategyConfig );
join.setDiscoveryConfig( discoveryConfig );
return config;
}
pom.xml:
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.19.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eureka-client-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>eureka-client-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud-services.version>1.6.6.RELEASE</spring-cloud-services.version>
<spring-cloud.version>Edgware.SR5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.pivotal.spring.cloud</groupId>
<artifactId>spring-cloud-services-starter-service-registry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-eureka-one</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.pivotal.spring.cloud</groupId>
<artifactId>spring-cloud-services-dependencies</artifactId>
<version>${spring-cloud-services.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>

#RefreshScope and /refresh not working

I have tried to implement spring external configurations using Config Server. It is working fine for the very first time when the application is started but any changes to the properties file are not being reflected. I tried to use /refresh endpoint to refresh my properties on the fly but it doesn't seem to be working. Any help on this would be greatly helpful.
I tried POSTing to localhost:8080/refresh but getting a 404 Error response.
Below is the code of my application class
#SpringBootApplication
public class Config1Application {
public static void main(String[] args) {
SpringApplication.run(Config1Application.class, args);
}
}
#RestController
#RefreshScope
class MessageRestController {
#Value("${message:Hello default}")
private String message;
#RequestMapping("/message")
String getMessage() {
return this.message;
}
}
and POM file is
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M8</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
and bootstrap.properties
spring.application.name=xxx
spring.cloud.config.uri=https://xxxxxx.com
management.security.enabled=false
endpoints.actuator.enabled=true
The endpoint is now /actuator/refresh for Spring 2 and greater
From the comments:
You do need to have the management.endpoints.web.exposure.include=refresh set in the bootstrap.properties/bootstrap.yml
Note: If you're new to Spring-Cloud and not quite sure of what all keywords can go in web.exposure you can set it to * (management.endpoints.web.exposure.include=*) to have all exposed and you can get to know the endpoints and their restrictions later.
It worked for me after adding the property "management.endpoints.web.exposure.include=*" in bootstrap.properties and changing the url to /actuator/refresh for spring version above 2.0.0
For spring version 1.0.5 url is /refresh
For YAML files, the property's value needs to be wrapped inside double quotes :
# Spring Boot Actuator
management:
endpoints:
web:
exposure:
include: "*"
Note : Ensure you use the right endpoints keyword (with 's') for this property as long as it exists for another property without 's' : "management.endpoint.health.... " .
Note: - It's a POST request (not GET)
I've posted the solution here
[https://stackoverflow.com/a/74465108/2171938][1]
If you have issues with accepting formurlencoded in SPRING 2.0>, use :
curl -H "Content-Type: application/json" -d {} http://localhost:port/actuator/refresh
instead of:
curl -d {} http://localhost:port/refresh
which was accepted in SPRING 1.*

SpringCloud Eureka - simple client doesnt register

I have an Eureka Server where I want to register a very basic SpringBoot service. Unfortunately the service doesnt register although I tried to follow all the articles I could find.
Moreover when I check description of the DiscoveryClient (that gets autowired), I see "Spring Cloud No-op DiscoveryClient" which suggests (as per NoopDiscoveryClient.java source) that Eureka client library isnt found.
In pom I have
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
which if I am right should make sure that proper netflix libraries are in place. #EnableEurekaClient annotation is present. No errors on the console when starting the client, nothing interesting in the Eureka Server console logs.
This is the configuration from the application.yml:
eureka:
client:
serviceUrl:
defaultZone: ${vcap.services.eureka-service.credentials.uri:http://127.0.0.1:8761}/eureka/
Any suggestions are really welcomed as I am running out of ideas :)
http://start.spring.io is your friend. You need to use the starters.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.M5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
and
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Except #spencergibb's answer, in my case it also require <spring-cloud.version> inside the <properties>:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M3</spring-cloud.version>
</properties>