Jesse A. Green / notebook

Apache Dubbo User Guide

Generated June 2026 from apache/dubbo at ee9c190

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Apache Dubbo is a high-performance, Java-native Web and RPC framework for building enterprise-grade microservices. You define an ordinary Java interface, publish its implementation as a service provider, and call it from a service consumer as if it were a local method — Dubbo handles the networking, serialization, service discovery, load balancing, and fault tolerance for you.

This guide is for the people who build applications with Dubbo: backend and microservice developers writing providers and consumers in Java or Spring Boot. It covers installation, the everyday API and configuration surface, the protocols and registries you will choose between, traffic-management features, day-to-day operations, troubleshooting, and a complete configuration reference.

Note

Dubbo is polyglot. This guide documents the Java SDK (the apache/dubbo repository). Sibling implementations exist for Go, Python, PHP, Rust, Erlang, and Node.js/Web. The concepts carry over, but the code in this guide is Java.


Table of Contents

  1. What Dubbo Does
  2. Quick Start (5 minutes)
  3. Installation
  4. Core Concepts
  5. Defining a Service Provider
  6. Consuming a Service
  7. Configuration Essentials
  8. Protocols
  9. Registries and Service Discovery
  10. Traffic Management
  11. Common Tasks (Recipes)
  12. Operating a Running Application (QOS)
  13. Troubleshooting
  14. Frequently Asked Questions
  15. Configuration Reference

1. What Dubbo Does

A microservice system has two recurring needs: services need to call each other, and callers need to find callees that move around as instances scale up, down, and redeploy. Dubbo solves both, plus the operational concerns that come with them.

Capability What you get
Remote invocation (RPC) Call a remote service through a normal Java interface. Multiple wire protocols: Triple (gRPC-compatible, HTTP/2), Dubbo2 (TCP), REST, and pluggable custom protocols.
Service discovery Providers register themselves in a registry (Zookeeper, Nacos, …); consumers subscribe and discover live instances automatically.
Traffic management Cluster fault-tolerance (failover, failfast, …), six load-balancing strategies, routing rules, and method-level configuration.
Observability Built-in metrics (Micrometer/Prometheus) and distributed tracing (OpenTelemetry, Zipkin, Brave).
Security Token authentication, TLS, serialization allow-listing, and a permission-gated operations port.
Extensibility Almost every component is a swappable SPI extension — you can replace protocols, registries, serializers, filters, routers, and load balancers without forking.

Tip

If you are starting a brand-new service, prefer the Triple protocol. It runs over HTTP/2, is gRPC- and cURL-compatible, works through service meshes, and is the protocol Dubbo invests in going forward. The classic dubbo TCP protocol remains the default for interface-based RPC and is fully supported.


2. Quick Start (5 minutes)

This is the smallest possible Dubbo system: one shared interface, one provider, one consumer, all wired with the programmatic (Bootstrap) API and an in-process registry-free setup is not used — a registry makes the example realistic. We use Zookeeper.

2.1 The shared interface

Put this in a module both sides depend on:

package org.apache.dubbo.demo;

public interface GreetingService {
    String sayHello(String name);
}

2.2 The provider

package org.apache.dubbo.demo.provider;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.demo.GreetingService;

public class Provider {
    public static void main(String[] args) {
        ServiceConfig<GreetingService> service = new ServiceConfig<>();
        service.setInterface(GreetingService.class);
        service.setRef((name) -> "Hello, " + name);

        DubboBootstrap.getInstance()
                .application(new ApplicationConfig("first-dubbo-provider"))
                .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
                .service(service)
                .start()
                .await();
    }
}

2.3 The consumer

package org.apache.dubbo.demo.consumer;

import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.demo.GreetingService;

public class Consumer {
    public static void main(String[] args) {
        ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
        reference.setInterface(GreetingService.class);

        DubboBootstrap.getInstance()
                .application(new ApplicationConfig("first-dubbo-consumer"))
                .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
                .reference(reference)
                .start();

        GreetingService greetingService = reference.get();
        System.out.println(greetingService.sayHello("Dubbo"));
    }
}

2.4 Run it

# 1. Start a Zookeeper registry (Docker is the fastest path)
docker run -d --name zookeeper -p 2181:2181 zookeeper:3.9

# 2. Start the provider, then the consumer (two JVMs)
java org.apache.dubbo.demo.provider.Provider
java org.apache.dubbo.demo.consumer.Consumer

Expected consumer output:

Hello, Dubbo

Important

The interface (GreetingService) must be on the classpath of both provider and consumer. Dubbo binds providers and consumers by the service's fully-qualified interface name (plus optional group and version), not by a generated stub. Keep the interface in a shared artifact.


