When a client application is registered into Spring Eureka server the client id appears at dashboard, but the link url only contains the hostname and port without the context-path of client.
If I create the Spring Boot client application without setting a context-path, I mean default root context, Eureka server can access all actuators available in there.
Is there any way to inform Eureka server about it? I tried to set health and info properties, but it did not work.
If your Eureka client is setup via Spring's #EnableEurekaClient, then the client will default the health check and status check to /health and /info respectively. (These paths may be the default values beyond the Spring #EnableEurekaClient setup, but I am unfamiliar with those at this point in time).
You can override these defaults by setting the following properties:
eureka.instance.statusPageUrlPath
eureka.instance.healthCheckUrlPath
The Spring Cloud Documentation contains this information, plus much more.
application.yml
server:
servlet:
context-path: /your-path
Related
I have a Spring Cloud Config server for configuration, a Eureka server for service discovery, and two app servers (App A and App B).
I'm trying to share a logging configuration (log4j2) between App A and App B by utilizing Spring Cloud Config for serving the configuration file. I can make the config file available from the server (http://localhost:1234/log4j2/default/config/log4j2.properties).
If I hardcode that value in my application configs (also served by my config server) then my applications can read the log4j config and everything works. However, I don't want to put the absolute URL of the config server in my application configuration file, as the config server information should be provided by the Eureka discovery server.
Sort of a chicken/egg problem. Does anybody have a method for resolving this?
We have following spring setup:
Our application is running on port 80, but our managment.server.port is set to 8081. And we use multiple checks of the management endpoints from this secured port already.
server.port=80
management.server.port=8081
management.endpoints.web.exposure.include=*
With this settings we can hide any sensitive information from the public interface on port 80.
But now our requirements changed: We need to display the version of our application on the public interface. This information is part of the info-endpoint of our management-server on /actuator/info
Is it possible to move only the info endpoint to port 80, and let all other management.server endpoints still on 8081?
Or is there any other suitable solution for our requirement to only open the info endpoint for external calls.
We prefer to not change any firewall setting: so one port is public, and the other is internal only
No you can't move only one endpoint to different port.
This about the actuator as an application that runs on one specific port (8081) in this case and exposes a bunch of services, so its all-or-nothing from this standpoint.
So you'll have to create a special rest controller that would read the file (or keep the memory) the data just like the info endpoint does.
Its a pretty staightforward code actually, it reads a file available in the spring boot artifact anyway and exposes its content.
You can checkout the source code of the info endpoint of the actuator here
I have a Spring boot app that runs https://localhost:8443. I am trying to get Spring actuator to work on that same port. Right now, I have it working on https://localhost:420/health but the issue is that it works on a different port and not on port 8443. This is my config in application.properties:
server.port=69
server.ssl.enabled=true
server.ssl.key-store=classpath:keystores/keys.jks
server.ssl.key-password=string
management.port=420
management.ssl.enabled=true
management.ssl.key-store=classpath:keystores/keys.jks
management.ssl.key-password=string
When I try to change both both server.port and management.port to 8443, I get the following error during compilation: java.lang.IllegalStateException: Management-specific SSL cannot be configured as the management server is not listening on a separate port and LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#194bcebf: startup date [Thu Jun 15 11:48:57 BST 2017]; root of context hierarchy
If it is of any use, the Spring boot app consists of spring boot, jetty and apache camel.
If you want actuator to use same port as server port, you can remove management port property. we have actuator in our project but we dont have any specific management port, we are able to access actuator end points on server port itself.
Context
I'm developing a proof of concept with Spring Zuul and Eureka. I want Zuul to work as an API Gateway and I want it to discover my microservices registered in Eureka. I want my microservices to be versioned. Zuul, Eureka and each microservice run on their own (I have a separate project for all of them).
I'm using Spring Boot 1.5.3 and Spring Cloud Dalston. But I can upgrade, if necessary.
Now, let's say that I have one microservice configured in the following way in the application.yml:
spring:
application:
name: microservice-v1
server:
port: 11001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:11000/eureka/
This microservice has a GET /microservice REST endpoint configured which I can access from the address http://localhost:11001/microservice. It runs well and it registers itself with Eureka.
This ZuulReverseProxy.java is the main class of my Zuul project:
#SpringBootApplication
#EnableDiscoveryClient
#EnableZuulProxy
public class ZuulReverseProxy {
public static void main(String[] args) {
SpringApplication.run(ZuulReverseProxy.class, args);
}
}
Based on the Spring Cloud Docs, I have this configuration class:
#Configuration
public class ZuulConfiguration {
#Bean
public PatternServiceRouteMapper serviceRouteMapper() {
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
}
And this is the application.yml of my Zuul project:
spring:
application:
name: zuul
server:
port: 8888
zuul:
prefix: /api
strip-prefix: true
eureka:
client:
serviceUrl:
defaultZone: http://localhost:11000/eureka/
Zuul looks into Eureka, gets the list of registered microservices and creates a mapping for each one according to the PatternServiceRouteMapper above. I'm not ignoring any services for now.
All of the above, allows Zuul to redirect http://localhost:8888/api/v1/microservice/microservice to http://localhost:11001/microservice, for example. In a more general way, it redirects anything with the path /api/v1/microservice/<some-path> to http://localhost:11001/<some-path>
Question
How can I avoid writing microservice twice in the URL, but still be able to request the mapping /microservice in the controller of my microservice?
A solution to this problem could be requesting the mapping / instead of /microservice. But I don't want to do that. The reason is that I'm using Swagger and its Codegen to generate interfaces and if I request the mappings without writing a collection name, I feel that my specification is not as good.
I thought of writing a route Zuul filter, but I couldn't find a good example. Also, I think that if I could alter the code that handles the moment when Zuul tries to map the Eureka services to a path, that could be a solution.
When not in conjunction with Eureka, Zuul allows to specify an input path and a forward URL with address, port and something else. The same should be possible when specifying a Service Id. Maybe I can modify some code in a way that the routing is still dynamic but that I can add that something else.
Would modifying the classes SimpleRouteLocator or ZuulHandlerMapping help? or is another class in charge of that dynamic routing? Also what would be the best way of implementing something like this?
Edit
I realized that when you configure Zuul like this for example:
zuul:
add-proxy-headers: true
sensitive-headers: Cookie,Set-Cookie
routes:
uaa:
path: /uaa/**
service-id: oauth-v1
strip-prefix: false
sensitive-headers:
It does what I want it to do. That strip-prefix is different from the global one.
When I configured my Zuul that way, in the log I see:
... o.s.c.n.zuul.filters.SimpleRouteLocator : Matching pattern:/uaa/**
... : route matched=ZuulProperties.ZuulRoute(id=uaa, path=/uaa/**, serviceId=oauth-v1, url=null, stripPrefix=false, retryable=null, sensitiveHeaders=[], customSensitiveHeaders=true)
When Zuul loads the services registered in Eureka, in the log I see
.... o.s.c.n.zuul.filters.SimpleRouteLocator : route matched=ZuulProperties.ZuulRoute(id=v1/microservice, path=/v1/microservice/**, serviceId=microservice-v1, url=null, stripPrefix=true, retryable=null, sensitiveHeaders=[], customSensitiveHeaders=false)
The only significant difference is that the latter says stripPrefix=true and to solve my problem, it should be false.
I think that it should be possible to change that default behaviour somehow...
What is the recommended configuration when running both Config Server with Eureka Server? Should Config Server be a client of Eureka? Or should Eureka be dependent on Config Server properties for its configuration? Or is both OK?
The default way to use Eureka and Config Server is to use Config First bootstrap. Essentially, you make eureka server a client of the config server but you don't make the config server a client of eureka.
As said by David Syer on these (and this) issues, the founder of spring cloud, you have to use the config server with a front end load balancer, so a single URL is already highly available.
I'm also a newbie in Spring Cloud but I agree with him since Eureka is a Service Discovery, IMHO it should function on it's problem domain only. It would make a complicated logic for Eureka servers who are asking the Config servers for it's configuration. I can't imagine how the Eureka Server would know which config server to get if the Config Server is also the Server of Eureka to get its list of defaultZone.
It would be much more simpler for me to separate the Config Server's HA.
Based on #Mideel's answer
Eureka and Config Client configuration (needs to be Bootstrap):
# bootstrap.yml
cloud:
config:
discovery:
enabled: true # This is required
service-id: configserver # Config Server's eureka registry name
enabled: true # This is default true already
Config Server configuration:
spring:
application:
name: configserver # Needs to match client configuration
Register the Config Server with the annotation #EnableEurekaClient (it should be Auto Configured to register with Eureka already though)
The Spring Cloud Config service provides configuration info for various other microservices, of which the Eureka service is one.
Each app/microservice is pointed to its configuration (from the Config service) via bootstrap.properties/.yml, which is loaded in the parent context for that application, before the app "recognizes" that it is a discovery/Eureka client per its annotated main class. This bit of documentation provides a bit more detail on that process.
Cheers,
Mark
EDIT1: I think this is a wrong answer, see the replies
If you use Spring Boot:
I'm using Spring Microservices in Action as my guide book and based on the source code example there, we make the configuration server as the Eureka Client with the #EnableEurekaClient annotation and in the config server application.yml, we need to add this property:
spring:
cloud:
config:
discovery:
enabled: true
And in the other Eureka client that uses this config server, you need to add this property to the application.yml :
spring:
cloud:
config:
enabled: true
That's it, just set up the config server normally, I think behind the scene the config libraries from spring cloud will take care of the rest using Eureka.