導航目錄
楔子
學習筆記 ,做個記錄
session 共享問題解決
1 session複製
-
優點
tomcat 原生支持,只需要修改配置文件
-
缺點
- session 同步需要數據傳輸,佔用大量網絡帶寬,降低了服務器羣的業務處理能力
- 任意一臺web-server保存的數據都是所有web-server的session總和,收到內存限制無法水平擴展更多的web-server
- 大型分佈式集羣情況下,由於所有web-server都全量保存數據,所有次方案不可取
2 hash一致性
-
優點
- 只需要該nginx配置,不需要修改應用代碼
- 負載均衡,只要hash屬性的值分佈式均勻的,多臺web-server的負載是均衡的
- 可以支持web-server水平擴展(session同步是不行的,受內存限制)
-
缺點
- session還是存在web-server中,所有web-server重啓可能導致session丟失,影響業務,如部分用戶需要重新登錄。
- 如果web-server水平擴展,rehash後的session重新分佈,也會有一部分用戶路由到不正確的session。
以上的缺點問題不大,因爲session本來都是有有效期的。所有這兩種反向代理的方式可以使用。
3 統一存儲
- 優點
- 沒有安全隱患
- 可以水平擴展,數據庫/緩存水平切分即可
- web-server重啓或擴容都不會丟失
- 不足
- 增加了一次網絡調用,並且需要修改相應的代碼,如將所有的getSession方法替換爲從Redis查數據的方式,redis獲取數據比內存慢很多。
- 上面的缺點可以用springSession完美解決。
4 session共享問題解決-不同服務,子域session共享|(springSession)
SpringSession 簡單使用
以下使用Redis作爲存儲session的介質
1 pom引入依賴
<!-- springSession -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2 使用註解開啓 springsession
# springboot啓動類加註解
@EnableRedisHttpSession
代碼中處理
@Slf4j
@RestController
@RequestMapping("/session")
public class SessionController {
@RequestMapping("login")
public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session,
User user) {
//TODO 1 默認發的令牌,SESSION=*** ,作用域:當前域(解決子域共享)
//TODO 2使用JSON的序列化存儲數據到 Redis
log.info("login user is {}", user);
session.setAttribute(SysUtils.LOGIN_NAME, user);
return String.format("%s|%s|", SysUtils.getDateSpan(), user.getUname());
}
@RequestMapping("show")
public Object showLoginUser(HttpSession session) {
Object attribute = session.getAttribute(SysUtils.LOGIN_NAME);
log.info("獲取的session user is {}", JSON.toJSONString(attribute));
return attribute;
}
}
設置Redis存儲爲JSON以及配置子域共享
@Configuration
public class SessionConfig {
/**
* 設置熱session cookie name 以及子域共享
*
* @return
*/
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("WEBJSESSIONID");
serializer.setCookiePath("/");
serializer.setDomainName("grq.com");
//serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}
/**
* 設置redis session 序列化方式爲JSON
*
* @return
*/
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
//return new FastJsonRedisSerializer();
//return new GenericFastJsonRedisSerializer();
return new GenericJackson2JsonRedisSerializer();
}
}
**域名和子域名使用Windows hosts模擬 **
3 配置文件
配置存儲方式爲redis,以及redis配置
################################ session
spring.session.store-type=redis
# more就是30分鐘
server.servlet.session.timeout=30m
################################ session |end
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
Redis存儲
**域名 使用SwitchHosts! 添加模擬 **
遇到的問題
使用fastjson 作爲序列化 JSON的時候,出現了**NoSuchMethodError: com.alibaba.fastjson.serializer.JavaBeanSerializer.processValue**
https://github.com/alibaba/fastjson/issues/2780
需要升級 將fastjson從1.2.57升級到1.2.61