3. Installation

Dubbo is consumed as a set of Maven artifacts under the org.apache.dubbo group. You do not "install Dubbo" as a standalone program — you add it to your application's build.

3.1 Version and compatibility

Dubbo line JDK support Status
3.3.x 1.8 – 25 Current, actively maintained — Triple, REST, Spring Boot starters, native-image, JDK 25
3.2.x 1.8 – 17 Maintained — metrics & tracing, thread-pool isolation, native image
3.1.x 1.8 – 17 Stable, not actively maintained

Note

This guide is generated from source at commit ee9c190 (development line 3.3.7-SNAPSHOT). For application dependencies, use the latest stable 3.3.x release (3.3.6 at time of writing) rather than a -SNAPSHOT. Snapshot builds are for contributors, not production.

3.2 Plain Maven / Gradle

The cleanest way to pin a consistent set of versions is the Dubbo BOM.

Maven (BOM + dependency)

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.dubbo</groupId>
      <artifactId>dubbo-bom</artifactId>
      <version>3.3.6</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
  </dependency>
  <!-- pick a registry -->
  <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-registry-zookeeper</artifactId>
  </dependency>
</dependencies>

Gradle (Kotlin DSL)

dependencies {
    implementation(platform("org.apache.dubbo:dubbo-bom:3.3.6"))
    implementation("org.apache.dubbo:dubbo")
    implementation("org.apache.dubbo:dubbo-registry-zookeeper")
}

Tip

The umbrella dubbo artifact pulls in the core plus the common protocols and serializers. As you move to production you will usually depend on specific modules instead (dubbo-rpc-triple, dubbo-remoting-netty4, dubbo-serialization-hessian2, a registry, a config center, a metadata report) to keep the dependency tree lean. See the Admin Guide for the full module map.

3.3 Spring Boot

For Spring Boot applications, add a starter and configure everything in application.yml.

<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-spring-boot-starter</artifactId>
  <version>3.3.6</version>
</dependency>
<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-zookeeper-curator5-spring-boot-starter</artifactId>
  <version>3.3.6</version>
</dependency>

Note

On JDK 17+, the build automatically uses dubbo-spring-boot-3-autoconfigure (Spring Boot 3 / Jakarta). On JDK 8–11 it uses the Spring Boot 2 autoconfigure path. You add the same dubbo-spring-boot-starter either way.

3.4 Which add-on modules?

Dubbo's functionality is split across optional modules so you only ship what you use. The most common ones:

Need Add this artifact
Zookeeper registry / config center dubbo-registry-zookeeper, dubbo-zookeeper-curator5-spring-boot-starter
Nacos registry dubbo-registry-nacos, dubbo-nacos-spring-boot-starter
Triple (gRPC/HTTP-2) protocol dubbo-rpc-triple
Classic Dubbo TCP protocol dubbo-rpc-dubbo, dubbo-remoting-netty4
Hessian2 serialization (default) dubbo-serialization-hessian2
Fastjson2 serialization dubbo-serialization-fastjson2
Metrics + tracing dubbo-observability-spring-boot-starter, dubbo-tracing-otel-zipkin-spring-boot-starter
Operations port (telnet/HTTP) dubbo-qos
Sentinel flow control dubbo-sentinel-spring-boot-starter
Seata distributed transactions dubbo-seata-spring-boot-starter

4. Core Concepts

You only need a handful of concepts to be productive. Deeper internals live in the Admin Guide.

Provider : An application that exposes a service implementation. It registers its address in the registry.

Consumer : An application that calls a service. It discovers providers from the registry and invokes them.

Service interface : A plain Java interface, shared by both sides, that defines the remotable methods. The interface's fully-qualified name (optionally narrowed by group and version) is the service's identity.

Registry : The directory where providers publish their addresses and consumers look them up — Zookeeper, Nacos, and others. Dubbo 3 defaults to application-level service discovery (instances register once per application, not once per interface), which scales to far larger clusters than the older interface-level model.

Protocol : The wire format and transport for a remote call (dubbo, tri, rest2, injvm, …). A single provider can expose the same service over several protocols at once.

Invoker : Dubbo's internal abstraction of "a callable target." Your interface proxy ultimately calls an Invoker; cluster, routing, and load balancing all manipulate invokers.

URL : The universal configuration carrier. Every component is configured by a URL such as dubbo://10.0.0.1:20880/org.apache.dubbo.demo.GreetingService?timeout=3000&version=1.0.0. You rarely write these by hand, but you will see them in logs and the operations port.

Note

A call flows: your proxy → Cluster (fault tolerance) → Router (filter candidates) → LoadBalance (pick one) → Filter chain → Protocol → network → provider. Each stage is a configurable, swappable extension.


