When I change a value from my properties repository and restart the Spring Cloud Config Server, the changes do not reflect on it's consumers.
my-microservice/application.properties:
spring.application.name=my-service
spring.cloud.config.uri=http://localhost:8888
MyServiceController.java
#RestController
public class MyServiceController {
#Autowired
private Configuration configuration;
#GetMapping("/my-service")
public MyServiceBean retrieveMyServiceProperties() {
// show propertie's values
return new MyServiceBean(configuration.getPropertie1(), configuration.getPropertie2());
}
}
spring-cloud-config-server/application.properties
server.port=8888
spring.application.name=spring-cloud-config-server
spring.cloud.config.server.git.uri=file://path
Git repo
my-service.properties
my-service.propertie1=1
my-service.propertie2=2
When I send a GET request to localhost:8080/my-service, that's the result I got:
{
"propertie1":1,
"propertie2":2
}
Fine, that's OK!
But, if I change the my-service.properties and restart my Spring Cloud Config Server, the changes do not reflect MyServiceController. I do need to restart my-microservice application, for changes to take effect.
Is this the normal behavior? I mean, if this is remote, then, it should be configured whether to cache or not.
In order to update the configurations, I sent a POST request to localhost:8080/actuator/refresh.
By default, /refresh isn't exposed in actuator endpoints.
I did exposed with the following line in application.properties:
management.endpoints.web.exposure.include=*
Then, sent a POST request with no body to the endpoint above.
To update your client application, It's better to use a message broker like RabbitMQ or Apache Kafka.
This process has three levels:
The client application and config server subscribe to a specific topic (/refresh) in the message broker.
The config server sends refresh event to that topic (/refresh), as soon as it gets updated. (for example application.properties file gets updated in git).
All client applications are listening to refresh event, when they get refresh message, they will be updated
In brief, we can use the pub-sub model for updating our client applications.
Config Server using Spring Cloud Config and Apache Kafka
Related
I am using Spring Boot and have an issue related #Scheduled.
#Scheduled(fixedRateString = "${timeRate}")
public void SaveStatisticData() {
System.out.println("save Info per "+timeRate+"msec");
...
}
this is a part of my code. this method will run by timeRate value from properties and Properties File is connected with web API.
That means someone can request to change timeRate in Properties File.
I want to know how to reload spring boot on client request which change Properties File.
AFAIK, I can use Hot Swapping in spring boot.
But I think this solution is not good to service.
Because The service have to reload whenever a client request changing timeRate.
In other words, is there another way to apply this client request in real time?
I have a Spring Boot app as follows:
#SpringBootApplication
#EnableResourceServer
#EnableDiscoveryClient
public class App
{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
And i have configured oauth2 properties in application.properties.
security.oauth2.resource.user-info-uri=http://localhost:9000/user
However, I need to change this URI depending on the request I send to my Spring Boot App.
For example:
If I receive a request to my Spring Boot App to URL htpp://test.localhost:8000 I would want the user-info-url to be http://test.localhost:9000/user.
But if I receive a request to http://localhost:8000 I want the user-info-url to be http://localhost:9000/user.
My intention is to manage different environments depending on the subdomain.
Is there a way to dynamically change this URI in code instead of hardcoding it as a property?
Spring Cloud Config
By leveraging a Spring Cloud Config server, you can externalize your configuration and push updates to application properties. A simple implementation is backed by a Git repository where you'll store your application.properties file. You commit your changes and then make a POST request the /refresh endpoint that will trigger a reload of your configuration.
There are more advanced scenarios as well but hopefully that's enough to get you started.
Here's a simple Getting Started guide.
I have two Spring Boot applications running on one server. Both use embedded ActiveMQ JMS. I want to have separate JMS instance for each application. How could I set the port for each of them? Is there any property like spring.activemq.port?
When I run second application I get the following expected error:
Failed to start JMX connector Cannot bind to URL [rmi://localhost:1099/jmxrmi]: javax.naming.NameAlreadyBoundException: jmxrmi [Root exception is java.rmi.AlreadyBoundException: jmxrmi]. Will restart management to re-create JMX connector, trying to remedy this issue.
I have same issue, two SpringBoot process and I want to send messages through the ActiveMQ.
First I got it working starting another process with the ActiveMQ, and configuring both SpringBoot process into their application.properties files with:
spring.activemq.broker-url = tcp://localhost:61616
Whit this configuration you tell Springboot to connect to a external ActiveMq service. This works, but then I need to first start the ActiveMQ and after my Springboot process. In some page I have read this must be the way to use at production environments.
Another solution is to use the embedded JMS support at one of the SpringBoot process, for this way you need to configure the ActiveMQ broker service listening for connections in one Springboot process. You can do this adding a Broker bean:
#Bean
public BrokerService broker() throws Exception {
final BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61616");
broker.addConnector("vm://localhost");
broker.setPersistent(false);
return broker;
}
Now this SpringBoot process with this bean do not need the previous configuration at the application.properties, and this will be the first process to start, in order to have the ActiveMQ listening for other process connections.
The other Springboot process still need to have the configuration at the application.properties in order to connect to the ActiveMq created by the first process.
Hope it helps you.
Best regards.
You can configure the broker url using the spring.activemq.broker-url property, e.g. set it to spring.activemq.broker-url=tcp://localhost:61616.
For a comprehensive reference of available properties you can check out this reference.
spring.activemq.broker-url
Including the port according to spring boot properties
I'm trying to make a basic project using spring cloud with the netflix addons such as Hystrix, Eureka and Ribbon to learn how this works. The project I'm trying to make is a simple message server that will keep messages. And a message-client that will just ask the server for a message, and I want to use the auto discovery client for this, or the RestTemplate discovery. But I can't get either to work.
I have the following structure:
message-client (eureka client)
message-server (eureka client)
configuration-service (config server)
discovery-service (eureka server)
What I currently do is I start up the configuration-service, and expose the application.yml details to all of these "apps/clients" when they are connecting by the following structure:
config-service\src\main\resources\config\appname.yml
app\src\main\resources\bootstrap.yml (contains the appname and url to cloud config)
This is working just fine, and my apps start up on the port they receive from the config server, as well as they all connect to my eureka server, and all of them are visible there. As well as the Hystrix failover is also working, not that it is related to this but it tells me that it can't be completely wrong then.
But here comes my confusion...
When using the #Autowired annotation in my service class (#Service annotated) inside my client module, I get a discoveryClient object, but I am unable to find any other services using that one.
Message Client - boot class:
#EnableAutoConfiguration
#EnableHystrix
#EnableEurekaClient
#ComponentScan("cloud.rest.resources, spring.cloud.client")
public class ClientBoot {
public static void main(String[] args) {
SpringApplication.run(ClientBoot.class, args);
}
}
Message Client - REST Resource:
#RestController
public class MessageResource {
#Autowired
private MessageClient messageClient;
#RequestMapping(value = "/message/{client}", method = RequestMethod.GET)
public Message getMessage(#PathVariable String client) {
return messageClient.getMessage(client);
}
}
Message Client - MessageClient:
#Service
public class RestMessageClient implements MessageClient {
#Autowired
private DiscoveryClient discoveryClient;
#Autowired
private RestTemplate restTemplate;
#Override
public Message getMessage(String client) {
return restTemplate.getForObject(String.format("http://message-server/message/%s", client), Message.class);
}
}
My message server boot class that is holding the messages has the same annotations as my client one.
And as I said, my service class are unable to find anything..
Which leads me to all of my questions:
What is required to actually use ribbon load balancer?
Do I have to use ribbon to be able to use the "auto discovery", I thought not but now I'm just confused.
From what I've understood, when using EnableEurekaClient I should not need to use the EnableDiscoveryClient as well?
Can I change the yml files on my config-server for the clients in runtime and just have to reboot the client?
How much configuration is really meant to be shared by the config-server, because currently all of my clients just contain a super basic bootstrap.yml file.
Does anyone have a good link to where I can read more about all the properties that is being set in my yml files? Both a documentation of what the properties that exists actually do as well as some documentation on how I can use them in combination with spring cloud?
Do I need specific properties to enable my apps/clients to find other apps/clients?
Edited information
Thank you for your quick and excellent reply, I've gone through this over and over today and I finally got my application working..
The problem (I can't understand why and was hoping you could help me understand that) is that my discovery service contains yml files for each of my other clients where I specify things like port and eureka information.. What I specified here as well was:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka
So, when I set this value it seems to override something that makes my service discovery not working.. Even tho I can see all my applications in the eureka server, they were unable to find each other when I had this value set.
I set this value by having a message-server.yml file in my configuration service that is sent out to my message-server application after bootstrap..
So then I have two new questions.
How do I override this eureka server property?
Why does my discovery client stop working when I set this value, what is it that it actually does?
What is required to actually use ribbon load balancer?
The ribbon-loadbalancer must be on the classpath (e.g. via "spring-cloud-starter-ribbon"). Then you can inject one as a LoadBalancerClient or you can inject a RestTemplate (it will be load-balancer aware if you have a LoadBalancerClient).
Do I have to use ribbon to be able to use the "auto discovery", I thought not but now I'm just confused.
What is "auto discovery"? You don't need to use Ribbon to use the DiscoveryClient (Ribbon is a load balancer, not a service registry).
From what I've understood, when using EnableEurekaClient I should not need to use the EnableDiscoveryClient as well?
Correct. #EnableEurekaClient is annotated with #EnableDiscoveryClient so it is only there to express a preference.
Can I change the yml files on my config-server for the clients in runtime and just have to reboot the client?
Yes. Or you can use the /refresh or /restart endpoints (a full reboot is probably best in production, at least periodically).
How much configuration is really meant to be shared by the config-server, because currently all of my clients just contain a super basic bootstrap.yml file.
As much as you want. How long is a piece of string? If I were you I would try and keep the central config to a minimum (only the things that change between environments, or at runtime).
Does anyone have a good link to where I can read more about all the properties that is being set in my yml files? Both a documentation of what the properties that exists actually do as well as some documentation on how I can use them in combination with spring cloud?
Spring Boot and Spring Cloud have autogenerated metadata for externalized properties. The new generation of IDEs understands them (so get STS 3.6.4 or IDEA 14.1), and they are listed in the user guide (for Spring Boot at least) under http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties
Do I need specific properties to enable my apps/clients to find other apps/clients?
You need to be able to locate your service registry (Eureka in this case). If you are using Eureka and your clients have registered then that is enough.
I managed to create simple Websocket application with Spring 4 and Stomp. See my last question here
Then I tried to use remote message broker(ActiveMQ). I just started the broker and changed
registry.enableSimpleBroker("/topic");
to
registry.enableStompBrokerRelay("/topic");
and it worked.
The question is how the broker is configured? I understand that in this case the application automagicaly finds the broker on localhost:defaultport, bu what if I need to point the app to some other broker on other machine?
The enableStompBrokerRelay method returns a convenient Registration instance that exposes a fluent API.
You can use this fluent API to configure your Broker relay:
registry.enableStompBrokerRelay("/topic").setRelayHost("host").setRelayPort("1234");
You can also configure various properties, like login/pass credentials for your broker, etc.
Same with XML Configuration:
<websocket:message-broker>
<websocket:stomp-endpoint path="/foo">
<websocket:handshake-handler ref="myHandler"/>
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue"
relay-host="relayhost" relay-port="1234"
client-login="clientlogin" client-passcode="clientpass"
system-login="syslogin" system-passcode="syspass"
heartbeat-send-interval="5000" heartbeat-receive-interval="5000"
virtual-host="example.org"/>
</websocket:message-broker>
See the StompBrokerRelayRegistration javadoc for more details on properties and default values.