@oriolrius/node-red-contrib-kafka
Version:
Node-RED Kafka nodes: Send, Receive, and Schema validation with modern KafkaJS
514 lines (388 loc) • 13.3 kB
Markdown
# Schema Guide for Kafka Schema Producer
This comprehensive guide covers using the Kafka Schema Producer node for Avro schema validation, including basic usage and advanced schema version management.
## Overview
The Kafka Schema Producer node provides:
- **Avro schema validation** using Confluent Schema Registry
- **Schema version management** for production stability and compatibility
- **Automatic schema registration** for development workflows
- **Version-aware caching** for optimal performance
- **Comprehensive error handling** and debugging support
## Basic Configuration
### Required Settings
1. **Kafka Broker**: Configure your existing hm-kafka-broker node
2. **Schema Registry**: Set up Schema Registry connection (usually running on port 8081)
3. **Topic**: The Kafka topic where messages will be published
4. **Schema Subject**: The subject name in Schema Registry (e.g., "my-topic-value")
5. **Schema Version**: The schema version to use (defaults to "latest")
### Default Schema
The node comes with a default schema that includes these fields:
```json
{
"type": "record",
"name": "Message",
"fields": [
{"name": "id", "type": "string"},
{"name": "message", "type": "string"},
{"name": "timestamp", "type": "long"}
]
}
```
### Message Format
Input messages should match the schema structure:
```json
{
"id": "unique-message-id",
"message": "Your message content",
"timestamp": 1640995200000
}
```
## Schema Version Management
The Schema Producer node supports both latest and specific schema versions, allowing you to:
- **Pin to specific versions** for production stability
- **Use latest version** for development and testing
- **Handle schema evolution** gracefully
- **Rollback to previous versions** when needed
### Version Configuration Options
The **Schema Version** field accepts:
- **"latest"** (default): Always uses the most recent schema version
- **Specific version numbers**: Use exact versions like "1", "2", "3", etc.
### Use Cases and Examples
#### Production Deployments
```json
{
"schemaVersion": "3",
"autoRegister": false
}
```
**Benefits:**
- Ensures all production instances use the same schema
- Prevents unexpected schema changes from breaking your application
- Allows controlled schema upgrades
#### Development and Testing
```json
{
"schemaVersion": "latest",
"autoRegister": true
}
```
**Benefits:**
- Automatically uses new schema versions as they're registered
- Simplifies development workflow
- Enables rapid prototyping
#### Rollback Scenarios
```json
{
"schemaVersion": "2"
}
```
**Benefits:**
- Quick recovery from problematic schema changes
- Temporary fix while investigating issues
- Gradual migration support
### Version Caching Behavior
The node implements intelligent version-aware caching:
#### Cache Logic
1. **Cache Key**: Combination of schema subject + version
2. **Cache Hit**: When requesting the same subject + version combination
3. **Cache Miss**: When version changes or cache is empty
4. **Automatic Refresh**: Cache invalidated when version changes
#### Example Cache Behavior
```text
Request: subject="test-topic-value", version="latest"
→ Cache miss, fetch schema ID 5, cache it
Request: subject="test-topic-value", version="latest"
→ Cache hit, use cached schema ID 5
Change config to version="3", deploy
→ Cache miss, fetch schema ID 3, cache it
Request: subject="test-topic-value", version="3"
→ Cache hit, use cached schema ID 3
```
## Development Workflow
### Typical Development Process
1. **Development Phase**
- Use `"schemaVersion": "latest"`
- Enable `autoRegister: true`
- Rapidly iterate on schema changes
2. **Testing Phase**
- Pin to specific version for consistent testing
- Use `"schemaVersion": "4"`
- Disable auto-registration
3. **Production Deployment**
- Use pinned version in production
- Monitor and validate before upgrading
- Coordinate schema version across all services
### Schema Evolution Example
```javascript
// Version 1: Initial schema
{
"type": "record",
"name": "UserEvent",
"fields": [
{"name": "userId", "type": "string"},
{"name": "action", "type": "string"}
]
}
// Version 2: Add optional field (backward compatible)
{
"type": "record",
"name": "UserEvent",
"fields": [
{"name": "userId", "type": "string"},
{"name": "action", "type": "string"},
{"name": "timestamp", "type": ["null", "long"], "default": null}
]
}
// Version 3: Add required field (forward compatible only)
{
"type": "record",
"name": "UserEvent",
"fields": [
{"name": "userId", "type": "string"},
{"name": "action", "type": "string"},
{"name": "timestamp", "type": "long"},
{"name": "sessionId", "type": "string"}
]
}
```
## Auto-Registration and Versioning
### Important Limitations
**Auto-registration only works with "latest" version**. You cannot auto-register to a specific historical version.
### Valid Auto-Registration
```json
{
"schemaVersion": "latest",
"autoRegister": true,
"autoSchema": "..."
}
```
### Invalid Auto-Registration
```json
{
"schemaVersion": "3", // ❌ Cannot auto-register to specific version
"autoRegister": true,
"autoSchema": "..."
}
```
## Node Configuration Examples
### Basic Configuration
```json
{
"id": "schema-producer-basic",
"type": "hm-kafka-schema-producer",
"name": "Basic Schema Producer",
"broker": "broker1",
"topic": "test-topic",
"registryUrl": "http://localhost:8081",
"schemaSubject": "test-topic-value",
"schemaVersion": "latest",
"autoRegister": true
}
```
### Production Configuration
```json
{
"id": "schema-producer-prod",
"type": "hm-kafka-schema-producer",
"name": "Producer (Schema v3)",
"broker": "broker1",
"topic": "test-topic",
"registryUrl": "http://localhost:8081",
"schemaSubject": "test-topic-value",
"schemaVersion": "3",
"autoRegister": false
}
```
## Error Handling
### Common Version-Related Errors
#### Invalid Version Format
```text
Error: Invalid schema version: "abc". Must be 'latest' or a positive integer.
```
**Solution**: Use "latest" or positive integers like "1", "2", "3"
#### Version Not Found
```text
Error: Schema not found for subject test-topic-value, version 7
```
**Solution**: Check available versions in Schema Registry or use a valid version
#### Auto-Register with Specific Version
```text
Error: Cannot auto-register schema for specific version 3. Auto-registration only works with 'latest' version.
```
**Solution**: Change version to "latest" or disable auto-registration
### Schema Validation Errors
The node provides detailed error information for:
- **Schema validation failures**: When message doesn't match schema
- **Registry connection issues**: When Schema Registry is unreachable
- **Authentication failures**: When registry credentials are invalid
- **Schema not found**: When subject doesn't exist and auto-register is disabled
Error output example:
```json
{
"error": "Schema validation failed: Field 'timestamp' is required but missing",
"originalMessage": {...}
}
```
## Example Flows
### Basic Example Flow
```json
[
{
"id": "inject1",
"type": "inject",
"name": "Test Message",
"props": [
{
"p": "payload",
"v": "{\"id\":\"msg-001\",\"message\":\"Hello Avro!\",\"timestamp\":1640995200000}",
"vt": "json"
}
],
"wires": [["schema-producer1"]]
},
{
"id": "schema-producer1",
"type": "hm-kafka-schema-producer",
"name": "Publish with Schema",
"broker": "broker1",
"topic": "test-topic",
"registryUrl": "http://localhost:8081",
"schemaSubject": "test-topic-value",
"autoRegister": true,
"autoSchema": "{\"type\":\"record\",\"name\":\"TestMessage\",\"fields\":[{\"name\":\"id\",\"type\":\"string\"},{\"name\":\"message\",\"type\":\"string\"},{\"name\":\"timestamp\",\"type\":\"long\"}]}",
"wires": [["debug1"]]
},
{
"id": "debug1",
"type": "debug",
"name": "Output",
"wires": []
}
]
```
## Advanced Usage Examples
### Schema Validation Only
Configure the node with `validateOnly: true` to test schema validation without publishing:
```json
{
"validateOnly": true
}
```
Output will include validation results:
```json
{
"validated": true,
"schemaId": 1,
"originalData": {...},
"encodedSize": 42
}
```
### Custom Schema with Complex Types
Example schema with optional fields and nested structures:
```json
{
"type": "record",
"name": "IoTSensorData",
"fields": [
{"name": "deviceId", "type": "string"},
{"name": "timestamp", "type": "long"},
{"name": "temperature", "type": "float"},
{"name": "humidity", "type": ["null", "float"], "default": null},
{
"name": "location",
"type": {
"type": "record",
"name": "Location",
"fields": [
{"name": "lat", "type": "double"},
{"name": "lon", "type": "double"}
]
}
}
]
}
```
### Schema Registry Authentication
For secured Schema Registry instances:
```json
{
"useRegistryAuth": true,
"registryUsername": "your-username",
"registryPassword": "your-password"
}
```
### Environment-Based Configuration
Use Node-RED context or environment variables for dynamic configuration:
```javascript
// In a function node before the schema producer
const environment = global.get("NODE_ENV") || "development";
if (environment === "production") {
msg.schemaVersion = "3"; // Pin to stable version
} else {
msg.schemaVersion = "latest"; // Use latest for dev
}
msg.registryUrl = global.get("SCHEMA_REGISTRY_URL");
msg.schemaSubject = global.get("SCHEMA_SUBJECT");
return msg;
```
## Best Practices
### Production Version Strategy
- **Pin versions in production**: Use specific version numbers
- **Test version compatibility**: Validate before upgrading
- **Coordinate upgrades**: Update all services together
- **Monitor compatibility**: Watch for schema evolution issues
### Development Version Strategy
- **Use "latest" for development**: Stay current with schema changes
- **Pin for integration tests**: Ensure consistent test results
- **Document version changes**: Track what changed between versions
### Schema Evolution Guidelines
- **Maintain backward compatibility**: Add optional fields with defaults
- **Plan forward compatibility**: Consider how consumers will handle new fields
- **Version your schemas semantically**: Major changes = new major version
- **Test compatibility thoroughly**: Validate producer/consumer combinations
### Performance Optimization
1. **Schema Caching**: The node caches schema IDs to avoid repeated registry calls
2. **Batch Processing**: Use with appropriate rate limiting for high-throughput scenarios
3. **Connection Pooling**: Reuse broker connections across multiple nodes
## Monitoring and Debugging
### Debug Information
Enable debug logging to see detailed operation information:
```text
[Kafka Schema Producer] Cache miss or version changed. Fetching schema for version: 3
[Kafka Schema Producer] Retrieved schema ID: 7 for subject: test-topic-value, version: 3
[Kafka Schema Producer] Using cached schema ID: 7 for version: 3
[Kafka Schema Producer] Message validated and encoded successfully
[Kafka Schema Producer] Message published successfully
```
### Status Messages
The node status shows which version is being used:
- `"Schema v3 retrieved"` - Successfully fetched specific version
- `"Schema latest retrieved"` - Successfully fetched latest version
- `"Using cached schema v3"` - Using cached version
## Troubleshooting
### Common Issues and Solutions
1. **"Schema not found"**: Ensure the subject exists in Schema Registry or enable auto-registration
2. **"Connection refused"**: Check Schema Registry URL and network connectivity
3. **"Validation failed"**: Verify message structure matches the registered schema
4. **"Authentication failed"**: Check registry credentials and permissions
5. **Performance issues**: Check if version caching is working correctly
6. **Compatibility issues**: Ensure all services use compatible versions
### Common Questions
**Q: Can I use version "0"?**
A: No, versions must be positive integers starting from 1.
**Q: What happens if I change from "3" to "latest"?**
A: The cache is invalidated and the latest schema is fetched on next message.
**Q: Can I use version ranges like ">=2"?**
A: No, only exact versions or "latest" are supported.
**Q: How do I see what versions are available?**
A: Check your Schema Registry web interface or use the REST API.
## Migration Guide
### From Version-Unaware Setup
If you're upgrading from a setup without version support:
1. **Current behavior**: Equivalent to `"schemaVersion": "latest"`
2. **No action needed**: Default behavior unchanged
3. **Optional**: Pin to specific versions for production stability
### Adding Version Control
1. **Identify current schema version** in Schema Registry
2. **Pin production nodes** to current version
3. **Test with specific versions** before upgrading
4. **Update gradually** across your infrastructure