5. Defining a Service Provider

There are three ways to publish a service. Pick the one that matches your stack.

Annotate your implementation with @DubboService. Component-scanning picks it up and Dubbo exports it on startup.

import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.demo.GreetingService;

@DubboService(version = "1.0.0", group = "demo", timeout = 3000)
public class GreetingServiceImpl implements GreetingService {
    @Override
    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

Enable Dubbo and point component-scanning at your packages:

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
# application.yml
dubbo:
  application:
    name: demo-provider
  registry:
    address: zookeeper://127.0.0.1:2181
  protocol:
    name: tri
    port: 50051

Tip

@EnableDubbo is the umbrella annotation — it combines @DubboComponentScan (find @DubboService/@DubboReference beans) and @EnableDubboConfig (bind the dubbo.* properties). Use @DubboComponentScan alone if you only need scanning.

5.2 Programmatic — ServiceConfig + DubboBootstrap

When you are not on Spring, use the Bootstrap API (shown in the Quick Start). Build a ServiceConfig, set the interface and the implementation ref, and register it with DubboBootstrap.

ServiceConfig<GreetingService> service = new ServiceConfig<>();
service.setInterface(GreetingService.class);
service.setRef(new GreetingServiceImpl());
service.setVersion("1.0.0");
service.setGroup("demo");
service.setTimeout(3000);

DubboBootstrap.getInstance()
        .application(new ApplicationConfig("demo-provider"))
        .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
        .protocol(new ProtocolConfig("tri", 50051))
        .service(service)
        .start()
        .await();

5.3 XML

For legacy Spring XML applications:

<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="tri" port="50051"/>

<bean id="greetingService" class="org.apache.dubbo.demo.provider.GreetingServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.demo.GreetingService"
               ref="greetingService" version="1.0.0" group="demo"/>

5.4 Per-service options worth knowing

Every attribute below is available on @DubboService, ServiceConfig, and <dubbo:service>:

Attribute Meaning Default
version Service version; consumers must match ""
group Logical grouping for the same interface ""
timeout Per-call timeout in ms -1 (inherit/1000)
retries Retry count on failover (excludes first try) -1 (→ 2)
loadbalance Default load balancer for this service empty (→ random)
cluster Fault-tolerance strategy empty (→ failover)
weight Static weight for load balancing -1
executes Max concurrent executions on the provider -1 (unlimited)
token Require a token from consumers (auth) ""
deprecated Mark service deprecated (warns consumers) false
register Whether to register in the registry true
accesslog Enable access logging (true or a file path) ""
filter Extra filters in the invocation chain {}
serialization Serialization for this service inherit
mcpEnabled Expose as an MCP (Model Context Protocol) tool false

Tip

Set common values once on dubbo.provider.* (see §7) and override per-service only when needed. A @DubboService(timeout = 5000) overrides dubbo.provider.timeout.


6. Consuming a Service

6.1 Spring Boot — @DubboReference

Inject a remote service into any Spring bean with @DubboReference:

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

@Service
public class GreetingClient {

    @DubboReference(version = "1.0.0", group = "demo", timeout = 3000, check = false)
    private GreetingService greetingService;

