Mastering Dubbo: Build Simple RPC Services with SpringBoot and Zookeeper
This article walks through the fundamentals of Apache Dubbo, covering its service discovery, RPC communication, traffic management, configuration, and deployment architecture, and provides a step‑by‑step SpringBoot implementation of a simple RPC service with Zookeeper registration, including code snippets for provider, consumer, and controller.
Dubbo Framework Overview
Apache Dubbo is a distributed microservice development framework that provides two key capabilities: RPC communication and service governance.
Service Discovery
Service discovery enables a consumer to automatically obtain a list of service addresses without needing to know the deployment location or IP address of the provider.
Dubbo implements a client‑based discovery mechanism and typically relies on external registries such as Nacos, Consul, or Zookeeper. The basic workflow is illustrated below:
RPC Communication
Dubbo3 provides native Triple (Dubbo3) and Dubbo2 protocols, and also integrates many third‑party protocols such as gRPC, Thrift, JsonRPC, Hessian2, and REST into its programming and governance model.
Service Traffic Management
By defining routing rules in Dubbo, you can control traffic distribution to achieve A/B testing, canary releases, blue‑green deployments, and other advanced scenarios.
Configuration Management
Dubbo supports dynamic configuration, covering three major categories: startup configuration items, service‑governance rules, and runtime dynamic configuration items.
Deployment Architecture (Registry, Config, Metadata Centers)
As a microservice framework, Dubbo defines several centralized components to enable cooperation among distributed modules:
Registry Center – coordinates address registration and discovery between consumers and providers.
Configuration Center – stores global startup configuration and governance rules, ensuring cross‑environment consistency.
Metadata Center – receives service‑interface metadata reported by providers, offering admin capabilities such as service testing and API documentation, and supplements the registry with method‑level configuration.
High Extensibility
Dubbo uses the SPI mechanism to provide flexible extensibility, allowing developers to customize behavior at almost any point in the framework.
Practical Example: Simple RPC with SpringBoot
Framework Dependencies
<!-- Include Zookeeper and Dubbo dependencies -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>Project Structure
RpcCommon – shared DTOs and service interfaces.
RpcProvider – service provider module.
RpcConsume – service consumer module.
Common Library (RpcCommon)
Entity class:
/**
* @author brand
* @Description User information entity
*/
@Getter
@Setter
public class UserInfo implements Serializable {
private Integer userId;
private String userName;
private Integer age;
private String sex;
}Service interface:
/**
* @author brand
* @Description User information service
*/
public interface UserInfoService {
UserInfo getUserInfo(int userId);
String getHello(int userId);
}Provider (RpcProvider)
Dubbo provider configuration (application.yml):
# Dubbo Provider configuration
dubbo:
application:
name: rpc-provider # service name
registry:
address: 127.0.0.1:2181
protocol: zookeeper
protocol:
name: dubbo
port: 20882 # expose service on this port
scan:
base-packages: rpcprovider.modules.serviceService implementation (annotated with Dubbo's @Service):
package rpcprovider.modules.service;
import com.alibaba.dubbo.config.annotation.Service;
import rpccommon.dto.UserInfo;
import rpccommon.service.UserInfoService;
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Override
public UserInfo getUserInfo(int userId) {
UserInfo userInfo = new UserInfo();
userInfo.setUserId(userId);
userInfo.setAge(18);
userInfo.setSex("男");
userInfo.setUserName("Brand");
return userInfo;
}
@Override
public String getHello(int userId) {
return " Hello, " + userId;
}
}After starting the provider, Zookeeper shows the registered node:
[zk: 127.0.0.1:2181(CONNECTED) 68] ls /
[dubbo, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 69] ls /dubbo
[rpccommon.service.UserInfoService]
[zk: 127.0.0.1:2181(CONNECTED) 70] ls /dubbo/rpccommon.service.UserInfoService
[configurators, consumers, providers, routers]
[zk: 127.0.0.1:2181(CONNECTED) 71] ls /dubbo/rpccommon.service.UserInfoService/providers
[dubbo%3A%2F172.21.213.159%3A20882%2Frpccommon.service.UserInfoService%3Fanyhost%3Dtrue%26application%3Drpc-provider%26dubbo%3D2.6.2%26generic%3Dfalse%26interface%3Drpccommon.service.UserInfoService%26methods%3DgetHello%2CgetUserInfo%26pid%3D60138%26side%3Dprovider%26timestamp%3D1646535565910]Consumer (RpcConsume)
Dubbo consumer configuration (application.yml):
# Dubbo Consumer configuration
dubbo:
application:
name: rpc-consumer
registry:
address: 127.0.0.1:2181
protocol: zookeeperConsumer implementation using @Reference to inject the remote service:
package rpcconsume.modules.service;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import rpccommon.dto.UserInfo;
import rpccommon.service.UserInfoService;
@Service
public class UserInfoConsumer implements UserInfoService {
@Reference
private UserInfoService userInfoService;
@Override
public UserInfo getUserInfo(int userId) {
return userInfoService.getUserInfo(userId);
}
@Override
public String getHello(int userId) {
return userInfoService.getHello(userId);
}
}Controller to expose the consumer via HTTP:
package rpcconsume.modules.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import rpccommon.dto.UserInfo;
import rpcconsume.modules.service.UserInfoConsumer;
@RestController
@Slf4j
@RequestMapping("/v1.0/consumer")
public class ConsumerController {
@Autowired
private UserInfoConsumer userInfoConsumer;
@GetMapping("/userinfo/{user_id}")
public UserInfo getUserInfo(@PathVariable("user_id") int userId) {
return userInfoConsumer.getUserInfo(userId);
}
@GetMapping("/hello/{user_id}")
public String getHello(@PathVariable("user_id") int userId) {
return userInfoConsumer.getHello(userId);
}
}Verify consumer registration in Zookeeper:
[zk: 127.0.0.1:2181(CONNECTED) 73] ls /dubbo/rpccommon.service.UserInfoService/consumers
[consumer%3A%2F172.21.213.159%2Frpccommon.service.UserInfoService%3Fapplication%3Drpc-consumer%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.6.2%26interface%3Drpccommon.service.UserInfoService%26methods%3DgetHello%2CgetUserInfo%26pid%3D60884%26side%3Dconsumer%26timestamp%3D1646536367371]Conclusion
RPC communication is only one part of Dubbo; together with service registration and discovery, configuration management, and traffic governance, it satisfies the basic capabilities required for a microservice architecture. Alternatives such as Baidu’s brpc and Google’s gRPC are also popular choices, and the appropriate framework should be selected based on specific business requirements.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture & Thinking
🍭 Frontline tech director and chief architect at top-tier companies 🥝 Years of deep experience in internet, e‑commerce, social, and finance sectors 🌾 Committed to publishing high‑quality articles covering core technologies of leading internet firms, application architecture, and AI breakthroughs.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
