Eureka Sever registers all my services, however when trying to access them through their application.name I cannot, I have tried RestTemplate and OpenFeign but it has not been possible in any way.
When FEATURES-SERVICE requests an image from IMAGES-SERVICE through: http://localhost:9005 work, but when FEATURES-SERVICE requests an image from IMAGES-SERVICE through: http://images-service fail.
This is my config for eureka-server:
server:
port: 8761
eureka:
client:
fetch-registry: false
register-with-eureka: false
and config for features-service and images-service
// IMAGES-SERVICE
server:
port:9005
spring:
application:
name: images-service
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
default-zone: http://localhost:8761/eureka
instance:
hostname: localhost
// FEATURES-SERVICE
server:
port:9004
spring:
application:
name: features-service
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
default-zone: http://localhost:8761/eureka
instance:
hostname: localhost
both services has the annotation #EnableEurekaClient in the Application file.
I was facing the same issue while using rest template and calling the other service, I got it running using the annotation #LoadBalanced on RestTemplate bean in my application class.
I was doing the same as what is suggested here in the answer (adding #LoadBalanced) for the restTemplate injector but it wasn't working for me.
I had written the gateway controller in the Eureka Server itself to receive request from front end and redirect it to other micro-services.
When I wrote whole new application to work as gateway service, everything is working fine now.
Check if you have Ribbon added as a dependency in your pom.xml file OR you are getting exception from Ribbon. If this is the case remove the Ribbon from your project.
Related
Good day,
At this moment I am working on a very simple gateway that (for now) only needs to redirect incoming HTTP POST and GET requests.
THE SETUP:
The Eureka Server: the location where my Spring Boot microservices are registered;
The Spring Gateway: maps all incoming HTTP POST and GET requests and routes them to the proper microservice;
The Spring Boot microservices: doing just some thingies as requested :)
Note: I'm kinda new to this gateway stuff, just you know :).
The microservice is registered fine with the Eureka server. Its webbased GUI shows me that the instance "MY-MICRO-SERVICE" is registered with the Eureka server. Other (Spring Boot) services can use that name ("MY-MICRO-SERVICE") without issues, so for them it works fine. Just this gateway can't handle the instance name; it seems it only accepts IP addresses (which I just want to prevent, as the microservice can change from servers and therefor their IP address). And the Eureka server is not configured to only allow/use IP addresses.
THE ISSUE:
All runs smooth when the Gateway has a route that holds an IP address of the microservice. But what I want is to let the Gateway resolve the service ID from the Eureka server. And if I do that, it throws me a java.net.UnknownHostException: MY-MICRO-SERVICE: Temporary failure in name resoultion.
THE QUESTION:
Now why can't I use the name of the Spring application "MY-MICRO-SERVICE" (being the registered Spring Boot microservice) in the Spring Gateway (while that construction works fine when used in other microservices)? Can't a Yaml config file handle such instance names, just only IP addresses?
THE DETAILS
The gateway is mostly configured via a yaml config file. There is only one simple Java class that kicks off the gateway application. The routing is all set in the yaml config file.
The Spring Gateway application class
#SpringBootApplication
#EnableEurekaClient
public class MyGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(MyGatewayApplication.class, args);
}
}
The Gateway Yaml configuration file (application.yml)
spring:
application:
name: my-gateway
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
- POST
routes:
- id: my_route
uri: http://MY-MICRO-SERVICE
predicates:
- Path=/test/**
server:
port: 8999
info:
app:
properties: dev
The Error
java.net.UnknownHostException: MY-MICRO-SERVICE: Temporary failure in name resolution
at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) ~[na:na]
at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:929) ~[na:na]
at java.base/java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1515) ~[na:na]
at java.base/java.net.InetAddress$NameServiceAddresses.get(InetAddress.java:848) ~[na:na]
at java.base/java.net.InetAddress.getAllByName0(InetAddress.java:1505) ~[na:na]
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1364) ~[na:na]
at java.base/java.net.InetAddress.getAllByName(InetAddress.java:1298) ~[na:na]
at java.base/java.net.InetAddress.getByName(InetAddress.java:1248) ~[na:na]
at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:146) ~[netty-common-4.1.36.Final.jar:4.1.36.Final]
...
Issue has been fixed.
I changed the "http" to "lb" protocol and that fixed my issue. To my understanding, "lb" stands for LoadBalancing. I have no loadbalancer active on my local machine, but anyway: this works.
- POST
routes:
- id: my_route
uri: lb://MY-MICRO-SERVICE
predicates:
- Path=/test/**
i have developed the micro service application, in that application there is a service call user service which is running on port 8281. This service handle the authentications. when i test the service in local environment this is worked fine. But if i call this service using zuul api gateway this is not working. following property in the application.yml file is use to get the redirect url in the local environment. This is worked fine.
security:
oauth2:
client:
registration:
google:
redirectUri: "http://localhost:8281/oauth2/callback/google"
But if i change this property as follow for connect with zuul api gateway.
security:
oauth2:
client:
registration:
google:
redirectUri: "http://localhost:8080/api/user/oauth2/callback/google"
This is not working and is throw this error message [authorization_request_not_found]. localhost:8080 is the zuul api gateway. zuul has configure to forward request to user service like this.
zuul:
prefix: /api
routes:
auth-service:
path: /user/**
serviceId: USER-SERVICE
stripPrefix: true
sensitiveHeaders: Cookie,Set-Cookie
so why this error is thrown ?
While I am trying to reach the service meeting via Zuul gateway, Zuul is unable to forward the request to the respective service. The following errors are what I am facing:
nettflix.zuul.exception.ZuulException: Forwarding error
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: meeting
Let me share the application.yml for the service, eureka and zuul gateway.
EurekaClient:
Application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
lease-renewal-interval-in-seconds: 300
client:
register-with-eureka: false
fetch-registry: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/
ZuulGateWay:
application.yml
server:
port: 8085
spring:
application:
name: gatekeeper
zuul:
routes:
meeting: /meeting/**
serviceId: meeting
ribbon:
eureka:
enabled: false
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
ZuulGateWay: SpringBootApplication
package com.sagarp.gatekeeper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
#SpringBootApplication
#EnableEurekaClient
#EnableZuulProxy
public class MeetingApplication {
public static void main(String[] args) {
SpringApplication.run(MeetingApplication.class, args);
}
}
My Service class (meeting): Application.yml
server:
port: 0
spring:
application:
name: meeting
datasource:
url: jdbc:mysql://localhost:3306/sagarp?useSSL=false
username: myUserName
password: myPassWord
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
eureka:
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
lease-renewal-interval-in-seconds: 5
My Service class (meeting): SpringBootApplication
package com.sagarp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
#SpringBootApplication
#EnableEurekaClient
public class MeetingApplication {
public static void main(String[] args) {
SpringApplication.run(MeetingApplication.class, args);
}
}
As you can see, the configuration ensures that all my services are discovered by eureka client.
In the eureka console, I have verified the same, the zuul gateway and my service(meeting) both are visible.
For better view, you can visit my git repo. https://github.com/sagar-patro/demo-microservices
Any help would be very much appreciable
Short answer
ribbon:
eureka:
enabled: false
Spring Cloud Netflix Zuul uses Netflix’s Ribbon to perform client-side load balancing, and by default, Ribbon would use Netflix Eureka for service discovery. You are skipping service discovery, so you've set ribbon.eureka.enabled to false. Since Ribbon now can’t use Eureka to look up services, you must specify an url for the meeting service:
meeting:
ribbon:
listOfServers: localhost:8080
Expanded answer
I will make it more clear for you.
The dependency org.springframework.cloud:spring-cloud-starter-netflix-zuul, which you are currently using in the gatekeeper project, has several compile dependencies:
com.netflix.zuul:zuul-core
org.springframework.boot:spring-boot-starter-web
org.springframework.boot:spring-boot-starter-actuator
org.springframework.cloud:spring-cloud-netflix-zuul
org.springframework.cloud:spring-cloud-starter
org.springframework.cloud:pring-cloud-starter-netflix-hystrix
org.springframework.cloud:spring-cloud-starter-netflix-ribbon
org.springframework.cloud:spring-cloud-starter-netflix-archaius
As you see, it constitutes many components gathered around the com.netflix.zuul:zuul-core module (including Eureka for instance discovery and Ribbon for routing):
When you are launching the gatekeeper application, the default ZuulProxyAutoConfiguration configuration is being applied. It imports Ribbon configuration classes:
#Configuration
#Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,
HttpClientConfiguration.class })
#ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration { ... }
HttpClientRibbonConfiguration, in turn, initialises RibbonLoadBalancingHttpClient which is responsible for the error messages you saw.
That RibbonLoadBalancingHttpClient by default utilises ZoneAwareLoadBalancer which comes from a com.netflix.ribbon:ribbon-loadbalancer package:
By default Zuul load balances using the ZoneAwareLoadBalancer from Ribbon. The algorithm is a round robin of the instances available in discovery, with availability zone success tracking for resiliency. The load balancer will keep stats for each zone and will drop a zone if the failure rates are above a configurable threshold.
If you want to use your own custom load balancer you can set the NFLoadBalancerClassName property for that Ribbon client namespace or override the getLoadBalancerClass() method in the DefaultClientChannelManager. Note that your class should extend DynamicServerListLoadBalancer.
It explains that Zuul delegates routing and load balancing work to Ribbon components and proves that you are actually using Ribbon in the gatekeeper project.
Unless you choose a different load balancer, you should go for my original answer.
I hope it will help.
Basic question so just want to ensure I understand it all correctly.
I have created a discovery server:
#SpringBootApplication
#EnableEurekaServer
public class DisocveryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(DisocveryServiceApplication.class, args);
}
and registered microservices with it successfully; If I hit localhost:8761 I can see my discovery service has found the microservices. The microservices run fine if i hit them on their designated port. For example, I have one called creds and if i hit localhost:9000 it returns. However, My understanding is I should now be able to hit localhost:8761/creds and it will show the same output but this isnt working.
Am I misunderstanding? Any suggestions on what I should try?
creds bootstrap.yml:
spring:
application:
name: creds
creds application.yml
server:
port: 9000
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
discover application.yml
server:
port: ${PORT:8761}
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
waitTimeInMsWhenSyncEmpty: 0
Another #EnableEurekaClient annotated Spring boot webservice can access your creds webservice by using an injected RestTemplate with http://creds/..., where creds is the spring.application.name registered with Eureka.
If you want to access the creds webservice from the outside of your web application, then what you want is a proxy like Zuul http://github.com/Netflix/zuul.
Just registering micro service to Eureka server wont make sure that you can access the microservice under a gateway. Eureka Server is not a gateway server , its just a service registry. You can think Eureka as just one more service that holds information about all the other services in the cluster. It doesnt do anything extra other than getting information to the Clients registered.
You may need a Gateway service for routing your request under the Eureka Server. Zuul Proxy routes a request coming to it to the under lying microservices using its service id or the URL configured.
Add this dependency in your classpath.
dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
<version>1.0.4.RELEASE</version>
</dependency>
Add this config in your properties filezuul:
routes:
serv1:
path: /serv1/**
serviceId: http://localhost:8080/serv1
serv2:
path: /serv2/**
serviceId: serv2
This will create a dynamic router that routes your request to appropriate service instances. This also provides a server end load balancer for your services
I have a problem with spring cloud: Turbine Amqp doesn't work. I exploit a local rabbit broker out of the box.
one of my services:
#EnableFeignClients(basePackages = "com.sample")
#EnableEurekaClient
#EnableAutoConfiguration
#SpringBootApplication
dependencies:
spring-cloud-config-client
spring-cloud-starter-eureka
spring-cloud-starter-feign
spring-boot-starter-actuator
spring-cloud-starter-hystrix
spring-cloud-netflix-hystrix-amqp
spring-cloud-starter-bus-amqp
bootstrap.yml:
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
my turbine service:
#EnableHystrixDashboard
#EnableTurbineAmqp
#EnableEurekaClient
#EnableAutoConfiguration
#SpringBootApplication
spring-cloud-config-client
spring-cloud-starter-eureka
spring-cloud-starter-bus-amqp
spring-cloud-starter-turbine-amqp
spring-cloud-starter-hystrix-dashboard
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
turbine:
amqp:
port: 8989
management:
port: 8090
when i try to execute http://127.0.0.1:8989/turbine.stream, i've got:
data: {"type":"Ping"} in cycle
rabbitmqctl list_queues - shows a new queue ...f1d5cfa119f5 0 at the same time when my "client" service is executed. when i turn it off the queue is removed.
turbine server writes:
SSE Request Received
Unsubscribing RxNetty server connection
What am i doing wrong? thanks.