    public String greet(String name) {
        return greetingService.sayHello(name);
    }
}

Important

The version and group on @DubboReference must match the provider's @DubboService. A mismatch is the single most common cause of No provider available for the service … (see Troubleshooting).

6.2 Programmatic — ReferenceConfig

ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
reference.setInterface(GreetingService.class);
reference.setVersion("1.0.0");
reference.setGroup("demo");
reference.setCheck(false);

GreetingService service = reference.get();   // returns the proxy
String result = service.sayHello("Dubbo");

Caution

ReferenceConfig is heavyweight: it holds a live invoker and a connection. Cache and reuse the proxy returned by get(). Never create a new ReferenceConfig per call — that leaks connections. (The class itself is documented as expensive; for new code the Spring/Bootstrap paths manage its lifecycle for you.)

6.3 Asynchronous calls

Declare your interface method to return CompletableFuture, or use RpcContext to retrieve the future of a synchronous-looking method:

// Interface-declared async
CompletableFuture<String> future = greetingService.sayHelloAsync("Dubbo");
future.whenComplete((reply, ex) -> System.out.println(reply));

// Context-based async on a sync signature
RpcContext.getServiceContext().asyncCall(() -> greetingService.sayHello("Dubbo"))
          .whenComplete((reply, ex) -> System.out.println(reply));

6.4 Generic calls (no interface on the classpath)

When the consumer does not have the interface class (gateways, test tools), use a generic reference:

ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setInterface("org.apache.dubbo.demo.GreetingService");
reference.setGeneric("true");

GenericService generic = reference.get();
Object result = generic.$invoke(
        "sayHello",
        new String[]{"java.lang.String"},
        new Object[]{"Dubbo"});

6.5 The check flag

By default, a consumer checks at startup that at least one provider exists, and fails fast if not. Set check = false to allow the consumer to start before its providers do (common in dev and in systems that boot in arbitrary order).


7. Configuration Essentials

Dubbo configuration is organized into config components, each with a dubbo.<component>.* property prefix. For Spring Boot you set them in application.yml; the same keys exist as XML elements and config-object setters.

dubbo:
  application:
    name: order-service          # required: the application identity
    qos-enable: true             # operations port on/off
    qos-port: 22222
  registry:
    address: nacos://127.0.0.1:8848
  protocol:
    name: tri                    # tri | dubbo | rest2 | grpc
    port: 50051
  provider:
    timeout: 3000                # default timeout for all exported services
    retries: 2
    loadbalance: roundrobin
  consumer:
    check: false                 # don't fail consumer startup if provider absent
    timeout: 3000
  config-center:
    address: nacos://127.0.0.1:8848
  metadata-report:
    address: nacos://127.0.0.1:8848

7.1 The configuration components

Prefix Config object Purpose
dubbo.application ApplicationConfig Application name, QOS, metadata, probes, shutdown
dubbo.registry / dubbo.registries RegistryConfig Where to register/discover services
dubbo.protocol / dubbo.protocols ProtocolConfig Wire protocol(s) and server tuning
dubbo.provider ProviderConfig Defaults applied to all exported services
dubbo.consumer ConsumerConfig Defaults applied to all references
dubbo.config-center ConfigCenterConfig External dynamic configuration source
dubbo.metadata-report MetadataReportConfig Where service metadata is published
dubbo.module ModuleConfig Module-scoped settings
dubbo.metrics MetricsConfig Metrics collection
dubbo.tracing TracingConfig Distributed tracing
dubbo.ssl SslConfig TLS certificates

Note

Use the singular prefix (dubbo.registry) for a single instance, and the plural prefix with an id (dubbo.registries.zk.address: …) when you have more than one registry or protocol. A service can then point at a specific one by id.

7.2 Configuration precedence

When the same setting appears in multiple places, Dubbo resolves it in this order (highest wins):

