Skip to content

Commit a869c9a

Browse files
committed
feat(moonzero): run a real unary zRPC call over moonrpc's h2c transport, and add a service registry, request metrics, and trace-id propagation.
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
1 parent f243732 commit a869c9a

12 files changed

Lines changed: 1203 additions & 8 deletions

README.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ let server = @moonzero.Server::new(conf, app)
6363
- **`maxbytes`** — rejects a request whose declared `Content-Length` exceeds the limit with `413`.
6464
- **`structured_logging`** — a [`RequestLog`](./logging.mbt) rendered as one JSON line per request (method, path, status, duration, request-id, client-ip, user-agent).
6565

66-
## Auth, YAML config, and zRPC groups
66+
## Auth, YAML config, and zRPC over the h2c transport
6767

6868
```moonbit
6969
// JWT HS256 — self-built SHA-256/HMAC (verified against NIST/RFC vectors)
@@ -73,24 +73,48 @@ let token = @moonzero.jwt_sign(
7373
)
7474
let server = @moonzero.Server::new(conf, app)
7575
.use_(@moonzero.auth("topsecret", clock)) // 401 unless a valid Bearer JWT
76+
.use_(@moonzero.tracing()) // W3C traceparent in/out
77+
.use_(@moonzero.metrics(m, clock)) // request counter + latency histogram
7678
7779
// YAML config — the etc/*.yaml format go-zero ships, same lenient defaults as JSON
7880
let conf = @moonzero.ServiceConf::from_yaml("name: greet\nport: 9000\nlog_level: error\n")
7981
80-
// zRPC service groups over moonrpc — register Method handlers, dispatch by gRPC path
82+
// A real unary zRPC call over moonrpc's h2c transport
8183
let rpc = @moonzero.RpcServer::new(@moonzero.RpcServerConf::new(name="greeter", port=9090))
8284
rpc.group("hello.Greeter").register("SayHello", req => handle(req))
83-
rpc.dispatch("/hello.Greeter/SayHello", request) // Ok(bytes) | Err(Unimplemented)
85+
let ch = @moonzero.RpcChannel::connect(rpc)
86+
ch.call("/hello.Greeter/SayHello", request) // Ok(reply) | Err(status)
8487
```
8588

8689
- **`jwt_sign` / `jwt_verify`** — compact HS256 tokens on a [self-built SHA-256 + HMAC-SHA256](./crypto.mbt), signatures compared in constant time, `exp`/`nbf` enforced, and the `alg:none` downgrade refused. Interop-verified against the canonical jwt.io token.
8790
- **`auth`** — the [middleware](./auth.mbt) that requires `Authorization: Bearer <jwt>` and answers `401` for an absent, malformed, tampered, or expired token.
8891
- **`ServiceConf::from_yaml`** — a [minimal-subset YAML parser](./yaml.mbt) (block maps, nesting, sequences, typed scalars, comments) feeding the same field reader as the JSON loader, so both formats agree field-for-field.
89-
- **`RpcServer` / `RpcGroup`**[config-driven zRPC groups](./rpc.mbt) that register [`moonrpc`](https://github.com/Lfan-ke/moonrpc) `Method` handlers by gRPC path and dispatch unary calls, returning `Unimplemented` for an unknown method.
92+
- **`RpcServer` / `RpcGroup`**[config-driven zRPC groups](./rpc.mbt) that register [`moonrpc`](https://github.com/Lfan-ke/moonrpc) `Method` handlers by gRPC path.
93+
- **`RpcChannel`** — a [client over the h2c transport](./zrpc.mbt): `to_h2` turns the registered handlers into a `moonrpc` `H2Server`, and a `call` runs a real unary exchange through it — HPACK-coded HEADERS, a length-prefixed DATA frame, and the `grpc-status` trailer read back off the reply. A call to an unregistered path comes back `UNIMPLEMENTED`, the trailers-only response a gRPC server sends for an unknown method.
94+
95+
## Discovery, metrics, tracing
96+
97+
```moonbit
98+
// Service registry (etcd-shaped): register instances, resolve, balance
99+
let reg = @moonzero.InMemoryRegistry::new()
100+
reg.register("greeter", @moonzero.Endpoint::new("10.0.0.1", 9090))
101+
reg.register("greeter", @moonzero.Endpoint::new("10.0.0.2", 9090))
102+
let lb = @moonzero.RoundRobin::new()
103+
@moonzero.resolve_one(reg, "greeter", lb) // Some(10.0.0.1:9090), then .2, cycling
104+
105+
// Metrics read out for a /metrics scrape after serving
106+
let m = @moonzero.ServerMetrics::new()
107+
m.requests().value("GET /ping 200") // request count for that label
108+
m.latency().mean() // mean request latency, ms
109+
```
110+
111+
- **`InMemoryRegistry`** — a [service registry](./registry.mbt) shaped like go-zero's etcd `discov` store: a `service -> instance -> endpoint` map with a monotonic store revision a watcher can compare against. `RoundRobin` and `pick_first` balancers select an endpoint from a resolved set; an etcd- or consul-backed store with the same `resolve` shape drops in unchanged.
112+
- **`ServerMetrics`** — a [`CounterVec`](./metrics.mbt) of per-method/route/status request tallies and a cumulative latency `Histogram` (Prometheus `le` buckets, sum, count), driven by the `metrics` middleware that times each request on the clock.
113+
- **`tracing`**[trace-id propagation](./tracing.mbt): continue an inbound W3C `traceparent` or start a new trace, mint a child span, and stamp `traceparent` + `x-trace-id` onto the response.
90114

91115
## Roadmap (transliterating go-zero)
92116

93-
Typed config (JSON + YAML loading with defaults, timeout + log level) + service assembly + the base middleware onion (logging, recovery, CORS, request-id) + the resilience set (timeout, rate-limit, breaker, maxbytes, structured logging) + route groups + JWT auth + zRPC service groups are here. Next, feature-by-feature: metrics/tracing/prometheus middleware, the real h2 transport under `moonrpc` for live RPC, and service discovery / registry (etcd/consul) — plus `moonctl`-driven scaffolding of a full `moonzero` service from a spec.
117+
Typed config (JSON + YAML with defaults, timeout + log level) + service assembly + the base middleware onion (logging, recovery, CORS, request-id) + the resilience set (timeout, rate-limit, breaker, maxbytes, structured logging) + route groups + JWT auth + zRPC groups with a real h2c round-trip + a service registry with balancers + request metrics + trace-id propagation are here. Next: server/client streaming once `moonrpc` lands it, an etcd/consul-backed registry, and `moonctl`-driven scaffolding of a full `moonzero` service from a spec.
94118

95119
## License
96120

0 commit comments

Comments
 (0)