I have designed a micro service prototype using below technologies
Eureka Server
a service
Spring Cloud API Gateway
Above mentioned service are registered in the Eureka Server
API Gateway routing Configuration
server.port=8080
eureka.client.serviceUrl.defaultZone = http://localhost:8083/eureka
spring.application.name=ApiGateway
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=lb://MICROSERVICE1
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1/**
The service Configuration
server.port=8081
server.address=127.0.0.1
eureka.client.serviceUrl.defaultZone = http://localhost:8083/eureka
spring.application.name=MicroService1
error.whitelabel.enabled= false
Controller
#RestController
#RequestMapping("/service1")
public class HomeController {
#GetMapping("/message")
public String hello() {
return "response from micro service1";
}
}
When I send a request to the gateway it's showing the below error
2020-12-16 22:26:09.770 ERROR 16700 --- [ctor-http-nio-3] a.w.r.e.AbstractErrorWebExceptionHandler : [d3334561-1] 500 Server Error for HTTP GET "/service1/message"
java.net.UnknownHostException: failed to resolve 'LAPTOP-KU56B6A8' after 3 queries
at io.netty.resolver.dns.DnsResolveContext.finishResolve(DnsResolveContext.java:1013) ~[netty-resolver-dns-4.1.55.Final.jar:4.1.55.Final]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/service1/message" [ExceptionHandlingWebHandler]
How can we solve the above issue?
Add eureka.instance.hostname=localhost in both the microservices instances this will work and not give an error
i have modified the API Gate Way routing Configuration like below
spring.cloud.gateway.routes[0].id=service1
spring.cloud.gateway.routes[0].uri=http://localhost:8081/service1/
spring.cloud.gateway.routes[0].predicates[0]=Path=/service1/**
Now is working fine
Add this bean in your API gateway and you are good to go.
#Bean
public HttpClient httpClient() {
return HttpClient.create().resolver(DefaultAddressResolverGroup.INSTANCE);
}
Add below to both gateway and individual microservice fix the issue
eureka.instance.hostname=localhost
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8010/eureka/
Add in your application.properties:
spring.cloud.discovery.enabled=true
I have modified my .yaml file with this configuration.
Issue resolved for me.
**server:
port: 9999
spring:
application:
name: gateway-ws
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: userService
uri: http://user-service/
predicates:
- Path=/user/**
- id: contactService
uri: http://contact-service/
predicates:
- Path=/contact/**
eureka:
client:
service-url:
defaultZone: http://localhost:8085/eureka**
This is the only solution works among all of the answers above.
#Bean
public HttpClient httpClient() {
return HttpClient.create().resolver(DefaultAddressResolverGroup.INSTANCE);
}
This is the default behavior, so no effect.
spring.cloud.discovery.enabled=true
This has nothing to do with the discovery client.
It is related with the discovery server.
eureka.instance.hostname=localhost
So if you don't know, just don't mess it up with wrong directions.
hello jebji if you still have this problem
add
spring.cloud.discovery.enabled=true
in application.properties
Only Add the following property into your API gateway:
spring.cloud.discovery.enabled=true
Make sure you already added DevTool maven dependency into your API gateway project but if not then restart it.
add flowing property in application.property file of all eruka client microservice and api gateway , i face same issue and resolve doing same activity
spring.cloud.discovery.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id= true
spring.cloud.gateway.discovery.locator.enabled= true
eureka.instance.hostname=localhost
after adding all the above properties then also if you are facing issue then try the below one,
don't use lb://albums_service , but use lb://albums-service .Because URI don‘t support underline.
You can add the following in application.yml file
spring:
cloud:
gateway:
routes:
- id: test-service
uri: lb://MICROSERVICE1
predicates:
- Path=/microservice1/**
filters:
- RewritePath=/microservice1/(?<segment>.*), /$\{segment}
with this it should works.
Like let say if your microservice1 is url is
localhost:8081/service1/message
then you can define the base path of your microservice1 in api-gateway by setting up the path as i did in above configuration.
The error message is "failed to resolve 'LAPTOP-KU56B6A8'".
This is an DNS issue.
You can set eureka.instance.prefer-ip-address=true in the service.
So it will register with its ip at Eureka and the DNS issue can be avoided.
This is actually the same issue as this QUESTION.
With this ANSWER
I have a spring boot app and i am trying to use feign client to make a request to an endpoint but its not able to resolve feign client name from application yml.
My application yml has following code :
ribbon:
eureka:
enabled: false
beacon:
ribbon:
isSecure: true
listOfServers: https://beacon.org
My interface look like this :
#FeignClient("beacon")
public interface BeaconClient {
#GetMapping("/api/organizations")
List<Org> getOrgs();
}
I am getting an error 500 internal server error because i see that it making a request to http://beacon/api/organizations endpoint instead of https://beacon.org/api/organizations
Your code is correct. The default feign Logger is misleading. http://beacon/.. that you see in the log isn't indicative of actual url that is being called. The actual request is resolved with https://beacon.org/...
We're moving away from the spring-cloud Netflix OSS ecosystem one step at a time. Currently we're implementing spring-cloud-loadbalancer and removing Ribbon.
However we used to have a lot of static services in our integration tests, now with the move from ribbon towards spring-cloud-loadbalancer those properties are not being picked up any longer.
i.e.:
foo-service.ribbon.NIWSServerListClassName=com.netflix.loadbalancer.ConfigurationBasedServerList
foo-service.ribbon.listOfServers=localhost:9876
We've migrated towards using spring-cloud-loadbalancer in the following way
First we annotated our Webclient.Builder with #LoadBalanced like this
#Bean
#LoadBalanced
fun webClientBuilder() = WebClient.builder()
And then we've added the #LoadBalancerClient annotation on the client classes like this
#LoadBalancerClient(name = "foo-service", configuration = [FooServiceConfiguration::class])
class FooServiceClient(private val basicAuthWebClient: WebClient)
This results in our tests failing with an UnknownHostException for foo-service.
Now My question is how do we configure this static server list in the new spring-cloud-loadbalancer?
Based on #spencergibb's comment, I guess something like this should work:
spring:
cloud:
discovery:
client:
simple:
instances:
foo-service:
- instanceId: foo1
serviceId: foo-service
host: localhost
port: 9876```
We were planning to use spring cloud Netflix oss components. So I was doing a small sample project.
I developed 2 spring microservices and those services runs well on
http://localhost:9000/microsvc-one http://localhost:9001/microsvc-two
And also wrote a sample spring cloud etflix eureka maven project which runs well on
http://localhost:8761
I used annotations #EurekaDiscoveryClient and #SpringBootApplication on both the spring boot microservices main class
I used annotation #EnableEurekaServer and #SpringBootApplication
Now I am facing a problem in registering those services in eureka server. I referred some samples. I am not understanding those.
I did some changes in application.yml files of microsvc-one and microsvc-two and also application.yml file of eureka server.
But still it shows empty.
What all changes are required or missing or correct configuration to be done so that my services are being registered on eureka.
I also have other question like do i need to create a separate project which has #EnableConfigServer and #SpringBootApplication Annotations other than the above 2 microservices and eureka server project module to register the services on eureka.
I see those in most of the examples.
If yes..how do we link between all these?
If you are using springBoot application you will need the annotaion #SpringBootApplication thats why that annotation is there on the project you are seeing. #EnableConfigServer is when you are using the spring-cloud config server it is used to externalize the configuration properties but since you have the application.yml inside the project so you donot need that either.
I am thinking you have a spring boot application for both Microservices and the Eureka server. You need to annotate the eureka main class with
#SpringBootApplication
#EnableEurekaServer
#EnableDiscoveryClient
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Additionally you need annotate you microservice's main class with..
#SpringBootApplication
#EnableDiscoveryClient
public class MicroApplication {
public static void main(String[] args) {
SpringApplication.run(MicroApplication.class, args);
}
}
Since you donot have you application.yml file in the question here is what you need.
You need the below configuration in application.yml of the microservices.
eureka:
client:
serviceUrl:
defaultZone: ${eurekaurl:http://localhost:8761/eureka/}
In the Eureka Server application.yml file I have this in mine. you might need to tweak it based on what you want.
info:
component: Registry Server
server:
port: ${port:8761}
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
enable-self-preservation: false
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: localhost
lease-expiration-duration-in-seconds: 15
lease-renewal-interval-in-seconds: 5
Suppose you have a microservice named "LoginServer" now, let's see how to register this service with discovery server (Eureka Server) at startup.
Here Spring Boot startup class of LoginServer.java:
#EnableAutoConfiguration
#EnableDiscoveryClient
public class LoginServer {
public static void main(String[] args) {
// Will configure using login-server.yml
System.setProperty("spring.config.name", "login-server");
SpringApplication.run(LoginServer.class, args);
}
}
The #EnableDiscoveryClient - enables service registration and discovery. In this case, this process registers itself with the discovery-server service using its application name, that is configured in YML configuration file.
let's see the complete setup:
First create a login-server.yml (any name but extension should be .yml) file into src/main/resources package folder. And write those configurations and save.
# Spring properties
spring:
application:
name: login-server # This name used as ID so ("spring.config.name",
#"login-server"); must be same.
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
# HTTP Server
server:
port: 2222 # HTTP (Tomcat) port
Run the LoginServer and let it finish initializing. Open the dashboard by putting this URL http://localhost:1111 in your favorite browser and refresh. After few seconds later you should see the LOGIN-SERVER. Generally registration takes up to 30 seconds (by default) so wait or restart.
And this is the microservice complete registration process.
I am running a simple Junit Testing a Controller in Spring Boot. The test code looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {FrontControllerApplication.class})
#WebAppConfiguration
#ComponentScan
#IntegrationTest({"server.port:0", "eureka.client.registerWithEureka:false", "eureka.client.fetchRegistry:false"})
#ActiveProfiles("integrationTest")
public class MyControllerIT {
In the application-integrationTest.properties I have the following Eureka Settings:
####### Eureka
eureka.serviceUrl.default=http://localhost:8767/eureka/
eureka.printDeltaFullDiff=false
eureka.client.refresh.interval=1
eureka.appinfo.replicate.interval=1
eureka.serviceUrlPollIntervalMs=1000
eureka.name=${spring.application.name}
####### Netflix Eureka #######
eureka.client.serviceUrl.defaultZone=http://localhost:8767/eureka/
eureka.client.instanceInfoReplicationIntervalSeconds=1
eureka.client.initialInstanceInfoReplicationIntervalSeconds=0
eureka.instance.virtualHostName=${spring.application.name}
eureka.instance.preferIpAddress=true
eureka.instance.initialStatus=DOWN
eureka.instance.leaseRenewalIntervalInSeconds=3
eureka.instance.leaseExpirationDurationInSeconds=10
eureka.instance.metadataMap.instanceId=${spring.application.name}:${spring.application.instance_id:${random.value}}
eureka.eurekaserver.connectionIdleTimeoutInSeconds=5
eureka.responseCacheAutoExpirationInSeconds=5
when a junit test started I see the following:
2015-09-16 16:46:03,905 ERROR localhost-startStop-1 com.netflix.discovery.DiscoveryClient Can't get a response from http://localhost:8767/eureka/apps/
Can't contact any eureka nodes - possibly a security group issue?
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:184) ~[jersey-apache-client4-1.11.jar:1.11]
The test passes, that is not the problem, but I see a lot of exception stack traces that has to do with Eureka. The questions is if there is a way to mock eureka or another way to skip brining it up when doing tests?
The benefit would be easier to see relevant stack traces if test would fail and tst would run much faster
Another solution is to disable the Eureka Client in your application.properties or application.yml file under test/resources
applications.properties:
eureka.client.enabled=false
application.yml:
eureka:
client:
enabled: false
This has the benefit of not needing to remeber to include the system property for every JUnit test that requires disabling the Eureka Client.
You can set a system property for eureka.client.enabled=false for tests.
If you're running the tests using gradle you can do this:
tasks.withType(Test) {
systemProperty 'eureka.client.enabled', 'false'
}
If you're running tests in an IDE then you'll have to set the system property there as well.