  1. JVM -D system properties (e.g. -Ddubbo.protocol.port=50052)
  2. External config center (Nacos/Zookeeper/Apollo dynamic config)
  3. Environment variables (DUBBO_PROTOCOL_PORT)
  4. application.yml / dubbo.properties in your application
  5. Per-service/reference annotation or XML attributes
  6. Built-in defaults

Tip

A bare dubbo.properties file on the classpath is still honored — it's the lowest-friction way to set a handful of values without Spring. The property key is dubbo.<component>.<field>.

A complete field-by-field reference for every config component is in §15.


8. Protocols

A protocol is the wire format plus transport. You choose it with dubbo.protocol.name (or per service). A provider can expose multiple protocols simultaneously by configuring several dubbo.protocols.*.

Name Transport When to use
dubbo Single long-lived TCP connection, Hessian2 by default The classic, highest-throughput interface RPC. Default protocol.
tri (Triple) HTTP/2 gRPC- and cURL-compatible, mesh-friendly, streaming. Recommended for new services.
grpc HTTP/2 Native gRPC interop.
rest2 HTTP/1.1 Expose services as REST endpoints.
injvm In-process Local calls within the same JVM — no network. Chosen automatically when provider and consumer share a JVM.

Note

The default protocol is dubbo, the default serialization is hessian2, the default proxy factory is javassist, and the default cluster strategy is failover — all confirmed from the framework's SPI definitions.

8.1 Triple, the gRPC/HTTP-friendly protocol

Triple speaks HTTP/2 and accepts plain HTTP/JSON, so you can call a Dubbo service with curl — no Dubbo client required:

curl -v -d '{"name":"dubbo"}' \
     -H 'Content-Type: application/json' \
     http://127.0.0.1:50051/org.apache.dubbo.demo.hello.GreeterService/sayHello

Server-streaming works the same way (the method returns a stream):

curl -v -d '{"name":"dubbo"}' \
     -H 'Content-Type: application/json' \
     http://127.0.0.1:50051/org.apache.dubbo.demo.hello.GreeterService/sayHelloStream

Tip

If you use Protobuf IDL, the dubbo-maven-plugin generates the Java stubs. Add the plugin to your build and run mvn dubbo:compile to turn .proto files into Dubbo Triple stubs.

8.2 Exposing two protocols at once

dubbo:
  protocols:
    tri:
      name: tri
      port: 50051
    dubbo:
      name: dubbo
      port: 20880
@DubboService(protocol = {"tri", "dubbo"})
public class GreetingServiceImpl implements GreetingService { /* ... */ }

9. Registries and Service Discovery

The registry is how consumers find providers. Configure it with dubbo.registry.address using a protocol://host:port URL.

Registry Address scheme Module
Zookeeper zookeeper://host:2181 dubbo-registry-zookeeper
Nacos nacos://host:8848 dubbo-registry-nacos
Multicast multicast://224.5.6.7:1234 dubbo-registry-multicast (dev/testing only)
Multiple composite of several registries dubbo-registry-multiple
dubbo:
  registry:
    address: zookeeper://127.0.0.1:2181
    timeout: 10000          # connect timeout (ms)
    check: true             # fail startup if registry unreachable
    group: dubbo            # namespace within the registry

9.1 Application-level vs interface-level discovery

Dubbo 3 introduced application-level service discovery: each application instance registers once, and the mapping from interface to application is stored as metadata. This dramatically reduces the number of registry entries compared to Dubbo 2's interface-level model (one entry per interface per instance), which is what lets Dubbo scale to very large clusters. Dubbo 3 supports both and migrates transparently; you generally do not need to configure it.

Warning

A registry being briefly unreachable should not take your application down. By default consumers cache the last-known provider list and keep working. However, with dubbo.registry.check: true, startup will fail if the registry is down. In environments where the registry (e.g. Zookeeper) is a weak dependency, set check: false so a registry outage during boot doesn't crash the app — this is a known sharp edge (see issue #16178).

9.2 Multiple registries

dubbo:
  registries:
    beijing:
      address: zookeeper://bj-zk:2181
    shanghai:
      address: nacos://sh-nacos:8848

A service can register to a subset: @DubboService(registry = {"beijing"}). With multiple subscriptions, consumers use the zone-aware cluster by default to prefer the nearest zone.


10. Traffic Management

10.1 Cluster fault tolerance

The cluster strategy decides what happens when a call fails. Set it with cluster on a service/reference, or dubbo.provider.cluster / dubbo.consumer.cluster.

Strategy Behavior Use for
failover (default) Retry on another provider (up to retries) Idempotent reads
failfast Fail immediately, no retry Non-idempotent writes
failsafe Swallow the exception, log it, return null Best-effort (audit logs)
failback Return immediately, retry failed calls in background Notifications, eventually-consistent
forking Call several providers in parallel, take the first success Low-latency reads, costlier
broadcast Call all providers; fail if any fails Cache/config invalidation
available Call the first available provider Simple
mergeable Call a group and merge results Aggregation across groups
@DubboReference(cluster = "failfast", retries = 0)
private OrderWriteService orderWriteService;

Caution

failover retries on failure. For non-idempotent operations (create order, charge card) this can cause duplicate side effects. Always use failfast (or retries = 0) for writes.

10.2 Load balancing

When more than one provider qualifies, the load balancer picks one. Set it with loadbalance.

Strategy How it picks
random (default) Weighted random
roundrobin Weighted round-robin
leastactive Provider with the fewest in-flight calls
shortestresponse Provider with the lowest recent response time
consistenthash Same arguments → same provider (sticky)
adaptive Adaptive, load-aware selection
dubbo:
  consumer:
    loadbalance: leastactive

10.3 Method-level configuration

You can tune individual methods, not just whole services:

@DubboReference(
    methods = {
        @Method(name = "sayHello", timeout = 5000, retries = 0),
        @Method(name = "sayHelloStream", timeout = 30000)
    }
)
private GreetingService greetingService;

10.4 Routing and dynamic rules

Dubbo supports condition, tag, script, affinity, and mesh routers for canary releases, traffic isolation, and gray deployments. These rules are typically pushed through the config center at runtime rather than hard-coded. The router architecture and rule syntax are covered in depth in the Admin Guide.

Tip

Tag routing is the simplest canary mechanism: tag a provider (dubbo.provider.tag: gray) and have a consumer request that tag at runtime via RpcContext.getClientAttachment().setAttachment("dubbo.tag", "gray"). Only gray-tagged providers will serve the call.


11. Common Tasks (Recipes)

11.1 Set a global default timeout and retries

dubbo:
  provider:
    timeout: 3000
    retries: 2
  consumer:
    timeout: 3000

11.2 Require token authentication on a service

@DubboService(token = "true")   // Dubbo generates a random token
public class SecureServiceImpl implements SecureService { }

Consumers that discover the provider through the registry receive the token automatically; direct (peer-to-peer) callers without it are rejected.

11.3 Enable access logging

dubbo:
  provider:
    accesslog: /var/log/dubbo/access.log   # or `true` to log via the framework logger

11.4 Enable metrics and tracing

Add dubbo-observability-spring-boot-starter and a tracing starter, then:

dubbo:
  metrics:
    protocol: prometheus
    enable-jvm-metrics: true
  tracing:
    enabled: true
    sampling:
      probability: 0.1
    tracing-exporter:
      zipkin-config:
        endpoint: http://localhost:9411/api/v2/spans

11.5 Graceful shutdown

Dubbo registers a JVM shutdown hook that drains in-flight requests before exiting. Tune the drain window:

dubbo:
  application:
    shutwait: 10s

Note

When Dubbo runs inside Spring, the framework coordinates shutdown with Spring's lifecycle so it doesn't tear down beans Spring still needs. You can disable Dubbo's own hook entirely with -Ddubbo.service.shutdown.wait set appropriately or the IGNORE_LISTEN_SHUTDOWN_HOOK property when an external supervisor owns shutdown.

11.6 Direct (peer-to-peer) invocation — skip the registry

Handy for local testing against a known provider:

@DubboReference(url = "tri://127.0.0.1:50051")
private GreetingService greetingService;

11.7 Kubernetes / service mesh

Set dubbo.consumer.mesh-enable: true (or meshEnable on a reference). In mesh mode, Triple is required and Dubbo resolves the provider through the Kubernetes service DNS (<service>.<namespace>.svc.<cluster-domain>), letting Envoy/Istio handle routing. The cluster domain defaults to cluster.local and the mesh port to 80.


12. Operating a Running Application (QOS)

Dubbo ships an operations port (the "QOS" port) that exposes runtime commands over telnet and HTTP. Enable it via dubbo.application.qos-enable: true (default port 22222).

dubbo:
  application:
    qos-enable: true
    qos-port: 22222
    qos-accept-foreign-ip: false   # only localhost by default — keep it that way in prod

Connect with telnet and run help to list commands:

telnet localhost 22222

Or call a command over HTTP:

curl http://localhost:22222/ls

12.1 The command set

Command What it does
ls List exported (provider) and subscribed (consumer) services and their status
ps Show ports and their bound services
online / offline Register / deregister all services (graceful in/out of rotation)
onlineApp / offlineApp Online/offline by application name
onlineInterface / offlineInterface Online/offline a single interface
getConfig Dump effective configuration
getAddress Show the resolved address list for a service
invoke Invoke a service method from the console
select Choose among candidate providers for a manual invoke
count Count invocations over an interval
version Print the Dubbo version
live / ready / startup Liveness / readiness / startup probes (Kubernetes-friendly)
shutdown / gracefulShutdown Shut the application down (gracefully drains first)
publishMetadata Re-publish service metadata to the metadata center
getOpenAPI Export the OpenAPI document for REST/Triple services
loggerInfo / switchLogger / switchLogLevel Inspect and change logging at runtime
enableSimpleProfiler / enableDetailProfiler / disableSimpleProfiler / disableDetailProfiler Toggle the invocation profiler
setProfilerWarnPercent Tune the profiler's slow-call warning threshold
enableRouterSnapshot / disableRouterSnapshot / getRouterSnapshot / getEnabledRouterSnapshot / getRecentRouterSnapshot Capture routing decisions for debugging
serializeCheckStatus / serializeWarnedClasses Inspect serialization allow-list status
quit Close the telnet session

Caution

The QOS port can change your application's runtime behavior (offline, shutdown, switchLogLevel). Never expose it to untrusted networks. Keep qos-accept-foreign-ip: false (localhost only) in production and restrict it further with qos-anonymous-access-permission-level and qos-anonymous-allow-commands if you must open it. See the Admin Guide security section.

12.2 Kubernetes probes

Wire the QOS HTTP probes into your pod spec:

livenessProbe:
  httpGet: { path: /live, port: 22222 }
readinessProbe:
  httpGet: { path: /ready, port: 22222 }
startupProbe:
  httpGet: { path: /startup, port: 22222 }

13. Troubleshooting

Error: No provider available for the service <interface>

Cause: No provider is registered for that exact interface + group + version, or the consumer started before any provider registered, or the registry is unreachable.

Solution:

