SpringCloud微服务架构分布式组件如何共享session对象_风情客家__的博客-程序员宝宝_requesttemplate验证sessionid

技术标签: 微服务  spring cloud  

参考文章: https://www.cnblogs.com/fengli9998/p/7881331.html

https://blog.csdn.net/dsen726/article/details/80880458

一.简单做一个背景说明
1.为说明问题,本文简单微服务架构示例如下

2.组件说明
分布式架构,每个组件都是集群或者主备。具体说明如下:
zuul service:网关,API调用都走zuul service。
micro service1 & micro service2:业务功能实现,数据库增删改查。
eureka:组件注册,zuul service,micro service等组件都注册到eureka,管理组件调用地址。
db-master & db-slave:数据库集群,一主两从。
redis master & redis slave:redis集群,缓存。这里主要存储session对象。

3.组件之间API调用
①:网关zuul接收到的API请求,路由至业务实现组件。
②:网关zuul以及业务组件将session对象存储到redis、或从redis获取session对象。
③:业务组件实现数据增删改查。
④:业务组件之间通过springCloud feign组件进行调用。
⑤:网关zuul以及micro service组件注册到eureka组件,或从eureka获取组件调用地址。

二.存在问题
基于如上微服务的分布式架构如果按照传统方式,将session对象存储在内存中。在zuul网关将路由请求至不同的micro service1或者micro service2时,内存中的session对象将不能被共享,无法判断用户的登陆状态,也无法获取session对象存储的全局数据。

三.解决方案
1.Spring管理session对象
通过EnableRedisHttpSession注解支持基于Redis存储session,全局共享session对象。

2.微服务架构下共享session对象实现说明
1)客户端API请求到zuul,zuul基于spring管理session将session对象存储到redis,并将生成的sessionId返回给客户端。
2)zuul将请求路由到micro service,将sessionId通过cookie头带给micro service。
3)micro service通过sessionId从redis获取到已经生成的session对象。
4)micro servcie1调用micro service2时,将sessionId也通过cookie头带给micro service2,micro service2通过sessionId从redis中获取session对象。
5)客户端再次调用时将a)步返回的sessionId增加到cookie头,在redis中存储的session失效之前zuul和micro service一直共享这个session。

5.具体实现
1)通过springframework的EnableRedisHttpSession注解管理session,zuul和micro service组件实现这个类以存储、获取redis中存储的session对象。

import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = GlobalConstants.SESSION_TIMOUT, 
redisFlushMode = RedisFlushMode.IMMEDIATE)
public class SessionConfig {
    
}

EnableRedisHttpSession注解参数说明:
maxInactiveIntervalInSeconds
:session过期时间配置。
redisFlushMode:redis session刷新模式。配置为RedisFlushMode.IMMEDIATE,可以确保zuul存储到redis的session对象在请求到micro service中能立即被获取。在实际开发过程中出现由于没有这个配置值,有时候zuul将session对象存储到了redis,但是micro service无法立即获取。

2)在zuul过滤器方法中调用addZuulRequestHeader增加请求头,将sessionId通过cookie头路由到micro service。

public class AccessFilter extends ZuulFilter {
    @Autowired
    HttpServletRequest httpServletRequest;
    @Autowired
    HttpServletResponse httpServletResponse;

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String sessionId = httpServletRequest.getSession().getId();
        ctx.addZuulRequestHeader("Cookie", "SESSION=" + sessionId);
        ctx.setSendZuulResponse(true);// 对该请求进行路由
        ctx.setResponseStatusCode(200); // 返回200正确响应
    }
}

3)micro service1通过feign调用micro service2时,实现RequestInterceptor接口。通过增加cookie头,将sessionId带到micro service2。

@Configuration
public class MyRequestInterceptor implements RequestInterceptor {
    @Autowired
    HttpServletRequest request;

    @Override
    public void apply(RequestTemplate requestTemplate) {
        logger.info("MyRequestInterceptor apply begin.");
        try {
            String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
            if (null != sessionId) {
                requestTemplate.header("Cookie", "SESSION=" + sessionId);
            }
        } catch (Exception e) {
            logger.error("MyRequestInterceptor exception: ", e);
        }
    }
}

6.验证

1)通过postman请求zuul服务地址,调用登陆接口。

2)查看各组件sessionId

zuul sessionId:

micro service1 sessionId:

micro service1调用micro service2 sessionId:

结论:可以看到zuul和micro service中sessionId都是相同的,都是586b*c9a4,通过这种方式实现了API调用过程中的session对象共享。

注意:springcloud项目中经过网关zuul转发请求后发生session失效问题,这是由于zuul默认会丢弃原来的session并生成新的session,解决方法网关配置文件application.yml 中添加 sensitiveHeaders: “*”

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/justlpf/article/details/80350943

智能推荐

数据结构第六章——图_允谦呀的博客-程序员宝宝_数据结构表示工程计划的方法

数据结构第六章——图图的定义和术语G = (V, E)V:顶点(数据元素的)有穷非空集合;E:边的有穷集合。**无向图:**每条边都是无方向的。**有向图:**每条边都是有方向的。**完全图:**任意两个顶点都有一条边两连**无向完全图:**n个顶点 n(n-1)/2条边**有向完全图:**n个顶点 n(n-1)条边**稀疏图:**有很少边或弧地的图**稠密图:**有较多的边或弧的图**网:**边/弧带权的图**邻接:**有边/弧相连的两个顶点之间的关系关联(依附):边/弧与顶

3D游戏之父--John Carmack(一)_JonnyLai的博客-程序员宝宝_游戏界第一个3d游戏第三人称视角鼻祖

游戏轴心-廖子鹏 [转载] .北京 2004年09月08日08:37 3D游戏之父--John Carmack(一)---连比尔.盖茨都欣赏的天才译者:小熊在线-大灰熊如果你问比尔.盖茨,“你最欣赏的程序员有哪些?”,在他的回答中,肯定会出现John Carmack(卡马克)的名字。没错,John Carmack 在程序员中的崇拜程度,甚至到了无以为加的地步, 他设计出了游

MobPush 厂商通道SDK集成指南_MobTech袤博科技的博客-程序员宝宝_集成厂商通道

开发工具:Android Studio集成方式:Gradle在线集成安卓版本支持:minSdkVersion 19。

knime简介_KNIME简介_weixin_26746401的博客-程序员宝宝

knime简介Data Science is abounding. It considers different realms of the data world including its preparation, cleaning, modeling, and whatnot. To be precise, it is massive in terms of the span it cover...

随便推点

对比度 亮度调整 OPENCV C+ 2_小井dsc的博客-程序员宝宝

#include <opencv2\opencv.hpp>#include <iostream>using namespace cv;using namespace std;int main(int argc, char** crgv) { Mat src, dst; src = imread("C:/Users/AA/Desktop/myc++/1.jpg"); imshow("input", src); int height = src.rows; int

Byte Order_七滴雨的博客-程序员宝宝_byte order选错会有什么影响

阅读文件格式文档的时候看到关于字节序(Byte Order)的要求:For values which span more than a single byte, the multiple byteordering followed is that of the Big Endian / Motorola standard.The most significant byte will occ

tensoflow模型中提示:ValueError: Variable rnn/basic_rnn_cell/kernel already exists, disallowed. Did you me..._weixin_30873847的博客-程序员宝宝

在利用tensorflow框架进行模型训练的时候,有时我们需要多次训练对结果求均值来得到一个均衡的评测结论。比如训练十次求平均值。但是tf的本质就是图,当变量第一次定义使用后,第二次再使用就是提示:ValueError: Variable rnn/basic_rnn_cell/kernel already exists, disallowed. Did you mean to set re...

已知某年某月,请输出这个月共有多少天(switch语句)_GHYshuai55的博客-程序员宝宝

package com.zhidi;public class Lianxi08 {public static void main(String[] args) {// 已知某年某月,请输出这个月共有多少天。(switch语句)int year = 2012;int month = 2;switch(month){case 1:case 3:

带壳截图 android,给手机截屏带个「套」:带壳截图应用合辑_红色有角的博客-程序员宝宝

现在,在社交平台分享手机截屏已经是各位习以为常的事情。而今天,少数派将为大家盘点几款独特的「带壳截图」应用,覆盖三大主流平台,种类繁多,总有一款适合你。新手教学:如何截屏既然今天的主角是「带壳截图」应用,那么文章开始之前,我们先来回顾各大平台的截屏方式。在 Android 2.x 时代,截取手机屏幕并不是一件容易的事情,需要获取 Root 权限,然后借助第三方截图应用才可实现手机屏幕的捕捉。而伴随...

推荐文章

热门文章

相关标签