记一次Spring Cloud Session微服务间传递丢失问题定位
来源:Java技术进阶     阅读:1251
黑蚁网络
发布于 2018-07-09 22:22
查看主页
记一次Spring Cloud Session微服务间传递丢失问题定位

在构建基于Spring Cloud微服务框架时,用了常使用的框架NGINX+ZUUL+Eureka+业务服务,Session用Spring boot的Redis集成,所有微服务间共享Session

所有业务的微服务Rest接口前端调使用接口通过ZUUL进行转发,而ZUUL通过创立ZUULFilter过滤器来对请求鉴权及少量Session操作,而且为了保证Session实时生效,故设置Spring boot的Redis Session公告为立即生效,如下所示:

@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)

在第一次业务请求时ZUUL过滤器会创立Session并设置属性,而后直接将请求转发到业务服务,


  1. @Component
  2. public class LoginFilter extends ZuulFilter {
  3. private final static Logger LOG = LoggerFactory.getLogger(LoginFilter.class);
  4. @Override
  5. public Object run() throws ZuulException {
  6. Double rand = Math.random() * 100;
  7. int randInt = rand.intValue();
  8. RequestContext ctx = RequestContext.getCurrentContext();
  9. HttpServletResponse response = ctx.getResponse();
  10. HttpServletRequest request = ctx.getRequest();
  11. HttpSession session = request.getSession();
  12. session.setAttribute("test", randInt);
  13. LOG.info("Session id:{} test:{}",session.getId(),randInt);
  14. return null;
  15. }
  16. @Override
  17. public boolean shouldFilter() {
  18. return true;
  19. }
  20. @Override
  21. public int filterOrder() {
  22. return 0;
  23. }
  24. @Override
  25. public String filterType() {
  26. return "pre";
  27. }
  28. }

然而业务服务在调使用方法时通过request.getSession(false)获取的Session为null,但紧接着第二次及后续调使用时业务服务都可以获取到了正确的Session。


  1. @RestController
  2. public class BusinessController {
  3. private final static Logger LOG = LoggerFactory.getLogger(BusinessController.class);
  4. @RequestMapping(path="/getsession/{key}")
  5. public String getSessionVal(HttpServletRequest request,@PathVariable("key") String key) {
  6. HttpSession session = request.getSession(false);
  7. Object value = null;
  8. if(null != session) {
  9. value = session.getAttribute(key);
  10. }
  11. LOG.info("Session id:{} value:{}",session == null ? null:session.getId(),value);
  12. return "";
  13. }
  14. }

这么奇葩的现象,第一次Session创立成功居然Session不可以传递,实在是令人匪夷所思。

因为没有特殊定制过Spring boot Session机制,都是用默认的Cookie传递方式。业务服务获取不到Session,有两种可可以,一种是Redis没有实时创立Session对象,另外一种是业务不可以通过SESSIONID获取到对象。

通过Debug断点定位,在ZUUL创立Session时,通过Redis用户端,直接连接到Redis服务器,查看发现Redis实时的生成了Session对象,故第一个假设应该不成立的。

而后通过打印在ZUUL与业务服务中Request Cookie信息,发现ZUUL在创立完Session后,并没有升级request的Cookie中的SESSIONID,且request.isRequestedSessionIdValid()为false,故业务第一次获取到的request中的Cookie没有新的SESSIONID,就更不可以根据Cookie获取Session了,第二种假设成立。

通过查询资料,明白了只有在请求Response响应后请求的Cookie才会升级,第一次请求时创立的Session不会在微服务间进行传递。天真的认为能宽心的用Spring cloud全家桶,殊不知还是需要细心与思考,同时也许需要知识积累。

从单体引使用根本不会出现这种情况,Session在一个服务中传递,不存在Session重新通过Cookie获取。而微服务简化了业务,但多了交互,外部交流越多,越容易出错,也许在微服务的路上还有更多的坑需要填补。

如何填补这个坑呢? 大家能关注我的头条号 以后会持续升级干货的

记得点赞转发一下 有不同的见地在下面评论区评论一下 小编会改进的

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 软件环境
相关推荐
javascript之Iframe之间通信
年末来一波面试“毒鸡汤”
python3测试工具开发快速入门教程2数据结构3列表
前台面试:大专也敢想大厂,不试试你怎样知道你不行!
非科班出身转行IT难吗?好找工作吗?
首页
搜索
订单
购物车
我的