micro--go-micro
96280678ee
* feat: expose framework primitives via API gateway and MCP
Add registry, store, and broker as both HTTP routes and MCP tools
so AI agents and HTTP clients can inspect and operate the framework.
API gateway (/micro/* namespace):
GET /micro/registry List registered services
GET /micro/registry/{name} Describe a service
GET /micro/store List store keys
GET /micro/store/{key} Read a record
POST /micro/store/{key} Write a record
POST /micro/broker/{topic} Publish a message
MCP gateway (micro_* tool prefix):
micro_registry_list List services
micro_registry_get Describe a service
micro_store_list List keys
micro_store_read Read a record
micro_store_write Write a record
micro_broker_publish Publish a message
Framework tools use a Handler field on the MCP Tool struct for
direct dispatch (no RPC). Service tools continue to use RPC.
Rate limiters and circuit breakers are applied to framework
tools the same as service tools.
* fix: make framework internals opt-in on API and MCP gateways
Framework primitives (registry, broker, store) are now only
exposed when explicitly enabled:
API gateway: micro api --internal
MCP gateway: Options{Internal: true}
Off by default — user services are always exposed, framework
internals require the flag. Banner output only shows framework
routes when enabled.
* fix: always expose framework internals, gate by auth in production
Revert the --internal flag approach. Framework primitives (registry,
broker, store) are now always exposed:
- micro api: /micro/* routes always available (dev tool)
- MCP gateway: micro_* tools always registered. When Auth is
configured (production), they require micro:admin scope.
Without Auth (dev), they're open — same as all other tools.
This follows the existing pattern: micro run/api = dev (open),
micro server = production (auth + scopes). Framework internals
follow the same security model as user services.
Remove the Internal option from MCP Options. Remove --internal
flag from micro api.
Note: scope persistence depends on the store backend. The default
in-memory store does not survive restarts. Use MICRO_STORE=file
for persistent scopes in production.
* fix: correct DefaultStore comment — it's file-backed, not memory
* fix(server): don't recreate deleted admin user on restart
When the default admin account is deleted via the dashboard, set
a marker key (auth/.admin-deleted) in the store. On startup, skip
admin creation if the marker exists. This prevents the default
admin/micro credentials from reappearing after restart when the
user has intentionally removed them.
* fix: improve agent playground first-run UX and fix doc 404s
Agent playground:
- Add setup hint in empty state explaining how to get started
(click Settings, enter API key, type a prompt)
- Hide hint automatically when API key is already configured
- Add all 7 providers to dropdown (was only OpenAI + Anthropic)
- Include CLI fallback suggestion (micro chat)
Docs:
- Fix .md links to .html across all doc pages — Jekyll serves
.html files, not .md. Fixes 404s including the micro run guide.
---------
Co-authored-by: Claude <noreply@anthropic.com>
229 行
6.7 KiB
Markdown
229 行
6.7 KiB
Markdown
# Performance Considerations
|
|
|
|
## Overview
|
|
|
|
go-micro is designed for **developer productivity and ease of use** while maintaining good performance for most use cases. This document explains the performance characteristics and trade-offs.
|
|
|
|
## Reflection Usage
|
|
|
|
go-micro uses Go's reflection package to enable its core feature: **registering any Go struct as a service handler** without code generation or boilerplate.
|
|
|
|
### Why Reflection?
|
|
|
|
```go
|
|
// Simple handler registration - no proto files, no code generation
|
|
type GreeterService struct{}
|
|
|
|
func (g *GreeterService) SayHello(ctx context.Context, req *Request, rsp *Response) error {
|
|
rsp.Message = "Hello " + req.Name
|
|
return nil
|
|
}
|
|
|
|
server.Handle(server.NewHandler(&GreeterService{}))
|
|
```
|
|
|
|
This simplicity is **only possible with reflection**. Alternative approaches (like gRPC or psrpc) require:
|
|
|
|
1. Writing `.proto` files
|
|
2. Running code generators
|
|
3. Implementing generated interfaces
|
|
4. Managing generated code in version control
|
|
|
|
### Performance Impact
|
|
|
|
Reflection adds approximately **40-60 microseconds (0.04-0.06ms)** overhead per RPC call for:
|
|
|
|
- Method discovery and validation (~5μs)
|
|
- Dynamic method invocation (~30-40μs)
|
|
- Request/response type construction (~10-15μs)
|
|
|
|
This totals ~50μs on average, though the exact overhead depends on the complexity of the handler signature and request/response types.
|
|
|
|
**Context**: In typical RPC scenarios:
|
|
|
|
| Component | Typical Time |
|
|
|-----------|--------------|
|
|
| Network I/O | 1-10ms |
|
|
| Protobuf serialization | 0.1-0.5ms |
|
|
| Business logic | Variable (often 1-100ms+) |
|
|
| **Reflection + framework overhead** | **~0.06ms (0.6-6% of total)** |
|
|
|
|
### When Reflection Matters
|
|
|
|
Reflection overhead is **only significant** when ALL of these conditions are true:
|
|
|
|
1. ✅ Request rate >100,000 RPS
|
|
2. ✅ Business logic <100μs
|
|
3. ✅ Local/loopback communication
|
|
4. ✅ Sub-millisecond latency requirements
|
|
|
|
**For 99% of applications**, database queries, external services, and business logic dominate performance. Reflection is negligible.
|
|
|
|
## Performance Best Practices
|
|
|
|
### 1. Profile Before Optimizing
|
|
|
|
Always measure before assuming reflection is your bottleneck:
|
|
|
|
```bash
|
|
# Enable pprof in your service
|
|
import _ "net/http/pprof"
|
|
|
|
# Profile CPU usage
|
|
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
|
|
```
|
|
|
|
If reflection shows up as <5% of CPU time, optimizing elsewhere will have more impact.
|
|
|
|
### 2. Optimize Business Logic First
|
|
|
|
Common optimization opportunities (typically 10-100x more impact than removing reflection):
|
|
|
|
- **Database queries**: Use connection pooling, indexes, query optimization
|
|
- **External API calls**: Use caching, batching, async processing
|
|
- **Serialization**: Use efficient protobuf instead of JSON
|
|
- **Concurrency**: Use goroutines and channels effectively
|
|
|
|
### 3. Use Appropriate Transports
|
|
|
|
go-micro supports multiple transports:
|
|
|
|
- **HTTP**: Good for debugging, ~1-2ms overhead
|
|
- **gRPC**: Binary protocol, ~0.2-0.5ms overhead
|
|
- **In-memory**: Development/testing, <0.1ms overhead
|
|
|
|
Choose based on your deployment:
|
|
|
|
```go
|
|
import "go-micro.dev/v5/server/grpc"
|
|
|
|
// Use gRPC for better performance
|
|
service := micro.NewService(
|
|
micro.Server(grpc.NewServer()),
|
|
)
|
|
```
|
|
|
|
### 4. Enable Connection Pooling
|
|
|
|
Reuse connections to avoid handshake overhead:
|
|
|
|
```go
|
|
// Client-side connection pooling (enabled by default)
|
|
client := service.Client()
|
|
```
|
|
|
|
### 5. Use Appropriate Codecs
|
|
|
|
go-micro supports multiple codecs:
|
|
|
|
```go
|
|
// Protobuf (fastest, binary)
|
|
import "go-micro.dev/v5/codec/proto"
|
|
|
|
// JSON (human-readable, slower)
|
|
import "go-micro.dev/v5/codec/json"
|
|
|
|
// MessagePack (compact, fast)
|
|
import "go-micro.dev/v5/codec/msgpack"
|
|
```
|
|
|
|
Protobuf is 2-5x faster than JSON for most payloads.
|
|
|
|
## When to Consider Alternatives
|
|
|
|
If you've profiled and determined reflection is genuinely a bottleneck (rare), consider:
|
|
|
|
### gRPC
|
|
|
|
**Pros**:
|
|
- No reflection overhead (uses code generation)
|
|
- Industry standard
|
|
- Excellent tooling
|
|
|
|
**Cons**:
|
|
- Requires `.proto` files
|
|
- More boilerplate
|
|
- Less flexible
|
|
|
|
**Use when**: You need absolute maximum performance and can invest in proto definitions.
|
|
|
|
### psrpc (livekit)
|
|
|
|
**Pros**:
|
|
- No reflection
|
|
- Built on pub/sub
|
|
- Good for distributed systems
|
|
|
|
**Cons**:
|
|
- Requires proto files
|
|
- Smaller ecosystem
|
|
- Different architecture
|
|
|
|
**Use when**: You're building LiveKit-style distributed systems and need pub/sub primitives.
|
|
|
|
### go-micro (Current)
|
|
|
|
**Pros**:
|
|
- Zero boilerplate
|
|
- Pure Go
|
|
- Rapid development
|
|
- Flexible
|
|
|
|
**Cons**:
|
|
- ~50μs reflection overhead per call
|
|
- Not suitable for <100μs latency requirements
|
|
|
|
**Use when**: Developer productivity and code simplicity matter more than squeezing every microsecond.
|
|
|
|
## Benchmarks
|
|
|
|
Synthetic benchmarks (single request/response, no business logic):
|
|
|
|
| Framework | Latency (p50) | Throughput | Notes |
|
|
|-----------|---------------|------------|-------|
|
|
| Direct function call | ~1μs | 1M+ RPS | No serialization, no networking |
|
|
| go-micro (reflection) | ~60μs | ~16k RPS | ~50μs reflection + ~10μs framework |
|
|
| gRPC (generated code) | ~40μs | ~25k RPS | ~10μs codegen + ~30μs framework |
|
|
|
|
**Real-world** (with database, business logic):
|
|
|
|
| Scenario | go-micro | gRPC | Difference |
|
|
|----------|----------|------|------------|
|
|
| REST API + DB | 15ms | 14.95ms | 0.3% |
|
|
| Microservice call | 5ms | 4.95ms | 1% |
|
|
| Batch processing | 100ms | 100ms | 0% |
|
|
|
|
Reflection overhead is **lost in the noise** for realistic workloads.
|
|
|
|
## Future Optimizations
|
|
|
|
Possible future improvements (without removing reflection):
|
|
|
|
1. **Method cache warming**: Pre-compute reflection metadata at startup
|
|
2. **Call argument pooling**: Reuse `reflect.Value` slices
|
|
3. **JIT optimization**: Generate specialized handlers for hot paths
|
|
|
|
These could reduce reflection overhead by 50-70% while maintaining the simple API.
|
|
|
|
## Summary
|
|
|
|
- **Reflection is a deliberate design choice** that enables go-micro's simplicity
|
|
- **Overhead is negligible** (<5%) for typical microservices
|
|
- **Optimize business logic first** - usually 10-100x more impact
|
|
- **Profile before optimizing** - measure, don't guess
|
|
- **Consider alternatives** only if profiling proves reflection is a bottleneck
|
|
|
|
For most applications, go-micro's productivity benefits far outweigh the minimal reflection overhead.
|
|
|
|
## Related Documents
|
|
|
|
- [Reflection Removal Analysis](reflection-removal-analysis.html) - Detailed technical analysis
|
|
- [Architecture](architecture.html) - go-micro design principles
|
|
- [Comparison with gRPC](grpc-comparison.md) - When to use each
|
|
|
|
## References
|
|
|
|
- [Go Reflection Laws](https://go.dev/blog/laws-of-reflection) - Official Go blog
|
|
- [Effective Go](https://go.dev/doc/effective_go) - Go best practices
|
|
- [gRPC Performance Best Practices](https://grpc.io/docs/guides/performance/)
|