A complete implementation of a service-to-service communication mechanism using Redis Pub/Sub for RPC-style request/response patterns. This solution is designed for multi-instance service environments with robust error handling and comprehensive JSON serialization.
- Redis Pub/Sub Communication: Uses Redis as the messaging backbone for inter-service communication
- RPC-Style Pattern: Supports both request/response and fire-and-forget notification patterns
- JSON Serialization: All messages are serialized using Newtonsoft.Json with consistent formatting
- Robust Error Handling: Comprehensive error handling with structured error responses (no automatic retries)
- Multi-Instance Support: Designed to work across multiple service instances
- Thread-Safe: All components are designed for concurrent usage
- Type-Safe: Generic methods for strongly-typed responses
- Extensive Documentation: Comprehensive inline documentation and examples
β
C# Implementation: Complete C# solution with .NET 9.0
β
JSON Serialization: Uses Newtonsoft.Json for all message payloads
β
Robust Error Handling: Structured error responses without automatic retries
β
Multi-Instance Support: Works with multiple service instances via Redis channels
β
Documentation: Extensive inline documentation and usage examples
- RpcClient - Sends RPC requests and handles responses
- RpcServer - Listens for requests and processes them using registered handlers
- BaseRpcMethodHandler - Base class for easy method handler implementation
- JsonSerializer - Consistent JSON serialization/deserialization
- RedisConnectionManager - Thread-safe Redis connection management
Client Redis Server
| | |
|-- RPC Request -------->| |
| |-- Request -----------> |
| | |-- Process
| |<-- Response -----------|
|<-- RPC Response -------| |
- .NET 9.0 or later
- Redis server (local or remote)
- Visual Studio 2022 or VS Code (optional)
-
Clone and Build
git clone <repository-url> cd redis-rpc-sample dotnet build
-
Start Redis (if not already running)
# Using Docker docker run -d -p 6379:6379 redis:alpine # Or install Redis locally and run redis-server
-
Run the Example
# Full demonstration (server + client) dotnet run --project RedisRpc.Example # Server only dotnet run --project RedisRpc.Example server # Client only (assumes server running elsewhere) dotnet run --project RedisRpc.Example client
using RedisRpc.Core;
using RedisRpc.Core.Implementation;
// Create server with default options
using var server = RpcFactory.CreateServer();
// Register method handlers
server.RegisterHandler(new CalculatorService());
server.RegisterHandler(new GreetingService());
// Start listening on channels
await server.StartListeningAsync(new[] { "calculator", "greeting" });
// Keep server running
Console.ReadKey();public class CalculatorService : BaseRpcMethodHandler
{
[RpcMethod("Add", Description = "Adds two numbers together")]
public int Add(int a, int b)
{
return a + b;
}
[RpcMethod("Divide", Description = "Divides two numbers")]
public double Divide(double a, double b)
{
if (Math.Abs(b) < double.Epsilon)
{
throw new InvalidParametersException("Division by zero is not allowed");
}
return a / b;
}
}using RedisRpc.Core;
// Create client
using var client = RpcFactory.CreateClient();
// Typed request/response
var result = await client.SendRequestAsync<int>("calculator", "Add",
new { a = 10, b = 5 });
// Untyped request/response
var response = await client.SendRequestAsync("greeting", "SayHello", "Alice");
// Fire-and-forget notification
await client.SendNotificationAsync("data", "LogActivity",
new { activity = "User login", userId = 123 });var options = new RedisRpcOptions
{
ConnectionString = "localhost:6379",
DefaultTimeoutMs = 15000,
MaxConcurrentRequests = 200,
ChannelPrefix = "myapp-rpc",
IncludeStackTraceInErrors = false, // Production setting
Database = 0
};
using var client = RpcFactory.CreateClient(options);
using var server = RpcFactory.CreateServer(options);| Option | Description | Default |
|---|---|---|
ConnectionString |
Redis connection string | "localhost:6379" |
DefaultTimeoutMs |
Default request timeout in milliseconds | 30000 |
MaxConcurrentRequests |
Maximum concurrent requests for server | 100 |
ChannelPrefix |
Prefix for all Redis channels | "redis-rpc" |
IncludeStackTraceInErrors |
Include stack traces in error responses | false |
Database |
Redis database index to use | 0 |
The solution includes three comprehensive example services:
- Mathematical operations (Add, Subtract, Multiply, Divide, Power, SquareRoot)
- Expression evaluation
- Batch operations
- Statistics tracking
- Multi-language greetings
- Personalized messages
- Time-based greetings
- Name formatting
- CRUD operations for users
- Data processing with various operations
- Activity logging
- Caching functionality
The system provides structured error handling with specific error codes:
public enum RpcErrorCode
{
Unknown = 0,
MethodNotFound = 1001,
InvalidParameters = 1002,
InternalError = 1003,
Timeout = 1004,
SerializationError = 1005,
ConnectionError = 1006
}Example error response:
{
"id": "req-123",
"success": false,
"error": {
"code": 1001,
"message": "Method 'NonExistentMethod' not found",
"details": {
"methodName": "NonExistentMethod"
}
},
"timestamp": "2024-01-01T12:00:00.000Z"
}- Consider Redis authentication and SSL/TLS
- Validate and sanitize all input parameters
- Use appropriate error detail levels for production
- Monitor Redis memory usage and performance
- Consider Redis clustering for high availability
- Implement circuit breakers for external dependencies
- Add structured logging (Serilog, NLog, etc.)
- Implement health checks
- Monitor message throughput and latency
// Production configuration example
var prodOptions = RpcFactory.CreateProductionOptions("your-redis-connection-string");
prodOptions.IncludeStackTraceInErrors = false;
prodOptions.DefaultTimeoutMs = 15000;The solution can be tested in several ways:
- Run full demo:
dotnet run --project RedisRpc.Example - Server only:
dotnet run --project RedisRpc.Example server - Client only:
dotnet run --project RedisRpc.Example client
- β Successful request/response cycles
- β Method not found errors
- β Invalid parameter handling
- β Division by zero and other business logic errors
- β Fire-and-forget notifications
- β Complex object serialization/deserialization
- β Multi-parameter method calls
- β Timeout handling (configurable)
redis-rpc-sample/
βββ RedisRpc.Core/ # Core library
β βββ Models/ # Request/Response/Error models
β βββ Interfaces/ # Service interfaces
β βββ Implementation/ # Core implementations
β βββ Infrastructure/ # Redis connection, serialization
β βββ Exceptions/ # Custom exceptions
β βββ RpcFactory.cs # Factory for easy setup
βββ RedisRpc.Example/ # Example application
β βββ Services/ # Example service implementations
β βββ Program.cs # Demonstration program
βββ README.md # This file
This is a sample implementation demonstrating Redis-based RPC patterns. Feel free to extend it with:
- Authentication and authorization
- Request/response middleware
- Circuit breaker patterns
- Metrics and monitoring
- Additional serialization formats
- Retry mechanisms (if needed)
This sample is provided as-is for educational and demonstration purposes.
Note: Make sure Redis is running before starting the application. The examples assume Redis is available at localhost:6379.