439 lines
10 KiB
Markdown
439 lines
10 KiB
Markdown
# Choosing HTTP vs gRPC
|
|
|
|
Understand when to use HTTP, gRPC, or both protocols for your application.
|
|
|
|
## Quick Decision Guide
|
|
|
|
| Scenario | Recommendation |
|
|
|----------|---------------|
|
|
| Public API | ✅ HTTP |
|
|
| Web browser clients | ✅ HTTP |
|
|
| Mobile apps (REST) | ✅ HTTP |
|
|
| Microservices (internal) | ✅ gRPC |
|
|
| High-performance APIs | ✅ gRPC |
|
|
| Low-latency requirements | ✅ gRPC |
|
|
| Need both internal & public | ✅ Both (Dual Protocol) |
|
|
| Existing REST clients | ✅ HTTP |
|
|
| .NET-to-.NET communication | ✅ gRPC |
|
|
|
|
## HTTP (Minimal API)
|
|
|
|
### What It Is
|
|
|
|
HTTP integration uses ASP.NET Core Minimal API to expose commands and queries as REST endpoints.
|
|
|
|
### When to Use
|
|
|
|
✅ **Best for:**
|
|
- Public APIs
|
|
- Web browser clients (JavaScript, React, Vue, etc.)
|
|
- Mobile apps expecting REST
|
|
- Third-party integrations
|
|
- Developer-friendly exploration (Swagger)
|
|
- Simple authentication (API keys, JWT)
|
|
|
|
### Pros
|
|
|
|
- ✅ **Universal compatibility** - Works everywhere (browsers, curl, Postman)
|
|
- ✅ **Human-readable** - JSON payloads are easy to debug
|
|
- ✅ **Swagger/OpenAPI** - Automatic API documentation
|
|
- ✅ **Caching** - HTTP caching headers work out of the box
|
|
- ✅ **Familiar** - Developers know REST
|
|
- ✅ **Tooling** - Excellent debugging and testing tools
|
|
|
|
### Cons
|
|
|
|
- ❌ **Lower performance** - Text-based JSON vs binary Protocol Buffers
|
|
- ❌ **Larger payloads** - JSON is verbose compared to binary
|
|
- ❌ **No streaming** - Single request-response (without SSE/WebSockets)
|
|
- ❌ **Manual client code** - No automatic client generation
|
|
|
|
### Example Setup
|
|
|
|
```csharp
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Register CQRS
|
|
builder.Services.AddSvrntyCQRS();
|
|
builder.Services.AddDefaultCommandDiscovery();
|
|
builder.Services.AddDefaultQueryDiscovery();
|
|
|
|
// Register handlers
|
|
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
|
|
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
|
|
|
|
// Add Swagger (optional)
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Map HTTP endpoints
|
|
app.UseSvrntyCqrs();
|
|
|
|
// Enable Swagger
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
|
|
app.Run();
|
|
```
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Commands (POST only)
|
|
curl -X POST http://localhost:5000/api/command/createUser \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"name":"Alice","email":"alice@example.com"}'
|
|
|
|
# Queries (GET or POST)
|
|
curl "http://localhost:5000/api/query/getUser?userId=1"
|
|
|
|
curl -X POST http://localhost:5000/api/query/getUser \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"userId":1}'
|
|
```
|
|
|
|
## gRPC
|
|
|
|
### What It Is
|
|
|
|
gRPC integration uses Protocol Buffers and HTTP/2 for high-performance, strongly-typed communication.
|
|
|
|
### When to Use
|
|
|
|
✅ **Best for:**
|
|
- Microservices (service-to-service)
|
|
- Internal APIs
|
|
- High-performance requirements
|
|
- Low-latency communication
|
|
- Strongly-typed contracts
|
|
- .NET-to-.NET or polyglot services
|
|
|
|
### Pros
|
|
|
|
- ✅ **High performance** - Binary protocol, HTTP/2 multiplexing
|
|
- ✅ **Compact payloads** - Protocol Buffers are smaller than JSON
|
|
- ✅ **Strong typing** - Compile-time type safety
|
|
- ✅ **Code generation** - Automatic client generation
|
|
- ✅ **Streaming** - Bidirectional streaming support
|
|
- ✅ **Rich error model** - Structured error details
|
|
|
|
### Cons
|
|
|
|
- ❌ **Browser support limited** - Requires gRPC-Web proxy
|
|
- ❌ **Learning curve** - .proto files, Protocol Buffers
|
|
- ❌ **Less human-readable** - Binary format
|
|
- ❌ **Tooling** - Fewer debugging tools than REST
|
|
- ❌ **Firewall issues** - HTTP/2 may be blocked
|
|
|
|
### Example Setup
|
|
|
|
```csharp
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Register CQRS
|
|
builder.Services.AddSvrntyCQRS();
|
|
builder.Services.AddDefaultCommandDiscovery();
|
|
builder.Services.AddDefaultQueryDiscovery();
|
|
|
|
// Register handlers
|
|
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
|
|
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
|
|
|
|
// Add gRPC
|
|
builder.Services.AddGrpc();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Map gRPC services (auto-generated by source generators)
|
|
app.MapGrpcService<CommandServiceImpl>();
|
|
app.MapGrpcService<QueryServiceImpl>();
|
|
|
|
// Enable gRPC reflection (for tools like grpcurl)
|
|
app.MapGrpcReflectionService();
|
|
|
|
app.Run();
|
|
```
|
|
|
|
### Proto File
|
|
|
|
Create `Protos/cqrs_services.proto`:
|
|
|
|
```protobuf
|
|
syntax = "proto3";
|
|
|
|
option csharp_namespace = "MyApp.Grpc";
|
|
|
|
service CommandService {
|
|
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
|
|
}
|
|
|
|
service QueryService {
|
|
rpc GetUser (GetUserRequest) returns (GetUserResponse);
|
|
}
|
|
|
|
message CreateUserRequest {
|
|
string name = 1;
|
|
string email = 2;
|
|
}
|
|
|
|
message CreateUserResponse {
|
|
int32 result = 1;
|
|
}
|
|
|
|
message GetUserRequest {
|
|
int32 user_id = 1;
|
|
}
|
|
|
|
message GetUserResponse {
|
|
int32 id = 1;
|
|
string name = 2;
|
|
string email = 3;
|
|
}
|
|
```
|
|
|
|
**Note:** Svrnty.CQRS source generators automatically implement these services for you!
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Using grpcurl
|
|
grpcurl -plaintext \
|
|
-d '{"name":"Alice","email":"alice@example.com"}' \
|
|
localhost:5000 \
|
|
CommandService/CreateUser
|
|
|
|
grpcurl -plaintext \
|
|
-d '{"userId":1}' \
|
|
localhost:5000 \
|
|
QueryService/GetUser
|
|
```
|
|
|
|
## Dual Protocol (Both HTTP & gRPC)
|
|
|
|
### What It Is
|
|
|
|
Run both HTTP and gRPC endpoints simultaneously, allowing clients to choose their preferred protocol.
|
|
|
|
### When to Use
|
|
|
|
✅ **Best for:**
|
|
- Hybrid scenarios (public + internal APIs)
|
|
- Gradual migration from REST to gRPC
|
|
- Supporting multiple client types
|
|
- Maximum flexibility
|
|
|
|
### Example Setup
|
|
|
|
```csharp
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Register CQRS
|
|
builder.Services.AddSvrntyCQRS();
|
|
builder.Services.AddDefaultCommandDiscovery();
|
|
builder.Services.AddDefaultQueryDiscovery();
|
|
|
|
// Register handlers
|
|
builder.Services.AddCommand<CreateUserCommand, int, CreateUserCommandHandler>();
|
|
builder.Services.AddQuery<GetUserQuery, UserDto, GetUserQueryHandler>();
|
|
|
|
// Add HTTP support
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen();
|
|
|
|
// Add gRPC support
|
|
builder.Services.AddGrpc();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Map HTTP endpoints
|
|
app.UseSvrntyCqrs();
|
|
|
|
// Map gRPC services
|
|
app.MapGrpcService<CommandServiceImpl>();
|
|
app.MapGrpcService<QueryServiceImpl>();
|
|
app.MapGrpcReflectionService();
|
|
|
|
// Enable Swagger
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
|
|
app.Run();
|
|
```
|
|
|
|
### Benefits
|
|
|
|
- ✅ **Flexibility** - Clients choose protocol
|
|
- ✅ **Same codebase** - One implementation, two protocols
|
|
- ✅ **Gradual migration** - Transition clients over time
|
|
- ✅ **Best of both** - Public REST + internal gRPC
|
|
|
|
### Trade-offs
|
|
|
|
- ❌ **Slightly more complexity** - More configuration
|
|
- ❌ **Two sets of clients** - Maintain both if not auto-generated
|
|
- ❌ **Larger dependencies** - Both HTTP and gRPC packages
|
|
|
|
## Performance Comparison
|
|
|
|
### Latency
|
|
|
|
**gRPC:** ~50% lower latency than HTTP/JSON
|
|
|
|
```
|
|
gRPC: 1-2 ms
|
|
HTTP/JSON: 2-4 ms
|
|
```
|
|
|
|
*Results vary based on payload size and network conditions*
|
|
|
|
### Throughput
|
|
|
|
**gRPC:** ~2-3x higher throughput
|
|
|
|
```
|
|
gRPC: 50,000+ requests/sec
|
|
HTTP/JSON: 15,000-20,000 requests/sec
|
|
```
|
|
|
|
*On same hardware*
|
|
|
|
### Payload Size
|
|
|
|
**gRPC:** ~30-50% smaller payloads
|
|
|
|
```
|
|
Protocol Buffers: 100 bytes
|
|
JSON: 200-300 bytes
|
|
```
|
|
|
|
*For typical messages*
|
|
|
|
## Feature Comparison
|
|
|
|
| Feature | HTTP (Minimal API) | gRPC |
|
|
|---------|-------------------|------|
|
|
| **Performance** | Good | Excellent |
|
|
| **Browser support** | ✅ Yes | ❌ No (requires gRPC-Web) |
|
|
| **Caching** | ✅ Native HTTP caching | ❌ Not built-in |
|
|
| **Streaming** | ❌ No (without WebSockets) | ✅ Yes (bidirectional) |
|
|
| **Code generation** | ❌ No | ✅ Yes |
|
|
| **Human-readable** | ✅ JSON | ❌ Binary |
|
|
| **Tooling** | ✅ Excellent (Swagger, Postman) | ⚠️ Limited (grpcurl, Postman) |
|
|
| **Learning curve** | ✅ Low | ⚠️ Medium |
|
|
| **Type safety** | ⚠️ Runtime | ✅ Compile-time |
|
|
|
|
## Decision Matrix
|
|
|
|
### Choose HTTP If:
|
|
|
|
- ✅ You need browser/JavaScript clients
|
|
- ✅ Public API for third parties
|
|
- ✅ You want Swagger documentation
|
|
- ✅ Team is familiar with REST
|
|
- ✅ Caching is important
|
|
- ✅ Human readability matters
|
|
|
|
### Choose gRPC If:
|
|
|
|
- ✅ Microservices architecture
|
|
- ✅ Internal APIs only
|
|
- ✅ Performance is critical
|
|
- ✅ You need streaming
|
|
- ✅ Strong typing is important
|
|
- ✅ Polyglot environment (.NET, Go, Java, Python)
|
|
|
|
### Choose Both If:
|
|
|
|
- ✅ You have both public and internal clients
|
|
- ✅ You want flexibility
|
|
- ✅ You're migrating from REST to gRPC
|
|
- ✅ Different teams have different needs
|
|
|
|
## Migration Path
|
|
|
|
### Start with HTTP
|
|
|
|
1. Build with HTTP (easy to test, debug)
|
|
2. Add gRPC later if needed
|
|
3. Same handlers work for both
|
|
|
|
### Start with gRPC
|
|
|
|
1. Build with gRPC (for performance)
|
|
2. Add HTTP later for public API
|
|
3. Same handlers work for both
|
|
|
|
## Real-World Examples
|
|
|
|
### E-Commerce Platform
|
|
|
|
```csharp
|
|
// Public-facing API → HTTP
|
|
// Mobile app → HTTP
|
|
// Internal order processing → gRPC
|
|
// Payment service → gRPC
|
|
// Inventory service → gRPC
|
|
```
|
|
|
|
**Recommendation:** Dual protocol
|
|
|
|
### Internal Microservices
|
|
|
|
```csharp
|
|
// All service-to-service → gRPC
|
|
// Admin dashboard → HTTP (optional)
|
|
```
|
|
|
|
**Recommendation:** gRPC only
|
|
|
|
### SaaS Product
|
|
|
|
```csharp
|
|
// Customer API → HTTP
|
|
// JavaScript SDK → HTTP
|
|
// Webhooks → HTTP
|
|
```
|
|
|
|
**Recommendation:** HTTP only
|
|
|
|
## Next Steps
|
|
|
|
Congratulations! You've completed the Getting Started guide. You now know:
|
|
|
|
- ✅ What CQRS is and when to use it
|
|
- ✅ How to install Svrnty.CQRS
|
|
- ✅ How to create commands and queries
|
|
- ✅ How to add validation
|
|
- ✅ When to use HTTP vs gRPC
|
|
|
|
### Continue Learning
|
|
|
|
- **[Architecture](../architecture/README.md)** - Understand the framework design
|
|
- **[Core Features](../core-features/README.md)** - Deep dive into commands, queries, and dynamic queries
|
|
- **[HTTP Integration](../http-integration/README.md)** - Master HTTP endpoints
|
|
- **[gRPC Integration](../grpc-integration/README.md)** - Master gRPC services
|
|
- **[Event Streaming](../event-streaming/README.md)** - Build event-sourced applications
|
|
- **[Tutorials](../tutorials/README.md)** - Learn through comprehensive examples
|
|
|
|
### Try the Sample Project
|
|
|
|
Check out the complete sample application:
|
|
|
|
```bash
|
|
cd Svrnty.Sample
|
|
dotnet run
|
|
```
|
|
|
|
Visit:
|
|
- HTTP: `http://localhost:5000/swagger`
|
|
- gRPC: Use grpcurl or a gRPC client
|
|
|
|
## See Also
|
|
|
|
- [HTTP Integration Overview](../http-integration/README.md) - Complete HTTP guide
|
|
- [gRPC Integration Overview](../grpc-integration/README.md) - Complete gRPC guide
|
|
- [Endpoint Mapping](../http-integration/endpoint-mapping.md) - How HTTP endpoints work
|
|
- [Proto File Setup](../grpc-integration/proto-file-setup.md) - How .proto files work
|