Redis报错:The client is closed,登录后缓存Token失败求助
问题排查:Redis客户端关闭错误(Error: The client is closed)
问题背景
在NestJS应用中实现用户登录后将JWT Token存入Redis缓存,但调用登录接口时控制台报错Error: The client is closed,执行DEBUG=* npm run start:dev启动应用也未看到Redis相关日志。相关代码如下:
缓存配置服务(cache.config.service.ts)
@Injectable() export class CacheConfigService { constructor(private configService: ConfigService) {} get url(): string { console.log(this.configService.get<string>('redis.url')); return this.configService.get<string>('redis.url') as string; } }
缓存模块(cacheModule.ts)
@Module({ imports: [ CacheModule.register<RedisClientOptions>({ // @ts-ignore store: createRedisStore, socket: { host: 'localhost', port: 6379, }, isGlobal: true, // url: 'redis://' + process.env.REDIS_HOST + ':' + process.env.REDIS_PORT, }), ], })
用户登录方法
emailPasswordSignInPOST: async (input: any) => { if ( originalImplementation.emailPasswordSignInPOST === undefined ) { throw Error('Should never come here'); } let response: any = await originalImplementation.emailPasswordSignInPOST(input); const formFields: any = input.formFields; const inputObject: any = {}; for (let index = 0; index < formFields.length; index++) { const element = formFields[index]; inputObject[element.id] = element.value; } const { email } = inputObject; const user = await this.userService.findOneByEmail(email); const id = user?.id; const payload = { email, id }; const secret = 'mysecret'; const token = jwt.sign(payload, secret, { expiresIn: '2h', }); response.token = token; const cacheKey = 'Token'; await this.redisClient.set(cacheKey, token, { EX: 60 * 60 * 24, }); return response; },
排查步骤与解决方案
1. 修正Redis客户端注入方式
The client is closed报错核心原因是代码中使用的redisClient未通过NestJS依赖注入正确获取实例,或未完成连接:
- 改用NestJS官方推荐的
CACHE_MANAGER注入:import { CACHE_MANAGER, Inject } from '@nestjs/common'; import { Cache } from 'cache-manager'; // 在类构造函数中注入缓存管理器 constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {} // 存储Token时替换原有redisClient调用 await this.cacheManager.set(cacheKey, token, 60 * 60 * 24); // 第三个参数为过期时间(秒)
2. 修复CacheModule配置兼容性问题
当前配置的Redis Store存在类型与版本适配问题:
- 移除
@ts-ignore,使用官方适配的Redis存储包(如cache-manager-redis-yet),调整配置为异步注册模式:import { CacheModule } from '@nestjs/cache-manager'; import { redisStore } from 'cache-manager-redis-yet'; import type { RedisClientOptions } from 'redis'; @Module({ imports: [ CacheModule.registerAsync<RedisClientOptions>({ isGlobal: true, useFactory: async () => ({ store: await redisStore({ socket: { host: 'localhost', port: 6379, }, }), }), }), ], }) - 配置中添加日志输出,便于排查连接问题:
store: await redisStore({ socket: { host: 'localhost', port: 6379, }, logger: 'debug', })
3. 验证Redis服务可用性
- 执行
redis-cli ping命令,返回PONG则表示Redis服务正常运行,否则启动本地Redis服务; - 检查6379端口是否被占用,确保应用能正常访问
localhost:6379。
4. 调试连接过程
在CacheModule的useFactory中添加错误捕获,直接输出连接失败原因:
useFactory: async () => { try { const store = await redisStore({ socket: { host: 'localhost', port: 6379, }, }); console.log('Redis连接成功'); return { store }; } catch (err) { console.error('Redis连接失败详情:', err); throw err; } },
内容的提问来源于stack exchange,提问作者John Oliver
相关产品推荐
相关产品推荐

