You may have noticed that most of the functions and examples in the documentation are based on the Spring Boot model, but Spring Boot or Spring is merely one application or microservice development model adapted by Dubbo. As an RPC framework, Dubbo defines a comprehensive set of API interfaces, enabling us to develop Dubbo applications based on the native APIs. Business scenarios that can be achieved with pure APIs include:
public class Application {
public static void main(String[] args) {
DubboBootstrap.getInstance()
.protocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051))
.service(ServiceBuilder.newBuilder().ref(new DemoServiceImpl()).build())
.start()
.await();
}
}
The above is a code example of starting a Dubbo RPC Server. The DubboBootstrap
instance represents a Dubbo application and serves as the entry point for starting the entire Dubbo application. Based on DubboBootstrap, we can set protocol
, service
, registry
, metrics
, etc., to register services, connect to the registry, etc., similar to adjusting application.yml or application.properties files in Spring Boot.
The official recommendation is to use DubboBootstrap.start()
as the centralized entry for application startup, but to facilitate the separate publication of some services after the process starts, the Dubbo framework also allows directly calling ServiceConfig.export()
or ReferenceConfig.refer()
methods to publish individual services. In this case, Service/Reference will register with the default DubboBootstrap instance, similar to calling DubboBootstrap.service(...).start()
.
Below are some components commonly used in development. For a complete component definition and detailed parameter description, please refer to the Reference Manual - Configuration Items Manual:
API Component | Globally Unique | Core Methods or Properties | Description |
---|---|---|---|
DubboBootstrap | Yes (except for multi-application scenarios) | start(), stop() | The DubboBootstrap instance represents a Dubbo application and serves as the entry point for starting the entire Dubbo application. |
ApplicationConfig | Yes | name | Application name and some global configurations at the application level |
MetricsConfig | Yes | protocol, prometheus, tracing | Configurations related to Metrics and tracing collection |
ProtocolConfig | No. Services in multi-protocol scenarios are associated by id | id, name, port, serialization, threadpool | RPC protocol port, serialization protocol, runtime behavior configuration |
RegistrtyConfig | No. Services in multi-registry scenarios are associated by id | id, address, protocol, group | Registry implementation, address, subscription, etc. configurations |
ConfigCenterConfig | No. Services in multi-configuration center scenarios are associated by id | id, address, protocol, group, namespace | Configuration center implementation, address, group isolation, etc. configurations |
MetadataReportConfig | No. Services in multi-metadata center scenarios are associated by id | id, address, protocol, group, namespace | Metadata center implementation, address, group isolation, etc. configurations |
ProviderConfig | No | Reference ServiceConfig | Default values for multiple ServiceConfig |
ConsumerConfig | No | Reference ReferenceConfig | Default values for multiple ReferenceConfig |
ServiceConfig | No | - Method: export() - Properties: interfaceClass, ref, group, version, timeout, retry | A ServiceConfig instance represents an RPC service |
ReferenceConfig | No | - Method: refer() - Properties: interfaceClass, group, version, timeout, retry, cluster, loadbalance | A ReferenceConfig instance represents an RPC service |
MethodConfig | No | name, oninvoke, onreturn, onthrow | Method-level configuration embedded in ServiceConfig/ReferenceConfig |
ArgumentConfig | No | index, type, callback | Parameter-level configuration embedded in MethodConfig |
This example demonstrates how to use the lightweight Dubbo SDK to develop RPC Server and Client. The example defines, publishes, and accesses RPC services using Java Interface, with Triple protocol communications. For complete code, please see dubbo-samples.
Based on the Triple protocol defined by Dubbo, you can easily write browser and gRPC compatible RPC services and run them simultaneously on HTTP/1 and HTTP/2. The Dubbo Java SDK supports defining services using IDL or language-specific methods and provides a lightweight API for publishing or calling these services.
Before coding with Dubbo RPC, you only need to add a lightweight dubbo
dependency package to your project. For Maven, it looks like this:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.3.0</version>
</dependency>
Define a standard Java interface named DemoService
as a Dubbo service (Dubbo also supports IDL-based service definition patterns).
public interface DemoService {
String sayHello(String name);
}
Implement the DemoService
interface and write the business logic code.
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello " + name + ", response from provider.";
}
}
Start the server and listen for RPC requests on the specified port. Before this, we registered the following information with the server:
Triple
as the communication RPC protocol and listening on port 50051
DemoService
serverpublic class Application {
public static void main(String[] args) {
DubboBootstrap.getInstance()
.protocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051))
.service(ServiceBuilder.newBuilder().ref(new DemoServiceImpl()).build())
.start()
.await();
}
}
The simplest way is to use an HTTP/1.1 POST request to access the service, with parameters passed as standard JSON format in the HTTP payload. Here is an example using the cURL command:
curl \
--header "Content-Type: application/json" \
--data '["Dubbo"]' \
http://localhost:50051/org.apache.dubbo.demo.DemoService/sayHello
Parameters must be passed in array format. If there are multiple parameters, the format should be like
["param1", {"param2-field": "param2-value"}, ...]
, please refer to the triple protocol specification for specifics.
Next, you can also use a standard Dubbo client to request the service, specifying the server address to initiate an RPC call. The format is protocol://ip:host
.
public class Application {
public static void main(String[] args) {
DemoService demoService =
ReferenceBuilder.newBuilder()
.interfaceClass(DemoService.class)
.url("tri://localhost:50051")
.build()
.get();
String message = demoService.sayHello("dubbo");
System.out.println(message);
}
}
Congratulations! The above is the basic usage of Dubbo Java RPC communication! 🎉
Besides the simple usage scenarios above, developers can also publish multiple services, directly call ServiceConfig/ReferenceConfig to publish/subscribe individual services, etc.
The following example registers and publishes any number of services FooService, BarService. These services will all use the default timeout configured in providerConfig, avoiding the hassle of repeated configurations for multiple services.
public static void main(String[] args) {
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setTimeout(5000);
ProtocolConfig protocolConfig = new ProtocolConfig(CommonConstants.TRIPLE, 50051);
DubboBootstrap.getInstance()
.protocol(protocolConfig)
.provider(providerConfig)
.service(ServiceBuilder.newBuilder().ref(new FooServiceImpl()).build())
.service(ServiceBuilder.newBuilder().ref(new BarServiceImpl()).build())
.start()
.await();
}
Directly call ServiceConfig.export() to publish services suitable for dynamic publication or subscription of a single service in runtime; it is similar for ReferenceConfig. For routine application startup processes, it is recommended to use DubboBootstrap instead of directly calling ServiceConfig.export() to publish individual services.
public static void main(String[] args) {
ServiceConfig<DemoService> demoServiceConfig = new ServiceConfig<>();
demoServiceConfig.setInterface(DemoService.class);
demoServiceConfig.setRef(new DemoServiceImpl());
demoServiceConfig.setVersion("1.0.0");
demoServiceConfig.export(); // this service will be registered to the default instance of DubboBootstrap.getInstance()
}
private DemoService referService() {
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
reference.setInterfaceClass(DemoService.class);
ReferenceCache cache = SimpleReferenceCache.getCache();
try {
return cache.get(reference);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
Because the proxy object created by ReferenceConfig.get() holds a lot of resources such as connections and addresses, it is recommended to cache and reuse it. Dubbo officially provides a SimpleReferenceCache implementation for reference. For more content on SimpleReferenceCache, please refer to RPC Framework.
Use DubboBootstrap as the startup entry, subscribe to services, and obtain proxy objects.
public static void main(String[] args) {
ReferenceConfig<GreetingsService> reference =
ReferenceBuilder.<GreetingsService>newBuilder()
.interfaceClass(GreetingsService.class)
.build();
DubboBootstrap.getInstance().reference(reference).start();
GreetingsService service = reference.get();
}
Compared to RPC server and RPC client, developing microservice applications based on APIs requires configurations for the application name and registry center.
public static void main(String[] args) {
DubboBootstrap.getInstance()
.application()
.registry(new RegistryConfig("nacos://127.0.0.1:8848"))
.protocol(new ProtocolConfig(CommonConstants.TRIPLE, 50051))
.service(ServiceBuilder.newBuilder().ref(new DemoServiceImpl()).build())
.service(ServiceBuilder.newBuilder().ref(new FooServiceImpl()).build())
.start()
.await();
}
Multiple registry centers can specify different ids, and services are associated with the registry center instances by id. In the following example, GreetingsService is published to bjRegistry, while DemoService is published to hzRegistry.
public static void main(String[] args) {
RegistryConfig bjRegistry = new RegistryConfig();
bjRegistry.setId("bj");
bjRegistry.setAddress("nacos://127.0.0.1:8848");
RegistryConfig hzRegistry = new RegistryConfig();
hzRegistry.setId("hz");
hzRegistry.setAddress("nacos://127.0.0.2:8848");
DubboBootstrap.getInstance()
.registry(bjRegistry)
.registry(hzRegistry)
.service(ServiceBuilder.newBuilder().registryIds("bj").interfaceClass(GreetingsService.class).ref(new GreetingsServiceImpl()).build())
.service(ServiceBuilder.newBuilder().registryIds("hz").interfaceClass(DemoService.class).ref(new DemoServiceImpl()).build())
.start()
.await();
}
Directly call ServiceConfig.export() to publish services, suitable for dynamically publishing or subscribing to a single service in runtime; it is similar for ReferenceConfig. For routine application startup processes, it is recommended to use DubboBootstrap instead of directly calling ServiceConfig.export() to publish individual services.
public static void main(String[] args) {
RegistryConfig hzRegistry = new RegistryConfig();
hzRegistry.setId("hz");
hzRegistry.setAddress("nacos://127.0.0.2:8848");
ServiceConfig<DemoService> demoServiceConfig = new ServiceConfig<>();
demoServiceConfig.setInterface(DemoService.class);
demoServiceConfig.setRef(new DemoServiceImpl());
demoServiceConfig.setVersion("1.0.0");
demoServiceConfig.setRegistry(hzRegistry);
demoServiceConfig.export(); // this service will be registered to the default instance of DubboBootstrap.getInstance()
}
private DemoService referService() {
RegistryConfig hzRegistry = new RegistryConfig();
hzRegistry.setId("hz");
hzRegistry.setAddress("nacos://127.0.0.2:8848");
ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
reference.setInterfaceClass(DemoService.class);
reference.setRegistry(hzRegistry)
ReferenceCache cache = SimpleReferenceCache.getCache();
try {
return cache.get(reference);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}