  1. Confirm the provider is up and registered (telnet localhost 22222 → ls on the provider).
  2. Verify group and version match exactly between @DubboService and @DubboReference.
  3. Check the registry address is identical on both sides.
  4. For boot-order issues, set check = false on the reference so it resolves lazily.

Prevention: Keep group/version in shared constants; use check: false in environments where boot order is not guaranteed.

Error: Failed to check the status of the service … No provider available … from the url …

Cause: The consumer's startup availability check timed out — same root causes as above, surfaced at ReferenceConfig.get().

Solution: Same as above. To stop startup from blocking on this check, set check = false.

Error: In mesh mode, a triple protocol must be specified

Cause: mesh-enable is on but no Triple protocol is configured.

Solution: Configure dubbo.protocol.name: tri (mesh mode requires HTTP/2 Triple) and ensure providedBy is set.

Error: dubbo.consumer.timeout setting too long leads to OOM

Cause: A very large consumer-side timeout lets requests pile up faster than they complete, exhausting heap (reported in issue #16294).

Solution: Keep timeouts realistic (seconds, not minutes). Combine with actives/executes limits to bound concurrency, and use failfast for writes so failed calls don't accumulate.

Error: NoClassDefFoundError: com/google/gson/JsonSyntaxException on JDK 25

Cause: A known JDK 25 + ServiceLoader interaction where an optional Gson dependency isn't on the classpath (issues #16295, #16296).

Solution: Use a Dubbo 3.3.x build with JDK 25 support and ensure Gson is present if you use components that need it; otherwise pin to JDK 21 for now.

Hessian2 deserialization sets fields to default/null

Cause: Hessian2 may not run field-initialization code during deserialization, assigning defaults instead (issue #15805). This is a serialization-format behavior, not a Dubbo bug.

Solution: Don't rely on field initializers running on the deserialized object; set values explicitly, or switch the affected service to serialization: fastjson2.

Provider start fails when Zookeeper is down

Cause: Zookeeper treated as a hard dependency at startup (issue #16178).

Solution: Set dubbo.registry.check: false so a weakly-dependent registry being down doesn't block startup; the app will register once the registry recovers.

NetUtils.matchIpExpression(...) fails to parse a normal IPv4 address with port

Cause: Edge case in IP-expression matching with a port suffix (issue #16308).

Solution: Specify host and port separately in config rather than embedding a port in an IP-match expression; upgrade to a release where it's fixed.

Tip

Most "it won't connect" problems are a group/version mismatch or a registry-address typo. Use the QOS ls and getAddress commands on both sides before digging deeper — they show exactly what each side thinks it is exporting and subscribing to.


14. Frequently Asked Questions

Q: Do I need Spring to use Dubbo? No. The programmatic DubboBootstrap API works without Spring. Spring Boot is the most popular path, but it's optional.

Q: Which protocol should I choose, dubbo or tri? For brand-new services, tri (Triple) — it's HTTP/2, gRPC- and cURL-compatible, and mesh-friendly. For maximum-throughput interface RPC between Java services, the classic dubbo TCP protocol is excellent and remains the default.

Q: Can one provider expose several protocols? Yes. Configure multiple dubbo.protocols.* and list them on the service (protocol = {"tri","dubbo"}).

Q: How do consumers find providers? Through the registry (Zookeeper, Nacos, …). Providers register their address; consumers subscribe and receive live updates. For testing you can bypass the registry with a direct url.

Q: What's the difference between group and version? version is for evolving the same logical service over time (e.g. 1.0.0 vs 2.0.0); group is for parallel variants of the same interface (e.g. tenant A vs B, or read vs write groups). Both participate in service identity, so consumer and provider must agree.

Q: Is the registry a single point of failure? No. Consumers cache the provider list and keep calling even if the registry goes down — as long as you don't force check: true at startup. Treat the registry as needed for discovery changes, not for every call.

Q: How do I call a Dubbo service without the Java interface? Use a generic reference (setGeneric("true") + $invoke), or expose the service over Triple/REST and call it with plain HTTP/JSON.

Q: What serialization does Dubbo use? hessian2 by default. fastjson2 is also bundled. Serialization is an SPI, so you can add others. Dubbo enforces a serialization allow-list for security (see Admin Guide).

Q: How do I take an instance out of rotation for a deploy? Use the QOS offline command (or offlineApp) to deregister gracefully, deploy, then online again. Combine with gracefulShutdown to drain in-flight calls.

Q: Does Dubbo work on the latest JDK? Dubbo 3.3.x supports JDK 8 through 25. Some very new JDK versions have known edge cases (see Troubleshooting); track the version-compatibility table in the README.

Q: Can I call a Dubbo (Java) service from Go/Python/Node? Yes — use the Triple protocol (gRPC-compatible) and the matching Dubbo SDK for that language, or plain gRPC/HTTP clients.


15. Configuration Reference

Every field below is a real property on its config object, exposed as dubbo.<prefix>.<field> (kebab-case in YAML), as an attribute on the corresponding annotation/XML element, and as a setter on the config class.

15.1 dubbo.application (ApplicationConfig)

Field Purpose
name Required. Application identity (used for app-level discovery)
version Application version
owner, organization, architecture, environment Descriptive metadata
logger Logging framework adapter (slf4j, log4j2, jcl, …)
compiler Bytecode compiler (javassist, jdk)
registry-ids Which registries this app uses
qos-enable Turn the operations port on/off
qos-port Operations port (default 22222)
qos-host Bind host for the operations port
qos-accept-foreign-ip Allow non-localhost connections to QOS (keep false in prod)
qos-accept-foreign-ip-whitelist Allowed remote IPs for QOS
qos-anonymous-access-permission-level Permission level for unauthenticated QOS access
qos-anonymous-allow-commands Commands permitted anonymously
qos-check Validate QOS config
metadata-type local or remote metadata storage
metadata-service-protocol, metadata-service-port Metadata service exposure
shutwait Graceful-shutdown drain window
register-mode interface, instance, or all (discovery model)
register-consumer Whether consumers register themselves
enable-empty-protection Ignore empty provider pushes (avoid wiping the address list)
serialize-check-status, auto-trust-serialize-class, trust-serialize-class-level, check-serializable Serialization security controls
executor-management-mode Thread-pool management (default, isolation)
liveness-probe, readiness-probe, startup-probe Custom probe implementations
dump-enable, dump-directory Thread/heap dump on overload
parameters Arbitrary extra parameters

15.2 dubbo.registry (RegistryConfig)

Field Purpose
address Required. protocol://host:port registry URL
protocol Registry protocol (zookeeper, nacos, multicast, …)
username, password Registry credentials
port Registry port (if not in address)
group, version Namespace within the registry
timeout Connect timeout (ms)
session Session timeout (ms)
file Local cache file for the provider list
check Fail startup if the registry is unreachable
register, subscribe Whether to register / subscribe
dynamic Auto-deregister on shutdown
simplified Register a reduced URL (less registry data)
use-as-config-center, use-as-metadata-center Reuse this registry for config / metadata
zone, weight, preferred Multi-registry zone routing
register-mode Discovery model override
enable-empty-protection Empty-push protection
secure TLS to the registry
parameters Extra parameters

15.3 dubbo.protocol (ProtocolConfig)

Field Purpose
name Protocol id (dubbo, tri, rest2, grpc, injvm)
host Bind/advertise host
port Listen port
contextpath Context path (HTTP-based protocols)
serialization Serializer (hessian2, fastjson2)
prefer-serialization Preferred serializer negotiation
threadpool Thread-pool type (fixed, cached, limited, eager)
corethreads, threads, iothreads Thread-pool sizing
alive, queues Pool keep-alive and queue depth
accepts Max accepted connections
payload Max request/response size (bytes)
buffer Network buffer size
heartbeat Heartbeat interval (ms)
accesslog Access logging
transporter, exchanger, dispatcher, networker Remoting layer plug points
server, client Server/client transport impls
codec Codec
telnet, prompt Telnet handler and prompt
status Status checkers
keep-alive Keep connections alive
ssl-enabled TLS for this protocol
register Register this protocol's services
ext-protocol, preferred-protocol Extended/preferred protocol negotiation
json-check-level JSON validation strictness

15.4 dubbo.provider (ProviderConfig)

Provider-side defaults inherited by every exported service. In addition to the service attributes in §5.4: host, port, contextpath, threadpool, threadname, threads, iothreads, alive, queues, accepts, codec, charset, payload, buffer, transporter, exchanger, dispatcher, networker, server, client, telnet, prompt, status, wait, export-thread-num, export-background.

15.5 dubbo.consumer (ConsumerConfig)

Consumer-side defaults inherited by every reference (plus the reference attributes from §5.4): threadpool, corethreads, threads, queues, shareconnections (connections shared across references), url-merge-processor, refer-thread-num, refer-background, mesh-enable.

15.6 Other components

  • dubbo.config-center (ConfigCenterConfig) — external dynamic configuration (address, protocol, group, namespace, timeout, check, highest-priority).
  • dubbo.metadata-report (MetadataReportConfig) — where service metadata is published (address, username, password, timeout, group).
  • dubbo.metrics (MetricsConfig) — metrics protocol and JVM/aggregation toggles.
  • dubbo.tracing (TracingConfig) — enabled, sampling probability, baggage, and exporter (Zipkin/OTLP) endpoints.
  • dubbo.ssl (SslConfig) — certificate/key/trust-cert paths for TLS.

Note

Spring Boot generates IDE auto-completion metadata for these properties from the Javadoc on the config classes, so your editor will suggest and document them as you type. The authoritative source for any field's exact semantics is always the config class in dubbo-common.