Hazelcast Session Replciation With Spring Boot - java

Am following this documentation for Hazelcast based session replication in a Spring Boot APP.
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/hazelcast-spring.html
The code works fine when a local Hazelcast node gets created from spring boot however what i need is a Hazelcast client code to connect to standalone cluster and do the replication and return back the Session ID as a header in "x-auth-header " field.
Client code is something like this
ClientConfig clientConfig = new ClientConfig();
clientConfig.getGroupConfig().setName("dev").setPassword("dev-pass");
clientConfig.getNetworkConfig().addAddress("x.x.x.x");
I am able to get it working with a WEB Filter but it stores the value as cookie and what i need is the header strategy to work.
I couldn't find any documenation or help to acheive it using a Hazelcast client. Can some one please guide me on how to do it.
Thanks
Aravind

Do you have
#Bean
public HeaderHttpSessionStrategy sessionStrategy() {
return new HeaderHttpSessionStrategy();
}
If everything else is working, this should be all you need

Thanks for the quick reply . It works when I create a springawarewebfilter and then define the cookie params.
In that case when I add the header strategy it doesn't work and still resolves to cookies.
May be it was misleading but it worked with springawarewebfilter which I think is different as the above specified link creates a different filter for handling session

The issue was related to the server nodes and firewall in between. Migrated to a separate set of nodes and everything started working.

Related

(GAE-Standard+Java11) Sessions with multiple instances running

I have deployed my spring boot application on GAE, Java 11, Standard Environment. As per the documentation for Java11 we need to use app.yaml for configuring the instances.
I wanted to know as to how I can enable sharing of sessions between instances. As per my research, Earlier we could simply solve this problem by setting sessions-enabled and async-session-persistence in appengine-web.xml. With appengine-web.xml gone, what is the equivalent way of doing this in app.yaml.
Use case that i am trying to achieve is :
Using spring security (Unfortunately i get logged out when according to me the request of the same user goes to another instance.)
Storing the user retrieved from DB in a #SessionScoped variable so as to avoid multiple DB calls.
Any help here would be really appreciated. Thanks!
I went through a lot of documentation, but I believe that this is not inside the app.yaml configuration reference.
Alternatively, I could find that you could use session affinity in order to use a instance to reply always the requests of a same user, this can be enabled in your app you can use the next tag in your app.yaml according to this documentation.
network:
session_affinity: true
Hope this works for you.

Dynamic scheduling with properties in spring boot

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?

Java Hazelcast Tomcat Web Clustering

I am trying to implement a sticky session based load balancing across two Tomcat instances using the Hazelcast Tomcat Web Session Replication. For testing purposes, I have deployed the application on two different Tomcat instances and the load balancing is handled through Apache HTTPD. The jvmroute parameters and the mod-proxy settings are fine and the load balancing has no issues.
The problem is with the session replication across the two instances. When the first server (currently serving the request) goes down the request is sent to the second server. The Hazelcast cluster identifies that the session is through fail-over and is copying the session with the new session id (suffixed with the jvmroute parameter of the second server) - as described in the Hazelcast documentation https://github.com/hazelcast/hazelcast-tomcat-sessionmanager#sticky-sessions-and-tomcat) . However for the failed-over request, the session attributes are getting updated in the older session(failed over jvmroute) and not getting replicated resulting in the failure of the subsequent request.
I have gone through the documentation but unable to find a resolution at this point. I am sure I am missing some setting as this would be a basic setting for a fail over scenario.
Can someone help me out? Please let me know if you need any additional details.
[UPDATE]
After tracing the flow, able to determine that the handleTomcatSessionChange in com.hazelcast.session.HazelcastSessionChangeValve is being called correctly. The request.changeSessionId(newSessionId) call happens and post this if I display the value of the requestedsession id, the value is updated. However, the session id by itself is not updated and this is resulting in the older id in a request.getSession().getId() call.

How can I get the Discovery Client working when using spring-cloud together with netflix Eureka?

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.

Hostname in tomcat cookies

Our Tomcat creates session IDs with the following format:
jsessionid=a345465820fce654354646ae.(server-name);
Is it possible to configure it so that server-name is not part of session id?
I think you need to implement your own session manager to change the format of JSESSIONID. I am not sure what you want to achieve but this question might be of interest, you also have a link to the session manager HOW-TO at Tomcat.
How to generate custom JSESSIONID, based on some hash of user's data in order to replicate session
However, if you have an Apache server in front of your Tomcat it might be easier to create your own cookie and use that instead of JSESSIONID. You can do this by using the mod_header and there is an example of this in the mod_proxy_balancer documentation.
Hope it helps you forward.

Categories