From 8a457d95bbb4b910a71b62cdf14cf7911d0dd429 Mon Sep 17 00:00:00 2001 From: Oxidaner <18622412361@163.com> Date: Wed, 20 May 2026 23:53:19 +0800 Subject: [PATCH 1/5] docs: add dubbo-go agent skills Signed-off-by: Oxidaner <18622412361@163.com> --- .agents/skills/dubbo-go-cluster/SKILL.md | 64 +++++++ .../references/routing-cluster-flow.md | 42 +++++ .agents/skills/dubbo-go-config/SKILL.md | 63 +++++++ .../dubbo-go-config/references/config-flow.md | 44 +++++ .agents/skills/dubbo-go-domain/SKILL.md | 164 ++++++++++++++++++ .../references/architecture-map.md | 46 +++++ .../references/project-rules.md | 37 ++++ .agents/skills/dubbo-go-metadata/SKILL.md | 63 +++++++ .../references/metadata-flow.md | 39 +++++ .../dubbo-go-observability-filters/SKILL.md | 64 +++++++ .../references/filter-observability-flow.md | 34 ++++ .agents/skills/dubbo-go-protocol/SKILL.md | 64 +++++++ .../references/protocol-flow.md | 42 +++++ .agents/skills/dubbo-go-registry/SKILL.md | 64 +++++++ .../references/registry-discovery-flow.md | 41 +++++ .agents/skills/dubbo-go-runtime/SKILL.md | 64 +++++++ .../references/client-server-lifecycle.md | 46 +++++ .agents/skills/dubbo-go-tools/SKILL.md | 62 +++++++ .../dubbo-go-tools/references/tooling-flow.md | 29 ++++ 19 files changed, 1072 insertions(+) create mode 100644 .agents/skills/dubbo-go-cluster/SKILL.md create mode 100644 .agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md create mode 100644 .agents/skills/dubbo-go-config/SKILL.md create mode 100644 .agents/skills/dubbo-go-config/references/config-flow.md create mode 100644 .agents/skills/dubbo-go-domain/SKILL.md create mode 100644 .agents/skills/dubbo-go-domain/references/architecture-map.md create mode 100644 .agents/skills/dubbo-go-domain/references/project-rules.md create mode 100644 .agents/skills/dubbo-go-metadata/SKILL.md create mode 100644 .agents/skills/dubbo-go-metadata/references/metadata-flow.md create mode 100644 .agents/skills/dubbo-go-observability-filters/SKILL.md create mode 100644 .agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md create mode 100644 .agents/skills/dubbo-go-protocol/SKILL.md create mode 100644 .agents/skills/dubbo-go-protocol/references/protocol-flow.md create mode 100644 .agents/skills/dubbo-go-registry/SKILL.md create mode 100644 .agents/skills/dubbo-go-registry/references/registry-discovery-flow.md create mode 100644 .agents/skills/dubbo-go-runtime/SKILL.md create mode 100644 .agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md create mode 100644 .agents/skills/dubbo-go-tools/SKILL.md create mode 100644 .agents/skills/dubbo-go-tools/references/tooling-flow.md diff --git a/.agents/skills/dubbo-go-cluster/SKILL.md b/.agents/skills/dubbo-go-cluster/SKILL.md new file mode 100644 index 0000000000..9e4754d9f1 --- /dev/null +++ b/.agents/skills/dubbo-go-cluster/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dubbo-go-cluster +description: >- + Implements and reviews dubbo-go cluster, routing, directory, and load-balancing changes. Use when the user asks about + failover, failfast, failsafe, failback, forking, broadcast, available, zoneaware, adaptive service, Directory, + RouterChain, condition, tag, script, affinity or Polaris routers, load balance algorithms, retries, provider + selection, or packages cluster/cluster/, cluster/directory/, cluster/router/, and cluster/loadbalance/. Do not use + for registry backend mechanics unless the directory snapshot contract is affected. +--- + +# dubbo-go Cluster + +## Purpose + +Use this skill to change or explain how provider invokers are listed, routed, load-balanced, retried, and invoked by cluster fault-tolerance strategies. + +## When to use + +Use for cluster invokers, directory snapshots, router chain behavior, dynamic routing rules, tag or condition matching, load balancing, retries, and adaptive service behavior. + +Do not use for registry backend code unless registry notifications affect directory snapshots. + +## Inputs + +Required: +- Cluster strategy, router, load balancer, directory, or invocation selection behavior. +- Intended routing/selection behavior or observed mismatch. + +Optional: +- Consumer URL, provider URLs, invocation attachments, method name, route rule, or registry event sequence. + +If missing, start at `cluster/router/chain/chain.go` for routing or `cluster/cluster/` for fault tolerance. + +## Workflow + +1. Classify the behavior as directory update, router filtering, load balance selection, or cluster fault tolerance. +2. Read `cluster/directory/` for provider invoker snapshots and registry notification handling. +3. Read `cluster/router/chain/chain.go` and the relevant router package for filtering behavior. +4. Read `cluster/loadbalance/` for provider selection. +5. Read the relevant `cluster/cluster/*/cluster_invoker.go` for retry and error behavior. +6. Check extension registration under `common/extension/cluster.go`, `loadbalance.go`, and `router_factory.go`. +7. Read `references/routing-cluster-flow.md` before changing selection semantics. + +## Output format + +Return directory source, router chain result, load balance or cluster strategy, changed files, and validation performed. + +## Validation + +- Confirm router priority and stable ordering still produce deterministic results. +- Confirm directory snapshots are copied safely and not mutated by callers. +- Confirm retry count and business-error handling match the strategy. +- Run focused tests such as `go test ./cluster/...`; use `make test` for broad invocation behavior. + +## Edge cases + +- RouterChain first narrows invokers by service key and falls back to all invokers if no service-key match exists. +- Static router config is injected after builtin routers are created. +- Failover retries non-business errors but returns business errors directly. +- Method-level URL params can override interface-level routing, retries, and load balance settings. + +## References + +- Read `references/routing-cluster-flow.md` for directory, router, load balance, and cluster invocation details. diff --git a/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md b/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md new file mode 100644 index 0000000000..46b4f5e7fd --- /dev/null +++ b/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md @@ -0,0 +1,42 @@ +# Routing and Cluster Flow + +## Invocation Path + +1. A proxy or protocol caller invokes a cluster invoker. +2. The cluster invoker asks its directory for invokers matching the invocation. +3. Directory output is routed through `RouterChain`. +4. The cluster strategy chooses or retries invokers using a load balancer. +5. The selected protocol invoker performs the remote call. + +## Directory + +- Static directory holds fixed invokers. +- Registry directory reacts to registry notifications and rebuilds invoker snapshots. +- Directory output should be treated as a snapshot for one invocation path. + +## Router Chain + +- `RouterChain.Route` copies invokers, filters by service key when possible, then applies routers in priority order. +- Router factories are registered through `extension.SetRouterFactory`. +- Static router configs are injected through routers implementing `StaticConfigSetter`. +- Dynamic routers may update internal state on `Notify`. + +## Load Balance + +- Load balance implementations live under `cluster/loadbalance/`. +- Selection receives candidate invokers and the invocation. +- Method-level URL params can affect algorithm choice. + +## Cluster Strategies + +- `failover`: retry non-business errors and reselect providers. +- `failfast`: fail immediately. +- `failsafe`: swallow failures according to strategy. +- `failback`: retry in background. +- `forking`, `broadcast`, `available`, `zoneaware`, and `adaptivesvc` have specialized selection behavior. + +## Contract Checks + +- Keep router output deterministic for the same snapshot and invocation. +- Avoid mutating shared invoker slices from callers. +- Preserve distinction between business errors and transport or provider errors. diff --git a/.agents/skills/dubbo-go-config/SKILL.md b/.agents/skills/dubbo-go-config/SKILL.md new file mode 100644 index 0000000000..75db3e4603 --- /dev/null +++ b/.agents/skills/dubbo-go-config/SKILL.md @@ -0,0 +1,63 @@ +--- +name: dubbo-go-config +description: >- + Implements and reviews dubbo-go configuration changes. Use when the user asks about dubbo.Load, config.Load, + RootConfig, InstanceOptions, global config structs, YAML or JSON loading, koanf parsing, config center integration, + dynamic configuration, hot reload, config post processors, or packages loader.go, config/, global/, config_center/, + and common/config/. Do not use for runtime export/refer behavior unless configuration injection is the contract. +--- + +# dubbo-go Config + +## Purpose + +Use this skill to change or explain how dubbo-go loads, initializes, validates, hot-reloads, and exposes configuration to runtime client and server code. + +## When to use + +Use for configuration files, builder APIs, `RootConfig`, `InstanceOptions`, global config models, config center factories, hot reload allowlists, and config post-processing. + +Do not use for protocol transport, registry events, or runtime export/refer behavior unless configuration injection is the contract being changed. + +## Inputs + +Required: +- Config key, config struct, loader API, or package path. +- Intended behavior or observed parse/init bug. + +Optional: +- YAML or JSON snippet. +- Config center protocol and data ID or group. +- Related client, server, reference, or service option. + +If missing, inspect `loader.go`, `config/config_loader.go`, and the relevant `global/*_config.go` or `config/*_config.go`. + +## Workflow + +1. Identify whether the task targets top-level `dubbo.Load` and `InstanceOptions` or legacy `config.Load` and `RootConfig`. +2. Read the owning config model under `global/` and compatibility or builder code under `config/`. +3. Trace initialization into `InstanceOptions.init`, `RootConfig.Init`, service/reference init, or config center startup. +4. For dynamic config, inspect `config/config_center_config.go`, `config_center/`, and `common/extension/config_center_factory.go`. +5. For hot reload, inspect `loader.go` and keep `safeChanged` semantics narrow. +6. Read `references/config-flow.md` before changing loader behavior or public config keys. + +## Output format + +Return changed config keys or structs, loader path, runtime injection impact, validation performed, and any compatibility notes. + +## Validation + +- Confirm new config fields are represented in the right `global/` or `config/` model and initialized before runtime use. +- Confirm config center changes register the correct extension factory. +- Confirm hot reload accepts only intended mutable keys. +- Run focused tests such as `go test ./config ./global ./config_center/...`; use `make test` for broad config behavior. + +## Edge cases + +- `dubbo.Load` starts provider and consumer runtime; `config.Load` only initializes `RootConfig`. +- Some config values are transported as URL params, while TLS, application, registry, shutdown, and Triple details often travel as URL attributes. +- Existing compatibility tests may depend on legacy field names. + +## References + +- Read `references/config-flow.md` for loader, config center, and runtime injection details. diff --git a/.agents/skills/dubbo-go-config/references/config-flow.md b/.agents/skills/dubbo-go-config/references/config-flow.md new file mode 100644 index 0000000000..6f9a509240 --- /dev/null +++ b/.agents/skills/dubbo-go-config/references/config-flow.md @@ -0,0 +1,44 @@ +# Config Flow + +## Entry Points + +- `loader.go`: top-level `dubbo.Load`, file watch, hot reload, and `InstanceOptions`. +- `config/config_loader.go`: package-level `config.Load`, `RootConfig` storage, and legacy config accessors. +- `dubbo.go`: maps `InstanceOptions` into `client.ClientOption` and `server.ServerOption`. +- `global/`: config models used by public client/server options. +- `config/`: builders, compatibility models, config center startup, and legacy `RootConfig` initialization. + +## Loader Flow + +Top-level `dubbo.Load`: +1. Build `loaderConf`. +2. Resolve config with koanf from file, raw bytes, or direct options. +3. Unmarshal into `InstanceOptions`. +4. Run `InstanceOptions.init`. +5. Create an `Instance` and start consumer/provider loading. +6. Start the file watcher once and register shutdown cleanup. + +Package `config.Load`: +1. Build `LoaderConf`. +2. Resolve into `RootConfig` when one is not provided. +3. Run `RootConfig.Init`. +4. Store the initialized root config through the atomic pointer. + +## Config Center + +- Config center setup is coordinated by `config/config_center_config.go`. +- Implementations live under `config_center/{apollo,file,nacos,zookeeper}`. +- Factories register through `common/extension/config_center_factory.go`. +- Parser behavior is under `config_center/parser/`. + +## Runtime Injection + +- `Instance.NewClient` clones consumer, application, registry, shutdown, metrics, otel, TLS, protocol, and router config into `client` options. +- `Instance.NewServer` clones application, registry, protocol, shutdown, metrics, otel, and TLS config into `server` options. +- Reference and service options ultimately build `common.URL` values. Use params for transportable Dubbo URL values and attributes for in-process objects. + +## Hot Reload + +- File watching is in `loader.go`. +- `hotUpdateConfig` compares old and new koanf trees with `safeChanged`. +- Keep hot reload allowlists conservative because changing immutable runtime fields after export or refer can leave stale protocols, registries, or metadata. diff --git a/.agents/skills/dubbo-go-domain/SKILL.md b/.agents/skills/dubbo-go-domain/SKILL.md new file mode 100644 index 0000000000..5eeef6a80b --- /dev/null +++ b/.agents/skills/dubbo-go-domain/SKILL.md @@ -0,0 +1,164 @@ +--- +name: dubbo-go-domain +description: >- + Use this skill when working on the dubbo-go codebase, including implementing features, fixing bugs, writing tests, + reviewing code, updating documentation, or routing work to a narrower dubbo-go-* domain skill. Use for cross-module + questions, end-to-end flows, subsystem boundaries, or deciding whether config, runtime, protocol, registry, metadata, + cluster routing, filters and observability, or tools guidance applies. +--- + +# dubbo-go Project Guide + +## Project Overview + +dubbo-go is the Go implementation of Apache Dubbo. It is an RPC and microservice framework that provides service export and reference, registry and service discovery, protocol interoperability, cluster fault tolerance, traffic governance, configuration, metadata, metrics, tracing, and developer tools. + +It mainly provides: +- Public client and server APIs for Go services. +- Dubbo, Dubbo3, Triple, gRPC, REST, JSONRPC, and related transport support. +- Registry integration with Nacos, Zookeeper, Etcd, Polaris, and application-level service discovery. +- Metadata collection, metadata reporting, service name mapping, routing, load balancing, filters, metrics, tracing, and CLI or code generation tools. + +This repository does not own external registry servers, Dubbo Java implementation, sample applications outside this repository, or production deployment infrastructure. + +## Tech Stack + +- Language: Go, module `dubbo.apache.org/dubbo-go/v3`. +- Go version: `go 1.25.0` in `go.mod`; root `Makefile` uses `GOTOOLCHAIN=go1.25.0+auto` for tests. +- Build: Go modules plus nested Go modules under selected `tools/` directories. +- Test: `go test`, `testify`, `gomock`, and focused package tests. +- Lint and format: `go fmt`, `imports-formatter`, `go vet`, `golangci-lint`, and `make fmt` or `make lint`. + +Do not introduce a new framework or dependency unless the task requires it and the compatibility impact is clear. + +## Repository Structure + +- `dubbo.go`, `loader.go`: public instance and top-level load/start APIs. +- `config/`, `global/`, `config_center/`, `common/config/`: config models, loading, config center, and compatibility behavior. +- `client/`, `server/`, `proxy/`, `graceful_shutdown/`: runtime client/server construction, refer/export, proxy, and shutdown behavior. +- `protocol/`, `remoting/`, `common/url.go`: protocol interfaces, codecs, transports, URL contract, invokers, and exporters. +- `registry/`, `metadata/`: registry discovery, service discovery, metadata, reports, mapping, and revisions. +- `cluster/`: directories, routers, load balancing, and cluster fault tolerance. +- `filter/`, `metrics/`, `otel/`, `logger/`: filters, observability, tracing, metrics, and logging. +- `tools/`: CLI, schema generator, protoc plugins, import formatter, and RPC contract scanner. +- `docs/`, `doc/`: project documentation and images. + +## Workflow + +When modifying code: + +1. Classify the owning subsystem and load the narrower `dubbo-go-*` skill when relevant. +2. Read the existing implementation and tests before editing. +3. Make the smallest correct change that follows current package boundaries. +4. Prefer existing abstractions, extension registries, URL params, and URL attributes over new patterns. +5. Add or update focused tests for behavior changes. +6. Run the most relevant validation command. +7. Summarize changed files, behavior, compatibility impact, and validation result. + +When fixing bugs: + +1. Reproduce the issue or identify the failing path from tests, logs, or code. +2. Find the smallest root cause. +3. Make a minimal safe change. +4. Add a regression test when feasible. +5. Explain why the fix works and what risk remains. + +When reviewing code: + +1. Check behavior, compatibility, concurrency, error handling, generated file handling, and missing tests first. +2. Ground findings in file and line references. +3. Keep summary secondary to concrete risks. + +## Coding Guidelines + +- Keep changes focused and reviewable. +- Follow existing package structure, naming, and extension registration patterns. +- Preserve backward compatibility for public APIs, config keys, URL params, wire behavior, and generated output unless explicitly requested. +- Use structured config, URL, and parser APIs instead of ad hoc string handling when available. +- Avoid broad refactors during bug fixes. +- Do not change unrelated files. + +## Testing and Validation + +Use the most relevant command: + +```bash +go test ./... +make test +make fmt +make lint +make rpc-contract-check +``` + +For focused work, prefer package-level tests first, for example: + +```bash +go test ./config ./global ./config_center/... +go test ./client ./server ./proxy ./graceful_shutdown +go test ./protocol/... ./remoting/... +go test ./registry/... ./metadata/... +go test ./cluster/... +go test ./filter/... ./metrics/... ./otel/... +``` + +For nested tools, run tests from the owning module directory. + +If validation cannot be run or fails, report the command, the error, and whether it appears related to the current change. + +## Do Not + +- Do not rewrite large parts of the project without explicit instruction. +- Do not introduce new dependencies or frameworks unless necessary. +- Do not change public APIs, config keys, wire contracts, or generated output without documenting compatibility impact. +- Do not remove or weaken tests to make validation pass. +- Do not commit secrets, tokens, passwords, private keys, or private config. +- Do not modify generated files manually unless the generation source is also updated or the repository already treats that file as hand-maintained. +- Do not ignore existing uncommitted user changes. + +## Common Tasks + +### Choose a Domain Skill + +1. Map the request to the primary package. +2. Use `references/architecture-map.md` when ownership is unclear. +3. Load one narrower skill when possible. +4. If multiple domains are involved, follow runtime flow: config, runtime, protocol, registry or metadata, cluster, filters, observability, tools. + +### Add a Feature + +1. Find the owning module and existing tests. +2. Add the core behavior using existing abstractions. +3. Add or update tests. +4. Update documentation when public behavior changes. +5. Run focused validation. + +### Add a Configuration Option + +1. Define the config key in the owning config model. +2. Add default and initialization behavior. +3. Wire it into the consuming module through existing options or URL params/attributes. +4. Add tests for default and custom behavior. +5. Update docs or schemas when relevant. + +### Fix a Bug + +1. Identify the root cause. +2. Make the minimal fix. +3. Add a regression test when possible. +4. Verify with the narrowest relevant command. + +## Output Format + +Return the selected skill or subsystem, changed files, behavior change, compatibility impact, validation performed, and any residual risk. + +## Edge cases + +- `dubbo.Load` and `config.Load` both load configuration, but they serve different public APIs. +- Registry discovery and metadata reporting are tightly coupled; use `dubbo-go-metadata` when revisions or metadata reports control behavior. +- Filters wrap protocols through `protocol/protocolwrapper`; use `dubbo-go-protocol` when transport semantics change and `dubbo-go-observability-filters` when interception semantics change. +- Some `tools/` subdirectories are independent Go modules. + +## References + +- Read `references/architecture-map.md` for subsystem ownership and end-to-end flow. +- Read `references/project-rules.md` for compatibility, generated-file, validation, and PR guidance. diff --git a/.agents/skills/dubbo-go-domain/references/architecture-map.md b/.agents/skills/dubbo-go-domain/references/architecture-map.md new file mode 100644 index 0000000000..36761e996c --- /dev/null +++ b/.agents/skills/dubbo-go-domain/references/architecture-map.md @@ -0,0 +1,46 @@ +# dubbo-go Architecture Map + +## Subsystem Ownership + +| Area | Primary paths | Owns | Related skill | +| --- | --- | --- | --- | +| Configuration | `loader.go`, `config/`, `global/`, `config_center/`, `common/config/` | YAML or option loading, `RootConfig`, `InstanceOptions`, config center, hot reload | `dubbo-go-config` | +| Runtime API | `dubbo.go`, `client/`, `server/`, `proxy/`, `graceful_shutdown/` | Public client/server construction, service registration, reference creation, export/refer lifecycle | `dubbo-go-runtime` | +| Protocols | `protocol/`, `remoting/`, `protocol/protocolwrapper/`, `common/url.go` | `Protocol`, `Invoker`, `Exporter`, codecs, transport clients and servers, URL semantics | `dubbo-go-protocol` | +| Registry discovery | `registry/`, `registry/servicediscovery/`, `registry/directory/`, `remoting/{nacos,zookeeper,etcdv3,polaris}/` | Registry factories, register/unregister, subscribe/unsubscribe, service instance notifications | `dubbo-go-registry` | +| Metadata | `metadata/`, `metadata/info/`, `metadata/report/`, `metadata/mapping/` | MetadataInfo, metadata service export, metadata reports, service name mapping, revisions | `dubbo-go-metadata` | +| Cluster and routing | `cluster/cluster/`, `cluster/directory/`, `cluster/router/`, `cluster/loadbalance/` | Fault tolerance, directory listing, route chain, load balancing, retries | `dubbo-go-cluster` | +| Filters and observability | `filter/`, `metrics/`, `otel/`, `logger/`, `protocol/protocolwrapper/` | Filter chain, metrics, tracing, logging, TPS and auth interception | `dubbo-go-observability-filters` | +| Tools and codegen | `tools/`, `Makefile` | CLI, schema generation, protoc plugins, import formatting, RPC contract scanner | `dubbo-go-tools` | + +## Common End-to-End Flows + +Provider startup: +1. Config is loaded into `InstanceOptions` or `RootConfig`. +2. `Instance.NewServer` or `server.NewServer` builds server options. +3. `ServiceOptions.Export` registers service metadata in `common.ServiceMap`, builds an export URL, wraps the protocol with filters, exports the service, and registers provider URLs or service instances. +4. Metadata is collected and may be published through a metadata report. + +Consumer startup: +1. Config is loaded into client and reference options. +2. `ReferenceOptions.Refer` builds an interface-level URL, loads direct or registry URLs, creates registry or protocol invokers, and builds the service proxy. +3. Registry notifications update directory invokers. +4. Cluster, router chain, load balancer, filters, and protocol invoker handle each invocation. + +Protocol invocation: +1. Runtime code builds a `common.URL` with transport params and non-transport attributes. +2. `extension.GetProtocol` resolves the registered protocol. +3. `protocolwrapper.FILTER` wraps provider or consumer invokers with configured filters. +4. The concrete protocol handles codec, remoting, request mapping, response mapping, and destroy semantics. + +Registry and metadata: +1. Provider export adds service URLs to metadata and registers URLs or application-level service instances. +2. Consumers subscribe through registry directories or service discovery registries. +3. Service name mapping and metadata reports connect interface names, application names, and metadata revisions. + +## Boundary Rules + +- Public API behavior belongs to runtime even when the root cause is config. +- Transport behavior belongs to protocol even when filters observe it. +- Service instance registration belongs to registry; metadata revision calculation and report storage belong to metadata. +- Routing decisions belong to cluster; rule source or dynamic config loading belongs to config or registry depending on the producer. diff --git a/.agents/skills/dubbo-go-domain/references/project-rules.md b/.agents/skills/dubbo-go-domain/references/project-rules.md new file mode 100644 index 0000000000..97c2aa2259 --- /dev/null +++ b/.agents/skills/dubbo-go-domain/references/project-rules.md @@ -0,0 +1,37 @@ +# dubbo-go Project Rules + +## Compatibility + +- Treat public Go APIs, config keys, URL params, URL attributes, protocol wire behavior, generated code shape, and registry or metadata semantics as compatibility surfaces. +- Document behavior and compatibility impact when changing any compatibility surface. +- Preserve Dubbo Java, Triple, and gRPC interoperability when touching protocol or generated-code paths. + +## Generated Files + +- Do not modify generated files manually unless the generation source is also updated or the file is intentionally hand-maintained in this repository. +- For proto-related output, inspect the owning tool under `tools/protoc-gen-go-triple` or `tools/protoc-gen-triple-openapi`. +- Keep generated output deterministic: stable ordering, imports, names, and comments. + +## Validation Selection + +- Start with the narrowest package tests that cover the change. +- Use `make test` for cross-cutting runtime behavior. +- Use `make fmt` after Go code changes that affect formatting or imports. +- Use `make lint` for changes that touch shared APIs, concurrency, generated code, or error handling. +- Use `make rpc-contract-check` when changing exported RPC service interfaces. + +## Nested Modules + +Run tests from the nested module directory when a tool has its own `go.mod`: + +- `tools/dubbogo-cli` +- `tools/imports-formatter` +- `tools/protoc-gen-go-triple` +- `tools/protoc-gen-triple-openapi` + +## PR Guidance + +- Keep PRs small and reviewable. +- Include tests or explain why tests are not feasible. +- Include compatibility notes for public behavior changes. +- Do not include unrelated formatting churn. diff --git a/.agents/skills/dubbo-go-metadata/SKILL.md b/.agents/skills/dubbo-go-metadata/SKILL.md new file mode 100644 index 0000000000..49a6271376 --- /dev/null +++ b/.agents/skills/dubbo-go-metadata/SKILL.md @@ -0,0 +1,63 @@ +--- +name: dubbo-go-metadata +description: >- + Implements and reviews dubbo-go metadata changes. Use when the user asks about MetadataInfo, metadata service V1 or + V2, metadata reports, app metadata publishing or fetching, service name mapping, metadata revision, subscribed or + exported service URLs, remote metadata storage, or packages metadata/, metadata/info/, metadata/report/, and + metadata/mapping/. Do not use for registry subscription mechanics unless metadata controls the behavior. +--- + +# dubbo-go Metadata + +## Purpose + +Use this skill to change or explain how dubbo-go collects exported and subscribed URLs, calculates and publishes metadata, exposes metadata services, and maps service names to applications. + +## When to use + +Use for `MetadataInfo`, metadata service export, metadata reports, metadata mapping, revisions, remote metadata storage, and application-level service discovery metadata interactions. + +Do not use for concrete registry notification mechanics unless metadata controls the contract. + +## Inputs + +Required: +- Metadata type, registry ID, metadata report backend, service name mapping, revision, or metadata service behavior. +- Intended metadata behavior or observed mismatch. + +Optional: +- Provider URL, consumer URL, service instance metadata, app name, revision string, or metadata report payload. + +If missing, start at `metadata/metadata.go` and follow into `metadata/info/`, `metadata/report/`, or `metadata/mapping/`. + +## Workflow + +1. Read `metadata/metadata.go` for global metadata storage and add/get helpers. +2. Inspect `metadata/info/` for `MetadataInfo` structure, URL addition, and revision-related behavior. +3. For metadata service behavior, read `metadata/metadata_service.go` and generated files under `metadata/triple_api/`. +4. For reports, inspect `metadata/report/report.go`, the backend package, and extension registration. +5. For service name mapping, inspect `metadata/mapping/` and the registry service discovery caller. +6. Verify how registry IDs connect metadata to registry URLs. +7. Read `references/metadata-flow.md` before changing revision, report, or service mapping behavior. + +## Output format + +Return metadata producer and consumer, revision or report contract, affected registry interaction, changed files, and validation performed. + +## Validation + +- Confirm exported and subscribed URLs are stored under the correct registry ID. +- Confirm remote metadata storage publishes before service discovery depends on it. +- Confirm metadata service V1 and V2 compatibility when changing service methods or response models. +- Run focused tests such as `go test ./metadata/...`; include `go test ./registry/servicediscovery/...` when service discovery depends on metadata. + +## Edge cases + +- Metadata globals are keyed by registry ID; missing registry IDs can merge unrelated data. +- Metadata service V1 and V2 expose different wire shapes but share the same delegate. +- Service name mapping is used by application-level discovery and may be backed by metadata reports. +- Remote metadata storage requires a metadata report instance. + +## References + +- Read `references/metadata-flow.md` for metadata collection, report, mapping, and service export details. diff --git a/.agents/skills/dubbo-go-metadata/references/metadata-flow.md b/.agents/skills/dubbo-go-metadata/references/metadata-flow.md new file mode 100644 index 0000000000..35874624b7 --- /dev/null +++ b/.agents/skills/dubbo-go-metadata/references/metadata-flow.md @@ -0,0 +1,39 @@ +# Metadata Flow + +## Core State + +- `metadata/metadata.go` stores `registryMetadataInfo` keyed by registry ID. +- `AddService` records exported provider URLs. +- `AddSubscribeURL` records consumer subscription URLs. +- `GetMetadataService` returns the metadata service delegate backed by the same map. + +## MetadataInfo + +- `metadata/info/` owns application metadata, exported services, subscribed URLs, service info, and serialization behavior. +- Provider export should add service URLs before application-level service discovery registers instances. +- Consumer refer paths can add subscribed URLs for metadata reporting. + +## Metadata Reports + +- Interface is in `metadata/report/report.go`. +- Factories register through `common/extension/metadata_report_factory.go`. +- Backends include Nacos, Zookeeper, and Etcd. +- Remote metadata storage depends on a report instance created from registry or metadata report config. + +## Metadata Service + +- `metadata/metadata_service.go` exports Dubbo and Triple metadata services. +- V1 and V2 generated service info lives in the same file and under `metadata/triple_api/`. +- The service delegates reads to `DefaultMetadataService`, which reads `MetadataInfo` by revision or current data. + +## Service Name Mapping + +- Mapping interfaces live under `metadata/mapping/`. +- Application-level discovery uses mapping to translate interface service names into provider application names. +- Mapping storage may be provided by metadata reports. + +## Contract Checks + +- Keep revision changes synchronized between `MetadataInfo`, service instance metadata, and report storage. +- Do not publish nil or incomplete metadata before service discovery registration. +- Preserve compatibility for Java class names and Dubbo metadata service method names. diff --git a/.agents/skills/dubbo-go-observability-filters/SKILL.md b/.agents/skills/dubbo-go-observability-filters/SKILL.md new file mode 100644 index 0000000000..6458577fc1 --- /dev/null +++ b/.agents/skills/dubbo-go-observability-filters/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dubbo-go-observability-filters +description: >- + Implements and reviews dubbo-go filters, metrics, tracing, logging, and related cross-cutting interception. Use when + the user asks about Filter, Invoke, OnResponse, service.filter, reference.filter, filter chain order, TPS limiting, + active limit, auth, token, access log, Sentinel, Seata, graceful shutdown filters, OpenTelemetry, tracing, + Prometheus metrics, metrics probes, logger integration, or packages filter/, metrics/, otel/, logger/, and + protocol/protocolwrapper/. Do not use for protocol wire behavior unless interception changes the transport contract. +--- + +# dubbo-go Observability and Filters + +## Purpose + +Use this skill to change or explain the filter chain and cross-cutting concerns such as metrics, tracing, logging, rate limiting, auth, and response interception. + +## When to use + +Use for filter registration, filter order, provider or consumer interception, `OnResponse`, TPS strategies, metrics collectors, OpenTelemetry tracing, logging integration, and probe endpoints. + +Do not use for concrete wire protocol behavior unless filter behavior changes the transport contract. + +## Inputs + +Required: +- Filter name, metrics/tracing component, config key, or package path. +- Intended interception or telemetry behavior. + +Optional: +- URL filter params, invocation attachments, context values, metric labels, span output, or log output. + +If missing, inspect `filter/filter.go` and `protocol/protocolwrapper/protocol_filter_wrapper.go`. + +## Workflow + +1. Read `filter/filter.go` for the `Invoke` and `OnResponse` contract. +2. Read `protocol/protocolwrapper/protocol_filter_wrapper.go` for provider and consumer chain construction. +3. Inspect extension registration in `common/extension/filter.go` and any TPS extension files. +4. Read the concrete filter under `filter/`. +5. For metrics, inspect `metrics/` and the `filter/metrics/` integration. +6. For tracing, inspect `filter/otel/`, `filter/tracing/`, and `otel/`. +7. Read `references/filter-observability-flow.md` before changing filter order, metric labels, or span semantics. + +## Output format + +Return filter chain position, provider or consumer side, telemetry contract, changed files, and validation performed. + +## Validation + +- Confirm filter names are registered and selected through `service.filter` or `reference.filter`. +- Confirm filters call the next invoker exactly once unless intentionally short-circuiting. +- Confirm `OnResponse` handles both success and error results. +- Run focused tests such as `go test ./filter/... ./metrics/... ./otel/...`; use `make test` for broad interception changes. + +## Edge cases + +- Filter names are listed left-to-right in config, but the wrapper builds the chain from right to left so invocation runs left-to-right. +- `extension.GetFilter` returns a boolean; missing filters can currently create nil filter risks if callers ignore it. +- Metrics and tracing filters must avoid changing invocation results unless that is the feature. +- Context and invocation attachments may be protocol-specific. + +## References + +- Read `references/filter-observability-flow.md` for filter chain and telemetry details. diff --git a/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md b/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md new file mode 100644 index 0000000000..1987c90c24 --- /dev/null +++ b/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md @@ -0,0 +1,34 @@ +# Filter and Observability Flow + +## Filter Contract + +- `filter.Filter.Invoke` receives context, next invoker, and invocation. +- `filter.Filter.OnResponse` receives the result after invocation and can observe or modify it. +- Filters should preserve result errors unless the filter intentionally converts or rejects a call. + +## Chain Construction + +1. Runtime exports or refers through `protocolwrapper.FILTER`. +2. Provider export reads `service.filter`; consumer refer reads `reference.filter`. +3. Filter names are parsed left-to-right from the URL param. +4. The wrapper builds from right to left so execution order is the configured left-to-right order. +5. `FilterInvoker.Invoke` calls the filter, then calls `OnResponse`. + +## Registration + +- Filters register through `extension.SetFilter`. +- TPS limiter, strategy, and rejected handler extensions have separate registries under `common/extension/tps_limit.go`. +- Some filters are enabled only when their package is imported. + +## Observability + +- Metrics filters and collectors live under `filter/metrics/` and `metrics/`. +- Probe endpoints live under `metrics/probe/`. +- OpenTelemetry and tracing behavior lives under `filter/otel/`, `filter/tracing/`, and `otel/`. +- Logger integration lives under `logger/` and is also affected by config. + +## Contract Checks + +- Keep labels, span names, and status classification stable unless the task explicitly changes telemetry output. +- Do not add blocking network calls to filters without timeouts. +- Avoid mutating shared invocation attachments unless the filter owns the key. diff --git a/.agents/skills/dubbo-go-protocol/SKILL.md b/.agents/skills/dubbo-go-protocol/SKILL.md new file mode 100644 index 0000000000..f794826dad --- /dev/null +++ b/.agents/skills/dubbo-go-protocol/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dubbo-go-protocol +description: >- + Implements and reviews dubbo-go protocol and transport changes. Use when the user asks about Protocol, Invoker, + Exporter, Invocation, Result, common.URL, protocol wrapper behavior, Dubbo, Dubbo3, Triple, gRPC, REST, JSONRPC, + HTTP or HTTP/3 transport, codecs, remoting clients or servers, or packages protocol/, remoting/, common/url.go, and + protocol/protocolwrapper/. Do not use for registry subscription or cluster routing unless protocol invoker semantics + are the changed contract. +--- + +# dubbo-go Protocol + +## Purpose + +Use this skill to change or explain transport behavior from URL construction through protocol export, refer, invocation, codec, remoting, result mapping, and destroy semantics. + +## When to use + +Use for `base.Protocol`, `base.Invoker`, `base.Exporter`, protocol implementations, codecs, remoting clients and servers, Triple/gRPC/Dubbo/REST/JSONRPC behavior, and URL param or attribute semantics. + +Do not use for registry discovery, metadata storage, or cluster selection unless the protocol invoker contract is the changed behavior. + +## Inputs + +Required: +- Protocol name, transport package path, invocation behavior, or URL shape. +- Intended wire behavior or observed protocol bug. + +Optional: +- Request or response payload, codec frame, headers, attachments, service info, or interoperability target. + +If missing, inspect `protocol/base/`, `protocol/protocolwrapper/`, and the concrete protocol package. + +## Workflow + +1. Read `protocol/base/base_protocol.go`, `base_invoker.go`, `base_exporter.go`, and invocation/result contracts. +2. Check how the protocol is registered through `common/extension/protocol.go`. +3. Trace filter wrapping through `protocol/protocolwrapper/protocol_filter_wrapper.go`. +4. Inspect the concrete protocol implementation under `protocol/{dubbo,dubbo3,triple,grpc,rest,jsonrpc}`. +5. For network behavior, follow into `remoting/` or protocol-specific server/client packages. +6. Verify URL params versus attributes before changing cross-package contracts. +7. Read `references/protocol-flow.md` before changing export, refer, codec, or destroy semantics. + +## Output format + +Return protocol path, URL contract, export or refer flow, invocation/result behavior, changed files, and validation performed. + +## Validation + +- Confirm concrete protocols register with the expected extension name. +- Confirm `Export`, `Refer`, `Invoke`, and `Destroy` semantics remain compatible with wrappers and graceful shutdown. +- Confirm wire changes preserve Dubbo Java or gRPC interoperability when relevant. +- Run focused tests for the changed protocol such as `go test ./protocol/triple/...`; use `go test ./protocol/... ./remoting/...` or `make test` for broad transport changes. + +## Edge cases + +- `protocolwrapper.FILTER` is registered as a protocol and delegates to the concrete protocol named in the URL. +- `common.URL` params are transported; attributes are process-local and should not be serialized. +- Destroyed invokers return a safe internal URL placeholder. +- Triple IDL, Triple non-IDL, and Dubbo interoperability paths can differ. + +## References + +- Read `references/protocol-flow.md` for export, refer, wrapper, URL, and destroy details. diff --git a/.agents/skills/dubbo-go-protocol/references/protocol-flow.md b/.agents/skills/dubbo-go-protocol/references/protocol-flow.md new file mode 100644 index 0000000000..73f98be33b --- /dev/null +++ b/.agents/skills/dubbo-go-protocol/references/protocol-flow.md @@ -0,0 +1,42 @@ +# Protocol Flow + +## Core Interfaces + +- `protocol/base/base_protocol.go`: `Protocol` with `Export`, `Refer`, and `Destroy`. +- `protocol/base/base_invoker.go`: `Invoker`, availability, destroyed state, safe URL access. +- `protocol/base/base_exporter.go`: `Exporter` and unexport behavior. +- `protocol/base/invocation.go` and `protocol/result/`: invocation data and result contract. + +## Extension Registration + +- Concrete protocols register through `common/extension/protocol.go`. +- The filter wrapper registers the synthetic `filter` protocol. +- Runtime export usually calls `extension.GetProtocol(protocolwrapper.FILTER)` so service and reference filters wrap the concrete protocol. + +## Export Flow + +1. Runtime creates an invoker with a service URL. +2. `protocolwrapper.FILTER.Export` resolves the concrete protocol from `invoker.GetURL().Protocol`. +3. It wraps the invoker with provider filters from `service.filter`. +4. The concrete protocol exports the invoker and stores an exporter key. +5. Server/remoting code receives requests and invokes the exported invoker. + +## Refer Flow + +1. Runtime or registry directory creates a URL for a remote provider. +2. `protocolwrapper.FILTER.Refer` resolves the concrete protocol from `url.Protocol`. +3. The concrete protocol creates a remote invoker. +4. The wrapper applies consumer filters from `reference.filter`. +5. Cluster and directory code call `Invoke` on the resulting invoker. + +## URL Rules + +- Use params for values that belong in Dubbo URLs or are needed by remote-compatible components. +- Use attributes for in-process objects such as service implementations, TLS configs, application config, Triple config, shutdown config, and generated service info. +- Treat `common.URL` as immutable after construction except for narrowly scoped builder/setup paths. + +## Destroy Rules + +- `BaseProtocol.Destroy` destroys invokers and unexports exporters. +- Concrete protocols should close remoting clients, servers, and exporter maps without double-unregistering unless implementing registry-specific cleanup. +- Avoid holding locks while calling external `Destroy` or `UnExport` code. diff --git a/.agents/skills/dubbo-go-registry/SKILL.md b/.agents/skills/dubbo-go-registry/SKILL.md new file mode 100644 index 0000000000..4cd13604bd --- /dev/null +++ b/.agents/skills/dubbo-go-registry/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dubbo-go-registry +description: >- + Implements and reviews dubbo-go registry and service discovery changes. Use when the user asks about registry + factories, Register, UnRegister, Subscribe, UnSubscribe, Notify, NotifyAll, LoadSubscribeInstances, service discovery, + registry directory, Nacos, Zookeeper, Etcd, Polaris, interface-level or application-level registration, service + instance listeners, or packages registry/, registry/servicediscovery/, registry/directory/, and remoting/* registry + integrations. Do not use for metadata revision or report storage unless registry behavior depends on it. +--- + +# dubbo-go Registry + +## Purpose + +Use this skill to trace service registration and subscription from runtime URLs through registry factories, concrete registry implementations, service discovery, directory updates, and listener notifications. + +## When to use + +Use for provider registration, consumer subscription, registry extension registration, application-level service discovery, registry directory behavior, and registry provider integrations. + +Do not use for metadata revision calculation, metadata report storage, or cluster routing unless registry notification data is the contract. + +## Inputs + +Required: +- Registry protocol, registry package path, URL, listener, or event behavior. +- Intended registration/subscription behavior or observed discovery bug. + +Optional: +- Provider URL, consumer URL, service instance metadata, registry backend, or notification sequence. + +If missing, start at `registry/registry.go` and follow the concrete protocol through `common/extension/registry.go`. + +## Workflow + +1. Read `registry/registry.go` and `registry/service_discovery.go` for the interface contract. +2. Check extension registration in `common/extension/registry.go` or `service_discovery.go`. +3. Trace URL loading through runtime or `internal.LoadRegistries` before entering concrete registry code. +4. For interface-level registries, inspect the concrete implementation under `registry/{nacos,zookeeper,etcdv3,polaris}` and matching `remoting/`. +5. For application-level discovery, inspect `registry/servicediscovery/service_discovery_registry.go`. +6. For consumer updates, follow listener output into `registry/directory/` and cluster routing. +7. Read `references/registry-discovery-flow.md` before changing notification semantics. + +## Output format + +Return registry protocol, registration or subscription flow, listener and directory impact, changed files, and validation commands or gaps. + +## Validation + +- Confirm `Register` and `UnRegister` use full URL matching semantics. +- Confirm `Subscribe`, `UnSubscribe`, and `LoadSubscribeInstances` preserve callback behavior. +- Confirm `NotifyAll` represents a complete list and `Notify` can represent incremental events. +- Run targeted tests such as `go test ./registry/...`; include matching `remoting/...` tests for backend-specific changes. + +## Edge cases + +- Application-level service discovery combines `ServiceDiscovery`, service name mapping, and metadata. +- `shouldRegister` and `shouldSubscribe` gates can skip work for some URL categories. +- Registry notification order affects directory snapshots and router updates. +- Some registry packages rely on blank imports to register extensions. + +## References + +- Read `references/registry-discovery-flow.md` for registry, service discovery, listener, and directory details. diff --git a/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md b/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md new file mode 100644 index 0000000000..ff9b694ee3 --- /dev/null +++ b/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md @@ -0,0 +1,41 @@ +# Registry and Discovery Flow + +## Interface Contracts + +- `registry.Registry` owns provider `Register`/`UnRegister` and consumer `Subscribe`/`UnSubscribe`. +- `registry.NotifyListener` receives `Notify` and `NotifyAll`. +- `registry.ServiceDiscovery` owns application-level service instance registration and watching. +- `registry.ServiceDiscoveryRegistry` combines normal registry behavior with service instance registration. + +## Extension Points + +- Registry factories register with `extension.SetRegistry`. +- Service discovery implementations register with `extension.SetServiceDiscovery`. +- Service name mapping and instance customizers are separate extension points used by application-level discovery. + +## Provider Registration + +1. Runtime builds service export URLs and loads registry URLs. +2. Interface-level registries store provider URLs directly. +3. Application-level registry uses metadata to create `ServiceInstance` values. +4. Remote metadata may be published before service instances are registered. + +## Consumer Subscription + +1. Runtime builds an interface-level consumer URL. +2. Registry directory subscribes and initially loads instances when needed. +3. Registry implementation emits complete or incremental service events. +4. Directory updates invoker snapshots. +5. Router chain and cluster selection consume the new snapshot on invocation. + +## Application-Level Discovery + +- `registry/servicediscovery/service_discovery_registry.go` maps interface names to application names and listens by application service names. +- Service instances include metadata storage type and revision properties. +- Metadata reports may be required to resolve provider service URLs. + +## Notification Rules + +- Treat `NotifyAll` as a full replacement list. +- Treat single `Notify` events as incremental unless the concrete registry documents otherwise. +- Keep listener callbacks non-blocking where possible because subscription paths can be shared by many references. diff --git a/.agents/skills/dubbo-go-runtime/SKILL.md b/.agents/skills/dubbo-go-runtime/SKILL.md new file mode 100644 index 0000000000..cf7551fb1b --- /dev/null +++ b/.agents/skills/dubbo-go-runtime/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dubbo-go-runtime +description: >- + Implements and reviews dubbo-go public client and server lifecycle changes. Use when the user asks about + dubbo.NewInstance, Instance.NewClient, Instance.NewServer, dubbo.Load runtime startup, client.NewClient, + server.NewServer, ReferenceOptions.Refer, ServiceOptions.Export, service registration, proxy creation, graceful + shutdown, direct URLs, mesh mode, TLS injection, or packages dubbo.go, client/, server/, proxy/, and graceful_shutdown/. + Do not use for low-level codec or registry implementation unless export/refer lifecycle owns the contract. +--- + +# dubbo-go Runtime + +## Purpose + +Use this skill to change or explain the public lifecycle from configuration and options to client reference creation, provider export, proxy generation, and shutdown. + +## When to use + +Use for public APIs, client/server options, reference/service initialization, export and refer behavior, direct URL mode, mesh mode, provider registration, consumer proxy creation, and graceful shutdown. + +Do not use for low-level protocol codecs, registry internals, or metadata storage unless runtime code controls the contract. + +## Inputs + +Required: +- Client, server, reference, service, proxy, or lifecycle behavior. +- Intended public API behavior or observed runtime bug. + +Optional: +- Config snippet, service interface, generated client/server code, URL, or stack trace. + +If missing, inspect `dubbo.go`, then the matching path in `client/` or `server/`. + +## Workflow + +1. Start at the public entry point: `dubbo.go`, `client/client.go`, `server/server.go`, or `loader.go`. +2. For consumer behavior, read `client/options.go` and `client/action.go`. +3. For provider behavior, read `server/options.go`, `server/action.go`, and `server/server.go`. +4. Trace URL construction and attributes before following into protocol, registry, metadata, or filters. +5. Trace proxy behavior through `proxy/` and `proxy/proxy_factory/`. +6. Check shutdown and destroy behavior in `graceful_shutdown/` and protocol `Destroy` methods. +7. Read `references/client-server-lifecycle.md` before changing export or refer flow. + +## Output format + +Return the public API impact, reference or service lifecycle path, URL or proxy contract, changed files, and validation performed. + +## Validation + +- Confirm user-provided options override cloned config when that is the existing contract. +- Confirm service/reference URLs carry required params and attributes. +- Confirm export/refer paths register shutdown and destroy the right protocols or registries. +- Run focused tests such as `go test ./client ./server ./proxy ./graceful_shutdown`; use `make test` for shared lifecycle behavior. + +## Edge cases + +- `ReferenceOptions.Refer` may use direct URLs or registry URLs. +- Mesh mode rewrites the reference URL and requires Triple. +- Provider export may use multiple protocol configs and random ports. +- Non-IDL and IDL Triple paths use different attributes and generated metadata. + +## References + +- Read `references/client-server-lifecycle.md` for client, server, export, refer, and shutdown flow. diff --git a/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md b/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md new file mode 100644 index 0000000000..9d3196191e --- /dev/null +++ b/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md @@ -0,0 +1,46 @@ +# Client and Server Lifecycle + +## Public Entry Points + +- `dubbo.NewInstance` initializes `InstanceOptions`. +- `Instance.NewClient` and `Instance.NewServer` clone config into runtime options. +- `dubbo.Load` starts configured consumer and provider services. +- `client.NewClient` and `server.NewServer` are lower-level constructors. + +## Consumer Reference Flow + +1. `ReferenceOptions.refer` resolves interface, methods, and optional generated `ClientInfo`. +2. It applies adaptive service overrides and mesh URL rewriting when enabled. +3. It builds an interface-level `common.URL` with reference params and runtime attributes. +4. It calls `processURL` to choose direct URL mode or registry URL loading. +5. It calls `buildInvoker` to create protocol or cluster invokers. +6. It creates a proxy through the configured proxy factory and implements the user service when needed. +7. It registers the reference protocol for graceful shutdown. + +## Provider Service Flow + +1. `ServiceOptions.Export` validates TPS and related extension names. +2. It loads registry URLs unless `NotRegister` is set. +3. It registers service methods in `common.ServiceMap`. +4. It builds one export URL per protocol config. +5. It adds in-process attributes such as RPC service, TLS config, Triple config, application, shutdown, provider, and registry config. +6. It exports through `extension.GetProtocol(protocolwrapper.FILTER)` so filters wrap the concrete protocol. +7. It records metadata and registers provider URLs or service instances. + +## Proxy Flow + +- `proxy.Proxy` is used for generated or reflective client callbacks. +- Proxy factories are registered under `common/extension/proxy_factory.go`. +- `proxy/proxy_factory/default.go` handles reflective calls; pass-through proxy handles direct invocation. + +## Shutdown Flow + +- Runtime registers protocols with `graceful_shutdown`. +- Protocol `Destroy` should close invokers and unexport providers. +- Registry-only unregister behavior should use `base.RegistryUnregisterer` when supported. + +## Contract Checks + +- Keep params and attributes consistent between consumer and provider URL construction. +- Do not assume one protocol per service. +- Keep direct URL and registry URL behavior equivalent after URL normalization. diff --git a/.agents/skills/dubbo-go-tools/SKILL.md b/.agents/skills/dubbo-go-tools/SKILL.md new file mode 100644 index 0000000000..eab6e8ea68 --- /dev/null +++ b/.agents/skills/dubbo-go-tools/SKILL.md @@ -0,0 +1,62 @@ +--- +name: dubbo-go-tools +description: >- + Implements and reviews dubbo-go developer tools and code generation. Use when the user asks about tools/dubbogo-cli, + tools/dubbo-go-schema, tools/protoc-gen-go-triple, tools/protoc-gen-triple-openapi, tools/imports-formatter, + tools/variadicrpccheck, generated Triple code, OpenAPI generation, schema output, import formatting, RPC contract + scanning, Makefile targets, or nested tool modules under tools/. Do not use for runtime protocol behavior unless the + generator output contract is the issue. +--- + +# dubbo-go Tools + +## Purpose + +Use this skill to change or explain dubbo-go developer tooling, generators, schema helpers, CLI behavior, import formatting, and contract scanning. + +## When to use + +Use for `tools/` changes, generated code templates, protoc plugins, schema generation, CLI commands, Makefile tool targets, and nested tool module validation. + +Do not use for runtime protocol behavior unless the generated code contract is the changed behavior. + +## Inputs + +Required: +- Tool name, command, generated file, template, or package path. +- Intended tool behavior or observed failure. + +Optional: +- CLI arguments, proto input, generated output diff, schema sample, or build/test output. + +If missing, inspect the specific tool README and its local `go.mod` when present. + +## Workflow + +1. Identify whether the change affects a root-module tool or a nested Go module under `tools/`. +2. Read the tool README and command entrypoint. +3. Inspect templates or generated output contracts before changing generator code. +4. For Makefile behavior, read the root `Makefile` and any nested module commands. +5. For generated runtime code, coordinate with `dubbo-go-protocol` only when wire or invocation semantics change. +6. Read `references/tooling-flow.md` before changing generators or validation commands. + +## Output format + +Return tool entrypoint, input and output contract, changed files, validation commands, and any runtime compatibility impact. + +## Validation + +- Run tests from the owning module directory when the tool has its own `go.mod`. +- Run root commands for root-module tools, such as `go test ./tools/variadicrpccheck` or `make rpc-contract-check`. +- Confirm generated output is deterministic. +- Run `make fmt` or the tool-specific formatter only when code changes require it. + +## Edge cases + +- Several `tools/` subdirectories are nested Go modules and should be tested from their own directory. +- Generated code can affect public APIs even when the generator change is small. +- `imports-formatter` is part of `make fmt`; avoid changing import output without checking repository formatting expectations. + +## References + +- Read `references/tooling-flow.md` for tool modules, entrypoints, and validation details. diff --git a/.agents/skills/dubbo-go-tools/references/tooling-flow.md b/.agents/skills/dubbo-go-tools/references/tooling-flow.md new file mode 100644 index 0000000000..b3f76afb1e --- /dev/null +++ b/.agents/skills/dubbo-go-tools/references/tooling-flow.md @@ -0,0 +1,29 @@ +# Tooling Flow + +## Tool Areas + +- `tools/dubbogo-cli`: CLI for bootstrapping and managing dubbo-go applications. It has its own Go module. +- `tools/dubbo-go-schema`: schema support for dubbo-go configuration files. +- `tools/protoc-gen-go-triple`: protoc plugin for Triple client and server code. It has its own Go module. +- `tools/protoc-gen-triple-openapi`: OpenAPI generator for Triple. It has its own Go module. +- `tools/imports-formatter`: import formatting helper used by `make fmt`. It has its own Go module. +- `tools/variadicrpccheck`: root-module scanner for exported variadic RPC contracts. + +## Root Make Targets + +- `make test`: runs root tests and `tools/dubbogo-cli` tests. +- `make fmt`: runs modernize, `go fmt`, `imports-formatter`, and CLI formatting. +- `make lint`: runs `go vet` and `golangci-lint`. +- `make rpc-contract-check`: runs the variadic RPC contract scanner. + +## Generator Checks + +1. Identify the source input format, usually proto files or config models. +2. Inspect the generated output expected by tests. +3. Keep output deterministic: stable ordering, stable import grouping, stable comments. +4. Run tests in the nested module that owns the generator. +5. When generated runtime code changes, run relevant protocol or server/client tests in the root module. + +## Nested Module Rule + +When a tool has its own `go.mod`, run `go test ./...` from that tool directory. Do not assume root `go test ./...` covers it. From 28b07926a7437d7cf9e4be8a0f25d496ba3931db Mon Sep 17 00:00:00 2001 From: Oxidaner <18622412361@163.com> Date: Mon, 25 May 2026 02:21:35 +0800 Subject: [PATCH 2/5] docs: update dubbo-go agent skills --- .agents/.claude-plugin/marketplace.json | 20 ++ .agents/.codex/INSTALL.md | 59 ++++ .agents/.gitignore | 20 ++ .../plugins/dubbo-go-agent-skills.js | 46 +++ .agents/GEMINI.md | 24 ++ .agents/README.md | 86 +++++ .agents/README_CN.md | 86 +++++ .agents/gemini-extension.json | 6 + .agents/package.json | 15 + .agents/plugin.json | 15 + .agents/skills/debug/SKILL.md | 229 +++++++++++++ .agents/skills/development/SKILL.md | 142 ++++++++ .agents/skills/dubbo-go-cluster/SKILL.md | 64 ---- .../references/routing-cluster-flow.md | 42 --- .agents/skills/dubbo-go-config/SKILL.md | 63 ---- .../dubbo-go-config/references/config-flow.md | 44 --- .agents/skills/dubbo-go-domain/SKILL.md | 164 --------- .../references/architecture-map.md | 46 --- .../references/project-rules.md | 37 -- .agents/skills/dubbo-go-metadata/SKILL.md | 63 ---- .../references/metadata-flow.md | 39 --- .../dubbo-go-observability-filters/SKILL.md | 64 ---- .../references/filter-observability-flow.md | 34 -- .agents/skills/dubbo-go-protocol/SKILL.md | 64 ---- .../references/protocol-flow.md | 42 --- .agents/skills/dubbo-go-registry/SKILL.md | 64 ---- .../references/registry-discovery-flow.md | 41 --- .agents/skills/dubbo-go-runtime/SKILL.md | 64 ---- .../references/client-server-lifecycle.md | 46 --- .agents/skills/dubbo-go-tools/SKILL.md | 62 ---- .../dubbo-go-tools/references/tooling-flow.md | 29 -- .agents/skills/extensions/SKILL.md | 269 +++++++++++++++ .agents/skills/guide/SKILL.md | 218 ++++++++++++ .agents/skills/guide/samples-index.md | 119 +++++++ .agents/skills/java-interop/SKILL.md | 232 +++++++++++++ .agents/skills/migrate/SKILL.md | 190 +++++++++++ .agents/skills/scaffolding/SKILL.md | 323 ++++++++++++++++++ 37 files changed, 2099 insertions(+), 1072 deletions(-) create mode 100644 .agents/.claude-plugin/marketplace.json create mode 100644 .agents/.codex/INSTALL.md create mode 100644 .agents/.gitignore create mode 100644 .agents/.opencode/plugins/dubbo-go-agent-skills.js create mode 100644 .agents/GEMINI.md create mode 100644 .agents/README.md create mode 100644 .agents/README_CN.md create mode 100644 .agents/gemini-extension.json create mode 100644 .agents/package.json create mode 100644 .agents/plugin.json create mode 100644 .agents/skills/debug/SKILL.md create mode 100644 .agents/skills/development/SKILL.md delete mode 100644 .agents/skills/dubbo-go-cluster/SKILL.md delete mode 100644 .agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md delete mode 100644 .agents/skills/dubbo-go-config/SKILL.md delete mode 100644 .agents/skills/dubbo-go-config/references/config-flow.md delete mode 100644 .agents/skills/dubbo-go-domain/SKILL.md delete mode 100644 .agents/skills/dubbo-go-domain/references/architecture-map.md delete mode 100644 .agents/skills/dubbo-go-domain/references/project-rules.md delete mode 100644 .agents/skills/dubbo-go-metadata/SKILL.md delete mode 100644 .agents/skills/dubbo-go-metadata/references/metadata-flow.md delete mode 100644 .agents/skills/dubbo-go-observability-filters/SKILL.md delete mode 100644 .agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md delete mode 100644 .agents/skills/dubbo-go-protocol/SKILL.md delete mode 100644 .agents/skills/dubbo-go-protocol/references/protocol-flow.md delete mode 100644 .agents/skills/dubbo-go-registry/SKILL.md delete mode 100644 .agents/skills/dubbo-go-registry/references/registry-discovery-flow.md delete mode 100644 .agents/skills/dubbo-go-runtime/SKILL.md delete mode 100644 .agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md delete mode 100644 .agents/skills/dubbo-go-tools/SKILL.md delete mode 100644 .agents/skills/dubbo-go-tools/references/tooling-flow.md create mode 100644 .agents/skills/extensions/SKILL.md create mode 100644 .agents/skills/guide/SKILL.md create mode 100644 .agents/skills/guide/samples-index.md create mode 100644 .agents/skills/java-interop/SKILL.md create mode 100644 .agents/skills/migrate/SKILL.md create mode 100644 .agents/skills/scaffolding/SKILL.md diff --git a/.agents/.claude-plugin/marketplace.json b/.agents/.claude-plugin/marketplace.json new file mode 100644 index 0000000000..a4a7ea13a5 --- /dev/null +++ b/.agents/.claude-plugin/marketplace.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", + "name": "dubbo-go-agent-skills", + "description": "Agent skills bundled with Apache dubbo-go for framework users and contributors", + "owner": { + "name": "Apache Dubbo" + }, + "plugins": [ + { + "name": "dubbo-go", + "description": "AI skills for Apache dubbo-go contributors and v3 users: repository development, scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "category": "development", + "source": { + "source": "url", + "url": "https://github.com/apache/dubbo-go.git" + }, + "homepage": "https://github.com/apache/dubbo-go/tree/develop/.agents" + } + ] +} diff --git a/.agents/.codex/INSTALL.md b/.agents/.codex/INSTALL.md new file mode 100644 index 0000000000..28d7cb345a --- /dev/null +++ b/.agents/.codex/INSTALL.md @@ -0,0 +1,59 @@ + + +# Installing dubbo-go Agent Skills for Codex + +## Quick install + +Tell Codex: + +```text +Fetch and follow instructions from https://raw.githubusercontent.com/apache/dubbo-go/main/.agents/.codex/INSTALL.md +``` + +## Manual installation + +Install the skills globally when you want Codex to use them outside an Apache dubbo-go checkout. + +```bash +git clone https://github.com/apache/dubbo-go.git ~/.codex/dubbo-go +mkdir -p ~/.agents/skills +ln -s ~/.codex/dubbo-go/.agents/skills ~/.agents/skills/dubbo-go +``` + +Restart Codex. + +### Windows + +```powershell +git clone https://github.com/apache/dubbo-go.git "$env:USERPROFILE\.codex\dubbo-go" +New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills" +cmd /c mklink /J "$env:USERPROFILE\.agents\skills\dubbo-go" "$env:USERPROFILE\.codex\dubbo-go\.agents\skills" +``` + +## Updating + +```bash +cd ~/.codex/dubbo-go +git pull --ff-only +``` + +Restart Codex after updating. + +## Usage + +The installed skills cover repository development, scaffolding, extensions, Java interoperability, debugging, guidance, and migration for dubbo-go. diff --git a/.agents/.gitignore b/.agents/.gitignore new file mode 100644 index 0000000000..fe850f695e --- /dev/null +++ b/.agents/.gitignore @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +node_modules/ +.DS_Store +*.log diff --git a/.agents/.opencode/plugins/dubbo-go-agent-skills.js b/.agents/.opencode/plugins/dubbo-go-agent-skills.js new file mode 100644 index 0000000000..aec4ea0290 --- /dev/null +++ b/.agents/.opencode/plugins/dubbo-go-agent-skills.js @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { readFileSync } from 'fs'; +import { join, dirname } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const pluginRoot = join(__dirname, '..', '..'); + +const skillNames = ['development', 'scaffolding', 'extensions', 'java-interop', 'debug', 'guide', 'migrate']; + +export const skills = skillNames.map(name => { + const skillPath = join(pluginRoot, 'skills', name, 'SKILL.md'); + let content; + try { + content = readFileSync(skillPath, 'utf-8'); + } catch (err) { + throw new Error(`dubbo-go-agent-skills: failed to read ${skillPath}: ${err.message}`); + } + // Parse frontmatter (tolerates both LF and CRLF line endings) + const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/); + const frontmatter = match ? match[1] : ''; + const body = match ? match[2] : content; + const nameMatch = frontmatter.match(/^name:\s*(.+)$/m); + const descMatch = frontmatter.match(/^description:\s*(.+)$/m); + return { + name: nameMatch ? nameMatch[1].trim() : `dubbo-go:${name}`, + description: descMatch ? descMatch[1].trim() : '', + content: body, + }; +}); diff --git a/.agents/GEMINI.md b/.agents/GEMINI.md new file mode 100644 index 0000000000..eeec3edb9c --- /dev/null +++ b/.agents/GEMINI.md @@ -0,0 +1,24 @@ + + +@./skills/development/SKILL.md +@./skills/scaffolding/SKILL.md +@./skills/extensions/SKILL.md +@./skills/java-interop/SKILL.md +@./skills/debug/SKILL.md +@./skills/guide/SKILL.md +@./skills/migrate/SKILL.md diff --git a/.agents/README.md b/.agents/README.md new file mode 100644 index 0000000000..b923164f3e --- /dev/null +++ b/.agents/README.md @@ -0,0 +1,86 @@ + + +# dubbo-go Agent Skills + +[English](README.md) | [中文](README_CN.md) + +This directory contains AI agent skills bundled with [Apache dubbo-go](https://github.com/apache/dubbo-go). The skills help coding agents work with the dubbo-go repository, dubbo-go v3 applications, examples, extension points, Java interoperability, debugging, and migration tasks. + +The package lives under `.agents/` so it can include multi-agent distribution metadata without overwriting dubbo-go repository root files. + +> Note: All skills target dubbo-go v3. v1 and v2 are deprecated. + +## Layout + +- `skills/`: Codex-compatible skills. Codex reads this directory when working in this repository. +- `.codex/INSTALL.md`: manual Codex installation notes for using these skills outside this checkout. +- `.claude-plugin/marketplace.json`: Claude Code plugin marketplace metadata for this `.agents` package. +- `.opencode/plugins/dubbo-go-agent-skills.js`: OpenCode adapter that exposes the bundled skills. +- `GEMINI.md` and `gemini-extension.json`: Gemini CLI extension entry points. +- `plugin.json` and `package.json`: generic plugin/package metadata for tools that can consume a package rooted at `.agents`. + +## Using These Skills + +When working inside an Apache dubbo-go checkout, Codex can load the repository-local skills from `.agents/skills` directly. No separate clone of a skills repository is required. + +For global Codex usage outside this checkout, follow [.codex/INSTALL.md](.codex/INSTALL.md). + +For OpenCode, Gemini CLI, or Claude Code packaging, treat `.agents` as the package root. The metadata files in this directory are intentionally relative to `.agents`. + +## Skills + +### development + +Guides agents modifying the apache/dubbo-go repository itself. It covers current Go/toolchain expectations, package boundaries, validation commands, generated files, and repository-specific do-not rules. + +### scaffolding + +Generates provider or consumer skeletons in the current dubbo-go v3 code-API style. It covers direct mode, registry-backed services, Protobuf generation, OpenAPI, HTTP handler mounting, HTTP/3, and current sample patterns. + +### extensions + +Guides custom SPI extensions such as Filter, LoadBalance, Router, Registry, Protocol, ConfigCenter, and Logger. It covers the `extension.SetXxx` registration pattern, blank imports, activation options, and common failure modes. + +### java-interop + +Guides interoperability between dubbo-go and dubbo-java. It helps choose Triple+Protobuf or Dubbo+Hessian2, handle service discovery mapping, and debug cross-language serialization. + +### debug + +Provides structured diagnosis for runtime issues such as missing providers, registry mapping, connection failures, serialization mismatches, timeouts, OpenAPI issues, attached HTTP handlers, shutdown behavior, and filter panics. + +### guide + +Explains current dubbo-go architecture, extension points, and best practices. It covers Instance, Protocol, Registry, Metadata, Filter, Cluster, LoadBalance, Router, Triple OpenAPI, HTTP/3, CORS, graceful shutdown, observability, and sample locations. + +### migrate + +Guides migration from gRPC-Go, Spring Cloud, Gin/plain HTTP, older dubbo-go v1/v2 usage, YAML-heavy apps, Java Dubbo, and Hessian2 services to current dubbo-go v3 patterns. + +## Contributing + +Skills live in `.agents/skills`. + +1. Add or edit a skill under `.agents/skills//SKILL.md`. +2. Keep `SKILL.md` frontmatter concise and trigger-focused. +3. Update this directory's metadata only when install paths, skill names, or supported agents change. +4. Submit the change through the normal dubbo-go contribution workflow. + +## License + +Apache License 2.0 diff --git a/.agents/README_CN.md b/.agents/README_CN.md new file mode 100644 index 0000000000..a629707a6e --- /dev/null +++ b/.agents/README_CN.md @@ -0,0 +1,86 @@ + + +# dubbo-go Agent Skills + +[English](README.md) | 中文 + +本目录存放随 [Apache dubbo-go](https://github.com/apache/dubbo-go) 仓库一起维护的 AI Agent Skills。这些 skills 用于帮助编码 Agent 处理 dubbo-go 仓库源码、dubbo-go v3 应用、示例生成、扩展点、Java 互通、问题排查和迁移任务。 + +这套包放在 `.agents/` 下,是为了把多 Agent 分发元数据集中在一起,同时避免覆盖 dubbo-go 仓库根目录已有文件。 + +> 注意:所有 skills 都面向 dubbo-go v3。v1 和 v2 已废弃。 + +## 目录结构 + +- `skills/`:Codex 可直接加载的 skills。Codex 在本仓库工作时会读取该目录。 +- `.codex/INSTALL.md`:在本仓库外全局使用这些 skills 的 Codex 手动安装说明。 +- `.claude-plugin/marketplace.json`:面向 Claude Code 插件市场的元数据。 +- `.opencode/plugins/dubbo-go-agent-skills.js`:OpenCode 适配器,用于暴露本目录内的 skills。 +- `GEMINI.md` 和 `gemini-extension.json`:Gemini CLI 扩展入口。 +- `plugin.json` 和 `package.json`:供能够以 `.agents` 为包根目录的工具读取的通用元数据。 + +## 使用方式 + +在 Apache dubbo-go 仓库内工作时,Codex 可以直接从 `.agents/skills` 加载仓库内置 skills,不需要再单独克隆一个 skills 仓库。 + +如果要在本仓库外全局使用这套 Codex skills,请参考 [.codex/INSTALL.md](.codex/INSTALL.md)。 + +如果用于 OpenCode、Gemini CLI 或 Claude Code 的插件包装,请把 `.agents` 视为包根目录。本目录中的元数据路径都按 `.agents` 为根来组织。 + +## Skills + +### development + +指导 Agent 修改 apache/dubbo-go 仓库本身,覆盖当前 Go/toolchain 要求、包边界、验证命令、生成文件和仓库级禁止事项。 + +### scaffolding + +生成当前 dubbo-go v3 code API 风格的 provider 或 consumer 骨架,覆盖直连模式、注册中心服务、Protobuf 生成、OpenAPI、HTTP handler 挂载、HTTP/3 和当前示例模式。 + +### extensions + +指导编写自定义 SPI 扩展,例如 Filter、LoadBalance、Router、Registry、Protocol、ConfigCenter、Logger。覆盖 `extension.SetXxx` 注册模式、blank import、启用方式和常见失败原因。 + +### java-interop + +指导 dubbo-go 和 dubbo-java 互通。根据服务形态和兼容性需求,在 Triple+Protobuf 与 Dubbo+Hessian2 之间做选择,并处理服务发现映射和跨语言序列化问题。 + +### debug + +为运行时问题提供结构化排查流程,例如 provider 找不到、注册中心映射、连接失败、序列化不匹配、超时、OpenAPI、HTTP handler 挂载、shutdown 和 filter panic。 + +### guide + +解释当前 dubbo-go 架构、扩展点和最佳实践,覆盖 Instance、Protocol、Registry、Metadata、Filter、Cluster、LoadBalance、Router、Triple OpenAPI、HTTP/3、CORS、graceful shutdown、可观测性和示例位置。 + +### migrate + +指导从 gRPC-Go、Spring Cloud、Gin/纯 HTTP、dubbo-go v1/v2、YAML-heavy 应用、Java Dubbo 和 Hessian2 服务迁移到当前 dubbo-go v3 模式。 + +## 贡献 + +Skills 位于 `.agents/skills`。 + +1. 在 `.agents/skills//SKILL.md` 下新增或修改 skill。 +2. 保持 `SKILL.md` frontmatter 简洁,并聚焦触发场景。 +3. 只有当安装路径、skill 名称或支持的 Agent 发生变化时,才更新本目录的元数据。 +4. 按 dubbo-go 正常贡献流程提交修改。 + +## License + +Apache License 2.0 diff --git a/.agents/gemini-extension.json b/.agents/gemini-extension.json new file mode 100644 index 0000000000..afe0b4182d --- /dev/null +++ b/.agents/gemini-extension.json @@ -0,0 +1,6 @@ +{ + "name": "dubbo-go-agent-skills", + "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "version": "0.2.0", + "contextFileName": "GEMINI.md" +} diff --git a/.agents/package.json b/.agents/package.json new file mode 100644 index 0000000000..57ee38cd45 --- /dev/null +++ b/.agents/package.json @@ -0,0 +1,15 @@ +{ + "name": "dubbo-go-agent-skills", + "version": "0.2.0", + "type": "module", + "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "author": "Apache Dubbo contributors", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/apache/dubbo-go.git", + "directory": ".agents" + }, + "homepage": "https://github.com/apache/dubbo-go/tree/develop/.agents", + "main": ".opencode/plugins/dubbo-go-agent-skills.js" +} diff --git a/.agents/plugin.json b/.agents/plugin.json new file mode 100644 index 0000000000..aa9dcb30dc --- /dev/null +++ b/.agents/plugin.json @@ -0,0 +1,15 @@ +{ + "name": "dubbo-go", + "version": "0.2.0", + "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "author": "Apache Dubbo contributors", + "skills": [ + "skills/development", + "skills/scaffolding", + "skills/extensions", + "skills/java-interop", + "skills/debug", + "skills/guide", + "skills/migrate" + ] +} diff --git a/.agents/skills/debug/SKILL.md b/.agents/skills/debug/SKILL.md new file mode 100644 index 0000000000..f6e10987f8 --- /dev/null +++ b/.agents/skills/debug/SKILL.md @@ -0,0 +1,229 @@ +--- +name: dubbo-go-debugging +description: Use when diagnosing dubbo-go runtime failures, logs, startup errors, missing providers, registry problems, serialization errors, timeouts, filter panics, OpenAPI issues, HTTP handler mounting, or graceful shutdown behavior. +--- + + + + +# Debugging dubbo-go + +## Overview + +Most dubbo-go runtime failures collapse into a small set of root causes: name/contract mismatch, registry/discovery mode mismatch, protocol mismatch, blocking filter, or missing blank import. Diagnose by symptom first, then verify the contract on both sides (provider and consumer). + +## Quick Triage + +| Symptom in logs | Jump to | +|---|---| +| `no provider available`, `no route`, `Should has at least one way to know` | [Missing Provider or No Route](#missing-provider-or-no-route) | +| `dial tcp ... connection refused`, `i/o timeout` on connect | [Connection Refused or Dial Error](#connection-refused-or-dial-error) | +| `hessian: failed to decode`, `protobuf: cannot parse invalid wire-format data` | [Serialization or Decode Error](#serialization-or-decode-error) | +| `context deadline exceeded`, `invoke timeout` | [Timeout](#timeout) | +| `filter not found`, panic inside a filter | [Filter Not Found or Filter Panic](#filter-not-found-or-filter-panic) | +| Provider process exits seconds after start | [Provider Starts Then Exits](#provider-starts-then-exits) | +| `404` at `/dubbo/openapi/...`, empty spec | [OpenAPI 404 or Empty Spec](#openapi-404-or-empty-spec) | +| `AttachHTTPHandler` returns error | [Attached HTTP Handler Errors](#attached-http-handler-errors) | +| Pods drain slowly, in-flight requests truncated on shutdown | [Graceful Shutdown Issues](#graceful-shutdown-issues) | + +## Collect First + +Before diving in, gather: + +1. Full error message and stack trace +2. Protocol: Triple, Dubbo, JSONRPC, REST, or gRPC-compatible path +3. Discovery mode: direct URL, Nacos, ZooKeeper, etcd, Polaris, mesh +4. Provider and consumer snippets for `NewInstance`, `NewServer`, `NewClient`, and `Register/NewService` +5. Whether the service uses Protobuf IDL, non-IDL, Hessian2, generic, OpenAPI, HTTP/3, or attached HTTP handlers + +## Missing Provider or No Route + +Common logs: + +```text +no provider available +No provider available +no route +Should has at least one way to know which services this interface belongs to +``` + +Check: + +- Provider reached `srv.Serve()` and did not exit. +- Provider registered the service: `pb.RegisterXxxHandler(srv, impl, ...)` returned nil. +- Consumer constructed the generated client with the same interface name. Override with `client.WithInterface("...")` if provider used `server.WithInterface("...")`. +- Registry addresses and IDs match. Multiple registries require `registry.WithID(...)` plus `client.WithRegistryIDs(...)` or server equivalents. +- Application-level discovery can resolve interface-to-application mapping. If metadata mapping is unavailable, set `client.WithProvidedBy("provider-app-name")`. +- Registry registration mode is correct: `registry.WithRegisterService`, `registry.WithRegisterInterface`, or `registry.WithRegisterServiceAndInterface`. +- Registry is not disabled by `server.WithNotRegister()` or service `server.WithNotRegister()`. +- Protocol matches. Triple consumers default to `tri`; Dubbo/Hessian2 consumers must use Dubbo protocol explicitly. + +For Nacos, inspect by application name for service-discovery mode and by interface if interface registration is enabled. + +## Connection Refused or Dial Error + +Check: + +- Provider is listening on the expected IP and port. +- For direct mode, `client.WithClientURL("127.0.0.1:20000")` or `tri://127.0.0.1:20000` points to the provider. +- Docker/Kubernetes clients are not using `localhost` to reach another container/pod. +- Triple server configured an explicit port if using `AttachHTTPHandler`. +- TLS/HTTP3 clients match server TLS and HTTP/3 setup. + +Useful commands: + +```bash +lsof -i :20000 +curl -v http://127.0.0.1:20000/greet.GreetService/Greet \ + -H "Content-Type: application/json" \ + -d '{"name":"Dubbo"}' +``` + +## Serialization or Decode Error + +Examples: + +```text +hessian: failed to decode +protobuf: cannot parse invalid wire-format data +``` + +Check: + +- Triple path uses Protobuf-generated code and the same `.proto` contract. +- Dubbo protocol with Hessian2 registers every POJO through `dubbo-go-hessian2.RegisterPOJO`. +- Java class names from `JavaClassName()` exactly match the Java fully-qualified class. +- Client protocol and provider protocol match. +- Generic calls use the expected generic type: `"true"`, `"gson"`, `"protobuf"`, or `"protobuf-json"`. + +## Timeout + +Examples: + +```text +context deadline exceeded +invoke timeout +``` + +Check: + +- Provider receives the request. +- Filters are not blocking, rate-limiting, or waiting on external systems. +- Consumer timeout is long enough. + +Per-reference timeout: + +```go +svc, _ := pb.NewGreetService(cli, client.WithRequestTimeout(10*time.Second)) +``` + +Client-wide timeout: + +```go +cli, _ := client.NewClient(client.WithClientRequestTimeout(10*time.Second)) +``` + +Call-site timeout: + +```go +ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) +defer cancel() +``` + +## Filter Not Found or Filter Panic + +Check: + +- The filter package is imported with `_ "path/to/filter"`. +- `extension.SetFilter("name", ...)` matches `server.WithFilter("name")`, `client.WithFilter("name")`, or YAML config. +- If using built-ins in examples, `_ "dubbo.apache.org/dubbo-go/v3/imports"` is present. +- Panic is not from filter order or nil attachment assumptions. + +## Provider Starts Then Exits + +`srv.Serve()` is blocking and should not be launched in a goroutine unless something else blocks the process. + +```go +if err := srv.Serve(); err != nil { + logger.Fatalf("failed to serve: %v", err) +} +``` + +## OpenAPI 404 or Empty Spec + +Check: + +- OpenAPI was enabled through `triple.WithOpenAPI(triple.OpenAPIEnable(), ...)`. +- Service was registered after OpenAPI-enabled Triple protocol was configured. +- Correct path is used. Defaults include: + - `/dubbo/openapi/openapi.json` + - `/dubbo/openapi/openapi.yaml` + - `/dubbo/openapi/api-docs/default.json` + - `/dubbo/openapi/swagger-ui` + - `/dubbo/openapi/redoc` +- Group-specific services use `server.WithOpenAPIGroup("group")` and can be requested with `/dubbo/openapi/api-docs/.json`. + +## Attached HTTP Handler Errors + +`srv.AttachHTTPHandler(handler)` rules: + +- Handler must not be nil. +- Attach before `Serve`. +- Only one root handler can be attached. +- At least one Triple protocol must be configured. +- Triple protocol needs an explicit port. + +Use a mux for multiple HTTP subroutes. + +## Graceful Shutdown Issues + +Current shutdown config includes total timeout, step timeout, notify timeout, consumer update wait time, offline request window timeout, internal signal handling, and closing invoker expiry. + +Check: + +- Graceful shutdown filters are imported or included through `_ "dubbo.apache.org/dubbo-go/v3/imports"`. +- Shutdown config is passed through `dubbo.NewInstance`, `client.WithClientShutdown`, or root YAML. +- Long-running calls fit within `step-timeout` and `timeout`. +- `internal-signal` is disabled only if the application handles OS signals itself. + +## Logs + +Enable debug logging: + +```go +ins, _ := dubbo.NewInstance( + dubbo.WithLogger( + logger.WithZap(), + logger.WithLevel("debug"), + logger.WithFormat("text"), + ), +) +``` + +Trace integration can inject trace IDs into logs when OpenTelemetry tracing is configured: + +```go +dubbo.WithLogger(logger.WithTraceIntegration(true)) +``` + +## Related Skills + +- `dubbo-go-extensions` - when a missing/registered SPI is the root cause (filter, LB, registry not found) +- `dubbo-go-java-interop` - when the symptom is Hessian2 decode failure or cross-language discovery +- `dubbo-go-guide` - for the conceptual map (Instance / Server / Client / Protocol / Registry / Filter) +- `dubbo-go-development` - when the issue is reproducible only inside the `apache/dubbo-go` repo and may need a fix or test there diff --git a/.agents/skills/development/SKILL.md b/.agents/skills/development/SKILL.md new file mode 100644 index 0000000000..651a2d87d4 --- /dev/null +++ b/.agents/skills/development/SKILL.md @@ -0,0 +1,142 @@ +--- +name: dubbo-go-development +description: Use when modifying, reviewing, testing, debugging, or documenting the apache/dubbo-go repository itself, including Go code, generated code, config structs, tools, CI, tests, or repository-local agent skills. +--- + + + + +# dubbo-go Repository Development + +## Overview + +Working inside `apache/dubbo-go` itself, not just using the framework from an application. Treat package boundaries, public APIs, and generated files as load-bearing - break them only with explicit user intent. + +## When to Use + +- Editing files under `apache/dubbo-go` (`client/`, `server/`, `protocol/`, `registry/`, `cluster/`, `filter/`, `metadata/`, `tools/`, etc.) +- Adding or updating unit tests, mocks, or fixtures inside this repo +- Touching `Makefile`, CI config, generated Protobuf/Triple stubs, or `tools/imports-formatter` +- Modifying `.agents/skills/*` documentation + +For application-side changes, use `dubbo-go-scaffolding`. For runtime failures, use `dubbo-go-debugging`. + +## Current Branch Facts + +- Module path: `dubbo.apache.org/dubbo-go/v3` +- Go version in `go.mod`: `1.25.0` +- Makefile test command uses `GOTOOLCHAIN=go1.25.0+auto` +- CI still runs `make check-fmt`, `make test`, and `make lint` +- Import style is enforced by `tools/imports-formatter` +- `make fmt` also runs the Go modernize analyzer to replace eligible `interface{}` with `any` + +## Workflow + +1. Read the owning package and nearby tests before editing. +2. Keep changes scoped to the owning module boundary. +3. Prefer current code API patterns over old YAML/config globals for new examples. +4. Preserve compatibility in public APIs unless the user explicitly asks for a breaking change. +5. Add or update focused tests for behavior changes. +6. Run the smallest meaningful validation first, then broader commands when risk is higher. +7. Summarize changed files, behavior, and validation results. + +## Important Package Boundaries + +- `dubbo.go`, `options.go`, `instance_options_init.go`: instance-level option initialization and root config bridging +- `client/`: reference options, consumer URL construction, invoker creation +- `server/`: provider options, service registration, `AttachHTTPHandler`, service metadata +- `protocol/base`, `protocol/result`, `protocol/invocation`: core invocation interfaces +- `protocol/triple`: main protocol implementation, reflection, HTTP/3, CORS, OpenAPI, attached HTTP hosting +- `registry/`: registry interfaces, service discovery, application-level mapping +- `metadata/`: metadata report and service name mapping +- `cluster/`: cluster strategies, directory, load balance, router chain +- `filter/`: provider/consumer filters; most runtime interception belongs here +- `config/`, `global/`, `config_center/`: YAML/config models and dynamic config loading +- `graceful_shutdown/`: shutdown runtime state and options +- `logger/`, `metrics/`, `otel/`: observability +- `tools/`: CLI, schema, generators, imports formatter, variadic RPC scanner + +## Current Implementation Notes + +- Config loading uses koanf. Do not introduce viper-based assumptions into new code. +- Triple config now includes CORS, HTTP/3, and OpenAPI sections. +- `server.AttachHTTPHandler` hosts one existing `http.Handler` on an explicit Triple port before `Serve`. +- Graceful shutdown has separate total timeout, step timeout, notify timeout, consumer update wait time, offline request window, and closing invoker expiry. +- Application-level service discovery may require metadata mapping or explicit `client.WithProvidedBy`. +- Registry config can choose service/interface/all registration through registry options. +- Router config supports static injection for routers that implement `router.StaticConfigSetter`. +- New extension code should import `protocol/base` and `protocol/result`, not old aliases. + +## Validation Commands + +Use the command that matches the scope. + +```bash +# format repository code +make fmt + +# check formatting exactly like CI +make check-fmt + +# targeted package tests +GOTOOLCHAIN=go1.25.0+auto go test ./protocol/triple/... +GOTOOLCHAIN=go1.25.0+auto go test ./server/... + +# full repository tests plus dubbogo-cli submodule tests +make test + +# lint +make lint + +# warn about exported variadic RPC contracts +make rpc-contract-check +``` + +If only `.agents` documentation changes, validate skill metadata and adapters instead of running the Go suite. + +## Generated and Tooling Files + +- Do not hand-edit generated Protobuf or Triple files unless the generator source is also in scope. +- For user services, generate with `protoc-gen-go` and `protoc-gen-go-triple/v3`. +- For OpenAPI generation, use runtime Triple OpenAPI or `tools/protoc-gen-triple-openapi` depending on the task. +- `tools/dubbogo-cli` has its own module and tests; run tests from that directory when editing it. + +## Do Not + +- Do not remove tests to make validation pass. +- Do not change public option names casually. +- Do not flatten package boundaries with unrelated refactors. +- Do not overwrite generated files without explaining the generator source. +- Do not introduce new dependencies unless the existing packages cannot reasonably solve the problem. + +## Red Flags - Stop and Reconsider + +- About to delete or skip a failing test to "unblock" CI +- About to rename or remove an exported option/function in `client/`, `server/`, `protocol/`, or `registry/` without a migration note +- About to bypass `tools/imports-formatter` by hand-editing import groupings +- About to replace koanf-based config loading with a viper-style assumption +- About to `--no-verify` a commit, or skip `make check-fmt` / `make lint` +- About to introduce a third-party dependency to do something `gost`, `koanf`, or stdlib already covers + +If any of these fire, stop and surface the tradeoff to the user before proceeding. + +## Related Skills + +- `dubbo-go-guide` - conceptual map of packages, options, and current capabilities +- `dubbo-go-extensions` - when the work is adding or fixing an SPI registration in this repo +- `dubbo-go-debugging` - when reproducing a user-reported failure to find the fix point diff --git a/.agents/skills/dubbo-go-cluster/SKILL.md b/.agents/skills/dubbo-go-cluster/SKILL.md deleted file mode 100644 index 9e4754d9f1..0000000000 --- a/.agents/skills/dubbo-go-cluster/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: dubbo-go-cluster -description: >- - Implements and reviews dubbo-go cluster, routing, directory, and load-balancing changes. Use when the user asks about - failover, failfast, failsafe, failback, forking, broadcast, available, zoneaware, adaptive service, Directory, - RouterChain, condition, tag, script, affinity or Polaris routers, load balance algorithms, retries, provider - selection, or packages cluster/cluster/, cluster/directory/, cluster/router/, and cluster/loadbalance/. Do not use - for registry backend mechanics unless the directory snapshot contract is affected. ---- - -# dubbo-go Cluster - -## Purpose - -Use this skill to change or explain how provider invokers are listed, routed, load-balanced, retried, and invoked by cluster fault-tolerance strategies. - -## When to use - -Use for cluster invokers, directory snapshots, router chain behavior, dynamic routing rules, tag or condition matching, load balancing, retries, and adaptive service behavior. - -Do not use for registry backend code unless registry notifications affect directory snapshots. - -## Inputs - -Required: -- Cluster strategy, router, load balancer, directory, or invocation selection behavior. -- Intended routing/selection behavior or observed mismatch. - -Optional: -- Consumer URL, provider URLs, invocation attachments, method name, route rule, or registry event sequence. - -If missing, start at `cluster/router/chain/chain.go` for routing or `cluster/cluster/` for fault tolerance. - -## Workflow - -1. Classify the behavior as directory update, router filtering, load balance selection, or cluster fault tolerance. -2. Read `cluster/directory/` for provider invoker snapshots and registry notification handling. -3. Read `cluster/router/chain/chain.go` and the relevant router package for filtering behavior. -4. Read `cluster/loadbalance/` for provider selection. -5. Read the relevant `cluster/cluster/*/cluster_invoker.go` for retry and error behavior. -6. Check extension registration under `common/extension/cluster.go`, `loadbalance.go`, and `router_factory.go`. -7. Read `references/routing-cluster-flow.md` before changing selection semantics. - -## Output format - -Return directory source, router chain result, load balance or cluster strategy, changed files, and validation performed. - -## Validation - -- Confirm router priority and stable ordering still produce deterministic results. -- Confirm directory snapshots are copied safely and not mutated by callers. -- Confirm retry count and business-error handling match the strategy. -- Run focused tests such as `go test ./cluster/...`; use `make test` for broad invocation behavior. - -## Edge cases - -- RouterChain first narrows invokers by service key and falls back to all invokers if no service-key match exists. -- Static router config is injected after builtin routers are created. -- Failover retries non-business errors but returns business errors directly. -- Method-level URL params can override interface-level routing, retries, and load balance settings. - -## References - -- Read `references/routing-cluster-flow.md` for directory, router, load balance, and cluster invocation details. diff --git a/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md b/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md deleted file mode 100644 index 46b4f5e7fd..0000000000 --- a/.agents/skills/dubbo-go-cluster/references/routing-cluster-flow.md +++ /dev/null @@ -1,42 +0,0 @@ -# Routing and Cluster Flow - -## Invocation Path - -1. A proxy or protocol caller invokes a cluster invoker. -2. The cluster invoker asks its directory for invokers matching the invocation. -3. Directory output is routed through `RouterChain`. -4. The cluster strategy chooses or retries invokers using a load balancer. -5. The selected protocol invoker performs the remote call. - -## Directory - -- Static directory holds fixed invokers. -- Registry directory reacts to registry notifications and rebuilds invoker snapshots. -- Directory output should be treated as a snapshot for one invocation path. - -## Router Chain - -- `RouterChain.Route` copies invokers, filters by service key when possible, then applies routers in priority order. -- Router factories are registered through `extension.SetRouterFactory`. -- Static router configs are injected through routers implementing `StaticConfigSetter`. -- Dynamic routers may update internal state on `Notify`. - -## Load Balance - -- Load balance implementations live under `cluster/loadbalance/`. -- Selection receives candidate invokers and the invocation. -- Method-level URL params can affect algorithm choice. - -## Cluster Strategies - -- `failover`: retry non-business errors and reselect providers. -- `failfast`: fail immediately. -- `failsafe`: swallow failures according to strategy. -- `failback`: retry in background. -- `forking`, `broadcast`, `available`, `zoneaware`, and `adaptivesvc` have specialized selection behavior. - -## Contract Checks - -- Keep router output deterministic for the same snapshot and invocation. -- Avoid mutating shared invoker slices from callers. -- Preserve distinction between business errors and transport or provider errors. diff --git a/.agents/skills/dubbo-go-config/SKILL.md b/.agents/skills/dubbo-go-config/SKILL.md deleted file mode 100644 index 75db3e4603..0000000000 --- a/.agents/skills/dubbo-go-config/SKILL.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: dubbo-go-config -description: >- - Implements and reviews dubbo-go configuration changes. Use when the user asks about dubbo.Load, config.Load, - RootConfig, InstanceOptions, global config structs, YAML or JSON loading, koanf parsing, config center integration, - dynamic configuration, hot reload, config post processors, or packages loader.go, config/, global/, config_center/, - and common/config/. Do not use for runtime export/refer behavior unless configuration injection is the contract. ---- - -# dubbo-go Config - -## Purpose - -Use this skill to change or explain how dubbo-go loads, initializes, validates, hot-reloads, and exposes configuration to runtime client and server code. - -## When to use - -Use for configuration files, builder APIs, `RootConfig`, `InstanceOptions`, global config models, config center factories, hot reload allowlists, and config post-processing. - -Do not use for protocol transport, registry events, or runtime export/refer behavior unless configuration injection is the contract being changed. - -## Inputs - -Required: -- Config key, config struct, loader API, or package path. -- Intended behavior or observed parse/init bug. - -Optional: -- YAML or JSON snippet. -- Config center protocol and data ID or group. -- Related client, server, reference, or service option. - -If missing, inspect `loader.go`, `config/config_loader.go`, and the relevant `global/*_config.go` or `config/*_config.go`. - -## Workflow - -1. Identify whether the task targets top-level `dubbo.Load` and `InstanceOptions` or legacy `config.Load` and `RootConfig`. -2. Read the owning config model under `global/` and compatibility or builder code under `config/`. -3. Trace initialization into `InstanceOptions.init`, `RootConfig.Init`, service/reference init, or config center startup. -4. For dynamic config, inspect `config/config_center_config.go`, `config_center/`, and `common/extension/config_center_factory.go`. -5. For hot reload, inspect `loader.go` and keep `safeChanged` semantics narrow. -6. Read `references/config-flow.md` before changing loader behavior or public config keys. - -## Output format - -Return changed config keys or structs, loader path, runtime injection impact, validation performed, and any compatibility notes. - -## Validation - -- Confirm new config fields are represented in the right `global/` or `config/` model and initialized before runtime use. -- Confirm config center changes register the correct extension factory. -- Confirm hot reload accepts only intended mutable keys. -- Run focused tests such as `go test ./config ./global ./config_center/...`; use `make test` for broad config behavior. - -## Edge cases - -- `dubbo.Load` starts provider and consumer runtime; `config.Load` only initializes `RootConfig`. -- Some config values are transported as URL params, while TLS, application, registry, shutdown, and Triple details often travel as URL attributes. -- Existing compatibility tests may depend on legacy field names. - -## References - -- Read `references/config-flow.md` for loader, config center, and runtime injection details. diff --git a/.agents/skills/dubbo-go-config/references/config-flow.md b/.agents/skills/dubbo-go-config/references/config-flow.md deleted file mode 100644 index 6f9a509240..0000000000 --- a/.agents/skills/dubbo-go-config/references/config-flow.md +++ /dev/null @@ -1,44 +0,0 @@ -# Config Flow - -## Entry Points - -- `loader.go`: top-level `dubbo.Load`, file watch, hot reload, and `InstanceOptions`. -- `config/config_loader.go`: package-level `config.Load`, `RootConfig` storage, and legacy config accessors. -- `dubbo.go`: maps `InstanceOptions` into `client.ClientOption` and `server.ServerOption`. -- `global/`: config models used by public client/server options. -- `config/`: builders, compatibility models, config center startup, and legacy `RootConfig` initialization. - -## Loader Flow - -Top-level `dubbo.Load`: -1. Build `loaderConf`. -2. Resolve config with koanf from file, raw bytes, or direct options. -3. Unmarshal into `InstanceOptions`. -4. Run `InstanceOptions.init`. -5. Create an `Instance` and start consumer/provider loading. -6. Start the file watcher once and register shutdown cleanup. - -Package `config.Load`: -1. Build `LoaderConf`. -2. Resolve into `RootConfig` when one is not provided. -3. Run `RootConfig.Init`. -4. Store the initialized root config through the atomic pointer. - -## Config Center - -- Config center setup is coordinated by `config/config_center_config.go`. -- Implementations live under `config_center/{apollo,file,nacos,zookeeper}`. -- Factories register through `common/extension/config_center_factory.go`. -- Parser behavior is under `config_center/parser/`. - -## Runtime Injection - -- `Instance.NewClient` clones consumer, application, registry, shutdown, metrics, otel, TLS, protocol, and router config into `client` options. -- `Instance.NewServer` clones application, registry, protocol, shutdown, metrics, otel, and TLS config into `server` options. -- Reference and service options ultimately build `common.URL` values. Use params for transportable Dubbo URL values and attributes for in-process objects. - -## Hot Reload - -- File watching is in `loader.go`. -- `hotUpdateConfig` compares old and new koanf trees with `safeChanged`. -- Keep hot reload allowlists conservative because changing immutable runtime fields after export or refer can leave stale protocols, registries, or metadata. diff --git a/.agents/skills/dubbo-go-domain/SKILL.md b/.agents/skills/dubbo-go-domain/SKILL.md deleted file mode 100644 index 5eeef6a80b..0000000000 --- a/.agents/skills/dubbo-go-domain/SKILL.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -name: dubbo-go-domain -description: >- - Use this skill when working on the dubbo-go codebase, including implementing features, fixing bugs, writing tests, - reviewing code, updating documentation, or routing work to a narrower dubbo-go-* domain skill. Use for cross-module - questions, end-to-end flows, subsystem boundaries, or deciding whether config, runtime, protocol, registry, metadata, - cluster routing, filters and observability, or tools guidance applies. ---- - -# dubbo-go Project Guide - -## Project Overview - -dubbo-go is the Go implementation of Apache Dubbo. It is an RPC and microservice framework that provides service export and reference, registry and service discovery, protocol interoperability, cluster fault tolerance, traffic governance, configuration, metadata, metrics, tracing, and developer tools. - -It mainly provides: -- Public client and server APIs for Go services. -- Dubbo, Dubbo3, Triple, gRPC, REST, JSONRPC, and related transport support. -- Registry integration with Nacos, Zookeeper, Etcd, Polaris, and application-level service discovery. -- Metadata collection, metadata reporting, service name mapping, routing, load balancing, filters, metrics, tracing, and CLI or code generation tools. - -This repository does not own external registry servers, Dubbo Java implementation, sample applications outside this repository, or production deployment infrastructure. - -## Tech Stack - -- Language: Go, module `dubbo.apache.org/dubbo-go/v3`. -- Go version: `go 1.25.0` in `go.mod`; root `Makefile` uses `GOTOOLCHAIN=go1.25.0+auto` for tests. -- Build: Go modules plus nested Go modules under selected `tools/` directories. -- Test: `go test`, `testify`, `gomock`, and focused package tests. -- Lint and format: `go fmt`, `imports-formatter`, `go vet`, `golangci-lint`, and `make fmt` or `make lint`. - -Do not introduce a new framework or dependency unless the task requires it and the compatibility impact is clear. - -## Repository Structure - -- `dubbo.go`, `loader.go`: public instance and top-level load/start APIs. -- `config/`, `global/`, `config_center/`, `common/config/`: config models, loading, config center, and compatibility behavior. -- `client/`, `server/`, `proxy/`, `graceful_shutdown/`: runtime client/server construction, refer/export, proxy, and shutdown behavior. -- `protocol/`, `remoting/`, `common/url.go`: protocol interfaces, codecs, transports, URL contract, invokers, and exporters. -- `registry/`, `metadata/`: registry discovery, service discovery, metadata, reports, mapping, and revisions. -- `cluster/`: directories, routers, load balancing, and cluster fault tolerance. -- `filter/`, `metrics/`, `otel/`, `logger/`: filters, observability, tracing, metrics, and logging. -- `tools/`: CLI, schema generator, protoc plugins, import formatter, and RPC contract scanner. -- `docs/`, `doc/`: project documentation and images. - -## Workflow - -When modifying code: - -1. Classify the owning subsystem and load the narrower `dubbo-go-*` skill when relevant. -2. Read the existing implementation and tests before editing. -3. Make the smallest correct change that follows current package boundaries. -4. Prefer existing abstractions, extension registries, URL params, and URL attributes over new patterns. -5. Add or update focused tests for behavior changes. -6. Run the most relevant validation command. -7. Summarize changed files, behavior, compatibility impact, and validation result. - -When fixing bugs: - -1. Reproduce the issue or identify the failing path from tests, logs, or code. -2. Find the smallest root cause. -3. Make a minimal safe change. -4. Add a regression test when feasible. -5. Explain why the fix works and what risk remains. - -When reviewing code: - -1. Check behavior, compatibility, concurrency, error handling, generated file handling, and missing tests first. -2. Ground findings in file and line references. -3. Keep summary secondary to concrete risks. - -## Coding Guidelines - -- Keep changes focused and reviewable. -- Follow existing package structure, naming, and extension registration patterns. -- Preserve backward compatibility for public APIs, config keys, URL params, wire behavior, and generated output unless explicitly requested. -- Use structured config, URL, and parser APIs instead of ad hoc string handling when available. -- Avoid broad refactors during bug fixes. -- Do not change unrelated files. - -## Testing and Validation - -Use the most relevant command: - -```bash -go test ./... -make test -make fmt -make lint -make rpc-contract-check -``` - -For focused work, prefer package-level tests first, for example: - -```bash -go test ./config ./global ./config_center/... -go test ./client ./server ./proxy ./graceful_shutdown -go test ./protocol/... ./remoting/... -go test ./registry/... ./metadata/... -go test ./cluster/... -go test ./filter/... ./metrics/... ./otel/... -``` - -For nested tools, run tests from the owning module directory. - -If validation cannot be run or fails, report the command, the error, and whether it appears related to the current change. - -## Do Not - -- Do not rewrite large parts of the project without explicit instruction. -- Do not introduce new dependencies or frameworks unless necessary. -- Do not change public APIs, config keys, wire contracts, or generated output without documenting compatibility impact. -- Do not remove or weaken tests to make validation pass. -- Do not commit secrets, tokens, passwords, private keys, or private config. -- Do not modify generated files manually unless the generation source is also updated or the repository already treats that file as hand-maintained. -- Do not ignore existing uncommitted user changes. - -## Common Tasks - -### Choose a Domain Skill - -1. Map the request to the primary package. -2. Use `references/architecture-map.md` when ownership is unclear. -3. Load one narrower skill when possible. -4. If multiple domains are involved, follow runtime flow: config, runtime, protocol, registry or metadata, cluster, filters, observability, tools. - -### Add a Feature - -1. Find the owning module and existing tests. -2. Add the core behavior using existing abstractions. -3. Add or update tests. -4. Update documentation when public behavior changes. -5. Run focused validation. - -### Add a Configuration Option - -1. Define the config key in the owning config model. -2. Add default and initialization behavior. -3. Wire it into the consuming module through existing options or URL params/attributes. -4. Add tests for default and custom behavior. -5. Update docs or schemas when relevant. - -### Fix a Bug - -1. Identify the root cause. -2. Make the minimal fix. -3. Add a regression test when possible. -4. Verify with the narrowest relevant command. - -## Output Format - -Return the selected skill or subsystem, changed files, behavior change, compatibility impact, validation performed, and any residual risk. - -## Edge cases - -- `dubbo.Load` and `config.Load` both load configuration, but they serve different public APIs. -- Registry discovery and metadata reporting are tightly coupled; use `dubbo-go-metadata` when revisions or metadata reports control behavior. -- Filters wrap protocols through `protocol/protocolwrapper`; use `dubbo-go-protocol` when transport semantics change and `dubbo-go-observability-filters` when interception semantics change. -- Some `tools/` subdirectories are independent Go modules. - -## References - -- Read `references/architecture-map.md` for subsystem ownership and end-to-end flow. -- Read `references/project-rules.md` for compatibility, generated-file, validation, and PR guidance. diff --git a/.agents/skills/dubbo-go-domain/references/architecture-map.md b/.agents/skills/dubbo-go-domain/references/architecture-map.md deleted file mode 100644 index 36761e996c..0000000000 --- a/.agents/skills/dubbo-go-domain/references/architecture-map.md +++ /dev/null @@ -1,46 +0,0 @@ -# dubbo-go Architecture Map - -## Subsystem Ownership - -| Area | Primary paths | Owns | Related skill | -| --- | --- | --- | --- | -| Configuration | `loader.go`, `config/`, `global/`, `config_center/`, `common/config/` | YAML or option loading, `RootConfig`, `InstanceOptions`, config center, hot reload | `dubbo-go-config` | -| Runtime API | `dubbo.go`, `client/`, `server/`, `proxy/`, `graceful_shutdown/` | Public client/server construction, service registration, reference creation, export/refer lifecycle | `dubbo-go-runtime` | -| Protocols | `protocol/`, `remoting/`, `protocol/protocolwrapper/`, `common/url.go` | `Protocol`, `Invoker`, `Exporter`, codecs, transport clients and servers, URL semantics | `dubbo-go-protocol` | -| Registry discovery | `registry/`, `registry/servicediscovery/`, `registry/directory/`, `remoting/{nacos,zookeeper,etcdv3,polaris}/` | Registry factories, register/unregister, subscribe/unsubscribe, service instance notifications | `dubbo-go-registry` | -| Metadata | `metadata/`, `metadata/info/`, `metadata/report/`, `metadata/mapping/` | MetadataInfo, metadata service export, metadata reports, service name mapping, revisions | `dubbo-go-metadata` | -| Cluster and routing | `cluster/cluster/`, `cluster/directory/`, `cluster/router/`, `cluster/loadbalance/` | Fault tolerance, directory listing, route chain, load balancing, retries | `dubbo-go-cluster` | -| Filters and observability | `filter/`, `metrics/`, `otel/`, `logger/`, `protocol/protocolwrapper/` | Filter chain, metrics, tracing, logging, TPS and auth interception | `dubbo-go-observability-filters` | -| Tools and codegen | `tools/`, `Makefile` | CLI, schema generation, protoc plugins, import formatting, RPC contract scanner | `dubbo-go-tools` | - -## Common End-to-End Flows - -Provider startup: -1. Config is loaded into `InstanceOptions` or `RootConfig`. -2. `Instance.NewServer` or `server.NewServer` builds server options. -3. `ServiceOptions.Export` registers service metadata in `common.ServiceMap`, builds an export URL, wraps the protocol with filters, exports the service, and registers provider URLs or service instances. -4. Metadata is collected and may be published through a metadata report. - -Consumer startup: -1. Config is loaded into client and reference options. -2. `ReferenceOptions.Refer` builds an interface-level URL, loads direct or registry URLs, creates registry or protocol invokers, and builds the service proxy. -3. Registry notifications update directory invokers. -4. Cluster, router chain, load balancer, filters, and protocol invoker handle each invocation. - -Protocol invocation: -1. Runtime code builds a `common.URL` with transport params and non-transport attributes. -2. `extension.GetProtocol` resolves the registered protocol. -3. `protocolwrapper.FILTER` wraps provider or consumer invokers with configured filters. -4. The concrete protocol handles codec, remoting, request mapping, response mapping, and destroy semantics. - -Registry and metadata: -1. Provider export adds service URLs to metadata and registers URLs or application-level service instances. -2. Consumers subscribe through registry directories or service discovery registries. -3. Service name mapping and metadata reports connect interface names, application names, and metadata revisions. - -## Boundary Rules - -- Public API behavior belongs to runtime even when the root cause is config. -- Transport behavior belongs to protocol even when filters observe it. -- Service instance registration belongs to registry; metadata revision calculation and report storage belong to metadata. -- Routing decisions belong to cluster; rule source or dynamic config loading belongs to config or registry depending on the producer. diff --git a/.agents/skills/dubbo-go-domain/references/project-rules.md b/.agents/skills/dubbo-go-domain/references/project-rules.md deleted file mode 100644 index 97c2aa2259..0000000000 --- a/.agents/skills/dubbo-go-domain/references/project-rules.md +++ /dev/null @@ -1,37 +0,0 @@ -# dubbo-go Project Rules - -## Compatibility - -- Treat public Go APIs, config keys, URL params, URL attributes, protocol wire behavior, generated code shape, and registry or metadata semantics as compatibility surfaces. -- Document behavior and compatibility impact when changing any compatibility surface. -- Preserve Dubbo Java, Triple, and gRPC interoperability when touching protocol or generated-code paths. - -## Generated Files - -- Do not modify generated files manually unless the generation source is also updated or the file is intentionally hand-maintained in this repository. -- For proto-related output, inspect the owning tool under `tools/protoc-gen-go-triple` or `tools/protoc-gen-triple-openapi`. -- Keep generated output deterministic: stable ordering, imports, names, and comments. - -## Validation Selection - -- Start with the narrowest package tests that cover the change. -- Use `make test` for cross-cutting runtime behavior. -- Use `make fmt` after Go code changes that affect formatting or imports. -- Use `make lint` for changes that touch shared APIs, concurrency, generated code, or error handling. -- Use `make rpc-contract-check` when changing exported RPC service interfaces. - -## Nested Modules - -Run tests from the nested module directory when a tool has its own `go.mod`: - -- `tools/dubbogo-cli` -- `tools/imports-formatter` -- `tools/protoc-gen-go-triple` -- `tools/protoc-gen-triple-openapi` - -## PR Guidance - -- Keep PRs small and reviewable. -- Include tests or explain why tests are not feasible. -- Include compatibility notes for public behavior changes. -- Do not include unrelated formatting churn. diff --git a/.agents/skills/dubbo-go-metadata/SKILL.md b/.agents/skills/dubbo-go-metadata/SKILL.md deleted file mode 100644 index 49a6271376..0000000000 --- a/.agents/skills/dubbo-go-metadata/SKILL.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: dubbo-go-metadata -description: >- - Implements and reviews dubbo-go metadata changes. Use when the user asks about MetadataInfo, metadata service V1 or - V2, metadata reports, app metadata publishing or fetching, service name mapping, metadata revision, subscribed or - exported service URLs, remote metadata storage, or packages metadata/, metadata/info/, metadata/report/, and - metadata/mapping/. Do not use for registry subscription mechanics unless metadata controls the behavior. ---- - -# dubbo-go Metadata - -## Purpose - -Use this skill to change or explain how dubbo-go collects exported and subscribed URLs, calculates and publishes metadata, exposes metadata services, and maps service names to applications. - -## When to use - -Use for `MetadataInfo`, metadata service export, metadata reports, metadata mapping, revisions, remote metadata storage, and application-level service discovery metadata interactions. - -Do not use for concrete registry notification mechanics unless metadata controls the contract. - -## Inputs - -Required: -- Metadata type, registry ID, metadata report backend, service name mapping, revision, or metadata service behavior. -- Intended metadata behavior or observed mismatch. - -Optional: -- Provider URL, consumer URL, service instance metadata, app name, revision string, or metadata report payload. - -If missing, start at `metadata/metadata.go` and follow into `metadata/info/`, `metadata/report/`, or `metadata/mapping/`. - -## Workflow - -1. Read `metadata/metadata.go` for global metadata storage and add/get helpers. -2. Inspect `metadata/info/` for `MetadataInfo` structure, URL addition, and revision-related behavior. -3. For metadata service behavior, read `metadata/metadata_service.go` and generated files under `metadata/triple_api/`. -4. For reports, inspect `metadata/report/report.go`, the backend package, and extension registration. -5. For service name mapping, inspect `metadata/mapping/` and the registry service discovery caller. -6. Verify how registry IDs connect metadata to registry URLs. -7. Read `references/metadata-flow.md` before changing revision, report, or service mapping behavior. - -## Output format - -Return metadata producer and consumer, revision or report contract, affected registry interaction, changed files, and validation performed. - -## Validation - -- Confirm exported and subscribed URLs are stored under the correct registry ID. -- Confirm remote metadata storage publishes before service discovery depends on it. -- Confirm metadata service V1 and V2 compatibility when changing service methods or response models. -- Run focused tests such as `go test ./metadata/...`; include `go test ./registry/servicediscovery/...` when service discovery depends on metadata. - -## Edge cases - -- Metadata globals are keyed by registry ID; missing registry IDs can merge unrelated data. -- Metadata service V1 and V2 expose different wire shapes but share the same delegate. -- Service name mapping is used by application-level discovery and may be backed by metadata reports. -- Remote metadata storage requires a metadata report instance. - -## References - -- Read `references/metadata-flow.md` for metadata collection, report, mapping, and service export details. diff --git a/.agents/skills/dubbo-go-metadata/references/metadata-flow.md b/.agents/skills/dubbo-go-metadata/references/metadata-flow.md deleted file mode 100644 index 35874624b7..0000000000 --- a/.agents/skills/dubbo-go-metadata/references/metadata-flow.md +++ /dev/null @@ -1,39 +0,0 @@ -# Metadata Flow - -## Core State - -- `metadata/metadata.go` stores `registryMetadataInfo` keyed by registry ID. -- `AddService` records exported provider URLs. -- `AddSubscribeURL` records consumer subscription URLs. -- `GetMetadataService` returns the metadata service delegate backed by the same map. - -## MetadataInfo - -- `metadata/info/` owns application metadata, exported services, subscribed URLs, service info, and serialization behavior. -- Provider export should add service URLs before application-level service discovery registers instances. -- Consumer refer paths can add subscribed URLs for metadata reporting. - -## Metadata Reports - -- Interface is in `metadata/report/report.go`. -- Factories register through `common/extension/metadata_report_factory.go`. -- Backends include Nacos, Zookeeper, and Etcd. -- Remote metadata storage depends on a report instance created from registry or metadata report config. - -## Metadata Service - -- `metadata/metadata_service.go` exports Dubbo and Triple metadata services. -- V1 and V2 generated service info lives in the same file and under `metadata/triple_api/`. -- The service delegates reads to `DefaultMetadataService`, which reads `MetadataInfo` by revision or current data. - -## Service Name Mapping - -- Mapping interfaces live under `metadata/mapping/`. -- Application-level discovery uses mapping to translate interface service names into provider application names. -- Mapping storage may be provided by metadata reports. - -## Contract Checks - -- Keep revision changes synchronized between `MetadataInfo`, service instance metadata, and report storage. -- Do not publish nil or incomplete metadata before service discovery registration. -- Preserve compatibility for Java class names and Dubbo metadata service method names. diff --git a/.agents/skills/dubbo-go-observability-filters/SKILL.md b/.agents/skills/dubbo-go-observability-filters/SKILL.md deleted file mode 100644 index 6458577fc1..0000000000 --- a/.agents/skills/dubbo-go-observability-filters/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: dubbo-go-observability-filters -description: >- - Implements and reviews dubbo-go filters, metrics, tracing, logging, and related cross-cutting interception. Use when - the user asks about Filter, Invoke, OnResponse, service.filter, reference.filter, filter chain order, TPS limiting, - active limit, auth, token, access log, Sentinel, Seata, graceful shutdown filters, OpenTelemetry, tracing, - Prometheus metrics, metrics probes, logger integration, or packages filter/, metrics/, otel/, logger/, and - protocol/protocolwrapper/. Do not use for protocol wire behavior unless interception changes the transport contract. ---- - -# dubbo-go Observability and Filters - -## Purpose - -Use this skill to change or explain the filter chain and cross-cutting concerns such as metrics, tracing, logging, rate limiting, auth, and response interception. - -## When to use - -Use for filter registration, filter order, provider or consumer interception, `OnResponse`, TPS strategies, metrics collectors, OpenTelemetry tracing, logging integration, and probe endpoints. - -Do not use for concrete wire protocol behavior unless filter behavior changes the transport contract. - -## Inputs - -Required: -- Filter name, metrics/tracing component, config key, or package path. -- Intended interception or telemetry behavior. - -Optional: -- URL filter params, invocation attachments, context values, metric labels, span output, or log output. - -If missing, inspect `filter/filter.go` and `protocol/protocolwrapper/protocol_filter_wrapper.go`. - -## Workflow - -1. Read `filter/filter.go` for the `Invoke` and `OnResponse` contract. -2. Read `protocol/protocolwrapper/protocol_filter_wrapper.go` for provider and consumer chain construction. -3. Inspect extension registration in `common/extension/filter.go` and any TPS extension files. -4. Read the concrete filter under `filter/`. -5. For metrics, inspect `metrics/` and the `filter/metrics/` integration. -6. For tracing, inspect `filter/otel/`, `filter/tracing/`, and `otel/`. -7. Read `references/filter-observability-flow.md` before changing filter order, metric labels, or span semantics. - -## Output format - -Return filter chain position, provider or consumer side, telemetry contract, changed files, and validation performed. - -## Validation - -- Confirm filter names are registered and selected through `service.filter` or `reference.filter`. -- Confirm filters call the next invoker exactly once unless intentionally short-circuiting. -- Confirm `OnResponse` handles both success and error results. -- Run focused tests such as `go test ./filter/... ./metrics/... ./otel/...`; use `make test` for broad interception changes. - -## Edge cases - -- Filter names are listed left-to-right in config, but the wrapper builds the chain from right to left so invocation runs left-to-right. -- `extension.GetFilter` returns a boolean; missing filters can currently create nil filter risks if callers ignore it. -- Metrics and tracing filters must avoid changing invocation results unless that is the feature. -- Context and invocation attachments may be protocol-specific. - -## References - -- Read `references/filter-observability-flow.md` for filter chain and telemetry details. diff --git a/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md b/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md deleted file mode 100644 index 1987c90c24..0000000000 --- a/.agents/skills/dubbo-go-observability-filters/references/filter-observability-flow.md +++ /dev/null @@ -1,34 +0,0 @@ -# Filter and Observability Flow - -## Filter Contract - -- `filter.Filter.Invoke` receives context, next invoker, and invocation. -- `filter.Filter.OnResponse` receives the result after invocation and can observe or modify it. -- Filters should preserve result errors unless the filter intentionally converts or rejects a call. - -## Chain Construction - -1. Runtime exports or refers through `protocolwrapper.FILTER`. -2. Provider export reads `service.filter`; consumer refer reads `reference.filter`. -3. Filter names are parsed left-to-right from the URL param. -4. The wrapper builds from right to left so execution order is the configured left-to-right order. -5. `FilterInvoker.Invoke` calls the filter, then calls `OnResponse`. - -## Registration - -- Filters register through `extension.SetFilter`. -- TPS limiter, strategy, and rejected handler extensions have separate registries under `common/extension/tps_limit.go`. -- Some filters are enabled only when their package is imported. - -## Observability - -- Metrics filters and collectors live under `filter/metrics/` and `metrics/`. -- Probe endpoints live under `metrics/probe/`. -- OpenTelemetry and tracing behavior lives under `filter/otel/`, `filter/tracing/`, and `otel/`. -- Logger integration lives under `logger/` and is also affected by config. - -## Contract Checks - -- Keep labels, span names, and status classification stable unless the task explicitly changes telemetry output. -- Do not add blocking network calls to filters without timeouts. -- Avoid mutating shared invocation attachments unless the filter owns the key. diff --git a/.agents/skills/dubbo-go-protocol/SKILL.md b/.agents/skills/dubbo-go-protocol/SKILL.md deleted file mode 100644 index f794826dad..0000000000 --- a/.agents/skills/dubbo-go-protocol/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: dubbo-go-protocol -description: >- - Implements and reviews dubbo-go protocol and transport changes. Use when the user asks about Protocol, Invoker, - Exporter, Invocation, Result, common.URL, protocol wrapper behavior, Dubbo, Dubbo3, Triple, gRPC, REST, JSONRPC, - HTTP or HTTP/3 transport, codecs, remoting clients or servers, or packages protocol/, remoting/, common/url.go, and - protocol/protocolwrapper/. Do not use for registry subscription or cluster routing unless protocol invoker semantics - are the changed contract. ---- - -# dubbo-go Protocol - -## Purpose - -Use this skill to change or explain transport behavior from URL construction through protocol export, refer, invocation, codec, remoting, result mapping, and destroy semantics. - -## When to use - -Use for `base.Protocol`, `base.Invoker`, `base.Exporter`, protocol implementations, codecs, remoting clients and servers, Triple/gRPC/Dubbo/REST/JSONRPC behavior, and URL param or attribute semantics. - -Do not use for registry discovery, metadata storage, or cluster selection unless the protocol invoker contract is the changed behavior. - -## Inputs - -Required: -- Protocol name, transport package path, invocation behavior, or URL shape. -- Intended wire behavior or observed protocol bug. - -Optional: -- Request or response payload, codec frame, headers, attachments, service info, or interoperability target. - -If missing, inspect `protocol/base/`, `protocol/protocolwrapper/`, and the concrete protocol package. - -## Workflow - -1. Read `protocol/base/base_protocol.go`, `base_invoker.go`, `base_exporter.go`, and invocation/result contracts. -2. Check how the protocol is registered through `common/extension/protocol.go`. -3. Trace filter wrapping through `protocol/protocolwrapper/protocol_filter_wrapper.go`. -4. Inspect the concrete protocol implementation under `protocol/{dubbo,dubbo3,triple,grpc,rest,jsonrpc}`. -5. For network behavior, follow into `remoting/` or protocol-specific server/client packages. -6. Verify URL params versus attributes before changing cross-package contracts. -7. Read `references/protocol-flow.md` before changing export, refer, codec, or destroy semantics. - -## Output format - -Return protocol path, URL contract, export or refer flow, invocation/result behavior, changed files, and validation performed. - -## Validation - -- Confirm concrete protocols register with the expected extension name. -- Confirm `Export`, `Refer`, `Invoke`, and `Destroy` semantics remain compatible with wrappers and graceful shutdown. -- Confirm wire changes preserve Dubbo Java or gRPC interoperability when relevant. -- Run focused tests for the changed protocol such as `go test ./protocol/triple/...`; use `go test ./protocol/... ./remoting/...` or `make test` for broad transport changes. - -## Edge cases - -- `protocolwrapper.FILTER` is registered as a protocol and delegates to the concrete protocol named in the URL. -- `common.URL` params are transported; attributes are process-local and should not be serialized. -- Destroyed invokers return a safe internal URL placeholder. -- Triple IDL, Triple non-IDL, and Dubbo interoperability paths can differ. - -## References - -- Read `references/protocol-flow.md` for export, refer, wrapper, URL, and destroy details. diff --git a/.agents/skills/dubbo-go-protocol/references/protocol-flow.md b/.agents/skills/dubbo-go-protocol/references/protocol-flow.md deleted file mode 100644 index 73f98be33b..0000000000 --- a/.agents/skills/dubbo-go-protocol/references/protocol-flow.md +++ /dev/null @@ -1,42 +0,0 @@ -# Protocol Flow - -## Core Interfaces - -- `protocol/base/base_protocol.go`: `Protocol` with `Export`, `Refer`, and `Destroy`. -- `protocol/base/base_invoker.go`: `Invoker`, availability, destroyed state, safe URL access. -- `protocol/base/base_exporter.go`: `Exporter` and unexport behavior. -- `protocol/base/invocation.go` and `protocol/result/`: invocation data and result contract. - -## Extension Registration - -- Concrete protocols register through `common/extension/protocol.go`. -- The filter wrapper registers the synthetic `filter` protocol. -- Runtime export usually calls `extension.GetProtocol(protocolwrapper.FILTER)` so service and reference filters wrap the concrete protocol. - -## Export Flow - -1. Runtime creates an invoker with a service URL. -2. `protocolwrapper.FILTER.Export` resolves the concrete protocol from `invoker.GetURL().Protocol`. -3. It wraps the invoker with provider filters from `service.filter`. -4. The concrete protocol exports the invoker and stores an exporter key. -5. Server/remoting code receives requests and invokes the exported invoker. - -## Refer Flow - -1. Runtime or registry directory creates a URL for a remote provider. -2. `protocolwrapper.FILTER.Refer` resolves the concrete protocol from `url.Protocol`. -3. The concrete protocol creates a remote invoker. -4. The wrapper applies consumer filters from `reference.filter`. -5. Cluster and directory code call `Invoke` on the resulting invoker. - -## URL Rules - -- Use params for values that belong in Dubbo URLs or are needed by remote-compatible components. -- Use attributes for in-process objects such as service implementations, TLS configs, application config, Triple config, shutdown config, and generated service info. -- Treat `common.URL` as immutable after construction except for narrowly scoped builder/setup paths. - -## Destroy Rules - -- `BaseProtocol.Destroy` destroys invokers and unexports exporters. -- Concrete protocols should close remoting clients, servers, and exporter maps without double-unregistering unless implementing registry-specific cleanup. -- Avoid holding locks while calling external `Destroy` or `UnExport` code. diff --git a/.agents/skills/dubbo-go-registry/SKILL.md b/.agents/skills/dubbo-go-registry/SKILL.md deleted file mode 100644 index 4cd13604bd..0000000000 --- a/.agents/skills/dubbo-go-registry/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: dubbo-go-registry -description: >- - Implements and reviews dubbo-go registry and service discovery changes. Use when the user asks about registry - factories, Register, UnRegister, Subscribe, UnSubscribe, Notify, NotifyAll, LoadSubscribeInstances, service discovery, - registry directory, Nacos, Zookeeper, Etcd, Polaris, interface-level or application-level registration, service - instance listeners, or packages registry/, registry/servicediscovery/, registry/directory/, and remoting/* registry - integrations. Do not use for metadata revision or report storage unless registry behavior depends on it. ---- - -# dubbo-go Registry - -## Purpose - -Use this skill to trace service registration and subscription from runtime URLs through registry factories, concrete registry implementations, service discovery, directory updates, and listener notifications. - -## When to use - -Use for provider registration, consumer subscription, registry extension registration, application-level service discovery, registry directory behavior, and registry provider integrations. - -Do not use for metadata revision calculation, metadata report storage, or cluster routing unless registry notification data is the contract. - -## Inputs - -Required: -- Registry protocol, registry package path, URL, listener, or event behavior. -- Intended registration/subscription behavior or observed discovery bug. - -Optional: -- Provider URL, consumer URL, service instance metadata, registry backend, or notification sequence. - -If missing, start at `registry/registry.go` and follow the concrete protocol through `common/extension/registry.go`. - -## Workflow - -1. Read `registry/registry.go` and `registry/service_discovery.go` for the interface contract. -2. Check extension registration in `common/extension/registry.go` or `service_discovery.go`. -3. Trace URL loading through runtime or `internal.LoadRegistries` before entering concrete registry code. -4. For interface-level registries, inspect the concrete implementation under `registry/{nacos,zookeeper,etcdv3,polaris}` and matching `remoting/`. -5. For application-level discovery, inspect `registry/servicediscovery/service_discovery_registry.go`. -6. For consumer updates, follow listener output into `registry/directory/` and cluster routing. -7. Read `references/registry-discovery-flow.md` before changing notification semantics. - -## Output format - -Return registry protocol, registration or subscription flow, listener and directory impact, changed files, and validation commands or gaps. - -## Validation - -- Confirm `Register` and `UnRegister` use full URL matching semantics. -- Confirm `Subscribe`, `UnSubscribe`, and `LoadSubscribeInstances` preserve callback behavior. -- Confirm `NotifyAll` represents a complete list and `Notify` can represent incremental events. -- Run targeted tests such as `go test ./registry/...`; include matching `remoting/...` tests for backend-specific changes. - -## Edge cases - -- Application-level service discovery combines `ServiceDiscovery`, service name mapping, and metadata. -- `shouldRegister` and `shouldSubscribe` gates can skip work for some URL categories. -- Registry notification order affects directory snapshots and router updates. -- Some registry packages rely on blank imports to register extensions. - -## References - -- Read `references/registry-discovery-flow.md` for registry, service discovery, listener, and directory details. diff --git a/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md b/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md deleted file mode 100644 index ff9b694ee3..0000000000 --- a/.agents/skills/dubbo-go-registry/references/registry-discovery-flow.md +++ /dev/null @@ -1,41 +0,0 @@ -# Registry and Discovery Flow - -## Interface Contracts - -- `registry.Registry` owns provider `Register`/`UnRegister` and consumer `Subscribe`/`UnSubscribe`. -- `registry.NotifyListener` receives `Notify` and `NotifyAll`. -- `registry.ServiceDiscovery` owns application-level service instance registration and watching. -- `registry.ServiceDiscoveryRegistry` combines normal registry behavior with service instance registration. - -## Extension Points - -- Registry factories register with `extension.SetRegistry`. -- Service discovery implementations register with `extension.SetServiceDiscovery`. -- Service name mapping and instance customizers are separate extension points used by application-level discovery. - -## Provider Registration - -1. Runtime builds service export URLs and loads registry URLs. -2. Interface-level registries store provider URLs directly. -3. Application-level registry uses metadata to create `ServiceInstance` values. -4. Remote metadata may be published before service instances are registered. - -## Consumer Subscription - -1. Runtime builds an interface-level consumer URL. -2. Registry directory subscribes and initially loads instances when needed. -3. Registry implementation emits complete or incremental service events. -4. Directory updates invoker snapshots. -5. Router chain and cluster selection consume the new snapshot on invocation. - -## Application-Level Discovery - -- `registry/servicediscovery/service_discovery_registry.go` maps interface names to application names and listens by application service names. -- Service instances include metadata storage type and revision properties. -- Metadata reports may be required to resolve provider service URLs. - -## Notification Rules - -- Treat `NotifyAll` as a full replacement list. -- Treat single `Notify` events as incremental unless the concrete registry documents otherwise. -- Keep listener callbacks non-blocking where possible because subscription paths can be shared by many references. diff --git a/.agents/skills/dubbo-go-runtime/SKILL.md b/.agents/skills/dubbo-go-runtime/SKILL.md deleted file mode 100644 index cf7551fb1b..0000000000 --- a/.agents/skills/dubbo-go-runtime/SKILL.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -name: dubbo-go-runtime -description: >- - Implements and reviews dubbo-go public client and server lifecycle changes. Use when the user asks about - dubbo.NewInstance, Instance.NewClient, Instance.NewServer, dubbo.Load runtime startup, client.NewClient, - server.NewServer, ReferenceOptions.Refer, ServiceOptions.Export, service registration, proxy creation, graceful - shutdown, direct URLs, mesh mode, TLS injection, or packages dubbo.go, client/, server/, proxy/, and graceful_shutdown/. - Do not use for low-level codec or registry implementation unless export/refer lifecycle owns the contract. ---- - -# dubbo-go Runtime - -## Purpose - -Use this skill to change or explain the public lifecycle from configuration and options to client reference creation, provider export, proxy generation, and shutdown. - -## When to use - -Use for public APIs, client/server options, reference/service initialization, export and refer behavior, direct URL mode, mesh mode, provider registration, consumer proxy creation, and graceful shutdown. - -Do not use for low-level protocol codecs, registry internals, or metadata storage unless runtime code controls the contract. - -## Inputs - -Required: -- Client, server, reference, service, proxy, or lifecycle behavior. -- Intended public API behavior or observed runtime bug. - -Optional: -- Config snippet, service interface, generated client/server code, URL, or stack trace. - -If missing, inspect `dubbo.go`, then the matching path in `client/` or `server/`. - -## Workflow - -1. Start at the public entry point: `dubbo.go`, `client/client.go`, `server/server.go`, or `loader.go`. -2. For consumer behavior, read `client/options.go` and `client/action.go`. -3. For provider behavior, read `server/options.go`, `server/action.go`, and `server/server.go`. -4. Trace URL construction and attributes before following into protocol, registry, metadata, or filters. -5. Trace proxy behavior through `proxy/` and `proxy/proxy_factory/`. -6. Check shutdown and destroy behavior in `graceful_shutdown/` and protocol `Destroy` methods. -7. Read `references/client-server-lifecycle.md` before changing export or refer flow. - -## Output format - -Return the public API impact, reference or service lifecycle path, URL or proxy contract, changed files, and validation performed. - -## Validation - -- Confirm user-provided options override cloned config when that is the existing contract. -- Confirm service/reference URLs carry required params and attributes. -- Confirm export/refer paths register shutdown and destroy the right protocols or registries. -- Run focused tests such as `go test ./client ./server ./proxy ./graceful_shutdown`; use `make test` for shared lifecycle behavior. - -## Edge cases - -- `ReferenceOptions.Refer` may use direct URLs or registry URLs. -- Mesh mode rewrites the reference URL and requires Triple. -- Provider export may use multiple protocol configs and random ports. -- Non-IDL and IDL Triple paths use different attributes and generated metadata. - -## References - -- Read `references/client-server-lifecycle.md` for client, server, export, refer, and shutdown flow. diff --git a/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md b/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md deleted file mode 100644 index 9d3196191e..0000000000 --- a/.agents/skills/dubbo-go-runtime/references/client-server-lifecycle.md +++ /dev/null @@ -1,46 +0,0 @@ -# Client and Server Lifecycle - -## Public Entry Points - -- `dubbo.NewInstance` initializes `InstanceOptions`. -- `Instance.NewClient` and `Instance.NewServer` clone config into runtime options. -- `dubbo.Load` starts configured consumer and provider services. -- `client.NewClient` and `server.NewServer` are lower-level constructors. - -## Consumer Reference Flow - -1. `ReferenceOptions.refer` resolves interface, methods, and optional generated `ClientInfo`. -2. It applies adaptive service overrides and mesh URL rewriting when enabled. -3. It builds an interface-level `common.URL` with reference params and runtime attributes. -4. It calls `processURL` to choose direct URL mode or registry URL loading. -5. It calls `buildInvoker` to create protocol or cluster invokers. -6. It creates a proxy through the configured proxy factory and implements the user service when needed. -7. It registers the reference protocol for graceful shutdown. - -## Provider Service Flow - -1. `ServiceOptions.Export` validates TPS and related extension names. -2. It loads registry URLs unless `NotRegister` is set. -3. It registers service methods in `common.ServiceMap`. -4. It builds one export URL per protocol config. -5. It adds in-process attributes such as RPC service, TLS config, Triple config, application, shutdown, provider, and registry config. -6. It exports through `extension.GetProtocol(protocolwrapper.FILTER)` so filters wrap the concrete protocol. -7. It records metadata and registers provider URLs or service instances. - -## Proxy Flow - -- `proxy.Proxy` is used for generated or reflective client callbacks. -- Proxy factories are registered under `common/extension/proxy_factory.go`. -- `proxy/proxy_factory/default.go` handles reflective calls; pass-through proxy handles direct invocation. - -## Shutdown Flow - -- Runtime registers protocols with `graceful_shutdown`. -- Protocol `Destroy` should close invokers and unexport providers. -- Registry-only unregister behavior should use `base.RegistryUnregisterer` when supported. - -## Contract Checks - -- Keep params and attributes consistent between consumer and provider URL construction. -- Do not assume one protocol per service. -- Keep direct URL and registry URL behavior equivalent after URL normalization. diff --git a/.agents/skills/dubbo-go-tools/SKILL.md b/.agents/skills/dubbo-go-tools/SKILL.md deleted file mode 100644 index eab6e8ea68..0000000000 --- a/.agents/skills/dubbo-go-tools/SKILL.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -name: dubbo-go-tools -description: >- - Implements and reviews dubbo-go developer tools and code generation. Use when the user asks about tools/dubbogo-cli, - tools/dubbo-go-schema, tools/protoc-gen-go-triple, tools/protoc-gen-triple-openapi, tools/imports-formatter, - tools/variadicrpccheck, generated Triple code, OpenAPI generation, schema output, import formatting, RPC contract - scanning, Makefile targets, or nested tool modules under tools/. Do not use for runtime protocol behavior unless the - generator output contract is the issue. ---- - -# dubbo-go Tools - -## Purpose - -Use this skill to change or explain dubbo-go developer tooling, generators, schema helpers, CLI behavior, import formatting, and contract scanning. - -## When to use - -Use for `tools/` changes, generated code templates, protoc plugins, schema generation, CLI commands, Makefile tool targets, and nested tool module validation. - -Do not use for runtime protocol behavior unless the generated code contract is the changed behavior. - -## Inputs - -Required: -- Tool name, command, generated file, template, or package path. -- Intended tool behavior or observed failure. - -Optional: -- CLI arguments, proto input, generated output diff, schema sample, or build/test output. - -If missing, inspect the specific tool README and its local `go.mod` when present. - -## Workflow - -1. Identify whether the change affects a root-module tool or a nested Go module under `tools/`. -2. Read the tool README and command entrypoint. -3. Inspect templates or generated output contracts before changing generator code. -4. For Makefile behavior, read the root `Makefile` and any nested module commands. -5. For generated runtime code, coordinate with `dubbo-go-protocol` only when wire or invocation semantics change. -6. Read `references/tooling-flow.md` before changing generators or validation commands. - -## Output format - -Return tool entrypoint, input and output contract, changed files, validation commands, and any runtime compatibility impact. - -## Validation - -- Run tests from the owning module directory when the tool has its own `go.mod`. -- Run root commands for root-module tools, such as `go test ./tools/variadicrpccheck` or `make rpc-contract-check`. -- Confirm generated output is deterministic. -- Run `make fmt` or the tool-specific formatter only when code changes require it. - -## Edge cases - -- Several `tools/` subdirectories are nested Go modules and should be tested from their own directory. -- Generated code can affect public APIs even when the generator change is small. -- `imports-formatter` is part of `make fmt`; avoid changing import output without checking repository formatting expectations. - -## References - -- Read `references/tooling-flow.md` for tool modules, entrypoints, and validation details. diff --git a/.agents/skills/dubbo-go-tools/references/tooling-flow.md b/.agents/skills/dubbo-go-tools/references/tooling-flow.md deleted file mode 100644 index b3f76afb1e..0000000000 --- a/.agents/skills/dubbo-go-tools/references/tooling-flow.md +++ /dev/null @@ -1,29 +0,0 @@ -# Tooling Flow - -## Tool Areas - -- `tools/dubbogo-cli`: CLI for bootstrapping and managing dubbo-go applications. It has its own Go module. -- `tools/dubbo-go-schema`: schema support for dubbo-go configuration files. -- `tools/protoc-gen-go-triple`: protoc plugin for Triple client and server code. It has its own Go module. -- `tools/protoc-gen-triple-openapi`: OpenAPI generator for Triple. It has its own Go module. -- `tools/imports-formatter`: import formatting helper used by `make fmt`. It has its own Go module. -- `tools/variadicrpccheck`: root-module scanner for exported variadic RPC contracts. - -## Root Make Targets - -- `make test`: runs root tests and `tools/dubbogo-cli` tests. -- `make fmt`: runs modernize, `go fmt`, `imports-formatter`, and CLI formatting. -- `make lint`: runs `go vet` and `golangci-lint`. -- `make rpc-contract-check`: runs the variadic RPC contract scanner. - -## Generator Checks - -1. Identify the source input format, usually proto files or config models. -2. Inspect the generated output expected by tests. -3. Keep output deterministic: stable ordering, stable import grouping, stable comments. -4. Run tests in the nested module that owns the generator. -5. When generated runtime code changes, run relevant protocol or server/client tests in the root module. - -## Nested Module Rule - -When a tool has its own `go.mod`, run `go test ./...` from that tool directory. Do not assume root `go test ./...` covers it. diff --git a/.agents/skills/extensions/SKILL.md b/.agents/skills/extensions/SKILL.md new file mode 100644 index 0000000000..d37463e68d --- /dev/null +++ b/.agents/skills/extensions/SKILL.md @@ -0,0 +1,269 @@ +--- +name: dubbo-go-extensions +description: Use when implementing or explaining dubbo-go extension points such as filters, load balancers, registries, protocols, routers, loggers, config centers, metrics, tracing, or custom SPI integration. +--- + + + + +# Writing dubbo-go Extensions + +## Overview + +Every dubbo-go extension follows the same four-step pattern: implement the interface, register a factory in `init()` through `dubbo.apache.org/dubbo-go/v3/common/extension`, blank-import the package, then activate by name. The string passed to `extension.SetXxx("name", ...)` is the contract - code-API options and YAML must use the exact same name. + +## When to Use + +- Adding a custom Filter, LoadBalance, Router, Registry, Protocol, ConfigCenter, or Logger backend +- Wiring an existing SPI into an application via blank import +- Diagnosing "filter not found", "loadbalance not found", or similar registration errors + +## When NOT to Use + +- Built-in filters/load balancers/routers already cover the use case (prefer config over code) +- The user only needs canary/tag/condition routing - use static or dynamic router config from `dubbo-go-guide` +- The change is application boilerplate - use `dubbo-go-scaffolding` + +## Pick the Extension Point + +| Need | Extension point | Register with | +|---|---|---| +| Intercept RPC calls | `filter.Filter` | `extension.SetFilter` | +| Choose one provider | `loadbalance.LoadBalance` | `extension.SetLoadbalance` | +| Filter provider lists | `router.PriorityRouterFactory` | `extension.SetRouterFactory` | +| Add service discovery backend | `registry.Registry` | `extension.SetRegistry` | +| Add wire protocol | `base.Protocol` | `extension.SetProtocol` | +| Add config center | `config_center.DynamicConfigurationFactory` | `extension.SetConfigCenterFactory` | +| Add logger backend | `logger.Logger` | `extension.SetLogger` | + +The name string is the contract. The string in `SetXxx("name", ...)` must match the string used in code API or YAML. + +## Filter + +Use filters for auth, token injection, tracing, metrics, rate limiting, logging, and graceful shutdown behavior. + +```go +package timing + +import ( + "context" + "time" +) + +import ( + "github.com/dubbogo/gost/log/logger" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/filter" + "dubbo.apache.org/dubbo-go/v3/protocol/base" + "dubbo.apache.org/dubbo-go/v3/protocol/result" +) + +func init() { + extension.SetFilter("timing", func() filter.Filter { return &timingFilter{} }) +} + +type timingFilter struct{} + +func (f *timingFilter) Invoke(ctx context.Context, invoker base.Invoker, inv base.Invocation) result.Result { + start := time.Now() + res := invoker.Invoke(ctx, inv) + logger.Infof("call %s took %s", inv.MethodName(), time.Since(start)) + return res +} + +func (f *timingFilter) OnResponse(ctx context.Context, res result.Result, invoker base.Invoker, inv base.Invocation) result.Result { + return res +} +``` + +Activate: + +```go +import _ "github.com/yourorg/yourapp/filter/timing" + +_ = pb.RegisterGreetServiceHandler(srv, impl, server.WithFilter("timing")) +svc, _ := pb.NewGreetService(cli, client.WithFilter("timing")) +``` + +Server-wide and client-wide defaults also exist: + +```go +server.NewServer(server.WithServerFilter("timing")) +client.NewClient(client.WithClientFilter("timing")) +``` + +Multiple filters use comma-separated names, for example `server.WithFilter("timing,auth")`. + +## LoadBalance + +Implement this interface: + +```go +type LoadBalance interface { + Select([]base.Invoker, base.Invocation) base.Invoker +} +``` + +Example: + +```go +func init() { + extension.SetLoadbalance("tenant-affinity", func() loadbalance.LoadBalance { + return &tenantAffinity{} + }) +} + +type tenantAffinity struct{} + +func (lb *tenantAffinity) Select(invokers []base.Invoker, inv base.Invocation) base.Invoker { + tenant := inv.Attachment("tenant-id") + for _, iv := range invokers { + if iv.GetURL().GetParam("tenant", "") == tenant { + return iv + } + } + if len(invokers) == 0 { + return nil + } + return invokers[0] +} +``` + +Activate per reference or client: + +```go +svc, _ := pb.NewGreetService(cli, client.WithLoadBalance("tenant-affinity")) +cli, _ := client.NewClient(client.WithClientLoadBalance("tenant-affinity")) +``` + +Built-ins include Random, RoundRobin, LeastActive, ConsistentHashing, P2C, and adaptive strategies. + +## Router + +Routers run before load balancing and can prune the invoker list. Current built-ins include condition, tag, script, affinity, and Polaris routers. + +Custom routers are uncommon. If the user only wants canary, tags, condition rules, or traffic split, prefer built-in routers and static/dynamic router config. + +Custom router shape: + +```go +type PriorityRouterFactory interface { + NewPriorityRouter(url *common.URL) (router.PriorityRouter, error) +} + +type PriorityRouter interface { + Route([]base.Invoker, *common.URL, base.Invocation) []base.Invoker + URL() *common.URL + Priority() int64 + Notify([]base.Invoker) +} +``` + +Register with: + +```go +extension.SetRouterFactory("my-router", func() router.PriorityRouterFactory { + return &myFactory{} +}) +``` + +Routers that accept static config can also implement `router.StaticConfigSetter`. + +## Registry + +Only write a registry if Nacos, ZooKeeper, etcd v3, or Polaris do not fit. + +```go +func init() { + extension.SetRegistry("myregistry", func(url *common.URL) (registry.Registry, error) { + return newMyRegistry(url) + }) +} +``` + +Implement `registry.Registry`: `Register`, `UnRegister`, `Subscribe`, `UnSubscribe`, and `LoadSubscribeInstances`. Study `registry/nacos`, `registry/zookeeper`, or `registry/etcdv3` before creating a new backend. + +Activate: + +```go +dubbo.WithRegistry( + registry.WithRegistry("myregistry"), + registry.WithAddress("127.0.0.1:1234"), +) +``` + +Registry options now also control metadata/config-center use and registration mode: + +```go +registry.WithRegisterService() +registry.WithRegisterInterface() +registry.WithRegisterServiceAndInterface() +registry.WithoutUseAsMetaReport() +registry.WithoutUseAsConfigCenter() +``` + +## Protocol + +Most users should not implement a protocol. Use Triple, Dubbo, JSONRPC, REST, or gRPC-compatible Triple unless there is a strong reason. + +Protocol interface: + +```go +type Protocol interface { + Export(base.Invoker) base.Exporter + Refer(*common.URL) base.Invoker + Destroy() +} +``` + +HTTP-backed protocols can optionally implement `base.HTTPHandlerHost` to support `server.AttachHTTPHandler`. + +## Config Center and Logger + +Config centers use `extension.SetConfigCenterFactory` or `extension.SetConfigCenter`. Existing backends include file, Nacos, ZooKeeper, and Apollo. + +Logger backends use: + +```go +extension.SetLogger("driver", func(url *common.URL) (logger.Logger, error) { + return newLogger(url) +}) +``` + +Current logger config supports driver, level, format, appender, file rolling config, and trace integration. + +## Troubleshooting + +| Symptom | Check | +|---|---| +| `filter not found` | Missing blank import or name mismatch | +| Filter never runs | The package containing `init()` is not imported | +| Custom LB ignored | Use `client.WithLoadBalance` or `client.WithClientLoadBalance` with the registered name | +| Router rule ignored | Confirm router factory name and whether rule is static, dynamic, service-scope, or application-scope | +| Registry not selected | Check registry ID and `WithRegistryIDs` | +| Metadata mapping missing | Use metadata report or set `client.WithProvidedBy` | +| Attached HTTP handler fails | Only Triple supports hosting it; attach before `Serve` and use an explicit port | + +## Related Skills + +- `dubbo-go-guide` - when deciding whether a built-in already covers the need before writing custom SPI +- `dubbo-go-scaffolding` - when the user also needs the surrounding provider/consumer skeleton +- `dubbo-go-debugging` - when an SPI is registered but does not run (missing blank import, name mismatch) diff --git a/.agents/skills/guide/SKILL.md b/.agents/skills/guide/SKILL.md new file mode 100644 index 0000000000..230ae8e6bd --- /dev/null +++ b/.agents/skills/guide/SKILL.md @@ -0,0 +1,218 @@ +--- +name: dubbo-go-guide +description: Use when explaining dubbo-go concepts, architecture, current v3 APIs, protocols, registries, routers, filters, OpenAPI, graceful shutdown, observability, samples, or best practices. +--- + + + + +# Guiding dubbo-go Development + +## Overview + +Develop-branch map for dubbo-go v3: code API first, Triple as the default wire protocol, application-level discovery as the default registration mode. Reach for this skill when the user asks "how does X work" or "which sample should I follow"; switch to `dubbo-go-scaffolding` when generating an app, `dubbo-go-extensions` when adding an SPI, or `dubbo-go-debugging` when troubleshooting a runtime failure. + +## When to Use + +- Conceptual questions: instance/server/client/protocol/registry/cluster/router/filter +- Choosing between Triple, Dubbo, JSONRPC, REST, gRPC-compatible Triple, HTTP/3 +- Pointing the user to the right `dubbo-go-samples` directory +- Explaining OpenAPI, CORS, AttachHTTPHandler, graceful shutdown, observability defaults + +## Project Snapshot + +- Module: `dubbo.apache.org/dubbo-go/v3` +- Go version in `go.mod`: `1.25.0` +- Main entry points: `dubbo.NewInstance`, `server.NewServer`, `client.NewClient` +- Preferred user style: code API +- Legacy/compat style: YAML-driven `dubbo.Load()` / `config.Load()` still exists and now uses koanf-based loading +- Preferred wire protocol: Triple +- Important recent capabilities: Triple OpenAPI, HTTP/3, CORS, attached HTTP handlers, refined graceful shutdown, logger trace integration, router static config, `variadicrpccheck` + +## Repository Map + +- `client/`: consumer/reference options, URL processing, invoker construction +- `server/`: provider/server options, service registration, `AttachHTTPHandler` +- `protocol/`: protocol abstractions and implementations; `protocol/triple` is the primary path +- `registry/`: registry and application-level service discovery implementations +- `metadata/`: metadata report and service-to-application mapping +- `cluster/`: cluster strategies, router chain, load balancing +- `filter/`: provider and consumer filter implementations +- `config/`, `global/`: YAML/config structs and runtime config models +- `config_center/`: Nacos, ZooKeeper, Apollo, and file dynamic config +- `graceful_shutdown/`: shutdown options and runtime state +- `metrics/`, `otel/`, `logger/`: observability integrations +- `tools/`: CLI, schema generator, Triple/OpenAPI generators, imports formatter, RPC contract scanner + +## Core Concepts + +**Instance**: global application context. Use `dubbo.NewInstance` when sharing application, registry, protocol, logger, shutdown, metrics, tracing, TLS, or router settings across clients and servers. + +**Server**: owns provider-side config and service exports. Register generated Triple handlers with `pb.RegisterXxxHandler`. + +**Client**: owns consumer-side config. Create generated service clients with `pb.NewXxxService`. + +**Protocol**: wire transport. Triple is HTTP/2 and gRPC-compatible; Dubbo is for legacy Hessian2 interop; JSONRPC and REST also exist; HTTP/3 is experimental under Triple. + +**Registry**: service discovery. Built-ins include Nacos, ZooKeeper, etcd v3, and Polaris. + +**Metadata mapping**: application-level discovery needs a mapping from interface to provider application. If metadata mapping is unavailable, use `client.WithProvidedBy("provider-app")`. + +**Filter**: interceptor chain around RPC calls. Filters run on provider and consumer paths and are used for auth, metrics, tracing, rate limiting, graceful shutdown, logging, and generic calls. + +**Cluster**: fault-tolerance strategy such as Failover, Failfast, Failsafe, Failback, Available, Broadcast, Forking, ZoneAware, and AdaptiveService. + +**LoadBalance**: provider selection. Built-ins include Random, RoundRobin, LeastActive, ConsistentHashing, P2C, and adaptive strategies. + +**Router**: filters providers before load balancing. Built-ins include tag, condition, script, affinity, and Polaris routers. Static router config can be supplied through client/root router options; dynamic rules can come from config centers. + +## Current API Patterns + +Direct server: + +```go +srv, err := server.NewServer( + server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithTriple(), + ), +) +``` + +Registry-backed instance: + +```go +ins, err := dubbo.NewInstance( + dubbo.WithName("orders-provider"), + dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")), + dubbo.WithProtocol(protocol.WithTriple(), protocol.WithPort(20000)), +) +``` + +Reference options: + +```go +svc, err := pb.NewOrderService( + cli, + client.WithInterface("shop.OrderService"), + client.WithProvidedBy("orders-provider"), + client.WithRequestTimeout(3*time.Second), +) +``` + +Service options: + +```go +err := pb.RegisterOrderServiceHandler( + srv, + impl, + server.WithInterface("shop.OrderService"), + server.WithGroup("beta"), + server.WithVersion("v2"), + server.WithOpenAPIGroup("orders-v2"), +) +``` + +## Extension Pattern + +Most extension points follow: + +1. Implement the interface. +2. Register a factory in `init()` through `common/extension`. +3. Blank-import the package so `init()` runs. +4. Activate by name through code API or config. + +Examples: + +- Filter: `extension.SetFilter("name", func() filter.Filter { ... })` +- LoadBalance: `extension.SetLoadbalance("name", func() loadbalance.LoadBalance { ... })` +- Registry: `extension.SetRegistry("name", func(*common.URL) (registry.Registry, error) { ... })` +- Protocol: `extension.SetProtocol("name", func() base.Protocol { ... })` +- Router: `extension.SetRouterFactory("name", func() router.PriorityRouterFactory { ... })` + +The string name is the contract. Keep registration and activation names identical. + +## Triple Extras + +OpenAPI: + +```go +protocol.WithTriple( + triple.WithOpenAPI( + triple.OpenAPIEnable(), + triple.OpenAPIPath("/dubbo/openapi"), + ), +) +``` + +CORS: + +```go +protocol.WithTriple( + triple.WithCORS( + triple.CORSAllowOrigins("https://example.com"), + triple.CORSAllowMethods("POST", "GET", "OPTIONS"), + ), +) +``` + +HTTP/3: + +```go +protocol.WithTriple(triple.Http3Enable()) +``` + +Attached HTTP handler: + +```go +_ = srv.AttachHTTPHandler(mux) +``` + +Attach before `Serve`, use one root handler, and configure an explicit Triple port. + +## Samples + +See [samples-index.md](samples-index.md) for the current dubbo-go-samples map. + +Start with: + +- `helloworld`: minimal direct Triple +- `direct`: direct URL connection +- `registry/nacos`: Nacos service discovery +- `rpc/triple/openapi`: runtime Triple OpenAPI +- `http3`: experimental HTTP/3 +- `graceful_shutdown`: shutdown flow +- `logger/trace-integration`: trace IDs in logs + +## Best Practices + +- Prefer Protobuf plus Triple for new services. +- Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` for examples and local demos; use selective blank imports in production when binary size matters. +- Use code API for new code; keep YAML only for existing config-driven applications. +- Use `client.WithProvidedBy` when application-level discovery cannot resolve interface-to-application mapping. +- Do not assume viper APIs in config work; current loading is koanf-centered. +- Run repository validation commands from the development skill before finishing code changes. + +## Related Skills + +- `dubbo-go-scaffolding` - when the user wants to generate a provider/consumer instead of read about it +- `dubbo-go-extensions` - when explaining a built-in is not enough and the user needs a custom SPI +- `dubbo-go-java-interop` - when the question involves dubbo-java compatibility +- `dubbo-go-debugging` - when the question is "why is X failing" rather than "how does X work" +- `dubbo-go-migration` - when the question is "how do I move from Y to dubbo-go" +- `dubbo-go-development` - when the explanation must dig into the `apache/dubbo-go` repo internals diff --git a/.agents/skills/guide/samples-index.md b/.agents/skills/guide/samples-index.md new file mode 100644 index 0000000000..b08f038937 --- /dev/null +++ b/.agents/skills/guide/samples-index.md @@ -0,0 +1,119 @@ + + +# dubbo-go-samples Index + +Use this index when a user asks which example to follow. Paths refer to `https://github.com/apache/dubbo-go-samples/tree/main/`. + +## Quick Start + +- `helloworld` - minimal Triple/Protobuf provider and consumer +- `direct` - direct URL connection without registry +- `config_yaml` - YAML-driven provider and consumer +- `context` - context propagation +- `error` - error behavior + +## Protocols + +- `rpc/triple/pb` - Triple with Protobuf +- `rpc/triple/pb2` - additional Triple Protobuf variant +- `rpc/triple/pb-json` - Triple JSON behavior +- `rpc/triple/instance` - `dubbo.NewInstance` style +- `rpc/triple/registry` - Triple with registry +- `rpc/triple/reflection` - reflection +- `rpc/triple/stream` - Triple streaming +- `rpc/triple/openapi` - runtime OpenAPI docs for Triple +- `rpc/triple/old_triple` - old Triple compatibility +- `rpc/grpc` - gRPC interop pattern +- `rpc/multi-protocols` - multiple protocols on one server +- `http3` - experimental Triple HTTP/3 + +## Service Discovery + +- `registry/nacos` +- `registry/zookeeper` +- `registry/etcd` +- `registry/polaris` +- `config_center/nacos` +- `config_center/zookeeper` +- `config_center/apollo` + +## Filters and Resilience + +- `filter/custom` - custom filters +- `filter/token` - token filter +- `filter/tpslimit` - TPS limiting +- `filter/sentinel` - Sentinel flow control +- `filter/hystrix` - Hystrix-style circuit breaker +- `filter/polaris/limit` - Polaris limit integration +- `retry` - retry behavior +- `timeout` - timeout behavior +- `graceful_shutdown` - graceful shutdown behavior + +## Traffic Management + +- `router/tag` - tag routing +- `router/condition` - condition routing +- `router/script` - script routing +- `router/static_config/tag` - static tag router config +- `router/static_config/condition` - static condition router config +- `router/polaris` - Polaris router integration +- `mesh` - proxyless mesh scenario +- `apisix` - APISIX gateway integration + +## Streaming and Async + +- `streaming` +- `async` + +## Observability and Operations + +- `metrics/prometheus_grafana` +- `metrics/probe` +- `otel/tracing/jaeger` +- `otel/tracing/otlp_http_exporter` +- `otel/tracing/stdout` +- `logger/default` +- `logger/level` +- `logger/rolling` +- `logger/custom` +- `logger/trace-integration` +- `healthcheck` + +## Security + +- `tls` +- `filter/token` + +## Java Interop + +- `java_interop/protobuf-triple` +- `java_interop/non-protobuf-dubbo` +- `java_interop/non-protobuf-triple` +- `java_interop/service_discovery` +- `helloworld` - includes Go and Java sides +- `direct` - includes Go and Java direct mode +- `http3` - includes Java HTTP/3 sample + +## Advanced + +- `generic` - generic invocation +- `llm` - LLM-related sample +- `book-flight-ai-agent` - AI agent sample +- `game` +- `online_boutique` +- `transcation/seata-go` - Seata transaction sample; upstream directory name is intentionally misspelled `transcation` diff --git a/.agents/skills/java-interop/SKILL.md b/.agents/skills/java-interop/SKILL.md new file mode 100644 index 0000000000..354d1b4fa8 --- /dev/null +++ b/.agents/skills/java-interop/SKILL.md @@ -0,0 +1,232 @@ +--- +name: dubbo-go-java-interop +description: Use when connecting dubbo-go v3 with dubbo-java, choosing Triple versus Dubbo protocol, sharing Protobuf contracts, mirroring Java interfaces, handling Hessian2 POJOs, or debugging cross-language discovery and serialization. +--- + + + + +# Dubbo Java and Go Interoperability + +## Overview + +Two interop paths, one decision: Triple + Protobuf for everything new and polyglot; Dubbo + Hessian2 only when the Java side already owns a non-proto interface. Picking the wrong path locks the team into bespoke serialization code. + +## When to Use + +- Bridging a Go service to existing Java Dubbo providers/consumers +- Choosing protocol/serialization for a new cross-language service +- Diagnosing `hessian: failed to decode`, missing-provider, or class-name-mismatch errors across languages + +## Path Selection + +| Path | Protocol | Serialization | Use when | +|---|---|---|---| +| Triple + Protobuf | Triple over HTTP/2 | Protobuf | New services, polyglot teams, gRPC-compatible clients, OpenAPI docs | +| Dubbo + Hessian2 | Dubbo TCP | Hessian2 | Existing Java Dubbo interfaces with POJO request/response classes | + +## Triple + Protobuf + +Shared `.proto`: + +```protobuf +syntax = "proto3"; + +package org.apache.dubbo.sample; + +option go_package = "github.com/yourorg/yourapp/proto;greet"; +option java_package = "org.apache.dubbo.sample"; +option java_multiple_files = true; + +service Greeter { + rpc SayHello(HelloRequest) returns (HelloReply); +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} +``` + +Go server: + +```go +srv, err := server.NewServer( + server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithTriple(), + ), +) +if err != nil { + return err +} + +if err := greet.RegisterGreeterHandler(srv, &impl{}); err != nil { + return err +} +return srv.Serve() +``` + +Triple exposes JSON-over-HTTP, which is useful for smoke tests: + +```bash +curl -H "Content-Type: application/json" \ + -d '{"name":"Dubbo"}' \ + http://127.0.0.1:20000/org.apache.dubbo.sample.Greeter/SayHello +``` + +The path is `/./`. Use the method name from the `.proto` file, for example `Greet` or `SayHello`. + +## Triple Interop Rules + +- `package` in `.proto` controls the Triple service path. +- `go_package` controls Go package path and package name. +- `java_package` controls Java generated classes and interface package. +- Renaming proto package, service, or method names is a wire-level breaking change. +- Use the same `.proto` source for Go and Java generation. +- Triple supports reflection and HTTP-friendly testing; use OpenAPI when documenting REST-like access for humans. + +## Dubbo + Hessian2 + +Use this for Java-defined services without Protobuf. The Go side must mirror Java classes and register POJOs. + +```go +package greet + +import ( + dubbohessian "github.com/apache/dubbo-go-hessian2" +) + +type GreetRequest struct { + Name string +} + +func (*GreetRequest) JavaClassName() string { + return "org.apache.dubbo.hessian2.api.GreetRequest" +} + +type GreetResponse struct { + Greeting string +} + +func (*GreetResponse) JavaClassName() string { + return "org.apache.dubbo.hessian2.api.GreetResponse" +} + +func init() { + dubbohessian.RegisterPOJO(new(GreetRequest)) + dubbohessian.RegisterPOJO(new(GreetResponse)) +} +``` + +Server protocol: + +```go +srv, err := server.NewServer( + server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithDubbo(), + ), +) +``` + +Consumer reference: + +```go +svc, err := greet.NewGreetingsService( + cli, + client.WithProtocolDubbo(), + client.WithSerialization("hessian2"), +) +``` + +## Hessian2 Rules + +- Every POJO type must implement `JavaClassName()` and be registered with `RegisterPOJO`. +- Fully-qualified Java class names must match exactly. +- Prefer primitives, strings, slices, maps, and registered nested POJOs. +- Avoid Go-only shapes such as channels, functions, and generics in RPC DTOs. +- Java enum mapping depends on Java-side serialization; verify before assuming string values. +- `hessian: failed to decode` usually means class name mismatch, missing `RegisterPOJO`, field/type mismatch, or wrong protocol/serialization. + +## Service Discovery Across Languages + +Use the same registry cluster and compatible registry mode on both sides. + +Provider: + +```go +ins, err := dubbo.NewInstance( + dubbo.WithName("polyglot-provider"), + dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")), + dubbo.WithProtocol(protocol.WithTriple(), protocol.WithPort(20000)), +) +``` + +Consumer: + +```go +svc, err := greet.NewGreeterService( + cli, + client.WithInterface("org.apache.dubbo.sample.Greeter"), + client.WithProvidedBy("polyglot-provider"), +) +``` + +`WithProvidedBy` is useful when application-level service discovery cannot load interface-to-application mapping from the metadata center. + +Registry modes: + +```go +registry.WithRegisterService() +registry.WithRegisterInterface() +registry.WithRegisterServiceAndInterface() +``` + +Use `WithRegisterServiceAndInterface` when bridging old interface-level discovery and newer application-level discovery during migration. + +## Decision Table + +| Scenario | Choice | +|---|---| +| New Go and Java service | Triple + Protobuf | +| Java service already has `.proto` | Triple + Protobuf | +| Existing Java interface only, no proto | Dubbo + Hessian2 | +| Need browser/curl smoke tests or OpenAPI docs | Triple + Protobuf | +| Need to preserve old Java POJOs exactly | Dubbo + Hessian2 | +| Metadata mapping is missing | Add metadata report or set `client.WithProvidedBy` | + +## Reference Samples + +- `dubbo-go-samples/java_interop/protobuf-triple` +- `dubbo-go-samples/java_interop/non-protobuf-dubbo` +- `dubbo-go-samples/java_interop/non-protobuf-triple` +- `dubbo-go-samples/java_interop/service_discovery` +- `dubbo-go-samples/helloworld` +- `dubbo-go-samples/direct` +- `dubbo-go-samples/http3` + +## Related Skills + +- `dubbo-go-scaffolding` - when generating the Go side of a polyglot service +- `dubbo-go-extensions` - when adding a Hessian2 codec, Java-aware filter, or custom registry shared with Java +- `dubbo-go-migration` - when porting an existing Java Dubbo service or splitting a Spring Cloud monolith +- `dubbo-go-debugging` - when the symptom is `hessian: failed to decode`, missing provider across languages, or registry-mode mismatch diff --git a/.agents/skills/migrate/SKILL.md b/.agents/skills/migrate/SKILL.md new file mode 100644 index 0000000000..692ce794e3 --- /dev/null +++ b/.agents/skills/migrate/SKILL.md @@ -0,0 +1,190 @@ +--- +name: dubbo-go-migration +description: Use when migrating to dubbo-go v3 from gRPC-Go, Spring Cloud, Gin, plain HTTP, older dubbo-go versions, YAML-based apps, Java Dubbo, or legacy Hessian2 services. +--- + + + + +# Migrating to dubbo-go + +## Overview + +Migration is mostly mechanical: the source framework decides the concept-mapping table, then dubbo-go v3 code-API patterns slot in. Triple + Protobuf is the default target; Dubbo + Hessian2 is reserved for Java-interface services without a `.proto`. + +## Source-System Decision Table + +| User says | Jump to | +|---|---| +| "We're on gRPC-Go" | [From gRPC-Go](#from-grpc-go) | +| "Spring Cloud / Java Dubbo" | [From Spring Cloud or Java Dubbo](#from-spring-cloud-or-java-dubbo) | +| "Gin / chi / net/http" | [From Gin or Plain HTTP](#from-gin-or-plain-http) | +| "Old dubbo-go v1/v2 or YAML-heavy v3" | [From dubbo-go v1/v2 or Old v3 YAML](#from-dubbo-go-v1v2-or-old-v3-yaml) | +| "Java owns the contract, no proto" | [From Java-interface Hessian2](#from-java-interface-hessian2) | + +Use code API for new work and keep YAML only when preserving an existing deployment model. + +## From gRPC-Go + +Concept mapping: + +| gRPC-Go | dubbo-go v3 | +|---|---| +| `grpc.NewServer()` | `server.NewServer()` | +| `pb.RegisterXxxServer(srv, impl)` | `pb.RegisterXxxHandler(srv, impl)` | +| `grpc.Dial` / `grpc.NewClient` | `client.NewClient()` + `pb.NewXxxService(cli)` | +| Unary interceptor | Filter | +| Service config / resolver | Registry + cluster + load balance | +| Reflection | Triple reflection sample and OpenAPI support | + +Protobuf can usually be reused. Generate Triple bindings: + +```bash +go install github.com/dubbogo/protoc-gen-go-triple/v3@latest +protoc --go_out=. --go_opt=paths=source_relative \ + --go-triple_out=. --go-triple_opt=paths=source_relative \ + proto/*.proto +``` + +Direct-mode consumer: + +```go +cli, err := client.NewClient( + client.WithClientURL("127.0.0.1:20000"), +) +svc, err := pb.NewGreetService(cli) +``` + +Add a registry later with `dubbo.NewInstance` and `dubbo.WithRegistry`. + +## From Spring Cloud or Java Dubbo + +Concept mapping: + +| Spring Cloud / Dubbo Java | dubbo-go v3 | +|---|---| +| Discovery client | `dubbo.WithRegistry(...)` | +| Feign/Dubbo reference | generated `pb.NewXxxService(cli, ...)` | +| Controller or Dubbo provider | `pb.RegisterXxxHandler(srv, impl, ...)` | +| Hystrix / Sentinel | Hystrix or Sentinel filters | +| Sleuth / tracing | OpenTelemetry integration | +| Actuator health | `metrics/probe` sample | +| Java interface + POJO | Dubbo protocol + Hessian2 | + +Migration path: + +1. Keep existing Java services running. +2. Use Triple + Protobuf for new Go services where possible. +3. Use Dubbo + Hessian2 only when the Java side has no proto contract. +4. Share registry and metadata mapping. If mapping is not available, use `client.WithProvidedBy`. +5. During transition, use `registry.WithRegisterServiceAndInterface()` when both app-level and interface-level discovery are needed. + +## From Gin or Plain HTTP + +dubbo-go is primarily an RPC and service governance framework, but current develop provides three practical migration options. + +Option A: keep HTTP externally, add dubbo-go internally. + +- Gin/http handles public REST. +- dubbo-go handles service-to-service RPC. +- Run both in one process if lifecycle is clear. + +Option B: attach existing HTTP routes to the Triple listener. + +```go +mux := http.NewServeMux() +mux.HandleFunc("/healthz", healthz) + +srv, _ := server.NewServer( + server.WithServerProtocol( + protocol.WithTriple(), + protocol.WithIp("127.0.0.1"), + protocol.WithPort(20000), + ), +) +_ = srv.AttachHTTPHandler(mux) +``` + +Rules: attach before `Serve`, attach one root handler, and use an explicit Triple port. + +Option C: move APIs to Protobuf + Triple and expose JSON-over-HTTP plus OpenAPI. + +```go +server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithTriple( + triple.WithOpenAPI(triple.OpenAPIEnable()), + ), +) +``` + +OpenAPI endpoints default to `/dubbo/openapi`. + +## From dubbo-go v1/v2 or Old v3 YAML + +Important changes: + +| Old style | Current v3 develop | +|---|---| +| Mostly YAML/config globals | Code API preferred | +| `config.Load()` as main entry | `dubbo.NewInstance()` for new apps; `dubbo.Load()`/`config.Load()` for compatibility | +| Interface-based Hessian2 default | Protobuf + Triple preferred | +| Global provider/consumer service registration | Generated `RegisterXxxHandler` and `NewXxxService` helpers | +| viper assumptions | koanf-based loading in current config path | +| Older `protocol` aliases | Prefer `protocol/base` and `protocol/result` packages in new extension code | + +Migration sequence: + +1. Move service contracts to `.proto` when possible. +2. Generate `*.pb.go` and `*.triple.go`. +3. Replace global registration with generated server/client helpers. +4. Move registry/protocol/application config to `dubbo.NewInstance`. +5. Keep YAML only for externally managed config and test it with `config_yaml` patterns. +6. Run `make rpc-contract-check` if exposed RPC methods use variadic parameters. + +## From Java-interface Hessian2 + +If Java owns the contract and there is no `.proto`, do not invent a partial proto. Mirror Java request/response POJOs in Go, implement `JavaClassName()`, register them with `dubbo-go-hessian2`, and use Dubbo protocol. + +See the Java interop skill for exact POJO and protocol rules. + +## Validation + +For application migration: + +```bash +go mod tidy +go test ./... +``` + +For changes inside the dubbo-go repository: + +```bash +make fmt +GOTOOLCHAIN=go1.25.0+auto go test ./... +make rpc-contract-check +``` + +Use targeted package tests first when the migration touches only one area. + +## Related Skills + +- `dubbo-go-scaffolding` - for the target-side provider/consumer skeleton after the source-side mapping is decided +- `dubbo-go-java-interop` - when the migration crosses the Java/Go boundary (Hessian2 POJO rules live there) +- `dubbo-go-extensions` - when porting a custom filter/LB/registry from gRPC-Go interceptors or Spring Cloud beans +- `dubbo-go-debugging` - when the migrated service starts but does not register, route, or decode diff --git a/.agents/skills/scaffolding/SKILL.md b/.agents/skills/scaffolding/SKILL.md new file mode 100644 index 0000000000..3f4486a9dd --- /dev/null +++ b/.agents/skills/scaffolding/SKILL.md @@ -0,0 +1,323 @@ +--- +name: dubbo-go-scaffolding +description: Use when creating, bootstrapping, or updating a dubbo-go v3 provider, consumer, sample, proto-based service, direct connection demo, registry-backed service, OpenAPI service, or HTTP-mounted Triple service. +--- + + + + +# Scaffolding dubbo-go Services + +## Overview + +Generate dubbo-go v3 provider/consumer skeletons in the current code-API style: `server.NewServer`, `client.NewClient`, and `dubbo.NewInstance`. Reach for YAML only when migrating an existing config-driven app. + +## When to Use + +- New provider, consumer, sample, or `.proto`-based service +- Adding direct mode, registry-backed, OpenAPI, HTTP/3, CORS, or HTTP-handler-mounted variants +- Generating Triple bindings from a fresh `.proto` + +## When NOT to Use + +- The repo already has the skeleton and you only need to add a method or option - edit in place +- The user wants to write a custom SPI extension - use `dubbo-go-extensions` +- The user is migrating from another framework - use `dubbo-go-migration` + +## Current Defaults + +- Module path: `dubbo.apache.org/dubbo-go/v3` +- Go version in `go.mod`: `1.25.0` +- Preferred protocol: Triple (`protocol.WithTriple()`), gRPC-compatible and HTTP-friendly +- Default direct server port in samples: `20000` +- Generated Triple files: `*.pb.go` and `*.triple.go` +- Recommended sample baseline: `dubbo-go-samples/helloworld` + +## Ask First + +Clarify these before generating files: + +1. Protocol: Triple by default; Dubbo/Hessian2 for legacy Java interface interop; gRPC only when explicitly required. +2. Discovery mode: direct URL for local demos; Nacos, ZooKeeper, etcd, or Polaris for service discovery. +3. Service definition: reuse an existing `.proto` if available; otherwise create one with stable `package` and `go_package`. +4. Extras: OpenAPI docs, HTTP/3, CORS, TLS, metrics/probe, or an attached existing `http.Handler`. + +## Layout + +Mirror the sample repository shape: + +```text +myservice/ +|-- go.mod +|-- proto/ +| |-- greet.proto +| |-- greet.pb.go +| `-- greet.triple.go +|-- go-server/cmd/main.go +`-- go-client/cmd/main.go +``` + +`dubbogo-cli newDemo .` can generate a direct-mode demo. Use `dubbogo-cli newApp .` for a larger application template with `api`, `cmd`, `conf`, `pkg`, `build`, and `chart`. + +## Proto + +```protobuf +syntax = "proto3"; + +package greet; + +option go_package = "github.com/yourorg/myservice/proto;greet"; + +message GreetRequest { + string name = 1; +} + +message GreetResponse { + string greeting = 1; +} + +service GreetService { + rpc Greet(GreetRequest) returns (GreetResponse); +} +``` + +Install generators: + +```bash +go install google.golang.org/protobuf/cmd/protoc-gen-go@latest +go install github.com/dubbogo/protoc-gen-go-triple/v3@latest +``` + +Generate: + +```bash +protoc --go_out=. --go_opt=paths=source_relative \ + --go-triple_out=. --go-triple_opt=paths=source_relative \ + proto/greet.proto +``` + +The `.proto` `package` is part of the Triple HTTP path. For the example above, JSON-over-HTTP requests use `/greet.GreetService/Greet`. + +## Direct Provider + +```go +package main + +import ( + "context" +) + +import ( + _ "dubbo.apache.org/dubbo-go/v3/imports" + "dubbo.apache.org/dubbo-go/v3/protocol" + "dubbo.apache.org/dubbo-go/v3/server" + + "github.com/dubbogo/gost/log/logger" +) + +import ( + greet "github.com/yourorg/myservice/proto" +) + +type GreetTripleServer struct{} + +func (s *GreetTripleServer) Greet(ctx context.Context, req *greet.GreetRequest) (*greet.GreetResponse, error) { + return &greet.GreetResponse{Greeting: req.Name}, nil +} + +func main() { + srv, err := server.NewServer( + server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithTriple(), + ), + ) + if err != nil { + logger.Fatalf("failed to create server: %v", err) + } + + if err := greet.RegisterGreetServiceHandler(srv, &GreetTripleServer{}); err != nil { + logger.Fatalf("failed to register greet service handler: %v", err) + } + + if err := srv.Serve(); err != nil { + logger.Fatalf("failed to serve: %v", err) + } +} +``` + +## Direct Consumer + +```go +package main + +import ( + "context" + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/client" + _ "dubbo.apache.org/dubbo-go/v3/imports" + + "github.com/dubbogo/gost/log/logger" +) + +import ( + greet "github.com/yourorg/myservice/proto" +) + +func main() { + cli, err := client.NewClient( + client.WithClientURL("127.0.0.1:20000"), + ) + if err != nil { + logger.Fatalf("failed to create client: %v", err) + } + + svc, err := greet.NewGreetService(cli) + if err != nil { + logger.Fatalf("failed to create greet service: %v", err) + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + resp, err := svc.Greet(ctx, &greet.GreetRequest{Name: "world"}) + if err != nil { + logger.Fatalf("failed to call greet: %v", err) + } + logger.Infof("Greet response: %s", resp.Greeting) +} +``` + +## Registry-backed Provider and Consumer + +Use `dubbo.NewInstance` when provider and consumer should share application, registry, protocol, logger, shutdown, metrics, or tracing config. + +```go +ins, err := dubbo.NewInstance( + dubbo.WithName("myservice-provider"), + dubbo.WithRegistry( + registry.WithNacos(), + registry.WithAddress("127.0.0.1:8848"), + ), + dubbo.WithProtocol( + protocol.WithTriple(), + protocol.WithPort(20000), + ), +) +if err != nil { + logger.Fatalf("new instance: %v", err) +} + +srv, err := ins.NewServer() +if err != nil { + logger.Fatalf("new server: %v", err) +} +``` + +Registry options: + +- Nacos: `registry.WithNacos()` +- ZooKeeper: `registry.WithZookeeper()` +- etcd v3: `registry.WithEtcdV3()` +- Polaris: `registry.WithPolaris()` +- Multiple registries: use `registry.WithID("nacos")` and select with `client.WithRegistryIDs("nacos")` or `server.WithRegistryIDs([]string{"nacos"})` + +For application-level service discovery, a consumer can use metadata mapping or set the provider application explicitly: + +```go +svc, err := greet.NewGreetService( + cli, + client.WithInterface("greet.GreetService"), + client.WithProvidedBy("myservice-provider"), +) +``` + +## OpenAPI, CORS, HTTP/3, HTTP Handler Mount + +Enable runtime OpenAPI docs on Triple: + +```go +server.WithServerProtocol( + protocol.WithPort(20000), + protocol.WithTriple( + triple.WithOpenAPI( + triple.OpenAPIEnable(), + triple.OpenAPIInfoTitle("My Service"), + triple.OpenAPIInfoVersion("1.0.0"), + ), + ), +) +``` + +Useful endpoints: + +- `/dubbo/openapi/openapi.json` +- `/dubbo/openapi/openapi.yaml` +- `/dubbo/openapi/api-docs/default.json` +- `/dubbo/openapi/swagger-ui` +- `/dubbo/openapi/redoc` + +Assign services to a docs group with `server.WithOpenAPIGroup("group-name")`. + +Attach an existing HTTP handler to the same Triple listener: + +```go +mux := http.NewServeMux() +mux.HandleFunc("/healthz", healthz) + +srv, _ := server.NewServer( + server.WithServerProtocol( + protocol.WithTriple(), + protocol.WithIp("127.0.0.1"), + protocol.WithPort(20000), + ), +) +if err := srv.AttachHTTPHandler(mux); err != nil { + logger.Fatalf("attach http handler: %v", err) +} +``` + +Rules: call `AttachHTTPHandler` before `Serve`, attach only one root handler, and configure an explicit Triple port. + +HTTP/3 is experimental and requires TLS-capable setup: + +```go +protocol.WithTriple(triple.Http3Enable()) +``` + +## Validation + +For generated app skeletons: + +```bash +go mod tidy +go test ./... +``` + +For changes inside the dubbo-go repository, use the repository development skill and prefer `make fmt`, targeted `go test`, then broader `make test` when relevant. + +## Related Skills + +- `dubbo-go-guide` - for the broader concept map and current capabilities +- `dubbo-go-extensions` - when scaffolding a service that also needs a custom Filter/LB/Registry +- `dubbo-go-java-interop` - when the new service must talk to dubbo-java +- `dubbo-go-migration` - when the user is moving from gRPC-Go, Spring Cloud, Gin, or older dubbo-go +- `dubbo-go-debugging` - when the new skeleton fails to start, register, or connect From 31d119769f5db2adc8c119ef3bf0733e7f982693 Mon Sep 17 00:00:00 2001 From: Oxidaner <18622412361@163.com> Date: Tue, 26 May 2026 00:07:33 +0800 Subject: [PATCH 3/5] docs: refine dubbo-go agent skills --- .agents/.claude-plugin/marketplace.json | 6 +- .agents/.codex/INSTALL.md | 2 +- .../plugins/dubbo-go-agent-skills.js | 2 +- .agents/GEMINI.md | 2 +- .agents/README.md | 106 +++++-- .agents/README_CN.md | 104 +++++-- .agents/gemini-extension.json | 2 +- .agents/package.json | 4 +- .agents/plugin.json | 6 +- .agents/skills/debug/SKILL.md | 235 ++++++-------- .agents/skills/development/SKILL.md | 156 ++++------ .agents/skills/extensions/SKILL.md | 234 ++++++-------- .agents/skills/guide/SKILL.md | 223 ++++--------- .agents/skills/guide/samples-index.md | 134 +++----- .agents/skills/java-interop/SKILL.md | 182 ++++------- .agents/skills/migrate/SKILL.md | 201 ++++++------ .agents/skills/scaffolding/SKILL.md | 293 ++++++++---------- 17 files changed, 808 insertions(+), 1084 deletions(-) diff --git a/.agents/.claude-plugin/marketplace.json b/.agents/.claude-plugin/marketplace.json index a4a7ea13a5..9be1d8ce3c 100644 --- a/.agents/.claude-plugin/marketplace.json +++ b/.agents/.claude-plugin/marketplace.json @@ -1,20 +1,20 @@ { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", "name": "dubbo-go-agent-skills", - "description": "Agent skills bundled with Apache dubbo-go for framework users and contributors", + "description": "Agent skills bundled with Apache dubbo-go for v3 framework users", "owner": { "name": "Apache Dubbo" }, "plugins": [ { "name": "dubbo-go", - "description": "AI skills for Apache dubbo-go contributors and v3 users: repository development, scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "description": "AI skills for Apache dubbo-go v3 users — scaffolding, extensions, Java interop, debugging, guidance, migration, plus contributor support.", "category": "development", "source": { "source": "url", "url": "https://github.com/apache/dubbo-go.git" }, - "homepage": "https://github.com/apache/dubbo-go/tree/develop/.agents" + "homepage": "https://github.com/apache/dubbo-go/tree/main/.agents" } ] } diff --git a/.agents/.codex/INSTALL.md b/.agents/.codex/INSTALL.md index 28d7cb345a..1dfad21f35 100644 --- a/.agents/.codex/INSTALL.md +++ b/.agents/.codex/INSTALL.md @@ -56,4 +56,4 @@ Restart Codex after updating. ## Usage -The installed skills cover repository development, scaffolding, extensions, Java interoperability, debugging, guidance, and migration for dubbo-go. +The installed skills cover scaffolding, custom SPI extensions, Java interoperability, runtime debugging, conceptual guidance, and migration for dubbo-go v3 — plus a contributor-focused skill for modifying the `apache/dubbo-go` repository itself. diff --git a/.agents/.opencode/plugins/dubbo-go-agent-skills.js b/.agents/.opencode/plugins/dubbo-go-agent-skills.js index aec4ea0290..015d4f8c7c 100644 --- a/.agents/.opencode/plugins/dubbo-go-agent-skills.js +++ b/.agents/.opencode/plugins/dubbo-go-agent-skills.js @@ -22,7 +22,7 @@ import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const pluginRoot = join(__dirname, '..', '..'); -const skillNames = ['development', 'scaffolding', 'extensions', 'java-interop', 'debug', 'guide', 'migrate']; +const skillNames = ['scaffolding', 'extensions', 'java-interop', 'debug', 'guide', 'migrate', 'development']; export const skills = skillNames.map(name => { const skillPath = join(pluginRoot, 'skills', name, 'SKILL.md'); diff --git a/.agents/GEMINI.md b/.agents/GEMINI.md index eeec3edb9c..211ce094f0 100644 --- a/.agents/GEMINI.md +++ b/.agents/GEMINI.md @@ -15,10 +15,10 @@ See the License for the specific language governing permissions and limitations under the License. --> -@./skills/development/SKILL.md @./skills/scaffolding/SKILL.md @./skills/extensions/SKILL.md @./skills/java-interop/SKILL.md @./skills/debug/SKILL.md @./skills/guide/SKILL.md @./skills/migrate/SKILL.md +@./skills/development/SKILL.md diff --git a/.agents/README.md b/.agents/README.md index b923164f3e..83149192d3 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -19,67 +19,117 @@ limitations under the License. [English](README.md) | [中文](README_CN.md) -This directory contains AI agent skills bundled with [Apache dubbo-go](https://github.com/apache/dubbo-go). The skills help coding agents work with the dubbo-go repository, dubbo-go v3 applications, examples, extension points, Java interoperability, debugging, and migration tasks. +AI agent skills bundled with [Apache dubbo-go](https://github.com/apache/dubbo-go) — make your coding assistant fluent in dubbo-go v3. -The package lives under `.agents/` so it can include multi-agent distribution metadata without overwriting dubbo-go repository root files. +## What This Gives You -> Note: All skills target dubbo-go v3. v1 and v2 are deprecated. +When you're using dubbo-go, your AI assistant now actually knows what it's doing. -## Layout +Ask it to scaffold a new provider or consumer and it picks the current code-API style (`dubbo.NewInstance` + `server.WithServerProtocol`), wires up the registry you actually use, and produces something that compiles on the first try. Need a custom filter or load balancer? It knows the SPI pattern — `extension.SetXxx` registration, blank imports, per-service or per-reference activation. Calling a Java Dubbo service? It picks Triple+Protobuf or Dubbo+Hessian2 based on whether you have a `.proto` or a Java interface, and gets the POJO class names right. -- `skills/`: Codex-compatible skills. Codex reads this directory when working in this repository. -- `.codex/INSTALL.md`: manual Codex installation notes for using these skills outside this checkout. -- `.claude-plugin/marketplace.json`: Claude Code plugin marketplace metadata for this `.agents` package. -- `.opencode/plugins/dubbo-go-agent-skills.js`: OpenCode adapter that exposes the bundled skills. -- `GEMINI.md` and `gemini-extension.json`: Gemini CLI extension entry points. -- `plugin.json` and `package.json`: generic plugin/package metadata for tools that can consume a package rooted at `.agents`. +Ask why your service won't connect, and it triages by structured checklist — registry, protocol, serialization, filter chain — instead of guessing. Migrating from gRPC-Go or Spring Cloud? It maps the concepts side by side. -## Using These Skills +Skills activate automatically when the conversation matches; you don't invoke them by name. -When working inside an Apache dubbo-go checkout, Codex can load the repository-local skills from `.agents/skills` directly. No separate clone of a skills repository is required. +> All skills target dubbo-go **v3**. v1 and v2 are deprecated. -For global Codex usage outside this checkout, follow [.codex/INSTALL.md](.codex/INSTALL.md). +## Install -For OpenCode, Gemini CLI, or Claude Code packaging, treat `.agents` as the package root. The metadata files in this directory are intentionally relative to `.agents`. +Install paths vary by AI tool. Claude Code and Cursor read a marketplace; Codex and OpenCode are manual. -## Skills +### Claude Code / Cursor -### development +```bash +/plugin marketplace add apache/dubbo-go +/plugin install dubbo-go@dubbo-go-agent-skills +``` + +### Codex + +Tell Codex: + +``` +Fetch and follow instructions from https://raw.githubusercontent.com/apache/dubbo-go/main/.agents/.codex/INSTALL.md +``` + +Full instructions: [.codex/INSTALL.md](.codex/INSTALL.md) + +### OpenCode + +Add to `opencode.json`: + +```json +{ + "plugin": ["dubbo-go-agent-skills@git+https://github.com/apache/dubbo-go.git#path:.agents"] +} +``` + +### Gemini CLI + +```bash +gemini extensions install https://github.com/apache/dubbo-go --path .agents +``` -Guides agents modifying the apache/dubbo-go repository itself. It covers current Go/toolchain expectations, package boundaries, validation commands, generated files, and repository-specific do-not rules. +Update later with: + +```bash +gemini extensions update dubbo-go-agent-skills +``` + +### Verify + +Open a new session and try one of these: + +- "Scaffold a dubbo-go provider with Nacos" +- "Why does my consumer log 'no provider available'?" +- "How do I call a Java Dubbo service from Go?" + +The assistant should auto-trigger the matching skill. + +## Skills ### scaffolding -Generates provider or consumer skeletons in the current dubbo-go v3 code-API style. It covers direct mode, registry-backed services, Protobuf generation, OpenAPI, HTTP handler mounting, HTTP/3, and current sample patterns. +Generates provider or consumer skeletons in v3 code-API style (`dubbo.NewInstance` / `server.NewServer` / `client.NewClient`). Asks about protocol (Triple / Dubbo / gRPC) and registry (Nacos / ZooKeeper / etcd / direct) first, then produces a complete, compilable skeleton matching the official samples. Covers OpenAPI, HTTP handler attachment, and HTTP/3. ### extensions -Guides custom SPI extensions such as Filter, LoadBalance, Router, Registry, Protocol, ConfigCenter, and Logger. It covers the `extension.SetXxx` registration pattern, blank imports, activation options, and common failure modes. +Custom SPI extensions — Filter, LoadBalance, Registry, Protocol, Router, Logger. Explains the uniform pattern (`extension.SetXxx` + blank import + `WithFilter` / `WithLoadBalance`), with runnable templates and the silent-failure modes that catch newcomers. ### java-interop -Guides interoperability between dubbo-go and dubbo-java. It helps choose Triple+Protobuf or Dubbo+Hessian2, handle service discovery mapping, and debug cross-language serialization. +Cross-language RPC between dubbo-go and dubbo-java. Picks Triple+Protobuf for new services, Dubbo+Hessian2 for existing Java-defined ones, and gets POJO class names, method-name casing, and the curl-friendly HTTP route format right. ### debug -Provides structured diagnosis for runtime issues such as missing providers, registry mapping, connection failures, serialization mismatches, timeouts, OpenAPI issues, attached HTTP handlers, shutdown behavior, and filter panics. +Structured diagnosis for runtime errors. Matches your error or log against known patterns — "no provider available", connection refused, serialization mismatch, timeout, filter panic, OpenAPI 404, AttachHTTPHandler failure, slow shutdown — and gives a targeted checklist. ### guide -Explains current dubbo-go architecture, extension points, and best practices. It covers Instance, Protocol, Registry, Metadata, Filter, Cluster, LoadBalance, Router, Triple OpenAPI, HTTP/3, CORS, graceful shutdown, observability, and sample locations. +Architecture, extension points, and best practices. Covers Instance, Protocol, Registry, Filter, Cluster, LoadBalance, Router, Triple OpenAPI, HTTP/3, CORS, graceful shutdown, observability, and points to the relevant `dubbo-go-samples` directory through `samples-index.md`. ### migrate -Guides migration from gRPC-Go, Spring Cloud, Gin/plain HTTP, older dubbo-go v1/v2 usage, YAML-heavy apps, Java Dubbo, and Hessian2 services to current dubbo-go v3 patterns. +Step-by-step migration guidance: + +- **gRPC-Go** — concept mapping, proto reuse, direct mode parallels +- **Spring Cloud (Java)** — registry sharing, Java/Go coexistence path +- **Gin / plain HTTP** — coexistence options and Triple REST mode +- **dubbo-go v1/v2 → v3** — breaking-change table, minimum migration path +- **YAML-heavy v3** — incremental move to the code API + +### development + +For contributors modifying the `apache/dubbo-go` repository itself — Go toolchain, package boundaries, validation commands, generated files, repository-level do-not rules. Not for application-side scaffolding. ## Contributing -Skills live in `.agents/skills`. +Skills live in `.agents/skills//SKILL.md`. -1. Add or edit a skill under `.agents/skills//SKILL.md`. -2. Keep `SKILL.md` frontmatter concise and trigger-focused. -3. Update this directory's metadata only when install paths, skill names, or supported agents change. -4. Submit the change through the normal dubbo-go contribution workflow. +1. Edit or add a skill in place. +2. Keep the frontmatter `description` trigger-focused — that line is what the agent reads to decide whether to use the skill. +3. Update `.agents/` metadata only when install paths, skill names, or supported agents change. +4. Submit through the normal dubbo-go contribution workflow. ## License diff --git a/.agents/README_CN.md b/.agents/README_CN.md index a629707a6e..4901fe7645 100644 --- a/.agents/README_CN.md +++ b/.agents/README_CN.md @@ -19,66 +19,116 @@ limitations under the License. [English](README.md) | 中文 -本目录存放随 [Apache dubbo-go](https://github.com/apache/dubbo-go) 仓库一起维护的 AI Agent Skills。这些 skills 用于帮助编码 Agent 处理 dubbo-go 仓库源码、dubbo-go v3 应用、示例生成、扩展点、Java 互通、问题排查和迁移任务。 +随 [Apache dubbo-go](https://github.com/apache/dubbo-go) 一起维护的 AI Agent Skills——让你的编码助手真正会写 dubbo-go v3。 -这套包放在 `.agents/` 下,是为了把多 Agent 分发元数据集中在一起,同时避免覆盖 dubbo-go 仓库根目录已有文件。 +## 它能给你什么 -> 注意:所有 skills 都面向 dubbo-go v3。v1 和 v2 已废弃。 +你在用 dubbo-go 时,AI 助手现在知道自己在做什么了。 -## 目录结构 +让它搭一个新的 provider 或 consumer,它会选对当前的 code-API 风格(`dubbo.NewInstance` + `server.WithServerProtocol`),接上你实际用的注册中心,第一次就能编译过。要写自定义 filter 或负载均衡?它懂 SPI 模式——`extension.SetXxx` 注册、blank import、按 service 或 reference 启用。要和 Java Dubbo 服务互通?它会根据你有的是 `.proto` 还是 Java 接口,正确选 Triple+Protobuf 或 Dubbo+Hessian2,POJO 类名也能对齐。 -- `skills/`:Codex 可直接加载的 skills。Codex 在本仓库工作时会读取该目录。 -- `.codex/INSTALL.md`:在本仓库外全局使用这些 skills 的 Codex 手动安装说明。 -- `.claude-plugin/marketplace.json`:面向 Claude Code 插件市场的元数据。 -- `.opencode/plugins/dubbo-go-agent-skills.js`:OpenCode 适配器,用于暴露本目录内的 skills。 -- `GEMINI.md` 和 `gemini-extension.json`:Gemini CLI 扩展入口。 -- `plugin.json` 和 `package.json`:供能够以 `.agents` 为包根目录的工具读取的通用元数据。 +问它服务为什么连不上,它按结构化清单逐步排查——注册中心、协议匹配、序列化、filter 链——而不是瞎猜。要从 gRPC-Go 或 Spring Cloud 迁移?它会把概念逐一映射。 -## 使用方式 +Skill 在上下文匹配时自动触发,不需要手动调用。 -在 Apache dubbo-go 仓库内工作时,Codex 可以直接从 `.agents/skills` 加载仓库内置 skills,不需要再单独克隆一个 skills 仓库。 +> 所有 skill 仅支持 dubbo-go **v3**,v1/v2 已废弃。 -如果要在本仓库外全局使用这套 Codex skills,请参考 [.codex/INSTALL.md](.codex/INSTALL.md)。 +## 安装 -如果用于 OpenCode、Gemini CLI 或 Claude Code 的插件包装,请把 `.agents` 视为包根目录。本目录中的元数据路径都按 `.agents` 为根来组织。 +不同 AI 工具安装方式不同。Claude Code 和 Cursor 内置市场,Codex 和 OpenCode 需要手动安装。 -## Skills +### Claude Code / Cursor -### development +```bash +/plugin marketplace add apache/dubbo-go +/plugin install dubbo-go@dubbo-go-agent-skills +``` + +### Codex + +告诉 Codex: + +``` +Fetch and follow instructions from https://raw.githubusercontent.com/apache/dubbo-go/main/.agents/.codex/INSTALL.md +``` + +详细文档:[.codex/INSTALL.md](.codex/INSTALL.md) + +### OpenCode + +在 `opencode.json` 中加: + +```json +{ + "plugin": ["dubbo-go-agent-skills@git+https://github.com/apache/dubbo-go.git#path:.agents"] +} +``` + +### Gemini CLI + +```bash +gemini extensions install https://github.com/apache/dubbo-go --path .agents +``` -指导 Agent 修改 apache/dubbo-go 仓库本身,覆盖当前 Go/toolchain 要求、包边界、验证命令、生成文件和仓库级禁止事项。 +更新: + +```bash +gemini extensions update dubbo-go-agent-skills +``` + +### 验证 + +新开一个会话,试试这些: + +- "帮我搭一个用 Nacos 的 dubbo-go provider" +- "consumer 报 'no provider available' 是什么原因" +- "怎么从 Go 调一个 Java Dubbo 服务?" + +助手应该会自动触发对应的 skill。 + +## Skills ### scaffolding -生成当前 dubbo-go v3 code API 风格的 provider 或 consumer 骨架,覆盖直连模式、注册中心服务、Protobuf 生成、OpenAPI、HTTP handler 挂载、HTTP/3 和当前示例模式。 +按 v3 code-API 风格(`dubbo.NewInstance` / `server.NewServer` / `client.NewClient`)生成 provider 或 consumer 骨架。先确认协议(Triple / Dubbo / gRPC)和注册中心(Nacos / ZooKeeper / etcd / 直连),再生成与官方 samples 一致、可直接编译运行的骨架。覆盖 OpenAPI、HTTP handler 挂载、HTTP/3。 ### extensions -指导编写自定义 SPI 扩展,例如 Filter、LoadBalance、Router、Registry、Protocol、ConfigCenter、Logger。覆盖 `extension.SetXxx` 注册模式、blank import、启用方式和常见失败原因。 +自定义 SPI 扩展——Filter、LoadBalance、Registry、Protocol、Router、Logger。讲清统一模式(`extension.SetXxx` + blank import + `WithFilter` / `WithLoadBalance`),附可运行模板和新人最常踩的"静默失败"陷阱。 ### java-interop -指导 dubbo-go 和 dubbo-java 互通。根据服务形态和兼容性需求,在 Triple+Protobuf 与 Dubbo+Hessian2 之间做选择,并处理服务发现映射和跨语言序列化问题。 +dubbo-go 与 dubbo-java 的跨语言 RPC。新服务选 Triple+Protobuf,老 Java 接口选 Dubbo+Hessian2,POJO 类名、方法名大小写、curl 友好的 HTTP 路由格式都对齐好。 ### debug -为运行时问题提供结构化排查流程,例如 provider 找不到、注册中心映射、连接失败、序列化不匹配、超时、OpenAPI、HTTP handler 挂载、shutdown 和 filter panic。 +运行时报错的结构化排查。把错误或日志和已知模式匹配——"no provider available"、连接被拒、序列化不匹配、超时、filter panic、OpenAPI 404、AttachHTTPHandler 失败、shutdown 偏慢——给出针对性的检查清单。 ### guide -解释当前 dubbo-go 架构、扩展点和最佳实践,覆盖 Instance、Protocol、Registry、Metadata、Filter、Cluster、LoadBalance、Router、Triple OpenAPI、HTTP/3、CORS、graceful shutdown、可观测性和示例位置。 +架构、扩展点、最佳实践。覆盖 Instance、Protocol、Registry、Filter、Cluster、LoadBalance、Router、Triple OpenAPI、HTTP/3、CORS、graceful shutdown、可观测性,并通过 `samples-index.md` 指向对应的 `dubbo-go-samples` 目录。 ### migrate -指导从 gRPC-Go、Spring Cloud、Gin/纯 HTTP、dubbo-go v1/v2、YAML-heavy 应用、Java Dubbo 和 Hessian2 服务迁移到当前 dubbo-go v3 模式。 +分步骤迁移指引: + +- **gRPC-Go**——概念映射、proto 复用、直连模式对照 +- **Spring Cloud(Java)**——注册中心复用、Java/Go 共存 +- **Gin / 纯 HTTP**——共存方案和 Triple REST 模式 +- **dubbo-go v1/v2 → v3**——breaking-change 对照、最小迁移路径 +- **YAML 重度依赖的 v3**——平滑迁移到 code API + +### development + +面向 `apache/dubbo-go` 仓库本身的贡献者——Go 工具链、包边界、校验命令、生成文件、仓库级禁止事项。**不**用于应用侧脚手架。 ## 贡献 -Skills 位于 `.agents/skills`。 +Skill 文件位于 `.agents/skills//SKILL.md`。 -1. 在 `.agents/skills//SKILL.md` 下新增或修改 skill。 -2. 保持 `SKILL.md` frontmatter 简洁,并聚焦触发场景。 -3. 只有当安装路径、skill 名称或支持的 Agent 发生变化时,才更新本目录的元数据。 +1. 直接修改或新增 skill。 +2. 保持 frontmatter 的 `description` 聚焦触发场景——Agent 就是靠这一行决定要不要使用该 skill。 +3. 只有当安装路径、skill 名称或支持的 Agent 发生变化时,才修改 `.agents/` 下的元数据。 4. 按 dubbo-go 正常贡献流程提交修改。 ## License diff --git a/.agents/gemini-extension.json b/.agents/gemini-extension.json index afe0b4182d..b10b95051c 100644 --- a/.agents/gemini-extension.json +++ b/.agents/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "dubbo-go-agent-skills", - "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "description": "Agent skills bundled with Apache dubbo-go for v3 framework users — scaffolding, extensions, Java interop, debugging, guidance, migration, plus contributor support.", "version": "0.2.0", "contextFileName": "GEMINI.md" } diff --git a/.agents/package.json b/.agents/package.json index 57ee38cd45..83c2337a8c 100644 --- a/.agents/package.json +++ b/.agents/package.json @@ -2,7 +2,7 @@ "name": "dubbo-go-agent-skills", "version": "0.2.0", "type": "module", - "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "description": "Agent skills bundled with Apache dubbo-go for v3 framework users — scaffolding, extensions, Java interop, debugging, guidance, migration, plus contributor support.", "author": "Apache Dubbo contributors", "license": "Apache-2.0", "repository": { @@ -10,6 +10,6 @@ "url": "https://github.com/apache/dubbo-go.git", "directory": ".agents" }, - "homepage": "https://github.com/apache/dubbo-go/tree/develop/.agents", + "homepage": "https://github.com/apache/dubbo-go/tree/main/.agents", "main": ".opencode/plugins/dubbo-go-agent-skills.js" } diff --git a/.agents/plugin.json b/.agents/plugin.json index aa9dcb30dc..92013f4454 100644 --- a/.agents/plugin.json +++ b/.agents/plugin.json @@ -1,15 +1,15 @@ { "name": "dubbo-go", "version": "0.2.0", - "description": "Agent skills bundled with Apache dubbo-go for repository development, v3 scaffolding, extensions, Java interop, debugging, guidance, and migration.", + "description": "Agent skills bundled with Apache dubbo-go for v3 framework users — scaffolding, extensions, Java interop, debugging, guidance, migration, plus contributor support.", "author": "Apache Dubbo contributors", "skills": [ - "skills/development", "skills/scaffolding", "skills/extensions", "skills/java-interop", "skills/debug", "skills/guide", - "skills/migrate" + "skills/migrate", + "skills/development" ] } diff --git a/.agents/skills/debug/SKILL.md b/.agents/skills/debug/SKILL.md index f6e10987f8..1337a39e47 100644 --- a/.agents/skills/debug/SKILL.md +++ b/.agents/skills/debug/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-debugging -description: Use when diagnosing dubbo-go runtime failures, logs, startup errors, missing providers, registry problems, serialization errors, timeouts, filter panics, OpenAPI issues, HTTP handler mounting, or graceful shutdown behavior. +description: Structured diagnosis for dubbo-go v3 runtime errors. Use when the user reports an error, pastes logs, mentions timeout/panic/connection refused/no provider/serialization mismatch, or asks why their dubbo-go service isn't working. --- - # Debugging dubbo-go -## Overview +When the user shares an error or log, match it to a pattern below. If unclear, ask for: -Most dubbo-go runtime failures collapse into a small set of root causes: name/contract mismatch, registry/discovery mode mismatch, protocol mismatch, blocking filter, or missing blank import. Diagnose by symptom first, then verify the contract on both sides (provider and consumer). +1. Full error message or stack trace +2. Registry type (Nacos / ZooKeeper / etcd / Polaris / direct) +3. Protocol (Triple / Dubbo / gRPC / JSONRPC) +4. Whether provider and consumer are separate processes ## Quick Triage | Symptom in logs | Jump to | |---|---| -| `no provider available`, `no route`, `Should has at least one way to know` | [Missing Provider or No Route](#missing-provider-or-no-route) | -| `dial tcp ... connection refused`, `i/o timeout` on connect | [Connection Refused or Dial Error](#connection-refused-or-dial-error) | -| `hessian: failed to decode`, `protobuf: cannot parse invalid wire-format data` | [Serialization or Decode Error](#serialization-or-decode-error) | +| `no provider available`, `no route`, `Should has at least one way to know` | [No provider / no route](#no-provider--no-route) | +| `dial tcp ... connection refused`, `i/o timeout` on connect | [Connection refused / dial error](#connection-refused--dial-error) | +| `hessian: failed to decode`, `protobuf: cannot parse invalid wire-format data` | [Serialization / decode error](#serialization--decode-error) | | `context deadline exceeded`, `invoke timeout` | [Timeout](#timeout) | -| `filter not found`, panic inside a filter | [Filter Not Found or Filter Panic](#filter-not-found-or-filter-panic) | -| Provider process exits seconds after start | [Provider Starts Then Exits](#provider-starts-then-exits) | -| `404` at `/dubbo/openapi/...`, empty spec | [OpenAPI 404 or Empty Spec](#openapi-404-or-empty-spec) | -| `AttachHTTPHandler` returns error | [Attached HTTP Handler Errors](#attached-http-handler-errors) | -| Pods drain slowly, in-flight requests truncated on shutdown | [Graceful Shutdown Issues](#graceful-shutdown-issues) | +| `filter not found`, panic inside a filter | [Filter not found / filter panic](#filter-not-found--filter-panic) | +| Provider exits seconds after start | [Provider starts but immediately exits](#provider-starts-but-immediately-exits) | +| `404` at `/dubbo/openapi/...`, empty spec | [OpenAPI 404 / empty spec](#openapi-404--empty-spec) | +| `AttachHTTPHandler` returns error | [AttachHTTPHandler errors](#attachhttphandler-errors) | +| Pods drain slowly, in-flight requests truncated on shutdown | [Graceful shutdown](#graceful-shutdown) | -## Collect First +## No provider / no route -Before diving in, gather: +**Cause**: Consumer cannot find a provider in the registry. -1. Full error message and stack trace -2. Protocol: Triple, Dubbo, JSONRPC, REST, or gRPC-compatible path -3. Discovery mode: direct URL, Nacos, ZooKeeper, etcd, Polaris, mesh -4. Provider and consumer snippets for `NewInstance`, `NewServer`, `NewClient`, and `Register/NewService` -5. Whether the service uses Protobuf IDL, non-IDL, Hessian2, generic, OpenAPI, HTTP/3, or attached HTTP handlers +Checklist: +- [ ] Provider started successfully? Look for `dubbo server started` and `A provider service ... was registered successfully` in provider logs. +- [ ] Same registry address on both sides (`dubbo.WithRegistry(registry.WithAddress(...))` / YAML `dubbo.registries.xxx.address`)? +- [ ] Same application name on both sides (`dubbo.WithName(...)`)? v3 defaults to **application-level** discovery — the registry stores the app name, not the interface FQN. +- [ ] Same `interface` name passed to `pb.RegisterXxxHandler` and `pb.NewXxxService`? +- [ ] Same protocol on both sides (both `tri` or both `dubbo`)? +- [ ] Provider visible in the registry? -## Missing Provider or No Route +```bash +# Nacos — application-level discovery, query by app name +curl "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=" -Common logs: +# ZooKeeper +zkCli.sh ls /services -```text -no provider available -No provider available -no route -Should has at least one way to know which services this interface belongs to +# etcd +etcdctl get --prefix /services ``` -Check: - -- Provider reached `srv.Serve()` and did not exit. -- Provider registered the service: `pb.RegisterXxxHandler(srv, impl, ...)` returned nil. -- Consumer constructed the generated client with the same interface name. Override with `client.WithInterface("...")` if provider used `server.WithInterface("...")`. -- Registry addresses and IDs match. Multiple registries require `registry.WithID(...)` plus `client.WithRegistryIDs(...)` or server equivalents. -- Application-level discovery can resolve interface-to-application mapping. If metadata mapping is unavailable, set `client.WithProvidedBy("provider-app-name")`. -- Registry registration mode is correct: `registry.WithRegisterService`, `registry.WithRegisterInterface`, or `registry.WithRegisterServiceAndInterface`. -- Registry is not disabled by `server.WithNotRegister()` or service `server.WithNotRegister()`. -- Protocol matches. Triple consumers default to `tri`; Dubbo/Hessian2 consumers must use Dubbo protocol explicitly. - -For Nacos, inspect by application name for service-discovery mode and by interface if interface registration is enabled. +If the consumer cannot map an interface to an application, hint with `client.WithProvidedBy("")`. -## Connection Refused or Dial Error +## Connection refused / dial error -Check: +**Cause**: Network or port misconfiguration. -- Provider is listening on the expected IP and port. -- For direct mode, `client.WithClientURL("127.0.0.1:20000")` or `tri://127.0.0.1:20000` points to the provider. -- Docker/Kubernetes clients are not using `localhost` to reach another container/pod. -- Triple server configured an explicit port if using `AttachHTTPHandler`. -- TLS/HTTP3 clients match server TLS and HTTP/3 setup. +Checklist: +- [ ] Provider port (`protocol.WithPort(...)`) matches what the consumer is dialing? +- [ ] Firewall / Docker network allows the port? +- [ ] Inside Docker: using container/service name instead of `localhost`? +- [ ] Provider actually listening? `lsof -i :20000` on the provider host. -Useful commands: +## Serialization / decode error -```bash -lsof -i :20000 -curl -v http://127.0.0.1:20000/greet.GreetService/Greet \ - -H "Content-Type: application/json" \ - -d '{"name":"Dubbo"}' ``` - -## Serialization or Decode Error - -Examples: - -```text hessian: failed to decode protobuf: cannot parse invalid wire-format data ``` -Check: +**Cause**: Provider and consumer using different serialization formats. -- Triple path uses Protobuf-generated code and the same `.proto` contract. -- Dubbo protocol with Hessian2 registers every POJO through `dubbo-go-hessian2.RegisterPOJO`. -- Java class names from `JavaClassName()` exactly match the Java fully-qualified class. -- Client protocol and provider protocol match. -- Generic calls use the expected generic type: `"true"`, `"gson"`, `"protobuf"`, or `"protobuf-json"`. +Checklist: +- [ ] Both sides on the same protocol (both `tri` or both `dubbo`)? +- [ ] Protobuf: same `.proto` compiled on both sides? Same `go_package`? +- [ ] Hessian2: POJO `JavaClassName()` matches the Java class FQN exactly? `RegisterPOJO` called in an `init()` that actually runs? -## Timeout +For Hessian2 specifics, see `dubbo-go-java-interop`. -Examples: +## Timeout -```text +``` context deadline exceeded invoke timeout ``` -Check: +**Cause**: Provider too slow, filter blocking, network delay, or low timeout. -- Provider receives the request. -- Filters are not blocking, rate-limiting, or waiting on external systems. -- Consumer timeout is long enough. - -Per-reference timeout: +Checklist: +- [ ] Provider actually receiving the request? Add a log line at the top of the handler. +- [ ] Any filter that may block? (auth, token, tps-limit) +- [ ] Timeout high enough? ```go +// per-reference svc, _ := pb.NewGreetService(cli, client.WithRequestTimeout(10*time.Second)) -``` - -Client-wide timeout: -```go -cli, _ := client.NewClient(client.WithClientRequestTimeout(10*time.Second)) -``` - -Call-site timeout: - -```go +// per-call ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() +resp, err := svc.Greet(ctx, req) ``` -## Filter Not Found or Filter Panic +## Filter not found / filter panic -Check: +**Cause**: Filter imported but `init()` not registered, or name mismatch between `extension.SetFilter` and `WithFilter`. -- The filter package is imported with `_ "path/to/filter"`. -- `extension.SetFilter("name", ...)` matches `server.WithFilter("name")`, `client.WithFilter("name")`, or YAML config. -- If using built-ins in examples, `_ "dubbo.apache.org/dubbo-go/v3/imports"` is present. -- Panic is not from filter order or nil attachment assumptions. +Checklist: +- [ ] Blank import present? e.g. `_ "dubbo.apache.org/dubbo-go/v3/filter/token"` or `_ "github.com/yourorg/yourapp/filter/myfilter"` +- [ ] String passed to `server.WithFilter("xxx")` / `client.WithFilter("xxx")` matches the name in `extension.SetFilter("xxx", ...)`? +- [ ] Built-ins not pulled in? Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` during development to auto-import all built-ins. -## Provider Starts Then Exits +## Provider starts but immediately exits -`srv.Serve()` is blocking and should not be launched in a goroutine unless something else blocks the process. +**Cause**: Missing blocking call or wrong shutdown setup. ```go -if err := srv.Serve(); err != nil { - logger.Fatalf("failed to serve: %v", err) -} -``` - -## OpenAPI 404 or Empty Spec +// Correct: blocking +if err := srv.Serve(); err != nil { panic(err) } -Check: - -- OpenAPI was enabled through `triple.WithOpenAPI(triple.OpenAPIEnable(), ...)`. -- Service was registered after OpenAPI-enabled Triple protocol was configured. -- Correct path is used. Defaults include: - - `/dubbo/openapi/openapi.json` - - `/dubbo/openapi/openapi.yaml` - - `/dubbo/openapi/api-docs/default.json` - - `/dubbo/openapi/swagger-ui` - - `/dubbo/openapi/redoc` -- Group-specific services use `server.WithOpenAPIGroup("group")` and can be requested with `/dubbo/openapi/api-docs/.json`. - -## Attached HTTP Handler Errors +// Wrong: non-blocking, process exits immediately +go srv.Serve() +``` -`srv.AttachHTTPHandler(handler)` rules: +For graceful shutdown: +```go +import _ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown" +``` -- Handler must not be nil. -- Attach before `Serve`. -- Only one root handler can be attached. -- At least one Triple protocol must be configured. -- Triple protocol needs an explicit port. +## OpenAPI 404 / empty spec -Use a mux for multiple HTTP subroutes. +Triple-only feature. Checklist: +- [ ] `triple.OpenAPIEnable(true)` set in the protocol options? +- [ ] Hitting the right route? Default is `/dubbo/openapi/openapi.json`. See `triple.OpenAPIPath(...)` to customize. +- [ ] Visiting the right port? OpenAPI lives on the Triple port, not a separate one. -## Graceful Shutdown Issues +## AttachHTTPHandler errors -Current shutdown config includes total timeout, step timeout, notify timeout, consumer update wait time, offline request window timeout, internal signal handling, and closing invoker expiry. +Checklist: +- [ ] Protocol is Triple? Triple is the only protocol that hosts plain HTTP handlers. +- [ ] Called *before* `srv.Serve()`? +- [ ] Path conflicts with the Triple-reserved namespace (`/dubbo/...`)? -Check: +## Graceful shutdown -- Graceful shutdown filters are imported or included through `_ "dubbo.apache.org/dubbo-go/v3/imports"`. -- Shutdown config is passed through `dubbo.NewInstance`, `client.WithClientShutdown`, or root YAML. -- Long-running calls fit within `step-timeout` and `timeout`. -- `internal-signal` is disabled only if the application handles OS signals itself. +Checklist: +- [ ] `_ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown"` blank-imported? +- [ ] Shutdown timeout long enough for in-flight calls to drain? +- [ ] If running behind Kubernetes: container `terminationGracePeriodSeconds` longer than dubbo-go's shutdown timeout? -## Logs +## Reading dubbo-go logs Enable debug logging: ```go +import "dubbo.apache.org/dubbo-go/v3/logger" + ins, _ := dubbo.NewInstance( - dubbo.WithLogger( - logger.WithZap(), - logger.WithLevel("debug"), - logger.WithFormat("text"), - ), + dubbo.WithLogger(logger.WithLevel("debug")), ) ``` -Trace integration can inject trace IDs into logs when OpenTelemetry tracing is configured: +Inject trace IDs into logs (when OpenTelemetry tracing is configured): ```go dubbo.WithLogger(logger.WithTraceIntegration(true)) ``` +Key log lines: +- `Registering service: ` — service registration starting +- `A provider service ... was registered successfully` — provider ready +- `export service failed` — registration error +- `No provider available` / `no route` — consumer lookup failed + ## Related Skills -- `dubbo-go-extensions` - when a missing/registered SPI is the root cause (filter, LB, registry not found) -- `dubbo-go-java-interop` - when the symptom is Hessian2 decode failure or cross-language discovery -- `dubbo-go-guide` - for the conceptual map (Instance / Server / Client / Protocol / Registry / Filter) -- `dubbo-go-development` - when the issue is reproducible only inside the `apache/dubbo-go` repo and may need a fix or test there +- `dubbo-go-extensions` — when a missing/registered SPI is the root cause +- `dubbo-go-java-interop` — for Hessian2 decode failures and cross-language discovery +- `dubbo-go-guide` — for the conceptual map (Instance / Server / Client / Protocol / Registry / Filter) diff --git a/.agents/skills/development/SKILL.md b/.agents/skills/development/SKILL.md index 651a2d87d4..feb76840c4 100644 --- a/.agents/skills/development/SKILL.md +++ b/.agents/skills/development/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-development -description: Use when modifying, reviewing, testing, debugging, or documenting the apache/dubbo-go repository itself, including Go code, generated code, config structs, tools, CI, tests, or repository-local agent skills. +description: Use when modifying, reviewing, testing, or debugging the apache/dubbo-go repository itself - including framework Go code, generated stubs, config structs, tools, CI, tests, or repository-local agent skills. Not for application-side scaffolding. --- +# Contributing to apache/dubbo-go -# dubbo-go Repository Development +This skill is for working **inside** the dubbo-go repository, not for using the framework from an application. For app-side work, use `dubbo-go-scaffolding`. -## Overview - -Working inside `apache/dubbo-go` itself, not just using the framework from an application. Treat package boundaries, public APIs, and generated files as load-bearing - break them only with explicit user intent. - -## When to Use - -- Editing files under `apache/dubbo-go` (`client/`, `server/`, `protocol/`, `registry/`, `cluster/`, `filter/`, `metadata/`, `tools/`, etc.) -- Adding or updating unit tests, mocks, or fixtures inside this repo -- Touching `Makefile`, CI config, generated Protobuf/Triple stubs, or `tools/imports-formatter` -- Modifying `.agents/skills/*` documentation - -For application-side changes, use `dubbo-go-scaffolding`. For runtime failures, use `dubbo-go-debugging`. - -## Current Branch Facts +## Branch Facts - Module path: `dubbo.apache.org/dubbo-go/v3` -- Go version in `go.mod`: `1.25.0` -- Makefile test command uses `GOTOOLCHAIN=go1.25.0+auto` -- CI still runs `make check-fmt`, `make test`, and `make lint` -- Import style is enforced by `tools/imports-formatter` -- `make fmt` also runs the Go modernize analyzer to replace eligible `interface{}` with `any` - -## Workflow - -1. Read the owning package and nearby tests before editing. -2. Keep changes scoped to the owning module boundary. -3. Prefer current code API patterns over old YAML/config globals for new examples. -4. Preserve compatibility in public APIs unless the user explicitly asks for a breaking change. -5. Add or update focused tests for behavior changes. -6. Run the smallest meaningful validation first, then broader commands when risk is higher. -7. Summarize changed files, behavior, and validation results. - -## Important Package Boundaries - -- `dubbo.go`, `options.go`, `instance_options_init.go`: instance-level option initialization and root config bridging -- `client/`: reference options, consumer URL construction, invoker creation -- `server/`: provider options, service registration, `AttachHTTPHandler`, service metadata -- `protocol/base`, `protocol/result`, `protocol/invocation`: core invocation interfaces -- `protocol/triple`: main protocol implementation, reflection, HTTP/3, CORS, OpenAPI, attached HTTP hosting -- `registry/`: registry interfaces, service discovery, application-level mapping -- `metadata/`: metadata report and service name mapping -- `cluster/`: cluster strategies, directory, load balance, router chain -- `filter/`: provider/consumer filters; most runtime interception belongs here -- `config/`, `global/`, `config_center/`: YAML/config models and dynamic config loading -- `graceful_shutdown/`: shutdown runtime state and options -- `logger/`, `metrics/`, `otel/`: observability -- `tools/`: CLI, schema, generators, imports formatter, variadic RPC scanner - -## Current Implementation Notes - -- Config loading uses koanf. Do not introduce viper-based assumptions into new code. -- Triple config now includes CORS, HTTP/3, and OpenAPI sections. -- `server.AttachHTTPHandler` hosts one existing `http.Handler` on an explicit Triple port before `Serve`. -- Graceful shutdown has separate total timeout, step timeout, notify timeout, consumer update wait time, offline request window, and closing invoker expiry. -- Application-level service discovery may require metadata mapping or explicit `client.WithProvidedBy`. -- Registry config can choose service/interface/all registration through registry options. -- Router config supports static injection for routers that implement `router.StaticConfigSetter`. -- New extension code should import `protocol/base` and `protocol/result`, not old aliases. +- Default branch: `main` +- `go.mod` Go version: `1.25.0` +- Toolchain: `GOTOOLCHAIN=go1.25.0+auto` (referenced by the Makefile) +- Import-block format is enforced by `tools/imports-formatter` +- `make fmt` also runs the Go `modernize` analyzer to replace eligible `interface{}` with `any` -## Validation Commands +## Validation -Use the command that matches the scope. +Pick the smallest scope that covers the change: ```bash -# format repository code -make fmt - -# check formatting exactly like CI -make check-fmt +make fmt # format the tree +make check-fmt # exactly what CI runs +make lint # golangci-lint +make test # full suite + dubbogo-cli submodule +make rpc-contract-check # warn on exported variadic RPC contracts # targeted package tests GOTOOLCHAIN=go1.25.0+auto go test ./protocol/triple/... GOTOOLCHAIN=go1.25.0+auto go test ./server/... - -# full repository tests plus dubbogo-cli submodule tests -make test - -# lint -make lint - -# warn about exported variadic RPC contracts -make rpc-contract-check ``` -If only `.agents` documentation changes, validate skill metadata and adapters instead of running the Go suite. +For `.agents/` doc-only changes, skip the Go suite and validate the skill frontmatter and adapter (`.agents/.opencode/plugins/dubbo-go-agent-skills.js`) instead. + +## Package Boundaries + +| Path | Scope | +|---|---| +| `dubbo.go`, `options.go`, `instance_options_init.go` | Instance-level options and root config bridging | +| `client/` | Reference options, consumer URL, invoker creation | +| `server/` | Provider options, service registration, `AttachHTTPHandler` | +| `protocol/base`, `protocol/result`, `protocol/invocation` | Core invocation interfaces | +| `protocol/triple` | Triple impl: HTTP/2, HTTP/3, CORS, OpenAPI, reflection, attached HTTP | +| `registry/`, `metadata/` | Registry, service discovery, app-to-interface mapping | +| `cluster/` | Cluster strategies, directory, load balance, router chain | +| `filter/` | Provider/consumer filters | +| `config/`, `global/`, `config_center/` | YAML/koanf config models, dynamic config loading | +| `graceful_shutdown/` | Shutdown timeouts and lifecycle | +| `logger/`, `metrics/`, `otel/` | Observability | +| `tools/` | CLI, schema, generators, imports formatter, RPC contract scanner | -## Generated and Tooling Files +## Current Implementation Notes -- Do not hand-edit generated Protobuf or Triple files unless the generator source is also in scope. -- For user services, generate with `protoc-gen-go` and `protoc-gen-go-triple/v3`. -- For OpenAPI generation, use runtime Triple OpenAPI or `tools/protoc-gen-triple-openapi` depending on the task. -- `tools/dubbogo-cli` has its own module and tests; run tests from that directory when editing it. +- Config loading uses **koanf**. Do not introduce viper-style assumptions in new code. +- Triple config now includes CORS, HTTP/3, and OpenAPI sub-options. +- `server.AttachHTTPHandler` hosts one `http.Handler` on an explicit Triple port and must be called before `Serve`. +- Graceful shutdown has separate total / step / notify / consumer-update / offline-request / closing-invoker timeouts. +- Application-level discovery may need metadata mapping or explicit `client.WithProvidedBy`. +- Registry config can choose service / interface / all registration via registry options. +- Routers implementing `router.StaticConfigSetter` accept static injection. +- New code should import `protocol/base` and `protocol/result` directly, not the older aliases. -## Do Not +## Generated and Tooling Files -- Do not remove tests to make validation pass. -- Do not change public option names casually. -- Do not flatten package boundaries with unrelated refactors. -- Do not overwrite generated files without explaining the generator source. -- Do not introduce new dependencies unless the existing packages cannot reasonably solve the problem. +- Do not hand-edit generated Protobuf / Triple files unless the generator source is also in scope. +- User-side stubs come from `protoc-gen-go` and `github.com/dubbogo/protoc-gen-go-triple/v3`. +- For OpenAPI: runtime Triple OpenAPI or `tools/protoc-gen-triple-openapi`, depending on task. +- `tools/dubbogo-cli` has its own module — run tests from that directory when editing it. -## Red Flags - Stop and Reconsider +## Red Flags -- About to delete or skip a failing test to "unblock" CI -- About to rename or remove an exported option/function in `client/`, `server/`, `protocol/`, or `registry/` without a migration note -- About to bypass `tools/imports-formatter` by hand-editing import groupings -- About to replace koanf-based config loading with a viper-style assumption -- About to `--no-verify` a commit, or skip `make check-fmt` / `make lint` -- About to introduce a third-party dependency to do something `gost`, `koanf`, or stdlib already covers +Stop and surface the tradeoff before doing any of these: -If any of these fire, stop and surface the tradeoff to the user before proceeding. +- Removing or skipping a failing test to "unblock" CI +- Renaming or removing an exported option/function in `client/`, `server/`, `protocol/`, or `registry/` without a migration note +- Bypassing `tools/imports-formatter` with hand-edited import groupings +- Replacing koanf-based config with a different config library +- `--no-verify` on a commit, or skipping `make check-fmt` / `make lint` +- Introducing a third-party dependency for something `gost`, `koanf`, or stdlib already covers ## Related Skills -- `dubbo-go-guide` - conceptual map of packages, options, and current capabilities -- `dubbo-go-extensions` - when the work is adding or fixing an SPI registration in this repo -- `dubbo-go-debugging` - when reproducing a user-reported failure to find the fix point +- `dubbo-go-guide` — conceptual map of packages and options +- `dubbo-go-extensions` — when adding or fixing an SPI in this repo +- `dubbo-go-debugging` — when reproducing a user-reported failure diff --git a/.agents/skills/extensions/SKILL.md b/.agents/skills/extensions/SKILL.md index d37463e68d..cc3ba72f30 100644 --- a/.agents/skills/extensions/SKILL.md +++ b/.agents/skills/extensions/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-extensions -description: Use when implementing or explaining dubbo-go extension points such as filters, load balancers, registries, protocols, routers, loggers, config centers, metrics, tracing, or custom SPI integration. +description: Guides writing custom dubbo-go v3 extensions — Filter, LoadBalance, Registry, Protocol, Router, Logger, ConfigCenter — through the SPI pattern. Use when the user asks how to write a filter, custom interceptor, custom load balancer, plug in a new registry, or hook into dubbo-go's extension points. --- - # Writing dubbo-go Extensions -## Overview - -Every dubbo-go extension follows the same four-step pattern: implement the interface, register a factory in `init()` through `dubbo.apache.org/dubbo-go/v3/common/extension`, blank-import the package, then activate by name. The string passed to `extension.SetXxx("name", ...)` is the contract - code-API options and YAML must use the exact same name. - -## When to Use - -- Adding a custom Filter, LoadBalance, Router, Registry, Protocol, ConfigCenter, or Logger backend -- Wiring an existing SPI into an application via blank import -- Diagnosing "filter not found", "loadbalance not found", or similar registration errors - -## When NOT to Use +dubbo-go exposes nearly every runtime behavior through a uniform SPI pattern: -- Built-in filters/load balancers/routers already cover the use case (prefer config over code) -- The user only needs canary/tag/condition routing - use static or dynamic router config from `dubbo-go-guide` -- The change is application boilerplate - use `dubbo-go-scaffolding` +1. Implement an interface +2. Call `extension.SetXxx(name, factory)` in an `init()` +3. Blank-import the package so `init()` runs +4. Enable the extension by name at the call site (`server.WithFilter`, `client.WithFilter`, etc.) -## Pick the Extension Point +The extension point you pick depends on **what you want to intercept**: -| Need | Extension point | Register with | +| You want to... | Extension point | `extension.Set*` fn | |---|---|---| -| Intercept RPC calls | `filter.Filter` | `extension.SetFilter` | -| Choose one provider | `loadbalance.LoadBalance` | `extension.SetLoadbalance` | -| Filter provider lists | `router.PriorityRouterFactory` | `extension.SetRouterFactory` | -| Add service discovery backend | `registry.Registry` | `extension.SetRegistry` | -| Add wire protocol | `base.Protocol` | `extension.SetProtocol` | -| Add config center | `config_center.DynamicConfigurationFactory` | `extension.SetConfigCenterFactory` | -| Add logger backend | `logger.Logger` | `extension.SetLogger` | +| Intercept every RPC call (auth, logging, metrics) | Filter | `SetFilter` | +| Choose which provider instance to call | LoadBalance | `SetLoadbalance` | +| Prune the provider list before LB (canary, A/B) | Router | `SetRouterFactory` (rules usually pushed via config center) | +| Plug in a new service-discovery backend | Registry | `SetRegistry` | +| Add a new wire protocol | Protocol | `SetProtocol` | +| Replace the logger backend | Logger | `SetLogger` | -The name string is the contract. The string in `SetXxx("name", ...)` must match the string used in code API or YAML. +## Filter (the 90% case) -## Filter +Filters run on every RPC. They're the right extension point for auth, token injection, metrics, tracing, rate limiting, and request/response logging. -Use filters for auth, token injection, tracing, metrics, rate limiting, logging, and graceful shutdown behavior. +**Package layout**: +``` +yourapp/filter/myfilter/myfilter.go +``` +**myfilter.go**: ```go -package timing +package myfilter import ( "context" "time" ) -import ( - "github.com/dubbogo/gost/log/logger" -) - import ( "dubbo.apache.org/dubbo-go/v3/common/extension" "dubbo.apache.org/dubbo-go/v3/filter" "dubbo.apache.org/dubbo-go/v3/protocol/base" "dubbo.apache.org/dubbo-go/v3/protocol/result" + + "github.com/dubbogo/gost/log/logger" ) func init() { @@ -94,104 +85,92 @@ func (f *timingFilter) OnResponse(ctx context.Context, res result.Result, invoke } ``` -Activate: - +**Activate in main.go**: ```go -import _ "github.com/yourorg/yourapp/filter/timing" +import _ "github.com/yourorg/yourapp/filter/myfilter" // triggers init() + +// Server side, per service +pb.RegisterGreetServiceHandler(srv, impl, server.WithFilter("timing")) -_ = pb.RegisterGreetServiceHandler(srv, impl, server.WithFilter("timing")) +// Client side, per reference svc, _ := pb.NewGreetService(cli, client.WithFilter("timing")) + +// Or globally on the server/client: +// server.WithServerFilter("timing") +// client.WithClientFilter("timing") ``` -Server-wide and client-wide defaults also exist: +**Chain multiple filters** with comma separation: `server.WithFilter("timing,auth")`. Filters run in order on the way in, reverse order on `OnResponse`. + +**Modify attachments** (e.g. add a request ID) in `Invoke` via `inv.SetAttachment(key, val)`; read on the other side with `inv.Attachment(key)`. +**Short-circuit a call** by returning a result without invoking the next link: ```go -server.NewServer(server.WithServerFilter("timing")) -client.NewClient(client.WithClientFilter("timing")) +func (f *authFilter) Invoke(ctx context.Context, invoker base.Invoker, inv base.Invocation) result.Result { + if !isAuthorized(inv) { + return &result.RPCResult{Err: errors.New("unauthorized")} + } + return invoker.Invoke(ctx, inv) +} ``` -Multiple filters use comma-separated names, for example `server.WithFilter("timing,auth")`. +See [filter/custom](https://github.com/apache/dubbo-go-samples/tree/main/filter/custom) for the canonical example. ## LoadBalance -Implement this interface: +Choose one provider out of a list. Built-ins: Random (default), RoundRobin, LeastActive, ConsistentHash, P2C. + +Write a custom one only when the built-ins do not cover your selection rule (e.g. pick by request header, pick by tenant ID). ```go -type LoadBalance interface { - Select([]base.Invoker, base.Invocation) base.Invoker -} -``` +package affinityLB -Example: +import ( + "dubbo.apache.org/dubbo-go/v3/cluster/loadbalance" + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/protocol/base" +) -```go func init() { extension.SetLoadbalance("tenant-affinity", func() loadbalance.LoadBalance { - return &tenantAffinity{} + return &tenantAffinityLB{} }) } -type tenantAffinity struct{} +type tenantAffinityLB struct{} -func (lb *tenantAffinity) Select(invokers []base.Invoker, inv base.Invocation) base.Invoker { +func (lb *tenantAffinityLB) Select(invokers []base.Invoker, inv base.Invocation) base.Invoker { tenant := inv.Attachment("tenant-id") for _, iv := range invokers { if iv.GetURL().GetParam("tenant", "") == tenant { return iv } } - if len(invokers) == 0 { - return nil - } return invokers[0] } ``` -Activate per reference or client: - +Activate per reference: ```go svc, _ := pb.NewGreetService(cli, client.WithLoadBalance("tenant-affinity")) -cli, _ := client.NewClient(client.WithClientLoadBalance("tenant-affinity")) ``` -Built-ins include Random, RoundRobin, LeastActive, ConsistentHashing, P2C, and adaptive strategies. - -## Router - -Routers run before load balancing and can prune the invoker list. Current built-ins include condition, tag, script, affinity, and Polaris routers. - -Custom routers are uncommon. If the user only wants canary, tags, condition rules, or traffic split, prefer built-in routers and static/dynamic router config. - -Custom router shape: - -```go -type PriorityRouterFactory interface { - NewPriorityRouter(url *common.URL) (router.PriorityRouter, error) -} - -type PriorityRouter interface { - Route([]base.Invoker, *common.URL, base.Invocation) []base.Invoker - URL() *common.URL - Priority() int64 - Notify([]base.Invoker) -} -``` - -Register with: - +Or as the client default: ```go -extension.SetRouterFactory("my-router", func() router.PriorityRouterFactory { - return &myFactory{} -}) +cli, _ := client.NewClient(client.WithClientLoadBalance("tenant-affinity")) ``` -Routers that accept static config can also implement `router.StaticConfigSetter`. +## Registry (new service-discovery backend) -## Registry - -Only write a registry if Nacos, ZooKeeper, etcd v3, or Polaris do not fit. +Only needed when the built-in set (Nacos, ZooKeeper, etcd, Polaris, Kubernetes) does not cover your platform. ```go +import ( + "dubbo.apache.org/dubbo-go/v3/common" + "dubbo.apache.org/dubbo-go/v3/common/extension" + "dubbo.apache.org/dubbo-go/v3/registry" +) + func init() { extension.SetRegistry("myregistry", func(url *common.URL) (registry.Registry, error) { return newMyRegistry(url) @@ -199,71 +178,44 @@ func init() { } ``` -Implement `registry.Registry`: `Register`, `UnRegister`, `Subscribe`, `UnSubscribe`, and `LoadSubscribeInstances`. Study `registry/nacos`, `registry/zookeeper`, or `registry/etcdv3` before creating a new backend. - -Activate: - -```go -dubbo.WithRegistry( - registry.WithRegistry("myregistry"), - registry.WithAddress("127.0.0.1:1234"), -) -``` - -Registry options now also control metadata/config-center use and registration mode: - -```go -registry.WithRegisterService() -registry.WithRegisterInterface() -registry.WithRegisterServiceAndInterface() -registry.WithoutUseAsMetaReport() -registry.WithoutUseAsConfigCenter() -``` - -## Protocol - -Most users should not implement a protocol. Use Triple, Dubbo, JSONRPC, REST, or gRPC-compatible Triple unless there is a strong reason. - -Protocol interface: +Implementing the full `registry.Registry` interface is a non-trivial undertaking — read `registry/nacos` or `registry/zookeeper` for reference. +Enable: ```go -type Protocol interface { - Export(base.Invoker) base.Exporter - Refer(*common.URL) base.Invoker - Destroy() -} +dubbo.WithRegistry(registry.WithRegistry("myregistry"), registry.WithAddress("...")) ``` -HTTP-backed protocols can optionally implement `base.HTTPHandlerHost` to support `server.AttachHTTPHandler`. +## Router (traffic-shaping) -## Config Center and Logger +Routers prune the provider list before the load balancer runs. Built-ins: tag, condition, script. -Config centers use `extension.SetConfigCenterFactory` or `extension.SetConfigCenter`. Existing backends include file, Nacos, ZooKeeper, and Apollo. +**Custom routers are uncommon.** The shipped routers read rules from the config center at runtime, so what users usually want is *rule authoring*, not a new router. See: +- [router/tag](https://github.com/apache/dubbo-go-samples/tree/main/router/tag) — tag-based canary +- [router/condition](https://github.com/apache/dubbo-go-samples/tree/main/router/condition) — predicate-based +- [router/script](https://github.com/apache/dubbo-go-samples/tree/main/router/script) — scripted rules -Logger backends use: +If you genuinely need a new routing algorithm, implement `router.PriorityRouter` and register via `extension.SetRouterFactory`. -```go -extension.SetLogger("driver", func(url *common.URL) (logger.Logger, error) { - return newLogger(url) -}) -``` +## Protocol (new wire protocol) -Current logger config supports driver, level, format, appender, file rolling config, and trace integration. +Rarely needed. Implement `base.Protocol`: `Export(invoker)`, `Refer(url)`, `Destroy()`. Register with `extension.SetProtocol(name, factory)`. Most users should stick with Triple, Dubbo, JSONRPC, or REST. ## Troubleshooting -| Symptom | Check | +| Symptom | Likely cause | |---|---| -| `filter not found` | Missing blank import or name mismatch | -| Filter never runs | The package containing `init()` is not imported | -| Custom LB ignored | Use `client.WithLoadBalance` or `client.WithClientLoadBalance` with the registered name | -| Router rule ignored | Confirm router factory name and whether rule is static, dynamic, service-scope, or application-scope | -| Registry not selected | Check registry ID and `WithRegistryIDs` | -| Metadata mapping missing | Use metadata report or set `client.WithProvidedBy` | -| Attached HTTP handler fails | Only Triple supports hosting it; attach before `Serve` and use an explicit port | +| `filter not found` at startup | Blank import missing, or string in `WithFilter("x")` does not match `SetFilter("x", ...)` | +| Filter registered but never called | `init()` lives in a file that is never imported — check the blank-import path | +| LoadBalance not used | Built-in LB took precedence; ensure the name in `WithLoadBalance(...)` matches your registered name | +| Filter modifies attachment but not visible on the other side | Triple attachments travel as HTTP/2 headers; reserved header names may be dropped | +| Custom registry not picked up | `extension.SetRegistry("name", ...)` must match `registry.WithRegistry("name")` exactly | + +## Key Rule of Thumb + +The **name string is the contract**. Whatever you pass to `extension.SetFilter("timing", ...)` must be the exact string passed to `server.WithFilter("timing")` or `client.WithFilter("timing")`. Typos here produce silent failures — the extension simply does not run. ## Related Skills -- `dubbo-go-guide` - when deciding whether a built-in already covers the need before writing custom SPI -- `dubbo-go-scaffolding` - when the user also needs the surrounding provider/consumer skeleton -- `dubbo-go-debugging` - when an SPI is registered but does not run (missing blank import, name mismatch) +- `dubbo-go-guide` — when deciding whether a built-in already covers the need +- `dubbo-go-scaffolding` — when the user also needs the surrounding provider/consumer skeleton +- `dubbo-go-debugging` — when an SPI is registered but does not run diff --git a/.agents/skills/guide/SKILL.md b/.agents/skills/guide/SKILL.md index 230ae8e6bd..f66584fdf4 100644 --- a/.agents/skills/guide/SKILL.md +++ b/.agents/skills/guide/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-guide -description: Use when explaining dubbo-go concepts, architecture, current v3 APIs, protocols, registries, routers, filters, OpenAPI, graceful shutdown, observability, samples, or best practices. +description: Explains dubbo-go v3 architecture, extension points, and best practices. Use when the user asks how dubbo-go works, what a concept means (Instance, Protocol, Registry, Filter, Cluster, LoadBalance, Router, OpenAPI, graceful shutdown), which sample to look at, or asks for best practices. --- - # Guiding dubbo-go Development -## Overview - -Develop-branch map for dubbo-go v3: code API first, Triple as the default wire protocol, application-level discovery as the default registration mode. Reach for this skill when the user asks "how does X work" or "which sample should I follow"; switch to `dubbo-go-scaffolding` when generating an app, `dubbo-go-extensions` when adding an SPI, or `dubbo-go-debugging` when troubleshooting a runtime failure. - -## When to Use - -- Conceptual questions: instance/server/client/protocol/registry/cluster/router/filter -- Choosing between Triple, Dubbo, JSONRPC, REST, gRPC-compatible Triple, HTTP/3 -- Pointing the user to the right `dubbo-go-samples` directory -- Explaining OpenAPI, CORS, AttachHTTPHandler, graceful shutdown, observability defaults - -## Project Snapshot - -- Module: `dubbo.apache.org/dubbo-go/v3` -- Go version in `go.mod`: `1.25.0` -- Main entry points: `dubbo.NewInstance`, `server.NewServer`, `client.NewClient` -- Preferred user style: code API -- Legacy/compat style: YAML-driven `dubbo.Load()` / `config.Load()` still exists and now uses koanf-based loading -- Preferred wire protocol: Triple -- Important recent capabilities: Triple OpenAPI, HTTP/3, CORS, attached HTTP handlers, refined graceful shutdown, logger trace integration, router static config, `variadicrpccheck` - -## Repository Map - -- `client/`: consumer/reference options, URL processing, invoker construction -- `server/`: provider/server options, service registration, `AttachHTTPHandler` -- `protocol/`: protocol abstractions and implementations; `protocol/triple` is the primary path -- `registry/`: registry and application-level service discovery implementations -- `metadata/`: metadata report and service-to-application mapping -- `cluster/`: cluster strategies, router chain, load balancing -- `filter/`: provider and consumer filter implementations -- `config/`, `global/`: YAML/config structs and runtime config models -- `config_center/`: Nacos, ZooKeeper, Apollo, and file dynamic config -- `graceful_shutdown/`: shutdown options and runtime state -- `metrics/`, `otel/`, `logger/`: observability integrations -- `tools/`: CLI, schema generator, Triple/OpenAPI generators, imports formatter, RPC contract scanner - ## Core Concepts -**Instance**: global application context. Use `dubbo.NewInstance` when sharing application, registry, protocol, logger, shutdown, metrics, tracing, TLS, or router settings across clients and servers. - -**Server**: owns provider-side config and service exports. Register generated Triple handlers with `pb.RegisterXxxHandler`. - -**Client**: owns consumer-side config. Create generated service clients with `pb.NewXxxService`. - -**Protocol**: wire transport. Triple is HTTP/2 and gRPC-compatible; Dubbo is for legacy Hessian2 interop; JSONRPC and REST also exist; HTTP/3 is experimental under Triple. +**Instance** — top-level entry point. `dubbo.NewInstance()` configures the application globally; create server and client from it. -**Registry**: service discovery. Built-ins include Nacos, ZooKeeper, etcd v3, and Polaris. +**Protocol** — how bytes travel on the wire. Triple is the default (HTTP/2, gRPC-compatible). Dubbo is for Java interop with Hessian2. JSONRPC and REST are also built-in. -**Metadata mapping**: application-level discovery needs a mapping from interface to provider application. If metadata mapping is unavailable, use `client.WithProvidedBy("provider-app")`. +**Registry** — service discovery. Provider registers itself; consumer queries to find providers. Built-ins: Nacos, ZooKeeper, etcd, Polaris, Kubernetes. -**Filter**: interceptor chain around RPC calls. Filters run on provider and consumer paths and are used for auth, metrics, tracing, rate limiting, graceful shutdown, logging, and generic calls. +**Filter** — interceptor chain around every RPC call, on both sides. Used for auth, metrics, tracing, rate limiting. -**Cluster**: fault-tolerance strategy such as Failover, Failfast, Failsafe, Failback, Available, Broadcast, Forking, ZoneAware, and AdaptiveService. +**Cluster** — fault-tolerance strategy when calling a provider group. Failover (default), Failfast, Failsafe, Forking, Broadcast. -**LoadBalance**: provider selection. Built-ins include Random, RoundRobin, LeastActive, ConsistentHashing, P2C, and adaptive strategies. +**LoadBalance** — selects one provider from the candidate list. Random (default), RoundRobin, LeastActive, ConsistentHash, P2C. -**Router**: filters providers before load balancing. Built-ins include tag, condition, script, affinity, and Polaris routers. Static router config can be supplied through client/root router options; dynamic rules can come from config centers. +**Router** — prunes the provider list before load balancing. Tag, condition, script. Rules typically come from the config center, not from custom code. -## Current API Patterns +**MetadataReport / ConfigCenter** — application-level metadata storage and dynamic configuration. Same backend as the registry in most setups. -Direct server: +## SPI Extension Pattern -```go -srv, err := server.NewServer( - server.WithServerProtocol( - protocol.WithPort(20000), - protocol.WithTriple(), - ), -) -``` - -Registry-backed instance: - -```go -ins, err := dubbo.NewInstance( - dubbo.WithName("orders-provider"), - dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")), - dubbo.WithProtocol(protocol.WithTriple(), protocol.WithPort(20000)), -) -``` - -Reference options: - -```go -svc, err := pb.NewOrderService( - cli, - client.WithInterface("shop.OrderService"), - client.WithProvidedBy("orders-provider"), - client.WithRequestTimeout(3*time.Second), -) -``` - -Service options: +Every dubbo-go extension follows the same shape: ```go -err := pb.RegisterOrderServiceHandler( - srv, - impl, - server.WithInterface("shop.OrderService"), - server.WithGroup("beta"), - server.WithVersion("v2"), - server.WithOpenAPIGroup("orders-v2"), -) +// 1. Implement the interface +type myFilter struct{} +func (f *myFilter) Invoke(ctx context.Context, invoker base.Invoker, inv base.Invocation) result.Result { + res := invoker.Invoke(ctx, inv) + return res +} +func (f *myFilter) OnResponse(ctx context.Context, res result.Result, invoker base.Invoker, inv base.Invocation) result.Result { + return res +} + +// 2. Register in init() +func init() { + extension.SetFilter("my-filter", func() filter.Filter { return &myFilter{} }) +} + +// 3. Activate with a blank import in main.go +// import _ "github.com/yourorg/yourapp/filter/myfilter" + +// 4. Enable per-service via the code API +// pb.RegisterGreetServiceHandler(srv, impl, server.WithFilter("my-filter")) ``` -## Extension Pattern - -Most extension points follow: +The same pattern applies to Protocol, Registry, LoadBalance, Router, ConfigCenter, MetadataReport, Logger. -1. Implement the interface. -2. Register a factory in `init()` through `common/extension`. -3. Blank-import the package so `init()` runs. -4. Activate by name through code API or config. +> Note: older samples still show `protocol.Invoker/Invocation/Result` aliases. They resolve to the same types in `protocol/base` and `protocol/result` — prefer the new packages in new code. -Examples: - -- Filter: `extension.SetFilter("name", func() filter.Filter { ... })` -- LoadBalance: `extension.SetLoadbalance("name", func() loadbalance.LoadBalance { ... })` -- Registry: `extension.SetRegistry("name", func(*common.URL) (registry.Registry, error) { ... })` -- Protocol: `extension.SetProtocol("name", func() base.Protocol { ... })` -- Router: `extension.SetRouterFactory("name", func() router.PriorityRouterFactory { ... })` - -The string name is the contract. Keep registration and activation names identical. - -## Triple Extras - -OpenAPI: - -```go -protocol.WithTriple( - triple.WithOpenAPI( - triple.OpenAPIEnable(), - triple.OpenAPIPath("/dubbo/openapi"), - ), -) -``` - -CORS: - -```go -protocol.WithTriple( - triple.WithCORS( - triple.CORSAllowOrigins("https://example.com"), - triple.CORSAllowMethods("POST", "GET", "OPTIONS"), - ), -) -``` - -HTTP/3: - -```go -protocol.WithTriple(triple.Http3Enable()) -``` - -Attached HTTP handler: - -```go -_ = srv.AttachHTTPHandler(mux) -``` - -Attach before `Serve`, use one root handler, and configure an explicit Triple port. - -## Samples +## Best Practices -See [samples-index.md](samples-index.md) for the current dubbo-go-samples map. +- Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` in development for convenience; switch to selective imports in production for smaller binaries. +- Define Triple services with Protobuf for cross-language interop. +- Configure via the code API: `dubbo.NewInstance(dubbo.WithRegistry(...), dubbo.WithProtocol(...))`. YAML via `dubbo.Load()` is the legacy path. +- Enable graceful shutdown by blank-importing `_ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown"`. +- Use `client.WithProvidedBy` when application-level discovery cannot resolve which application owns the interface. +- Apply per-reference timeouts: `client.WithRequestTimeout(...)` or a `context.WithTimeout` at the call site. -Start with: +## Triple-Only Capabilities -- `helloworld`: minimal direct Triple -- `direct`: direct URL connection -- `registry/nacos`: Nacos service discovery -- `rpc/triple/openapi`: runtime Triple OpenAPI -- `http3`: experimental HTTP/3 -- `graceful_shutdown`: shutdown flow -- `logger/trace-integration`: trace IDs in logs +- **OpenAPI** — `triple.OpenAPIEnable(true)` publishes a runtime OpenAPI spec. +- **HTTP handler attachment** — `srv.AttachHTTPHandler("/path", handler)` mounts plain HTTP on the same port. +- **HTTP/3** — `triple.Http3Enable()` (experimental, TLS required). +- **CORS** — `triple.CORSAllowOrigins(...)` etc. +- **Reflection** — gRPC reflection is on by default; tools like `grpcurl` work without extra config. -## Best Practices +## Samples Index -- Prefer Protobuf plus Triple for new services. -- Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` for examples and local demos; use selective blank imports in production when binary size matters. -- Use code API for new code; keep YAML only for existing config-driven applications. -- Use `client.WithProvidedBy` when application-level discovery cannot resolve interface-to-application mapping. -- Do not assume viper APIs in config work; current loading is koanf-centered. -- Run repository validation commands from the development skill before finishing code changes. +See [samples-index.md](samples-index.md) for the full `dubbo-go-samples` directory organized by scenario (Quick Start, Protocols, Service Discovery, Filters, Routing, Streaming, Observability, Security, Java Interop, Advanced). ## Related Skills -- `dubbo-go-scaffolding` - when the user wants to generate a provider/consumer instead of read about it -- `dubbo-go-extensions` - when explaining a built-in is not enough and the user needs a custom SPI -- `dubbo-go-java-interop` - when the question involves dubbo-java compatibility -- `dubbo-go-debugging` - when the question is "why is X failing" rather than "how does X work" -- `dubbo-go-migration` - when the question is "how do I move from Y to dubbo-go" -- `dubbo-go-development` - when the explanation must dig into the `apache/dubbo-go` repo internals +- `dubbo-go-scaffolding` — when the user wants to generate a provider/consumer +- `dubbo-go-extensions` — when a built-in is not enough and the user needs a custom SPI +- `dubbo-go-java-interop` — when the question involves dubbo-java compatibility +- `dubbo-go-debugging` — when the question is "why is X failing" +- `dubbo-go-migration` — when the question is "how do I move from Y to dubbo-go" diff --git a/.agents/skills/guide/samples-index.md b/.agents/skills/guide/samples-index.md index b08f038937..5b0ebcea81 100644 --- a/.agents/skills/guide/samples-index.md +++ b/.agents/skills/guide/samples-index.md @@ -17,103 +17,69 @@ limitations under the License. # dubbo-go-samples Index -Use this index when a user asks which example to follow. Paths refer to `https://github.com/apache/dubbo-go-samples/tree/main/`. +Each entry links to a directory under [apache/dubbo-go-samples](https://github.com/apache/dubbo-go-samples). ## Quick Start - -- `helloworld` - minimal Triple/Protobuf provider and consumer -- `direct` - direct URL connection without registry -- `config_yaml` - YAML-driven provider and consumer -- `context` - context propagation -- `error` - error behavior +- [helloworld](https://github.com/apache/dubbo-go-samples/tree/main/helloworld) — minimal Triple/Protobuf provider + consumer +- [direct](https://github.com/apache/dubbo-go-samples/tree/main/direct) — direct URL connection, no registry ## Protocols - -- `rpc/triple/pb` - Triple with Protobuf -- `rpc/triple/pb2` - additional Triple Protobuf variant -- `rpc/triple/pb-json` - Triple JSON behavior -- `rpc/triple/instance` - `dubbo.NewInstance` style -- `rpc/triple/registry` - Triple with registry -- `rpc/triple/reflection` - reflection -- `rpc/triple/stream` - Triple streaming -- `rpc/triple/openapi` - runtime OpenAPI docs for Triple -- `rpc/triple/old_triple` - old Triple compatibility -- `rpc/grpc` - gRPC interop pattern -- `rpc/multi-protocols` - multiple protocols on one server -- `http3` - experimental Triple HTTP/3 +- [rpc/triple](https://github.com/apache/dubbo-go-samples/tree/main/rpc/triple) — Triple variants (Protobuf, JSON, streaming, reflection, OpenAPI) +- [rpc/grpc](https://github.com/apache/dubbo-go-samples/tree/main/rpc/grpc) — gRPC interop +- [rpc/multi-protocols](https://github.com/apache/dubbo-go-samples/tree/main/rpc/multi-protocols) — multiple protocols on one server +- [http3](https://github.com/apache/dubbo-go-samples/tree/main/http3) — Triple over HTTP/3 (experimental) ## Service Discovery - -- `registry/nacos` -- `registry/zookeeper` -- `registry/etcd` -- `registry/polaris` -- `config_center/nacos` -- `config_center/zookeeper` -- `config_center/apollo` - -## Filters and Resilience - -- `filter/custom` - custom filters -- `filter/token` - token filter -- `filter/tpslimit` - TPS limiting -- `filter/sentinel` - Sentinel flow control -- `filter/hystrix` - Hystrix-style circuit breaker -- `filter/polaris/limit` - Polaris limit integration -- `retry` - retry behavior -- `timeout` - timeout behavior -- `graceful_shutdown` - graceful shutdown behavior +- [registry/nacos](https://github.com/apache/dubbo-go-samples/tree/main/registry/nacos) +- [registry/zookeeper](https://github.com/apache/dubbo-go-samples/tree/main/registry/zookeeper) +- [registry/etcd](https://github.com/apache/dubbo-go-samples/tree/main/registry/etcd) +- [registry/polaris](https://github.com/apache/dubbo-go-samples/tree/main/registry/polaris) + +## Configuration +- [config_yaml](https://github.com/apache/dubbo-go-samples/tree/main/config_yaml) +- [config_center/nacos](https://github.com/apache/dubbo-go-samples/tree/main/config_center/nacos) +- [config_center/zookeeper](https://github.com/apache/dubbo-go-samples/tree/main/config_center/zookeeper) +- [config_center/apollo](https://github.com/apache/dubbo-go-samples/tree/main/config_center/apollo) + +## Filters & Resilience +- [filter/custom](https://github.com/apache/dubbo-go-samples/tree/main/filter/custom) — writing custom filters +- [filter/sentinel](https://github.com/apache/dubbo-go-samples/tree/main/filter/sentinel) — flow control +- [filter/hystrix](https://github.com/apache/dubbo-go-samples/tree/main/filter/hystrix) — circuit breaker +- [filter/token](https://github.com/apache/dubbo-go-samples/tree/main/filter/token) +- [filter/tpslimit](https://github.com/apache/dubbo-go-samples/tree/main/filter/tpslimit) +- [retry](https://github.com/apache/dubbo-go-samples/tree/main/retry) +- [timeout](https://github.com/apache/dubbo-go-samples/tree/main/timeout) +- [graceful_shutdown](https://github.com/apache/dubbo-go-samples/tree/main/graceful_shutdown) ## Traffic Management +- [router/tag](https://github.com/apache/dubbo-go-samples/tree/main/router/tag) +- [router/condition](https://github.com/apache/dubbo-go-samples/tree/main/router/condition) +- [router/script](https://github.com/apache/dubbo-go-samples/tree/main/router/script) +- [mesh](https://github.com/apache/dubbo-go-samples/tree/main/mesh) — proxyless mesh +- [apisix](https://github.com/apache/dubbo-go-samples/tree/main/apisix) — APISIX gateway -- `router/tag` - tag routing -- `router/condition` - condition routing -- `router/script` - script routing -- `router/static_config/tag` - static tag router config -- `router/static_config/condition` - static condition router config -- `router/polaris` - Polaris router integration -- `mesh` - proxyless mesh scenario -- `apisix` - APISIX gateway integration - -## Streaming and Async +## Streaming +- [streaming](https://github.com/apache/dubbo-go-samples/tree/main/streaming) -- `streaming` -- `async` - -## Observability and Operations - -- `metrics/prometheus_grafana` -- `metrics/probe` -- `otel/tracing/jaeger` -- `otel/tracing/otlp_http_exporter` -- `otel/tracing/stdout` -- `logger/default` -- `logger/level` -- `logger/rolling` -- `logger/custom` -- `logger/trace-integration` -- `healthcheck` +## Observability +- [metrics/prometheus_grafana](https://github.com/apache/dubbo-go-samples/tree/main/metrics/prometheus_grafana) +- [metrics/probe](https://github.com/apache/dubbo-go-samples/tree/main/metrics/probe) — Kubernetes health probes +- [otel/tracing](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing) — Jaeger / OTLP / stdout exporters +- [logger](https://github.com/apache/dubbo-go-samples/tree/main/logger) — default, level, rolling, custom, trace integration ## Security - -- `tls` -- `filter/token` +- [tls](https://github.com/apache/dubbo-go-samples/tree/main/tls) +- [filter/token](https://github.com/apache/dubbo-go-samples/tree/main/filter/token) ## Java Interop - -- `java_interop/protobuf-triple` -- `java_interop/non-protobuf-dubbo` -- `java_interop/non-protobuf-triple` -- `java_interop/service_discovery` -- `helloworld` - includes Go and Java sides -- `direct` - includes Go and Java direct mode -- `http3` - includes Java HTTP/3 sample +- [java_interop/protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/protobuf-triple) +- [java_interop/non-protobuf-dubbo](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-dubbo) +- [java_interop/non-protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-triple) +- [java_interop/service_discovery](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/service_discovery) ## Advanced - -- `generic` - generic invocation -- `llm` - LLM-related sample -- `book-flight-ai-agent` - AI agent sample -- `game` -- `online_boutique` -- `transcation/seata-go` - Seata transaction sample; upstream directory name is intentionally misspelled `transcation` +- [generic](https://github.com/apache/dubbo-go-samples/tree/main/generic) — generic invocation +- [async](https://github.com/apache/dubbo-go-samples/tree/main/async) +- [llm](https://github.com/apache/dubbo-go-samples/tree/main/llm) — LLM integration +- [book-flight-ai-agent](https://github.com/apache/dubbo-go-samples/tree/main/book-flight-ai-agent) — AI agent +- [transcation/seata-go](https://github.com/apache/dubbo-go-samples/tree/main/transcation/seata-go) — Seata distributed transactions diff --git a/.agents/skills/java-interop/SKILL.md b/.agents/skills/java-interop/SKILL.md index 354d1b4fa8..face3489b1 100644 --- a/.agents/skills/java-interop/SKILL.md +++ b/.agents/skills/java-interop/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-java-interop -description: Use when connecting dubbo-go v3 with dubbo-java, choosing Triple versus Dubbo protocol, sharing Protobuf contracts, mirroring Java interfaces, handling Hessian2 POJOs, or debugging cross-language discovery and serialization. +description: Guides interoperability between dubbo-go v3 and dubbo-java — cross-language RPC using Triple+Protobuf or Dubbo+Hessian2. Use when the user asks how to call a Java Dubbo service from Go, expose a Go service to Java clients, share a proto/interface across languages, or pick between Triple and Dubbo for interop. --- +# Dubbo Java and Go Interop -# Dubbo Java and Go Interoperability +A single service definition can be served by Go and consumed by Java (or vice versa) without a gateway. Two viable paths: -## Overview - -Two interop paths, one decision: Triple + Protobuf for everything new and polyglot; Dubbo + Hessian2 only when the Java side already owns a non-proto interface. Picking the wrong path locks the team into bespoke serialization code. - -## When to Use - -- Bridging a Go service to existing Java Dubbo providers/consumers -- Choosing protocol/serialization for a new cross-language service -- Diagnosing `hessian: failed to decode`, missing-provider, or class-name-mismatch errors across languages - -## Path Selection - -| Path | Protocol | Serialization | Use when | +| Path | Wire format | Serialization | When to use | |---|---|---|---| -| Triple + Protobuf | Triple over HTTP/2 | Protobuf | New services, polyglot teams, gRPC-compatible clients, OpenAPI docs | -| Dubbo + Hessian2 | Dubbo TCP | Hessian2 | Existing Java Dubbo interfaces with POJO request/response classes | +| **Triple + Protobuf** (recommended) | HTTP/2 | Protobuf | New services, polyglot teams, gRPC-compatible clients | +| **Dubbo + Hessian2** | TCP (dubbo) | Hessian2 | Calling existing Java services that were originally defined as Java interfaces (no `.proto`) | + +Pick Triple unless integrating with an existing Hessian2 Java codebase. -## Triple + Protobuf +## Path 1: Triple + Protobuf (recommended) -Shared `.proto`: +A shared `.proto` file drives both sides. Set both `go_package` and `java_package`: ```protobuf syntax = "proto3"; @@ -57,69 +48,59 @@ service Greeter { rpc SayHello(HelloRequest) returns (HelloReply); } -message HelloRequest { - string name = 1; -} - -message HelloReply { - string message = 1; -} +message HelloRequest { string name = 1; } +message HelloReply { string message = 1; } ``` -Go server: +**Go server** — nothing interop-specific, just Triple: ```go -srv, err := server.NewServer( +srv, _ := server.NewServer( server.WithServerProtocol( protocol.WithPort(20000), protocol.WithTriple(), ), ) -if err != nil { - return err -} - -if err := greet.RegisterGreeterHandler(srv, &impl{}); err != nil { - return err -} -return srv.Serve() +greet.RegisterGreeterHandler(srv, &impl{}) +srv.Serve() ``` -Triple exposes JSON-over-HTTP, which is useful for smoke tests: +**Test interop with curl** — Triple supports JSON over HTTP/1.1: ```bash curl -H "Content-Type: application/json" \ - -d '{"name":"Dubbo"}' \ - http://127.0.0.1:20000/org.apache.dubbo.sample.Greeter/SayHello + -d '{"name":"Dubbo"}' \ + http://localhost:20000/org.apache.dubbo.sample.Greeter/sayHello ``` -The path is `/./`. Use the method name from the `.proto` file, for example `Greet` or `SayHello`. +The path is `/./` — the Java side uses lowercase-first-letter method names by convention. -## Triple Interop Rules +**Java client** uses standard dubbo-java APIs; no Go-specific code. See [java_interop/protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/protobuf-triple) for the working pair. -- `package` in `.proto` controls the Triple service path. -- `go_package` controls Go package path and package name. -- `java_package` controls Java generated classes and interface package. -- Renaming proto package, service, or method names is a wire-level breaking change. -- Use the same `.proto` source for Go and Java generation. -- Triple supports reflection and HTTP-friendly testing; use OpenAPI when documenting REST-like access for humans. +### Rules of thumb for Triple interop -## Dubbo + Hessian2 +- **Method-name casing**: Protobuf generators emit `SayHello` in Go and `sayHello` on the Java wire. The HTTP route uses the lowercase-first form. +- **Package matters**: `java_package` in the proto becomes the Java interface FQN — pick deliberately, renaming later is breaking. +- **Reflection**: Triple exposes gRPC reflection automatically; tools like `grpcurl` and `bloomrpc` work without extra config. -Use this for Java-defined services without Protobuf. The Go side must mirror Java classes and register POJOs. +## Path 2: Dubbo + Hessian2 (Java-defined services) + +Use this when the service is **defined by a Java interface** (no `.proto`) and you need to add a Go side. + +The Go side mirrors the Java POJO via Hessian2 registration. Field names, types, and `JavaClassName()` must match the Java class. ```go package greet import ( - dubbohessian "github.com/apache/dubbo-go-hessian2" + dubbo_go_hessian2 "github.com/apache/dubbo-go-hessian2" ) type GreetRequest struct { Name string } -func (*GreetRequest) JavaClassName() string { +func (x *GreetRequest) JavaClassName() string { return "org.apache.dubbo.hessian2.api.GreetRequest" } @@ -127,106 +108,77 @@ type GreetResponse struct { Greeting string } -func (*GreetResponse) JavaClassName() string { +func (x *GreetResponse) JavaClassName() string { return "org.apache.dubbo.hessian2.api.GreetResponse" } func init() { - dubbohessian.RegisterPOJO(new(GreetRequest)) - dubbohessian.RegisterPOJO(new(GreetResponse)) + dubbo_go_hessian2.RegisterPOJO(new(GreetRequest)) + dubbo_go_hessian2.RegisterPOJO(new(GreetResponse)) } ``` -Server protocol: +**Go server** — pick the Dubbo protocol, not Triple: ```go -srv, err := server.NewServer( +srv, _ := server.NewServer( server.WithServerProtocol( protocol.WithPort(20000), protocol.WithDubbo(), ), ) +greet.RegisterGreetServiceHandler(srv, &impl{}) +srv.Serve() ``` -Consumer reference: +See [java_interop/non-protobuf-dubbo](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-dubbo) for the canonical end-to-end example. -```go -svc, err := greet.NewGreetingsService( - cli, - client.WithProtocolDubbo(), - client.WithSerialization("hessian2"), -) -``` +### Hessian2 gotchas -## Hessian2 Rules - -- Every POJO type must implement `JavaClassName()` and be registered with `RegisterPOJO`. -- Fully-qualified Java class names must match exactly. -- Prefer primitives, strings, slices, maps, and registered nested POJOs. -- Avoid Go-only shapes such as channels, functions, and generics in RPC DTOs. -- Java enum mapping depends on Java-side serialization; verify before assuming string values. -- `hessian: failed to decode` usually means class name mismatch, missing `RegisterPOJO`, field/type mismatch, or wrong protocol/serialization. +- **Field names are case-sensitive on the wire** — Go's exported names are serialized lowercase-first to match Java conventions. The hessian2 library handles this; custom struct tags can break it. +- **Unsupported types**: Go generics, channels, functions will not serialize. Stick to primitives, slices, maps, and other registered POJOs. +- **Unregistered POJOs** → `hessian: failed to decode` at runtime. Always `RegisterPOJO` in the package's `init()`. +- **Java `enum` maps to Go `int`** (the ordinal), not a string — unless the Java side customized serialization. +- **Time**: Java `Date` ↔ Go `time.Time` generally works; `java.time.*` types need extra care. ## Service Discovery Across Languages -Use the same registry cluster and compatible registry mode on both sides. - -Provider: +When both sides use the **same registry** (Nacos / ZooKeeper), they discover each other automatically — the registry entry is language-agnostic, just a URL with protocol + address. ```go -ins, err := dubbo.NewInstance( - dubbo.WithName("polyglot-provider"), +dubbo.NewInstance( + dubbo.WithName("polyglot-service"), // same application name as the Java side dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")), dubbo.WithProtocol(protocol.WithTriple(), protocol.WithPort(20000)), ) ``` -Consumer: - -```go -svc, err := greet.NewGreeterService( - cli, - client.WithInterface("org.apache.dubbo.sample.Greeter"), - client.WithProvidedBy("polyglot-provider"), -) -``` - -`WithProvidedBy` is useful when application-level service discovery cannot load interface-to-application mapping from the metadata center. +If application-level discovery cannot resolve which application owns the interface, hint with `client.WithProvidedBy("")`. -Registry modes: - -```go -registry.WithRegisterService() -registry.WithRegisterInterface() -registry.WithRegisterServiceAndInterface() -``` - -Use `WithRegisterServiceAndInterface` when bridging old interface-level discovery and newer application-level discovery during migration. +See [java_interop/service_discovery](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/service_discovery). ## Decision Table -| Scenario | Choice | +| Scenario | Path | |---|---| -| New Go and Java service | Triple + Protobuf | -| Java service already has `.proto` | Triple + Protobuf | -| Existing Java interface only, no proto | Dubbo + Hessian2 | -| Need browser/curl smoke tests or OpenAPI docs | Triple + Protobuf | -| Need to preserve old Java POJOs exactly | Dubbo + Hessian2 | -| Metadata mapping is missing | Add metadata report or set `client.WithProvidedBy` | +| New service, Go and Java teams both need clients | **Triple + Protobuf** | +| Calling an existing Java Dubbo service defined by a Java interface | **Dubbo + Hessian2** | +| Legacy Java service exports both Triple and Dubbo endpoints | **Triple + Protobuf** on the Go side | +| Need a gRPC-compatible wire | **Triple + Protobuf** | +| Cannot touch the Java side, and it is not Protobuf | **Dubbo + Hessian2** | ## Reference Samples -- `dubbo-go-samples/java_interop/protobuf-triple` -- `dubbo-go-samples/java_interop/non-protobuf-dubbo` -- `dubbo-go-samples/java_interop/non-protobuf-triple` -- `dubbo-go-samples/java_interop/service_discovery` -- `dubbo-go-samples/helloworld` -- `dubbo-go-samples/direct` -- `dubbo-go-samples/http3` +- [java_interop/protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/protobuf-triple) — both directions, Triple + Protobuf +- [java_interop/non-protobuf-dubbo](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-dubbo) — Hessian2 POJO bridge +- [java_interop/non-protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-triple) — Triple without Protobuf (rare) +- [java_interop/service_discovery](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/service_discovery) — Nacos-based cross-language discovery + +Official guide: [Interoperability with Dubbo Java](https://cn.dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/tutorial/interop-dubbo/). ## Related Skills -- `dubbo-go-scaffolding` - when generating the Go side of a polyglot service -- `dubbo-go-extensions` - when adding a Hessian2 codec, Java-aware filter, or custom registry shared with Java -- `dubbo-go-migration` - when porting an existing Java Dubbo service or splitting a Spring Cloud monolith -- `dubbo-go-debugging` - when the symptom is `hessian: failed to decode`, missing provider across languages, or registry-mode mismatch +- `dubbo-go-scaffolding` — for the Go side of a polyglot service +- `dubbo-go-extensions` — when adding a Hessian2 codec, Java-aware filter, or shared registry +- `dubbo-go-migration` — when porting an existing Java service or splitting a Spring Cloud monolith +- `dubbo-go-debugging` — when the symptom is `hessian: failed to decode`, missing-provider across languages, or registry-mode mismatch diff --git a/.agents/skills/migrate/SKILL.md b/.agents/skills/migrate/SKILL.md index 692ce794e3..ab5a6355d2 100644 --- a/.agents/skills/migrate/SKILL.md +++ b/.agents/skills/migrate/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-migration -description: Use when migrating to dubbo-go v3 from gRPC-Go, Spring Cloud, Gin, plain HTTP, older dubbo-go versions, YAML-based apps, Java Dubbo, or legacy Hessian2 services. +description: Guides migration to dubbo-go v3 from gRPC-Go, Spring Cloud, Gin / plain HTTP, dubbo-go v1/v2, YAML-heavy v3 apps, and Java-interface Hessian2 services. Use when the user asks how to migrate, port, or upgrade an existing service to dubbo-go v3. --- - # Migrating to dubbo-go -## Overview - -Migration is mostly mechanical: the source framework decides the concept-mapping table, then dubbo-go v3 code-API patterns slot in. Triple + Protobuf is the default target; Dubbo + Hessian2 is reserved for Java-interface services without a `.proto`. - -## Source-System Decision Table +First question: **where are you migrating from?** | User says | Jump to | |---|---| | "We're on gRPC-Go" | [From gRPC-Go](#from-grpc-go) | -| "Spring Cloud / Java Dubbo" | [From Spring Cloud or Java Dubbo](#from-spring-cloud-or-java-dubbo) | -| "Gin / chi / net/http" | [From Gin or Plain HTTP](#from-gin-or-plain-http) | -| "Old dubbo-go v1/v2 or YAML-heavy v3" | [From dubbo-go v1/v2 or Old v3 YAML](#from-dubbo-go-v1v2-or-old-v3-yaml) | -| "Java owns the contract, no proto" | [From Java-interface Hessian2](#from-java-interface-hessian2) | +| "Spring Cloud / Java microservices" | [From Spring Cloud](#from-spring-cloud-java) | +| "Gin / chi / net/http" | [From Gin or plain HTTP](#from-gin--plain-http) | +| "dubbo-go v1 or v2" | [From dubbo-go v1/v2 → v3](#from-dubbo-go-v1v2--v3) | +| "YAML-heavy v3 app" | [From YAML-heavy v3](#from-yaml-heavy-v3) | -Use code API for new work and keep YAML only when preserving an existing deployment model. +For Java-interface Hessian2 services, see `dubbo-go-java-interop`. + +Use the code API for new work; keep YAML only when preserving an existing deployment model. ## From gRPC-Go -Concept mapping: +**Concept mapping** -| gRPC-Go | dubbo-go v3 | +| gRPC-Go | dubbo-go | |---|---| -| `grpc.NewServer()` | `server.NewServer()` | -| `pb.RegisterXxxServer(srv, impl)` | `pb.RegisterXxxHandler(srv, impl)` | -| `grpc.Dial` / `grpc.NewClient` | `client.NewClient()` + `pb.NewXxxService(cli)` | -| Unary interceptor | Filter | -| Service config / resolver | Registry + cluster + load balance | -| Reflection | Triple reflection sample and OpenAPI support | +| `grpc.NewServer()` | `server.NewServer()` (or `ins.NewServer()` with `dubbo.NewInstance`) | +| `pb.RegisterXxxServer(srv, impl)` | `pb.RegisterXxxHandler(srv, impl)` (Triple) | +| `grpc.Dial(addr)` | `client.NewClient()` → `pb.NewXxxService(cli)` | +| `UnaryServerInterceptor` | Filter | +| `grpc.WithUnaryInterceptor(...)` | `server.WithFilter("my-filter")` + blank import | +| Service reflection | Built-in with Triple | -Protobuf can usually be reused. Generate Triple bindings: +**Proto file**: no changes needed. Triple is wire-compatible with gRPC. -```bash -go install github.com/dubbogo/protoc-gen-go-triple/v3@latest -protoc --go_out=. --go_opt=paths=source_relative \ - --go-triple_out=. --go-triple_opt=paths=source_relative \ - proto/*.proto -``` - -Direct-mode consumer: +**Key difference**: dubbo-go adds service discovery on top of gRPC. For direct connection, use direct mode — no registry needed. ```go -cli, err := client.NewClient( - client.WithClientURL("127.0.0.1:20000"), -) -svc, err := pb.NewGreetService(cli) +// gRPC-Go +conn, _ := grpc.NewClient("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials())) +client := pb.NewGreetClient(conn) + +// dubbo-go (direct mode) +cli, _ := client.NewClient(client.WithClientURL("127.0.0.1:20000")) +svc, _ := pb.NewGreetService(cli) ``` -Add a registry later with `dubbo.NewInstance` and `dubbo.WithRegistry`. +See [rpc/grpc](https://github.com/apache/dubbo-go-samples/tree/main/rpc/grpc) and [direct](https://github.com/apache/dubbo-go-samples/tree/main/direct). -## From Spring Cloud or Java Dubbo +## From Spring Cloud (Java) -Concept mapping: +**Concept mapping** -| Spring Cloud / Dubbo Java | dubbo-go v3 | +| Spring Cloud | dubbo-go | |---|---| -| Discovery client | `dubbo.WithRegistry(...)` | -| Feign/Dubbo reference | generated `pb.NewXxxService(cli, ...)` | -| Controller or Dubbo provider | `pb.RegisterXxxHandler(srv, impl, ...)` | -| Hystrix / Sentinel | Hystrix or Sentinel filters | -| Sleuth / tracing | OpenTelemetry integration | -| Actuator health | `metrics/probe` sample | -| Java interface + POJO | Dubbo protocol + Hessian2 | +| `@EnableDiscoveryClient` | `dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress(...))` | +| `@FeignClient` | `client.NewClient()` + generated `pb.NewXxxService(cli)` | +| `@RestController` | `pb.RegisterXxxHandler(srv, impl)` + Triple/REST | +| Spring Cloud Gateway | Apache APISIX or direct | +| Hystrix / Resilience4j | Hystrix filter / Sentinel filter | +| Sleuth / Zipkin | OpenTelemetry filter | +| Actuator `/health` | `metrics/probe` (`/live`, `/ready`) | -Migration path: +**Migration path**: +1. Keep Java services running. +2. Add dubbo-go providers for new Go services using Triple + Protobuf. +3. Java consumers can call Go providers via Triple (wire-compatible). +4. Migrate Java consumers to Go one by one. -1. Keep existing Java services running. -2. Use Triple + Protobuf for new Go services where possible. -3. Use Dubbo + Hessian2 only when the Java side has no proto contract. -4. Share registry and metadata mapping. If mapping is not available, use `client.WithProvidedBy`. -5. During transition, use `registry.WithRegisterServiceAndInterface()` when both app-level and interface-level discovery are needed. +See [java_interop](https://github.com/apache/dubbo-go-samples/tree/main/java_interop) and `dubbo-go-java-interop`. -## From Gin or Plain HTTP +## From Gin / plain HTTP -dubbo-go is primarily an RPC and service governance framework, but current develop provides three practical migration options. +**Concept mapping** + +| Gin / HTTP | dubbo-go | +|---|---| +| `gin.Default()` + `r.POST(...)` | `server.NewServer()` + `pb.RegisterXxxHandler(...)` | +| `http.Get(url)` / `http.Client` | `client.NewClient()` + `pb.NewXxxService(cli)` | +| Gin middleware | Filter | +| `r.Run(":8080")` | `srv.Serve()` | +| Route handler func | Method on a service struct | -Option A: keep HTTP externally, add dubbo-go internally. +dubbo-go is an RPC framework, not an HTTP framework. Two coexistence options: -- Gin/http handles public REST. -- dubbo-go handles service-to-service RPC. -- Run both in one process if lifecycle is clear. +**Option A — Keep Gin for HTTP, add dubbo-go for internal RPC**. No conflict; run both in the same process. -Option B: attach existing HTTP routes to the Triple listener. +**Option B — Mount the HTTP handler on the Triple port**: ```go -mux := http.NewServeMux() -mux.HandleFunc("/healthz", healthz) - -srv, _ := server.NewServer( - server.WithServerProtocol( - protocol.WithTriple(), - protocol.WithIp("127.0.0.1"), - protocol.WithPort(20000), - ), -) -_ = srv.AttachHTTPHandler(mux) +srv.AttachHTTPHandler("/api", r) // r is your Gin router ``` -Rules: attach before `Serve`, attach one root handler, and use an explicit Triple port. - -Option C: move APIs to Protobuf + Triple and expose JSON-over-HTTP plus OpenAPI. +**Option C — Use Triple's OpenAPI / REST mode** to expose RPC methods as HTTP/JSON: ```go server.WithServerProtocol( - protocol.WithPort(20000), - protocol.WithTriple( - triple.WithOpenAPI(triple.OpenAPIEnable()), - ), + protocol.WithTriple(triple.OpenAPIEnable(true)), ) ``` -OpenAPI endpoints default to `/dubbo/openapi`. +```bash +# Triple supports JSON over HTTP/1.1 — call any method without a generated client +curl -H "Content-Type: application/json" \ + -d '{"name":"world"}' \ + http://localhost:20000/greet.GreetService/Greet +``` + +See [rpc/triple/openapi](https://github.com/apache/dubbo-go-samples/tree/main/rpc/triple/openapi). -## From dubbo-go v1/v2 or Old v3 YAML +## From dubbo-go v1/v2 → v3 -Important changes: +**Breaking-change summary** -| Old style | Current v3 develop | +| v1/v2 | v3 | |---|---| -| Mostly YAML/config globals | Code API preferred | -| `config.Load()` as main entry | `dubbo.NewInstance()` for new apps; `dubbo.Load()`/`config.Load()` for compatibility | -| Interface-based Hessian2 default | Protobuf + Triple preferred | -| Global provider/consumer service registration | Generated `RegisterXxxHandler` and `NewXxxService` helpers | -| viper assumptions | koanf-based loading in current config path | -| Older `protocol` aliases | Prefer `protocol/base` and `protocol/result` packages in new extension code | +| `config.Load()` | `dubbo.NewInstance()` (code API, recommended) or `dubbo.Load()` (YAML, legacy) | +| `hessian.RegisterPOJO()` + Java-interface | Protobuf + generated Triple stubs (recommended) | +| `config.SetProviderService()` | `pb.RegisterGreetServiceHandler(srv, impl)` | +| `config.ConsumerConfig.References` | `client.NewClient()` → `pb.NewGreetService(cli)` | +| `getty` as default transport | Triple (HTTP/2) as default | +| Interface-level discovery | Application-level discovery | -Migration sequence: +**Recommended path**: migrate to the code API. YAML via `dubbo.Load()` still works, but the YAML key structure is not guaranteed identical across versions — expect to rewrite `registries`, `protocols`, and service registration. -1. Move service contracts to `.proto` when possible. -2. Generate `*.pb.go` and `*.triple.go`. -3. Replace global registration with generated server/client helpers. -4. Move registry/protocol/application config to `dubbo.NewInstance`. -5. Keep YAML only for externally managed config and test it with `config_yaml` patterns. -6. Run `make rpc-contract-check` if exposed RPC methods use variadic parameters. +`getty`-style v1/v2 Dubbo+Hessian2 services can keep working with `protocol.WithDubbo()` while interfaces are rebuilt as `.proto` for Triple. See `dubbo-go-java-interop` for the Hessian2 POJO bridge. -## From Java-interface Hessian2 +## From YAML-heavy v3 -If Java owns the contract and there is no `.proto`, do not invent a partial proto. Mirror Java request/response POJOs in Go, implement `JavaClassName()`, register them with `dubbo-go-hessian2`, and use Dubbo protocol. +You don't have to abandon YAML. `dubbo.Load()` is still supported. Migration to code API is incremental: -See the Java interop skill for exact POJO and protocol rules. +1. Move shared config (registries, protocols) into `dubbo.NewInstance(...)`. +2. Replace `dubbo.Load()` with `ins.NewServer()` / `ins.NewClient()` per service. +3. Keep YAML for environment-specific overrides via the config center. -## Validation +See [config_yaml](https://github.com/apache/dubbo-go-samples/tree/main/config_yaml). -For application migration: +## Validation ```bash go mod tidy +go build ./... go test ./... ``` -For changes inside the dubbo-go repository: - -```bash -make fmt -GOTOOLCHAIN=go1.25.0+auto go test ./... -make rpc-contract-check -``` +## Reference -Use targeted package tests first when the migration touches only one area. +Official guide: [dubbo-go v3 user manual](https://cn.dubbo.apache.org/zh-cn/overview/mannual/golang-sdk/) (also available in English on the same site). ## Related Skills -- `dubbo-go-scaffolding` - for the target-side provider/consumer skeleton after the source-side mapping is decided -- `dubbo-go-java-interop` - when the migration crosses the Java/Go boundary (Hessian2 POJO rules live there) -- `dubbo-go-extensions` - when porting a custom filter/LB/registry from gRPC-Go interceptors or Spring Cloud beans -- `dubbo-go-debugging` - when the migrated service starts but does not register, route, or decode +- `dubbo-go-scaffolding` — for the target-side provider/consumer skeleton +- `dubbo-go-java-interop` — when the migration crosses the Java/Go boundary +- `dubbo-go-extensions` — when porting custom interceptors / filters +- `dubbo-go-debugging` — when the migrated service starts but does not register, route, or decode diff --git a/.agents/skills/scaffolding/SKILL.md b/.agents/skills/scaffolding/SKILL.md index 3f4486a9dd..0a8ef11e23 100644 --- a/.agents/skills/scaffolding/SKILL.md +++ b/.agents/skills/scaffolding/SKILL.md @@ -1,6 +1,6 @@ --- name: dubbo-go-scaffolding -description: Use when creating, bootstrapping, or updating a dubbo-go v3 provider, consumer, sample, proto-based service, direct connection demo, registry-backed service, OpenAPI service, or HTTP-mounted Triple service. +description: Generates dubbo-go v3 provider or consumer skeletons in the code-API style (dubbo.NewInstance / server.NewServer / client.NewClient). Use when the user asks to create, bootstrap, or scaffold a new dubbo-go service, provider, or consumer, including direct mode, registry-backed, OpenAPI, HTTP-mounted, or HTTP/3 variants. --- - # Scaffolding dubbo-go Services -## Overview - -Generate dubbo-go v3 provider/consumer skeletons in the current code-API style: `server.NewServer`, `client.NewClient`, and `dubbo.NewInstance`. Reach for YAML only when migrating an existing config-driven app. - -## When to Use - -- New provider, consumer, sample, or `.proto`-based service -- Adding direct mode, registry-backed, OpenAPI, HTTP/3, CORS, or HTTP-handler-mounted variants -- Generating Triple bindings from a fresh `.proto` - -## When NOT to Use - -- The repo already has the skeleton and you only need to add a method or option - edit in place -- The user wants to write a custom SPI extension - use `dubbo-go-extensions` -- The user is migrating from another framework - use `dubbo-go-migration` - -## Current Defaults - -- Module path: `dubbo.apache.org/dubbo-go/v3` -- Go version in `go.mod`: `1.25.0` -- Preferred protocol: Triple (`protocol.WithTriple()`), gRPC-compatible and HTTP-friendly -- Default direct server port in samples: `20000` -- Generated Triple files: `*.pb.go` and `*.triple.go` -- Recommended sample baseline: `dubbo-go-samples/helloworld` - -## Ask First - -Clarify these before generating files: +dubbo-go v3 has two entry styles. Use the **code API** by default — it is the style the samples repo has converged on. Fall back to YAML-driven `dubbo.Load()` only if the user is migrating an existing YAML project. -1. Protocol: Triple by default; Dubbo/Hessian2 for legacy Java interface interop; gRPC only when explicitly required. -2. Discovery mode: direct URL for local demos; Nacos, ZooKeeper, etcd, or Polaris for service discovery. -3. Service definition: reuse an existing `.proto` if available; otherwise create one with stable `package` and `go_package`. -4. Extras: OpenAPI docs, HTTP/3, CORS, TLS, metrics/probe, or an attached existing `http.Handler`. +Before generating code, confirm three things: +1. **Protocol** — Triple (default, HTTP/2, gRPC-compatible) / Dubbo (Java interop with Hessian2) / JSONRPC / REST. Pick Triple unless the user has a reason. +2. **Registry** — Nacos / ZooKeeper / etcd / Polaris / direct (no registry). Pick direct for local demos, Nacos for production Apache stacks. +3. **Service definition** — does the user already have a `.proto` file? -## Layout +## Project Layout -Mirror the sample repository shape: +Mirror the [samples repo](https://github.com/apache/dubbo-go-samples) layout so the user can cross-reference: -```text +``` myservice/ -|-- go.mod -|-- proto/ -| |-- greet.proto -| |-- greet.pb.go -| `-- greet.triple.go -|-- go-server/cmd/main.go -`-- go-client/cmd/main.go +├── go.mod +├── proto/ +│ ├── greet.proto +│ ├── greet.pb.go # protoc-gen-go +│ └── greet.triple.go # protoc-gen-go-triple +├── go-server/cmd/main.go +└── go-client/cmd/main.go ``` -`dubbogo-cli newDemo .` can generate a direct-mode demo. Use `dubbogo-cli newApp .` for a larger application template with `api`, `cmd`, `conf`, `pkg`, `build`, and `chart`. - -## Proto +## Step 1: Proto Definition ```protobuf syntax = "proto3"; - package greet; - option go_package = "github.com/yourorg/myservice/proto;greet"; -message GreetRequest { - string name = 1; -} - -message GreetResponse { - string greeting = 1; -} +message GreetRequest { string name = 1; } +message GreetResponse { string greeting = 1; } service GreetService { rpc Greet(GreetRequest) returns (GreetResponse); } ``` -Install generators: - +Install codegen plugins (one-time): ```bash go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install github.com/dubbogo/protoc-gen-go-triple/v3@latest ``` Generate: - ```bash protoc --go_out=. --go_opt=paths=source_relative \ - --go-triple_out=. --go-triple_opt=paths=source_relative \ - proto/greet.proto + --go-triple_out=. --go-triple_opt=paths=source_relative \ + proto/greet.proto ``` -The `.proto` `package` is part of the Triple HTTP path. For the example above, JSON-over-HTTP requests use `/greet.GreetService/Greet`. +## Step 2: Provider -## Direct Provider +**Direct mode** (no registry, simplest local demo): ```go package main -import ( - "context" -) +import "context" import ( _ "dubbo.apache.org/dubbo-go/v3/imports" @@ -130,14 +89,12 @@ import ( "github.com/dubbogo/gost/log/logger" ) -import ( - greet "github.com/yourorg/myservice/proto" -) +import greet "github.com/yourorg/myservice/proto" type GreetTripleServer struct{} func (s *GreetTripleServer) Greet(ctx context.Context, req *greet.GreetRequest) (*greet.GreetResponse, error) { - return &greet.GreetResponse{Greeting: req.Name}, nil + return &greet.GreetResponse{Greeting: "hello " + req.Name}, nil } func main() { @@ -148,20 +105,57 @@ func main() { ), ) if err != nil { - logger.Fatalf("failed to create server: %v", err) + logger.Fatalf("new server: %v", err) } if err := greet.RegisterGreetServiceHandler(srv, &GreetTripleServer{}); err != nil { - logger.Fatalf("failed to register greet service handler: %v", err) + logger.Fatalf("register handler: %v", err) } if err := srv.Serve(); err != nil { - logger.Fatalf("failed to serve: %v", err) + logger.Fatalf("serve: %v", err) } } ``` -## Direct Consumer +**Registry-backed** — wrap with `dubbo.NewInstance` so registry and protocol are applied globally: + +```go +import ( + "dubbo.apache.org/dubbo-go/v3" + "dubbo.apache.org/dubbo-go/v3/registry" +) + +func main() { + ins, err := dubbo.NewInstance( + dubbo.WithName("myservice-provider"), + dubbo.WithRegistry( + registry.WithNacos(), + registry.WithAddress("127.0.0.1:8848"), + ), + dubbo.WithProtocol( + protocol.WithTriple(), + protocol.WithPort(20000), + ), + ) + if err != nil { panic(err) } + + srv, err := ins.NewServer() + if err != nil { panic(err) } + if err := greet.RegisterGreetServiceHandler(srv, &GreetTripleServer{}); err != nil { panic(err) } + if err := srv.Serve(); err != nil { panic(err) } +} +``` + +Swap registries by changing two lines: +- Nacos: `registry.WithNacos()` + `registry.WithAddress("127.0.0.1:8848")` +- ZooKeeper: `registry.WithZookeeper()` + `registry.WithAddress("127.0.0.1:2181")` +- etcd: `registry.WithEtcdV3()` + `registry.WithAddress("127.0.0.1:2379")` +- Polaris: `registry.WithPolaris()` + `registry.WithAddress("127.0.0.1:8091")` + +## Step 3: Consumer + +**Direct mode**: ```go package main @@ -178,146 +172,111 @@ import ( "github.com/dubbogo/gost/log/logger" ) -import ( - greet "github.com/yourorg/myservice/proto" -) +import greet "github.com/yourorg/myservice/proto" func main() { - cli, err := client.NewClient( - client.WithClientURL("127.0.0.1:20000"), - ) - if err != nil { - logger.Fatalf("failed to create client: %v", err) - } + cli, err := client.NewClient(client.WithClientURL("127.0.0.1:20000")) + if err != nil { logger.Fatalf("new client: %v", err) } svc, err := greet.NewGreetService(cli) - if err != nil { - logger.Fatalf("failed to create greet service: %v", err) - } + if err != nil { logger.Fatalf("new service: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() resp, err := svc.Greet(ctx, &greet.GreetRequest{Name: "world"}) - if err != nil { - logger.Fatalf("failed to call greet: %v", err) - } - logger.Infof("Greet response: %s", resp.Greeting) + if err != nil { logger.Fatalf("call: %v", err) } + logger.Infof("resp: %s", resp.Greeting) } ``` -## Registry-backed Provider and Consumer - -Use `dubbo.NewInstance` when provider and consumer should share application, registry, protocol, logger, shutdown, metrics, or tracing config. +**With registry** — drop `WithClientURL`, attach the same registry to an `Instance`: ```go -ins, err := dubbo.NewInstance( - dubbo.WithName("myservice-provider"), - dubbo.WithRegistry( - registry.WithNacos(), - registry.WithAddress("127.0.0.1:8848"), - ), - dubbo.WithProtocol( - protocol.WithTriple(), - protocol.WithPort(20000), - ), +ins, _ := dubbo.NewInstance( + dubbo.WithName("myservice-consumer"), + dubbo.WithRegistry(registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")), ) -if err != nil { - logger.Fatalf("new instance: %v", err) -} - -srv, err := ins.NewServer() -if err != nil { - logger.Fatalf("new server: %v", err) -} +cli, _ := ins.NewClient() +svc, _ := greet.NewGreetService(cli) ``` -Registry options: - -- Nacos: `registry.WithNacos()` -- ZooKeeper: `registry.WithZookeeper()` -- etcd v3: `registry.WithEtcdV3()` -- Polaris: `registry.WithPolaris()` -- Multiple registries: use `registry.WithID("nacos")` and select with `client.WithRegistryIDs("nacos")` or `server.WithRegistryIDs([]string{"nacos"})` - -For application-level service discovery, a consumer can use metadata mapping or set the provider application explicitly: +If application-level discovery cannot resolve which application owns the interface, hint with: ```go -svc, err := greet.NewGreetService( - cli, - client.WithInterface("greet.GreetService"), - client.WithProvidedBy("myservice-provider"), -) +svc, _ := greet.NewGreetService(cli, client.WithProvidedBy("myservice-provider")) ``` -## OpenAPI, CORS, HTTP/3, HTTP Handler Mount +## Triple Extras -Enable runtime OpenAPI docs on Triple: +**OpenAPI docs** — Triple can publish a runtime OpenAPI spec: ```go server.WithServerProtocol( protocol.WithPort(20000), protocol.WithTriple( - triple.WithOpenAPI( - triple.OpenAPIEnable(), - triple.OpenAPIInfoTitle("My Service"), - triple.OpenAPIInfoVersion("1.0.0"), - ), + triple.OpenAPIEnable(true), + triple.OpenAPIInfoTitle("Greet API"), ), ) ``` -Useful endpoints: - -- `/dubbo/openapi/openapi.json` -- `/dubbo/openapi/openapi.yaml` -- `/dubbo/openapi/api-docs/default.json` -- `/dubbo/openapi/swagger-ui` -- `/dubbo/openapi/redoc` - -Assign services to a docs group with `server.WithOpenAPIGroup("group-name")`. +See [rpc/triple/openapi](https://github.com/apache/dubbo-go-samples/tree/main/rpc/triple/openapi). -Attach an existing HTTP handler to the same Triple listener: +**Mount an HTTP handler** on the same Triple port (Triple-only): ```go -mux := http.NewServeMux() -mux.HandleFunc("/healthz", healthz) - -srv, _ := server.NewServer( - server.WithServerProtocol( - protocol.WithTriple(), - protocol.WithIp("127.0.0.1"), - protocol.WithPort(20000), - ), -) -if err := srv.AttachHTTPHandler(mux); err != nil { - logger.Fatalf("attach http handler: %v", err) -} +srv.AttachHTTPHandler("/healthz", http.HandlerFunc(healthz)) ``` -Rules: call `AttachHTTPHandler` before `Serve`, attach only one root handler, and configure an explicit Triple port. - -HTTP/3 is experimental and requires TLS-capable setup: +**HTTP/3** — experimental, requires TLS: ```go protocol.WithTriple(triple.Http3Enable()) ``` -## Validation +See [http3](https://github.com/apache/dubbo-go-samples/tree/main/http3). -For generated app skeletons: +## Conventions + +These are non-obvious rules the samples repo follows; preserve them when scaffolding: + +- **Three import blocks**: stdlib, third-party, same-module — separated by blank lines. The repo's `tools/imports-formatter` enforces this. +- **Blank-import `imports` during development**: `_ "dubbo.apache.org/dubbo-go/v3/imports"` pulls in every built-in filter, protocol, registry, serializer. Switch to selective imports for production builds. +- **Fail fast on startup** — samples `panic` or `logger.Fatalf` on `NewInstance` / `NewServer` / `NewClient` / `Register*Handler` errors. Do not swallow them. +- **Application name matters** — v3 defaults to **application-level** service discovery, so `dubbo.WithName("...")` is what appears in the registry, not the interface FQN. + +## Quick Decision Table + +| User says | Use | +|---|---| +| "just want to try it" / "local demo" | direct mode, no registry | +| "production" / "service discovery" | `dubbo.NewInstance` + Nacos or ZK | +| "talk to Java Dubbo" | Triple + Protobuf — see `dubbo-go-java-interop` | +| "expose REST or curl-friendly endpoint" | Triple + OpenAPI, or Triple REST mode | +| "existing YAML config" | `dubbo.Load()` (legacy) — see `config_yaml` sample | + +## Reference Samples + +- [helloworld](https://github.com/apache/dubbo-go-samples/tree/main/helloworld) — minimal Triple, direct mode +- [direct](https://github.com/apache/dubbo-go-samples/tree/main/direct) — explicit `tri://` URL +- [registry/nacos](https://github.com/apache/dubbo-go-samples/tree/main/registry/nacos) +- [registry/zookeeper](https://github.com/apache/dubbo-go-samples/tree/main/registry/zookeeper) +- [registry/etcd](https://github.com/apache/dubbo-go-samples/tree/main/registry/etcd) +- [rpc/triple/openapi](https://github.com/apache/dubbo-go-samples/tree/main/rpc/triple/openapi) — runtime OpenAPI +- [http3](https://github.com/apache/dubbo-go-samples/tree/main/http3) — Triple over HTTP/3 + +## Validation ```bash go mod tidy +go build ./... go test ./... ``` -For changes inside the dubbo-go repository, use the repository development skill and prefer `make fmt`, targeted `go test`, then broader `make test` when relevant. - ## Related Skills -- `dubbo-go-guide` - for the broader concept map and current capabilities -- `dubbo-go-extensions` - when scaffolding a service that also needs a custom Filter/LB/Registry -- `dubbo-go-java-interop` - when the new service must talk to dubbo-java -- `dubbo-go-migration` - when the user is moving from gRPC-Go, Spring Cloud, Gin, or older dubbo-go -- `dubbo-go-debugging` - when the new skeleton fails to start, register, or connect +- `dubbo-go-guide` — broader concept map and best practices +- `dubbo-go-extensions` — when the new service needs a custom Filter/LB/Registry +- `dubbo-go-java-interop` — when the new service must talk to dubbo-java +- `dubbo-go-debugging` — when the new skeleton fails to start, register, or connect From bb19ec31630343667d94a22d217a0dc8ca9dad2c Mon Sep 17 00:00:00 2001 From: Oxidaner <18622412361@163.com> Date: Mon, 1 Jun 2026 13:50:41 +0800 Subject: [PATCH 4/5] docs: refine agent skill guidance --- .agents/.codex/INSTALL.md | 37 +++++++----- .agents/.gitignore | 20 ------- .agents/README.md | 8 ++- .agents/README_CN.md | 8 ++- .agents/skills/debug/SKILL.md | 14 ++--- .agents/skills/guide/SKILL.md | 6 +- .agents/skills/guide/samples-index.md | 85 --------------------------- .gitignore | 1 + 8 files changed, 46 insertions(+), 133 deletions(-) delete mode 100644 .agents/.gitignore delete mode 100644 .agents/skills/guide/samples-index.md diff --git a/.agents/.codex/INSTALL.md b/.agents/.codex/INSTALL.md index 1dfad21f35..a4a2cf1b7b 100644 --- a/.agents/.codex/INSTALL.md +++ b/.agents/.codex/INSTALL.md @@ -17,39 +17,48 @@ limitations under the License. # Installing dubbo-go Agent Skills for Codex -## Quick install +## Install -Tell Codex: - -```text -Fetch and follow instructions from https://raw.githubusercontent.com/apache/dubbo-go/main/.agents/.codex/INSTALL.md -``` - -## Manual installation - -Install the skills globally when you want Codex to use them outside an Apache dubbo-go checkout. +Install these skills globally when the user asks to install dubbo-go skills for Codex. ```bash -git clone https://github.com/apache/dubbo-go.git ~/.codex/dubbo-go +if [ -d ~/.codex/dubbo-go/.git ]; then + git -C ~/.codex/dubbo-go pull --ff-only +else + git clone https://github.com/apache/dubbo-go.git ~/.codex/dubbo-go +fi + mkdir -p ~/.agents/skills +rm -rf ~/.agents/skills/dubbo-go ln -s ~/.codex/dubbo-go/.agents/skills ~/.agents/skills/dubbo-go ``` -Restart Codex. +Restart Codex after installation. ### Windows ```powershell -git clone https://github.com/apache/dubbo-go.git "$env:USERPROFILE\.codex\dubbo-go" +$repo = "$env:USERPROFILE\.codex\dubbo-go" +if (Test-Path "$repo\.git") { + git -C $repo pull --ff-only +} else { + git clone https://github.com/apache/dubbo-go.git $repo +} + New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills" +Remove-Item -Recurse -Force "$env:USERPROFILE\.agents\skills\dubbo-go" -ErrorAction SilentlyContinue cmd /c mklink /J "$env:USERPROFILE\.agents\skills\dubbo-go" "$env:USERPROFILE\.codex\dubbo-go\.agents\skills" ``` -## Updating +Restart Codex after installation. + +## Update ```bash cd ~/.codex/dubbo-go git pull --ff-only +rm -rf ~/.agents/skills/dubbo-go +ln -s ~/.codex/dubbo-go/.agents/skills ~/.agents/skills/dubbo-go ``` Restart Codex after updating. diff --git a/.agents/.gitignore b/.agents/.gitignore deleted file mode 100644 index fe850f695e..0000000000 --- a/.agents/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -node_modules/ -.DS_Store -*.log diff --git a/.agents/README.md b/.agents/README.md index 83149192d3..11e1ba5dad 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -86,6 +86,12 @@ Open a new session and try one of these: The assistant should auto-trigger the matching skill. +## Reference Docs + +Use the official Dubbo Golang SDK documentation as the primary reference for user-facing behavior and tutorials: + +- [Dubbo Golang SDK documentation](https://github.com/apache/dubbo-website/tree/master/content/zh-cn/overview/mannual/golang-sdk) + ## Skills ### scaffolding @@ -106,7 +112,7 @@ Structured diagnosis for runtime errors. Matches your error or log against known ### guide -Architecture, extension points, and best practices. Covers Instance, Protocol, Registry, Filter, Cluster, LoadBalance, Router, Triple OpenAPI, HTTP/3, CORS, graceful shutdown, observability, and points to the relevant `dubbo-go-samples` directory through `samples-index.md`. +Architecture, extension points, and best practices. Covers Instance, Protocol, Registry, Filter, Cluster, LoadBalance, Router, Triple OpenAPI, HTTP/3, CORS, graceful shutdown, observability, and tells agents to read the current `apache/dubbo-go-samples` README and directories when choosing examples. ### migrate diff --git a/.agents/README_CN.md b/.agents/README_CN.md index 4901fe7645..3de1ff3a4b 100644 --- a/.agents/README_CN.md +++ b/.agents/README_CN.md @@ -86,6 +86,12 @@ gemini extensions update dubbo-go-agent-skills 助手应该会自动触发对应的 skill。 +## 参考文档 + +面向用户的行为说明和教程,以官方 Dubbo Golang SDK 文档为主要参考: + +- [Dubbo Golang SDK 文档](https://github.com/apache/dubbo-website/tree/master/content/zh-cn/overview/mannual/golang-sdk) + ## Skills ### scaffolding @@ -106,7 +112,7 @@ dubbo-go 与 dubbo-java 的跨语言 RPC。新服务选 Triple+Protobuf,老 Ja ### guide -架构、扩展点、最佳实践。覆盖 Instance、Protocol、Registry、Filter、Cluster、LoadBalance、Router、Triple OpenAPI、HTTP/3、CORS、graceful shutdown、可观测性,并通过 `samples-index.md` 指向对应的 `dubbo-go-samples` 目录。 +架构、扩展点、最佳实践。覆盖 Instance、Protocol、Registry、Filter、Cluster、LoadBalance、Router、Triple OpenAPI、HTTP/3、CORS、graceful shutdown、可观测性,并要求 Agent 在选择示例时读取当前 `apache/dubbo-go-samples` README 和目录。 ### migrate diff --git a/.agents/skills/debug/SKILL.md b/.agents/skills/debug/SKILL.md index 1337a39e47..054a3fdf40 100644 --- a/.agents/skills/debug/SKILL.md +++ b/.agents/skills/debug/SKILL.md @@ -51,6 +51,7 @@ Checklist: - [ ] Provider started successfully? Look for `dubbo server started` and `A provider service ... was registered successfully` in provider logs. - [ ] Same registry address on both sides (`dubbo.WithRegistry(registry.WithAddress(...))` / YAML `dubbo.registries.xxx.address`)? - [ ] Same application name on both sides (`dubbo.WithName(...)`)? v3 defaults to **application-level** discovery — the registry stores the app name, not the interface FQN. +- [ ] Same service discovery level on both sides? Latest dubbo-go defaults to **application-level** discovery, while older dubbo-go versions commonly defaulted to **interface-level** discovery; application-level and interface-level discovery do not interoperate. - [ ] Same `interface` name passed to `pb.RegisterXxxHandler` and `pb.NewXxxService`? - [ ] Same protocol on both sides (both `tri` or both `dubbo`)? - [ ] Provider visible in the registry? @@ -92,7 +93,7 @@ Checklist: - [ ] Protobuf: same `.proto` compiled on both sides? Same `go_package`? - [ ] Hessian2: POJO `JavaClassName()` matches the Java class FQN exactly? `RegisterPOJO` called in an `init()` that actually runs? -For Hessian2 specifics, see `dubbo-go-java-interop`. +For Hessian2 specifics, see [dubbo-go-java-interop](../java-interop/SKILL.md). ## Timeout @@ -123,7 +124,7 @@ resp, err := svc.Greet(ctx, req) **Cause**: Filter imported but `init()` not registered, or name mismatch between `extension.SetFilter` and `WithFilter`. Checklist: -- [ ] Blank import present? e.g. `_ "dubbo.apache.org/dubbo-go/v3/filter/token"` or `_ "github.com/yourorg/yourapp/filter/myfilter"` +- [ ] Blank import present? e.g. `_ "dubbo.apache.org/dubbo-go/v3/filter/token"`, `_ "github.com/apache/dubbo-go-extensions/filter/hystrix"`, or `_ "github.com/yourorg/yourapp/filter/myfilter"` - [ ] String passed to `server.WithFilter("xxx")` / `client.WithFilter("xxx")` matches the name in `extension.SetFilter("xxx", ...)`? - [ ] Built-ins not pulled in? Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` during development to auto-import all built-ins. @@ -139,11 +140,6 @@ if err := srv.Serve(); err != nil { panic(err) } go srv.Serve() ``` -For graceful shutdown: -```go -import _ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown" -``` - ## OpenAPI 404 / empty spec Triple-only feature. Checklist: @@ -161,7 +157,7 @@ Checklist: ## Graceful shutdown Checklist: -- [ ] `_ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown"` blank-imported? +- [ ] Built-in graceful shutdown filters registered? `_ "dubbo.apache.org/dubbo-go/v3/imports"` includes them; with selective imports, add `_ "dubbo.apache.org/dubbo-go/v3/filter/graceful_shutdown"` so `pshutdown` / `cshutdown` are registered. - [ ] Shutdown timeout long enough for in-flight calls to drain? - [ ] If running behind Kubernetes: container `terminationGracePeriodSeconds` longer than dubbo-go's shutdown timeout? @@ -192,5 +188,5 @@ Key log lines: ## Related Skills - `dubbo-go-extensions` — when a missing/registered SPI is the root cause -- `dubbo-go-java-interop` — for Hessian2 decode failures and cross-language discovery +- [dubbo-go-java-interop](../java-interop/SKILL.md) — for Hessian2 decode failures and cross-language discovery - `dubbo-go-guide` — for the conceptual map (Instance / Server / Client / Protocol / Registry / Filter) diff --git a/.agents/skills/guide/SKILL.md b/.agents/skills/guide/SKILL.md index f66584fdf4..f31915cc9b 100644 --- a/.agents/skills/guide/SKILL.md +++ b/.agents/skills/guide/SKILL.md @@ -76,7 +76,7 @@ The same pattern applies to Protocol, Registry, LoadBalance, Router, ConfigCente - Use `_ "dubbo.apache.org/dubbo-go/v3/imports"` in development for convenience; switch to selective imports in production for smaller binaries. - Define Triple services with Protobuf for cross-language interop. - Configure via the code API: `dubbo.NewInstance(dubbo.WithRegistry(...), dubbo.WithProtocol(...))`. YAML via `dubbo.Load()` is the legacy path. -- Enable graceful shutdown by blank-importing `_ "dubbo.apache.org/dubbo-go/v3/graceful_shutdown"`. +- Keep `srv.Serve()` as the blocking entry point for process-level shutdown. `_ "dubbo.apache.org/dubbo-go/v3/imports"` registers the default graceful shutdown filters; with selective imports, include `_ "dubbo.apache.org/dubbo-go/v3/filter/graceful_shutdown"`. - Use `client.WithProvidedBy` when application-level discovery cannot resolve which application owns the interface. - Apply per-reference timeouts: `client.WithRequestTimeout(...)` or a `context.WithTimeout` at the call site. @@ -88,9 +88,9 @@ The same pattern applies to Protocol, Registry, LoadBalance, Router, ConfigCente - **CORS** — `triple.CORSAllowOrigins(...)` etc. - **Reflection** — gRPC reflection is on by default; tools like `grpcurl` work without extra config. -## Samples Index +## Finding Samples -See [samples-index.md](samples-index.md) for the full `dubbo-go-samples` directory organized by scenario (Quick Start, Protocols, Service Discovery, Filters, Routing, Streaming, Observability, Security, Java Interop, Advanced). +When the user asks which sample to follow, read the current [apache/dubbo-go-samples](https://github.com/apache/dubbo-go-samples) README and relevant directories instead of relying on a copied index. The samples repository changes independently of dubbo-go; prefer its live README, directory names, and nearby sample code as the source of truth. ## Related Skills diff --git a/.agents/skills/guide/samples-index.md b/.agents/skills/guide/samples-index.md deleted file mode 100644 index 5b0ebcea81..0000000000 --- a/.agents/skills/guide/samples-index.md +++ /dev/null @@ -1,85 +0,0 @@ - - -# dubbo-go-samples Index - -Each entry links to a directory under [apache/dubbo-go-samples](https://github.com/apache/dubbo-go-samples). - -## Quick Start -- [helloworld](https://github.com/apache/dubbo-go-samples/tree/main/helloworld) — minimal Triple/Protobuf provider + consumer -- [direct](https://github.com/apache/dubbo-go-samples/tree/main/direct) — direct URL connection, no registry - -## Protocols -- [rpc/triple](https://github.com/apache/dubbo-go-samples/tree/main/rpc/triple) — Triple variants (Protobuf, JSON, streaming, reflection, OpenAPI) -- [rpc/grpc](https://github.com/apache/dubbo-go-samples/tree/main/rpc/grpc) — gRPC interop -- [rpc/multi-protocols](https://github.com/apache/dubbo-go-samples/tree/main/rpc/multi-protocols) — multiple protocols on one server -- [http3](https://github.com/apache/dubbo-go-samples/tree/main/http3) — Triple over HTTP/3 (experimental) - -## Service Discovery -- [registry/nacos](https://github.com/apache/dubbo-go-samples/tree/main/registry/nacos) -- [registry/zookeeper](https://github.com/apache/dubbo-go-samples/tree/main/registry/zookeeper) -- [registry/etcd](https://github.com/apache/dubbo-go-samples/tree/main/registry/etcd) -- [registry/polaris](https://github.com/apache/dubbo-go-samples/tree/main/registry/polaris) - -## Configuration -- [config_yaml](https://github.com/apache/dubbo-go-samples/tree/main/config_yaml) -- [config_center/nacos](https://github.com/apache/dubbo-go-samples/tree/main/config_center/nacos) -- [config_center/zookeeper](https://github.com/apache/dubbo-go-samples/tree/main/config_center/zookeeper) -- [config_center/apollo](https://github.com/apache/dubbo-go-samples/tree/main/config_center/apollo) - -## Filters & Resilience -- [filter/custom](https://github.com/apache/dubbo-go-samples/tree/main/filter/custom) — writing custom filters -- [filter/sentinel](https://github.com/apache/dubbo-go-samples/tree/main/filter/sentinel) — flow control -- [filter/hystrix](https://github.com/apache/dubbo-go-samples/tree/main/filter/hystrix) — circuit breaker -- [filter/token](https://github.com/apache/dubbo-go-samples/tree/main/filter/token) -- [filter/tpslimit](https://github.com/apache/dubbo-go-samples/tree/main/filter/tpslimit) -- [retry](https://github.com/apache/dubbo-go-samples/tree/main/retry) -- [timeout](https://github.com/apache/dubbo-go-samples/tree/main/timeout) -- [graceful_shutdown](https://github.com/apache/dubbo-go-samples/tree/main/graceful_shutdown) - -## Traffic Management -- [router/tag](https://github.com/apache/dubbo-go-samples/tree/main/router/tag) -- [router/condition](https://github.com/apache/dubbo-go-samples/tree/main/router/condition) -- [router/script](https://github.com/apache/dubbo-go-samples/tree/main/router/script) -- [mesh](https://github.com/apache/dubbo-go-samples/tree/main/mesh) — proxyless mesh -- [apisix](https://github.com/apache/dubbo-go-samples/tree/main/apisix) — APISIX gateway - -## Streaming -- [streaming](https://github.com/apache/dubbo-go-samples/tree/main/streaming) - -## Observability -- [metrics/prometheus_grafana](https://github.com/apache/dubbo-go-samples/tree/main/metrics/prometheus_grafana) -- [metrics/probe](https://github.com/apache/dubbo-go-samples/tree/main/metrics/probe) — Kubernetes health probes -- [otel/tracing](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing) — Jaeger / OTLP / stdout exporters -- [logger](https://github.com/apache/dubbo-go-samples/tree/main/logger) — default, level, rolling, custom, trace integration - -## Security -- [tls](https://github.com/apache/dubbo-go-samples/tree/main/tls) -- [filter/token](https://github.com/apache/dubbo-go-samples/tree/main/filter/token) - -## Java Interop -- [java_interop/protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/protobuf-triple) -- [java_interop/non-protobuf-dubbo](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-dubbo) -- [java_interop/non-protobuf-triple](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/non-protobuf-triple) -- [java_interop/service_discovery](https://github.com/apache/dubbo-go-samples/tree/main/java_interop/service_discovery) - -## Advanced -- [generic](https://github.com/apache/dubbo-go-samples/tree/main/generic) — generic invocation -- [async](https://github.com/apache/dubbo-go-samples/tree/main/async) -- [llm](https://github.com/apache/dubbo-go-samples/tree/main/llm) — LLM integration -- [book-flight-ai-agent](https://github.com/apache/dubbo-go-samples/tree/main/book-flight-ai-agent) — AI agent -- [transcation/seata-go](https://github.com/apache/dubbo-go-samples/tree/main/transcation/seata-go) — Seata distributed transactions diff --git a/.gitignore b/.gitignore index a38e3cf5cc..5d94ee689d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ classes # go mod, go test .go-version +node_modules/ vendor/ logs/ .vscode/ From d65ffb930e004aee47a5e57fa5fd97756023e7c1 Mon Sep 17 00:00:00 2001 From: Oxidaner <18622412361@163.com> Date: Sun, 28 Jun 2026 21:07:19 +0800 Subject: [PATCH 5/5] fix: 1.delete gemini support 2.add Apache 2.0 license headers Signed-off-by: Oxidaner <18622412361@163.com> --- .agents/GEMINI.md | 24 --------------------- .agents/README.md | 12 ----------- .agents/README_CN.md | 12 ----------- .agents/gemini-extension.json | 6 ------ .agents/skills/debug/SKILL.md | 31 +++++++++++++--------------- .agents/skills/development/SKILL.md | 31 +++++++++++++--------------- .agents/skills/extensions/SKILL.md | 31 +++++++++++++--------------- .agents/skills/guide/SKILL.md | 31 +++++++++++++--------------- .agents/skills/java-interop/SKILL.md | 31 +++++++++++++--------------- .agents/skills/migrate/SKILL.md | 31 +++++++++++++--------------- .agents/skills/scaffolding/SKILL.md | 31 +++++++++++++--------------- 11 files changed, 98 insertions(+), 173 deletions(-) delete mode 100644 .agents/GEMINI.md delete mode 100644 .agents/gemini-extension.json diff --git a/.agents/GEMINI.md b/.agents/GEMINI.md deleted file mode 100644 index 211ce094f0..0000000000 --- a/.agents/GEMINI.md +++ /dev/null @@ -1,24 +0,0 @@ - - -@./skills/scaffolding/SKILL.md -@./skills/extensions/SKILL.md -@./skills/java-interop/SKILL.md -@./skills/debug/SKILL.md -@./skills/guide/SKILL.md -@./skills/migrate/SKILL.md -@./skills/development/SKILL.md diff --git a/.agents/README.md b/.agents/README.md index 11e1ba5dad..834d3b6eae 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -64,18 +64,6 @@ Add to `opencode.json`: } ``` -### Gemini CLI - -```bash -gemini extensions install https://github.com/apache/dubbo-go --path .agents -``` - -Update later with: - -```bash -gemini extensions update dubbo-go-agent-skills -``` - ### Verify Open a new session and try one of these: diff --git a/.agents/README_CN.md b/.agents/README_CN.md index 3de1ff3a4b..d6154d2920 100644 --- a/.agents/README_CN.md +++ b/.agents/README_CN.md @@ -64,18 +64,6 @@ Fetch and follow instructions from https://raw.githubusercontent.com/apache/dubb } ``` -### Gemini CLI - -```bash -gemini extensions install https://github.com/apache/dubbo-go --path .agents -``` - -更新: - -```bash -gemini extensions update dubbo-go-agent-skills -``` - ### 验证 新开一个会话,试试这些: diff --git a/.agents/gemini-extension.json b/.agents/gemini-extension.json deleted file mode 100644 index b10b95051c..0000000000 --- a/.agents/gemini-extension.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "dubbo-go-agent-skills", - "description": "Agent skills bundled with Apache dubbo-go for v3 framework users — scaffolding, extensions, Java interop, debugging, guidance, migration, plus contributor support.", - "version": "0.2.0", - "contextFileName": "GEMINI.md" -} diff --git a/.agents/skills/debug/SKILL.md b/.agents/skills/debug/SKILL.md index 054a3fdf40..2d7e55af6b 100644 --- a/.agents/skills/debug/SKILL.md +++ b/.agents/skills/debug/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-debugging description: Structured diagnosis for dubbo-go v3 runtime errors. Use when the user reports an error, pastes logs, mentions timeout/panic/connection refused/no provider/serialization mismatch, or asks why their dubbo-go service isn't working. --- - - # Debugging dubbo-go When the user shares an error or log, match it to a pattern below. If unclear, ask for: diff --git a/.agents/skills/development/SKILL.md b/.agents/skills/development/SKILL.md index feb76840c4..fddff8deca 100644 --- a/.agents/skills/development/SKILL.md +++ b/.agents/skills/development/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-development description: Use when modifying, reviewing, testing, or debugging the apache/dubbo-go repository itself - including framework Go code, generated stubs, config structs, tools, CI, tests, or repository-local agent skills. Not for application-side scaffolding. --- - - # Contributing to apache/dubbo-go This skill is for working **inside** the dubbo-go repository, not for using the framework from an application. For app-side work, use `dubbo-go-scaffolding`. diff --git a/.agents/skills/extensions/SKILL.md b/.agents/skills/extensions/SKILL.md index cc3ba72f30..03fb0fc500 100644 --- a/.agents/skills/extensions/SKILL.md +++ b/.agents/skills/extensions/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-extensions description: Guides writing custom dubbo-go v3 extensions — Filter, LoadBalance, Registry, Protocol, Router, Logger, ConfigCenter — through the SPI pattern. Use when the user asks how to write a filter, custom interceptor, custom load balancer, plug in a new registry, or hook into dubbo-go's extension points. --- - - # Writing dubbo-go Extensions dubbo-go exposes nearly every runtime behavior through a uniform SPI pattern: diff --git a/.agents/skills/guide/SKILL.md b/.agents/skills/guide/SKILL.md index f31915cc9b..5ee1db7fbd 100644 --- a/.agents/skills/guide/SKILL.md +++ b/.agents/skills/guide/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-guide description: Explains dubbo-go v3 architecture, extension points, and best practices. Use when the user asks how dubbo-go works, what a concept means (Instance, Protocol, Registry, Filter, Cluster, LoadBalance, Router, OpenAPI, graceful shutdown), which sample to look at, or asks for best practices. --- - - # Guiding dubbo-go Development ## Core Concepts diff --git a/.agents/skills/java-interop/SKILL.md b/.agents/skills/java-interop/SKILL.md index face3489b1..324fab0f85 100644 --- a/.agents/skills/java-interop/SKILL.md +++ b/.agents/skills/java-interop/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-java-interop description: Guides interoperability between dubbo-go v3 and dubbo-java — cross-language RPC using Triple+Protobuf or Dubbo+Hessian2. Use when the user asks how to call a Java Dubbo service from Go, expose a Go service to Java clients, share a proto/interface across languages, or pick between Triple and Dubbo for interop. --- - - # Dubbo Java and Go Interop A single service definition can be served by Go and consumed by Java (or vice versa) without a gateway. Two viable paths: diff --git a/.agents/skills/migrate/SKILL.md b/.agents/skills/migrate/SKILL.md index ab5a6355d2..9337be6109 100644 --- a/.agents/skills/migrate/SKILL.md +++ b/.agents/skills/migrate/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-migration description: Guides migration to dubbo-go v3 from gRPC-Go, Spring Cloud, Gin / plain HTTP, dubbo-go v1/v2, YAML-heavy v3 apps, and Java-interface Hessian2 services. Use when the user asks how to migrate, port, or upgrade an existing service to dubbo-go v3. --- - - # Migrating to dubbo-go First question: **where are you migrating from?** diff --git a/.agents/skills/scaffolding/SKILL.md b/.agents/skills/scaffolding/SKILL.md index 0a8ef11e23..bdc84c0411 100644 --- a/.agents/skills/scaffolding/SKILL.md +++ b/.agents/skills/scaffolding/SKILL.md @@ -1,25 +1,22 @@ --- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. name: dubbo-go-scaffolding description: Generates dubbo-go v3 provider or consumer skeletons in the code-API style (dubbo.NewInstance / server.NewServer / client.NewClient). Use when the user asks to create, bootstrap, or scaffold a new dubbo-go service, provider, or consumer, including direct mode, registry-backed, OpenAPI, HTTP-mounted, or HTTP/3 variants. --- - - # Scaffolding dubbo-go Services dubbo-go v3 has two entry styles. Use the **code API** by default — it is the style the samples repo has converged on. Fall back to YAML-driven `dubbo.Load()` only if the user is migrating an existing YAML project.