容器化C# Web API连接Redis缓存失败问题排查
问题描述
容器化部署的C# Web API无法连接Redis,报错信息如下:
"No connection is active/available to service this operation: EVAL; UnableToConnect on http://localhost:6379:6379/Interactive, Initializing/NotStarted, last: NONE, origin: BeginConnectAsync, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 60s, state: Connecting, mgr: 10 of 10 available, last-heartbeat: never, global: 0s ago, v: 2.2.4.27433, mc: 1/1/0, mgr: 10 of 10 available, clientName: d252797b3b96, IOCP: (Busy=0,Free=1000,Min=1,Max=1000), WORKER: (Busy=1,Free=32766,Min=8,Max=32767), v: 2.2.4.27433\n at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor
1 processor, ServerEndPoint server) in /_/src/StackExchange.Redis/ConnectionMultiplexer.cs:line 2798\n at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor1 processor, ServerEndPoint server) in //src/StackExchange.Redis/RedisBase.cs:line 54\n at StackExchange.Redis.RedisDatabase.ScriptEvaluate(String script, RedisKey[] keys, RedisValue[] values, CommandFlags flags) in //src/StackExchange.Redis/RedisDatabase.cs:line 1189\n at Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache.Set(String key, Byte[] value, DistributedCacheEntryOptions options)\n at Program.<>c.<$>b__0_1(String name, String val, IDistributedCache cache) in /src/Program.cs:line 25"
非容器环境下连接Redis正常,相关配置代码如下:
Program.cs
builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration["RedisConnection"]; });
docker-compose.yaml
version: "3.7" services: web-api: build: ./WebAPI image: webapi container_name: api ports: - "3000:80" environment: - RedisConnection=http://localhost:6379 depends_on: - cache cache: image: redis container_name: redis_cache ports: - "6379:6379"
问题根源
容器内的localhost指向容器自身,而非宿主机或Redis容器。当前配置中Web API容器尝试连接自身的6379端口,自然无法访问到独立的Redis容器。此外,StackExchange.Redis的连接字符串不需要http://前缀,该前缀会导致连接解析错误。
修复步骤
修正Redis连接字符串
修改docker-compose.yaml中Web API的环境变量,将RedisConnection的值改为Redis服务的名称cache(Docker Compose会自动为服务创建内部DNS解析),同时去掉无效的http://前缀:environment: - RedisConnection=cache:6379添加Redis健康检查(可选)
depends_on仅保证Redis容器先启动,但不确保Redis服务完全就绪。添加健康检查可让Web API等待Redis服务可用后再启动:cache: image: redis container_name: redis_cache ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 web-api: build: ./WebAPI image: webapi container_name: api ports: - "3000:80" environment: - RedisConnection=cache:6379 depends_on: cache: condition: service_healthy重启容器服务
执行以下命令重新部署容器:docker-compose down && docker-compose up -d
内容的提问来源于stack exchange,提问作者Pedro

