分布式 Session
分布式会话是构建可扩展 Web 应用的关键组件,特别是在集群部署环境中。通过本文档,您将学会如何在 Feat Cloud 中配置和使用基于 Redis 的分布式会话。
在传统的单机应用中,会话信息通常存储在服务器的内存中。但在分布式或集群环境中,这种方式会出现问题,因为用户的请求可能会被负载均衡器分发到不同的服务器实例,导致会话信息无法共享。
Feat Cloud 提供了内置的分布式会话支持,目前支持基于 Redis 的会话存储。通过将用户的会话信息存储在共享的 Redis 数据库中,所有的服务器实例都可以访问和更新同一个用户的会话数据,从而解决了集群环境下的会话共享问题。
Feat Cloud 的分布式会话主要由以下两个核心组件构成:
- ClusterSessionManager - 负责管理会话的创建、获取和更新
- RedisSession - 代表一个具体的会话实例,提供会话数据的操作接口
要启用分布式会话功能,您需要在 feat.yml 配置文件中进行相应配置。
server: session: timeout: 1800 # 会话超时时间(秒),默认30分钟 store-type: redis # 会话存储类型,设置为redis启用分布式会话feat: redis: address: redis://127.0.0.1:6379 # Redis服务器地址 password: # Redis密码(可选) database: 0 # Redis数据库索引- server.session.timeout: 会话超时时间,单位为秒。默认值为1800秒(30分钟)。超过这个时间没有访问的会话会被自动清除。
- server.session.store-type: 会话存储类型。设置为
redis以启用分布式会话功能。 - feat.redis.address: Redis 服务器地址,支持多种格式:
redis://127.0.0.1:6379- 普通连接rediss://127.0.0.1:6380- SSL加密连接
- feat.redis.password: Redis 访问密码(如果需要的话)
- feat.redis.database: Redis 数据库索引,默认为0
下面通过一个完整的示例来展示如何使用分布式会话功能。
Maven 依赖
Section titled “Maven 依赖”首先确保您的 pom.xml 文件中包含了必要的依赖:
<dependencies> <dependency> <groupId>tech.smartboot.feat</groupId> <artifactId>feat-cloud-starter</artifactId> <version>${feat.version}</version> </dependency> <dependency> <groupId>tech.smartboot</groupId> <artifactId>redisun</artifactId> <version>1.2.0</version> </dependency></dependencies>创建 src/main/resources/feat.yml 配置文件:
server: session: timeout: 1800 store-type: redisfeat: redis: address: redis://127.0.0.1:6379 password: database: 0创建 Bootstrap.java 启动类:
@Controllerpublic class Bootstrap {
@RequestMapping("/") public String helloWorld(Session session) { // 将访问次数存储在session中 String visitCount = session.get("visitCount"); if (visitCount == null) { visitCount = "0"; } int count = Integer.parseInt(visitCount) + 1; session.put("visitCount", String.valueOf(count));
return "hello Feat Cloud, visit count: " + count; }
/** * 设置session属性 */ @RequestMapping("/setSession") public String setSession(Session session) { session.put("username", "FeatUser"); session.put("role", "developer"); return "Session attributes set successfully"; }
/** * 获取session属性 */ @RequestMapping("/getSession") public String getSession(Session session) { String username = session.get("username"); String role = session.get("role");
if (username == null || role == null) { return "No session data found. Please visit /setSession first."; }
return "Username: " + username + ", Role: " + role; }
/** * 清除session */ @RequestMapping("/clearSession") public String clearSession(Session session) { session.invalidate(); return "Session cleared"; }
public static void main(String[] args) { FeatCloud.cloudServer().listen(); }}分布式会话的工作原理如下图所示:
Session API
Section titled “Session API”RedisSession 提供了以下核心方法:
get(String key)
Section titled “get(String key)”获取会话中指定键的值。
String username = session.get("username");put(String key, String value)
Section titled “put(String key, String value)”将会话数据存储到 Redis 中。
session.put("username", "FeatUser");invalidate()
Section titled “invalidate()”使当前会话失效,删除 Redis 中的会话数据。
session.invalidate();getSessionId()
Section titled “getSessionId()”获取当前会话的唯一标识符。
String sessionId = session.getSessionId();setTimeout(int expiry)
Section titled “setTimeout(int expiry)”设置会话的最大存活时间(秒)。
session.setTimeout(3600); // 设置会话1小时后过期getTimeout()
Section titled “getTimeout()”获取会话的最大存活时间(秒)。
int maxAge = session.getTimeout();1. 合理设置会话超时时间
Section titled “1. 合理设置会话超时时间”根据应用的特点合理设置会话超时时间:
server: session: timeout: 1800 # 敏感应用可设置较短时间,如30分钟 # timeout: 86400 # 不敏感应用可设置较长时间,如24小时 store-type: redis2. 及时清理会话数据
Section titled “2. 及时清理会话数据”在用户登出或执行敏感操作后及时清理会话数据:
@RequestMapping("/logout")public String logout(Session session) { // 清理用户相关会话数据 session.invalidate(); return "Logged out successfully";}3. 避免在会话中存储大量数据
Section titled “3. 避免在会话中存储大量数据”会话数据存储在 Redis 中,应避免存储大量数据以节省内存和网络传输:
// 不推荐:存储大对象session.put("userProfile", userProfileJson);
// 推荐:只存储关键信息session.put("userId", userId);session.put("username", username);4. 处理会话异常
Section titled “4. 处理会话异常”在使用会话时要考虑异常情况:
@RequestMapping("/profile")public String profile(Session session) { try { String userId = session.get("userId"); if (userId == null) { return "Please login first"; } // 处理业务逻辑 return "User profile"; } catch (Exception e) { // 记录日志 logger.error("Session error", e); return "Session error occurred"; }}集群部署架构
Section titled “集群部署架构”在集群部署环境中,分布式会话的架构如下所示:
在这种架构中:
- 所有的应用实例都连接到同一个 Redis 实例或 Redis 集群
- 用户的会话数据存储在 Redis 中
- 无论用户的请求被负载均衡器分发到哪个应用实例,都可以访问到相同的会话数据
分布式会话是构建可扩展、高可用 Web 应用的基础组件。通过 Feat Cloud 内置的支持,您可以轻松地在应用中实现这一功能,为用户提供一致的使用体验。
有关完整示例,请参见 Redis Session 示例