eureka zuul cannot find my python app registered on eureka - netflix-eureka

I have a python web app, and registered with eureka using restfull api[https://github.com/Netflix/eureka/wiki/Eureka-REST-operations], and I found it status UP on the eureka web page, but my gateway server(also registered with eureka) can not find it, I call the url "gateway-server-host/myapp-url" and the following response is:
com.netflix.zuul.exception.ZuulException: Forwarding error at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:188)
at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:163)
at
org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:111)
...
Caused by: com.netflix.client.ClientException: Load balancer does not
have available server for client: test at
com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483)
at
com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184)
at
com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
any advise for this problem???

Have you looked over Spring Cloud's Sidecar ?
It basically a service over your non-jvm language service (in your case python) and with sidecar service (you have to deploy your python service and the sidecar service on the same host, if I am not mistaken) and you will include in your Zuul the endpoint to the sidecar service, which will try to handle things like eureka and such.
You spin up a new spring-boot app, with #EnableSidecar annotated, you configure the health-uri and port
example application.yml
server:
port: 5678
spring:
application:
name: sidecar
sidecar:
port: 8000
health-uri: http://localhost:8000/health.json
You can checkout Spring Cloud's documentation regarding Sidecar here for more details how to set it up

Since you are using Zuul you need to manually register routes. Its okay for them to just include the application name, from Eureka.
Example of Zuul route config:
zuul:
routes:
application1: /app1/**
application2: /app2/**
application3:
path: /app3/**
url: http://10.0.8.11:3000/
applicationN is the name registred in Eureka. The url will be resolved and load balanced automatically. For app3 the url is manually specified.

Adding Sidecar solves this problem to an extent where your Zuul /routes shows the registered Application Name.
You must have experienced , even if you do not have an actual app and just put any name with a payload following this document - [https://github.com/Netflix/eureka/wiki/Eureka-REST-operations] , that too gets registered in Eureka as an app.

Related

Kubernetes - route static IP to multiple services (Google Cloud Platform)

I have a small application comprising three services:
A single page application (SPA) served from nginx
A simple nodejs HTTP API used by the SPA
An MQtt broker exposing ports 1883 and 9001
Ideally I'd like the all to be served from the same subdomain and static IP address and have been trying to configure this in Kubernetes on the Google Cloud Platform.
I've created deployments for each of the services, with the SPA exposing port 80, the API 3000 and the MQTT broker 1883/9001. I've then followed the instructions here to set up a static IP and a Service to route to the SPA, then created similar services for the API and the MQTT app. (I've initally adapted these from deployments and services generated from a docker-compose file and Kompose).
The SPA and API seem to work fine but the MQTT service does not. When I run kubetl get events I see:
Error creating load balancer (will retry): failed to ensure load balancer for service default/mqtt-broker: failed to create forwarding rule for load balancer (a5529f2a9bdaf11e8b35d42010a84005(default/mqtt-broker)): googleapi: Error 400: Invalid value for field 'resource.IPAddress': '35.190.221.113'. Specified IP address is in-use and would result in a conflict., invalid
So I'm wondering if I should be creating a single service to route to the three deployments but can't find any documentation or examples that explain how to do this for a non http service.
I guess I could put the mqtt service on a separate IP address but this seems to be hacking around the problem rather than solving it.
Thanks in advance for any advice.
I eventually found an almost identical use case to my own on this github repository.
In essence, they are creating the MQTT broker on a separate static IP and using Kubernetes API calls to expose the details to the front end, which they explain in the following comment at the top of the web.yaml file:
This needs a bit of trickery
as it needs to expose the LB ip address for the MQTT server. That
requires kubernetes API calls to look it up, and the ability to
store it somewhere (we put it in a secret). To be secure this is
done with a dedicated service account and an init container.
https://github.com/IBM/ny-power

spring zuul + eureka route delegation

Im working with Spring Cloud Zuul + Eureka Server. i know that Zuul will create routes dynamically when there is a service registered on Eureka and it will be route using their Service ID. Is it possible to delegate routes to group services ?
for example i have 2 services that i want to group:
server.port=8081
spring.application.name=company-account-api
server.port=8082
spring.application.name=company-transaction-api
eureka config
spring.application.name=api-discovery
spring.cloud.config.uri=${CONFIG_SERVER_URL:http://localhost:8888}
on Zuul is it possible define a route where i can access the 2 services registered on eureka ?
server.port=9090
spring.application.name=api-gateway
eureka.instance.preferIpAddress=true
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.serviceurl.defaultzone=http://localhost:8761/eureka
zuul.routes.company-api=/company-**
so when i access http://localhost:9090/company-api/company-account-api & http://localhost:9090/company-api/company-transaction-api the service registered on eureka will be available
You can achieve this with the following config
zuul.ignored-services=*
zuul.routes.company-account-api.serviceId=company-account-api
zuul.routes.company-account-api.path=/company-api/company-account-api/**
zuul.routes.company-transaction-api.serviceId=company-transaction-api
zuul.routes.company-transaction-api.path=/company-api/company-transaction-api/**
Explanation:
zuul.ignored-services=* This will supress the default config
zuul.routes.company-account-api.serviceId=company-account-api
zuul.routes.company-account-api.path=/company-api/company-account-api/**
What is exposed to public is /company-api/company-account-api/** which will be internally mapped to company-account-api service.
If you are not using service discovery then you can do it using url instead of service name
zuul.routes.company-account-api.url=http://accountapihost:accountapiport
zuul.routes.company-account-api.path=/company-api/company-account-api/**

spring cloud netflix service to service through zuul

In a spring-cloud-netflix setup (everything uses feign,ribbon,eureka,zuul), is there any simple/elegant/out-of-the-box way (i.e. discovery based on serviceId vs URL) for CompositeAB to communicate to ServiceA and ServiceB through Zuul? In all of the examples I've seen, CompositeAB discovers and calls ServiceA directly vs. via the Zuul route for ServiceA.
Put another way, if ServiceA registers itself in Eureka as service-a, is the automatically created Zuul proxy for service-a exposed in Eureka in any discoverable way?
For real world context, this relates to network topology and firewalls (there's no direct route between CompositeAB and ServiceA - everything needs to go through the gateway). Using URLs in CompositeAB isn't awful, but seems to defeat the purpose of having the registry present (ideally, Zuul would register the proxy for service-a as something like "zuul-service-a" in the registry). That said, i do get how this particular use case doesn't really fit Zuul's purpose as an edge gateway.
Finally, i think i know how to get my desired effect through code - just wanted to check that i wasn't reinventing any wheels first.
Make sure that your Zuul proxy is registering with Eureka and fetching the registry. Any service that registers with eureka will get a route.
You don't have to allow every service that registers with eureka to be accessible via the proxy either.
A sample application.yml for your Zuul proxy that only allows service-a and service-b:
eureka:
client:
fetchRegistry: true
zuul:
add-proxy-headers: true
ignored-services: "*"
routes:
service-a:
serviceId: service-a
service-b:
serviceId: service-b

Ribbon- Calling a specific uri of an application from urls obtained from Eureka

Lets consider the following situation.This example will only have urls containing localhost. I have a zuul proxy setup and lets say its running on port 8080. So
Zuul proxy-
localhost:8080
I have an eureka server setup running on port 81.
Eureka server-
localhost:8081.
I have an application lets call it by name-example which is a REST web service. Its running on 3 different ports 82,83 and 84. All 3 instances are registered with eureka server. I have a filter setup in zuul for the uri /example.
So i expect consumers to call the zuul proxy at locahost:8080/example.
Now, in the application example for the request mapping /example, there is a controller setup.
So what i want to do is basically have the consumers call localhost:8080/example and route that request to localhost:8082/example, localhost:8083/example, localhost:8084/example . I know how to load balance using ribbon and eureka and have all the appropriate properties set to achieve that.
zuul.routes.example.serviceid=example
ribbon.eureka.enabled=true.
What i want to do is have ribbon look up the list of url(s) from eureka server and then call localhost:8082/example rather localhost:8082.
Is this possible?
Thank you in advance.
You need to specify the path & serviceId
zuul:
routes:
examplepath:
path: /example/**
serviceId: name-example
stripPrefix: false
The serviceId is the name registered with Eureka. Hope you are specifying Eureka server details in you Zuul gateway.

Can Zuul Edge Server be used without Eureka / Ribbon

We have an infrastructure with service discovery and load balancing (i.e. server side with STM and weblogic cluster). Now we are in the process of refactoring into micro-services. We would need an API gateway which does basic routing to other microservices. Netflix Zuul looks a good candidate however I could not get Zuul working without Eureka - but we do not need Eureka since we already have service discovery and load balancing in place.
Is it possible to use Zuul without Eureka and Ribbon?
If yes please provide some guild-lines since the there's no mention about in the wiki.
Thanks.
Yes, it is totally possible.You have to use #EnableZuulProxy on your config class and config it something like this :
zuul:
routes:
yourService:
path: /yourService/**
serviceId: yourService
ribbon:
eureka:
enabled: false
yourService:
ribbon:
listOfServers: localhost:8080
A sample usage can be like this:
shared.microservice.customer.service1.url=zttp://127.0.0.1:8080/shared/microservice/customer/
shared.microservice.customer.service2.url=zttp://127.0.0.1:8181/shared/microservice/customer/
ribbon.eureka.enabled = false
zuul.routes.customer-micro-service.path: /shared/microservice/customer/**
zuul.routes.customer-micro-service.serviceId: customers
customers.ribbon.listOfServers =
zttp://ip:port1/shared/microservice/customer/,zttp://ip2:port2/shared/microservice/customer/
Yes, Of course you can. Actually, by default, if you use #EnableZuulProxy with the Spring Boot Actuator, you enable two additional endpoints:
Routes
Filters
application.yaml
zuul:
routes:
users:
path: /myusers/**
url: https://example.com/users_service
These simple url-routes do not get executed as a HystrixCommand, nor do they load-balance multiple URLs with Ribbon.
Yo can get more information from here.