- Introduced Redis configuration in appsettings.json to enable SignalR backplane functionality. - Updated Program.cs to conditionally configure SignalR with Redis if a connection string is provided. - Added Redis connection service registration in ApiBootstrap for distributed scenarios. - Included necessary package references for StackExchange.Redis and Microsoft.Extensions.Caching.StackExchangeRedis in project files. - Implemented password masking for Redis connection strings to enhance security.
6.6 KiB
Redis + SignalR Multi-Instance Deployment Guide
Summary
The Managing API now supports multiple instances with SignalR (for LlmHub, BotHub, BacktestHub) using a Redis backplane.
This solves the "No Connection with that ID" error that occurs when:
/llmhub/negotiatehits instance A- WebSocket connection hits instance B (which doesn't know about the connection ID)
What Was Added
1. Infrastructure Layer - Generic Redis Service
Files Created:
src/Managing.Application.Abstractions/Services/IRedisConnectionService.cs- Interfacesrc/Managing.Infrastructure.Storage/RedisConnectionService.cs- Implementationsrc/Managing.Infrastructure.Storage/README-REDIS.md- Documentation
Purpose: Generic Redis connectivity that can be used for SignalR, caching, or any Redis needs.
2. SignalR Redis Backplane
Files Modified:
src/Managing.Api/Program.cs- Auto-configures SignalR with Redis when availablesrc/Managing.Bootstrap/ApiBootstrap.cs- Registers Redis service
How It Works:
- Checks if Redis is configured
- If yes: Adds Redis backplane to SignalR
- If no: Runs in single-instance mode (graceful degradation)
3. Configuration
Files Modified:
src/Managing.Api/appsettings.json- Default config (empty, for local dev)src/Managing.Api/appsettings.Sandbox.json-srv-captain--redis:6379src/Managing.Api/appsettings.Production.json-srv-captain--redis:6379
4. NuGet Packages Added
Microsoft.AspNetCore.SignalR.StackExchangeRedis(8.0.10) - SignalR backplaneMicrosoft.Extensions.Caching.StackExchangeRedis(8.0.10) - Redis cachingStackExchange.Redis(2.8.16) - Redis client
Deployment Steps for CapRover
Step 1: Create Redis Service
- In CapRover, go to Apps
- Click One-Click Apps/Databases
- Search for "Redis"
- Deploy Redis (or use existing one)
- Note the service name:
srv-captain--redis(or your custom name)
Step 2: Configure CapRover App
For dev-managing-api (Sandbox):
-
Enable WebSocket Support
- Go to HTTP Settings
- Toggle "WebSocket Support" to ON
- Save
-
Enable Sticky Sessions
- In HTTP Settings
- Toggle "Enable Sticky Sessions" to ON
- Save
-
Verify Redis Connection String
- The connection string is already in
appsettings.Sandbox.json - Default:
srv-captain--redis:6379 - If you used a different Redis service name, update via environment variable:
ConnectionStrings__Redis=srv-captain--your-redis-name:6379 - Or use the fallback:
REDIS_URL=srv-captain--your-redis-name:6379
- The connection string is already in
Step 3: Deploy
-
Build and deploy the API:
cd src/Managing.Api # Your normal deployment process -
Watch the logs during startup. You should see:
✅ Configuring SignalR with Redis backplane: srv-captain--redis:6379 ✅ Redis connection established successfully
Step 4: Scale to Multiple Instances
- In CapRover, go to your
dev-managing-apiapp - App Configs tab
- Set "Number of app instances" to
2or3 - Click Save & Update
Step 5: Test
- Open the frontend (Kaigen Web UI)
- Open the AI Chat
- Send a message
- Should work without "No Connection with that ID" errors
Verification Checklist
After deployment, verify:
- Redis service is running in CapRover
- WebSocket support is enabled
- Sticky sessions are enabled
- API logs show Redis connection success
- Multiple instances are running
- AI Chat works without connection errors
- Browser Network tab shows WebSocket upgrade successful
Troubleshooting
Issue: "No Connection with that ID" Still Appears
Check:
- Redis service is running:
redis-cli -h srv-captain--redis ping - API logs show Redis connected (not "Redis not configured")
- Sticky sessions are ON
- WebSocket support is ON
Quick Test:
- Temporarily set instances to 1
- If it works with 1 instance, the issue is multi-instance setup
- If it fails with 1 instance, check WebSocket/proxy configuration
Issue: Redis Connection Failed
Check Logs For:
⚠️ Failed to configure SignalR Redis backplane: <error>
SignalR will work in single-instance mode only
Solutions:
- Verify Redis service name matches configuration
- Ensure Redis is not password-protected (or add password to config)
- Check Redis service health in CapRover
Issue: WebSocket Upgrade Failed
Not related to Redis. Check:
- CapRover WebSocket support is ON
- Nginx configuration allows upgrades
- Browser console for detailed error
Configuration Reference
Connection String Formats
Simple (no password):
srv-captain--redis:6379
With Password:
srv-captain--redis:6379,password=your-password
Multiple Options:
srv-captain--redis:6379,password=pwd,ssl=true,abortConnect=false
Configuration Priority
The app checks these in order:
ConnectionStrings:Redis(appsettings.json orConnectionStrings__Redisenvironment variable)REDIS_URL(fallback environment variable)
Recommended: Use ConnectionStrings__Redis environment variable to override appsettings without rebuilding.
Architecture Benefits
Before (Single Instance)
Frontend → Nginx → API Instance
- In-memory SignalR
- Connection IDs stored locally
❌ Scale limited to 1 instance
After (Multi-Instance with Redis)
Frontend → Nginx (sticky) → API Instance 1 ┐
→ API Instance 2 ├─→ Redis ← SignalR Backplane
→ API Instance 3 ┘
- Connection IDs in Redis
- Messages distributed via pub/sub
- Any instance can handle any connection
✅ Scale to N instances
Next Steps
After successful deployment:
-
Monitor Performance
- Watch Redis memory usage
- Check API response times
- Monitor WebSocket connection stability
-
Consider Redis Clustering
- For high availability
- If scaling beyond 3-4 API instances
-
Extend Redis Usage
- Distributed caching
- Rate limiting
- Session storage
Rollback Plan
If issues occur:
- Immediate: Set instances to 1
- Environment Variable: Set
REDIS_URL=(empty) to disable Redis - Code Rollback: Previous version still works (graceful degradation)
The implementation is backward-compatible and doesn't require Redis to function.
Support
For issues:
- Check logs:
src/Managing.Infrastructure.Storage/README-REDIS.md - Review this guide
- Check CapRover app logs for Redis/SignalR messages
- Test with 1 instance first, then scale up