Apache Dubbo 是高性能 RPC 框架,配合 Zookeeper 做服務註冊發現,構建分布式服務治理體系。本文提供完整可運行的 Maven 多模塊項目,涵蓋提供者、消費者、API 共享、配置詳解、啟動步驟與監控中心部署。
| 組件 | 版本 | 說明 |
|---|---|---|
| JDK | 1.7 | |
| Spring | 4.0.2.RELEASE | |
| Dubbo | 2.4.10 | 阿里巴巴開源版 |
| Zookeeper | 3.4.6 | 註冊中心 |
| MyBatis | 3.2.6 | ORM 框架 |
| Tomcat | 8.0 | 消費者 Web 容器 |
| Dubbo Monitor | 2.5.4-SNAPSHOT | 簡易監控中心 |
banksteel-yesen (pom, 聚合父項目)
├── banksteel-yesen-api (jar) -- 服務接口、實體類
│ ├── com.yesen.entity.User
│ └── com.yesen.service.UserService
└── banksteel-yesen-provider (jar) -- 服務提供者,Main 類啟動
├── com.yesen.dao.UserDAO + impl
├── com.yesen.service.impl.UserServiceImpl
├── resources/spring/dubbo-service.xml
├── resources/spring/mybatis-config.xml
└── resources/mybatis/mapper/userMapper.xml
banksteel-userapp (war) -- 服務消費者,部署 Tomcat
├── com.yesen.controller.UserController
├── resources/META-INF/spring/dubbo-user.xml
├── resources/META-INF/spring/root-config.xml
├── resources/META-INF/spring/spring-mvc.xml
└── webapp/WEB-INF/web.xml

// User.java - 實體
public class User implements Serializable {
private long id; private String username, password; private int age;
// getter/setter
}
// UserService.java - 服務接口
public interface UserService {
List<User> getUserByMap(Map<String, Object> paramMap);
void insertUser(User user);
}
// UserDAOImpl.java - MyBatis Template 方式
@Repository("userDAO")
public class UserDAOImpl implements UserDAO {
@Autowired private SqlSessionTemplate sqlSessionTemplate;
private static final String INSERT = "com.yesen.model.userMapper.insertUser";
private static final String LISTBY = "com.yesen.model.userMapper.listBy";
public List<User> getUserByMap(Map<String, Object> paramMap) {
return sqlSessionTemplate.getSqlSessionFactory().openSession().selectList(LISTBY, paramMap);
}
public void insertUser(User user) {
sqlSessionTemplate.getSqlSessionFactory().openSession().insert(INSERT, user);
}
}
// UserServiceImpl.java
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired private UserDAO userDAO;
// 透傳調用 DAO
}
<mapper namespace="com.yesen.model.userMapper">
<resultMap id="userMap" type="user">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="age" property="age"/>
</resultMap>
<insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (USERNAME, PASSWORD, AGE) VALUES (#{username}, #{password}, #{age})
</insert>
<select id="listBy" parameterType="map" resultMap="userMap">
SELECT ID, USERNAME, PASSWORD, AGE FROM user
<where>
<if test="username != null"> AND USERNAME = #{username} </if>
<if test="password != null"> AND PASSWORD = #{password} </if>
</where>
ORDER BY id DESC
<if test="rowNum != null"> LIMIT #{rowNum} </if>
</select>
</mapper>
<beans xmlns:dubbo="https://code.alibabatech.com/schema/dubbo"> <bean id="userService" class="com.yesen.service.impl.UserServiceImpl"/> <dubbo:application name="banksteel-user-provider"/> <dubbo:registry address="localhost:2181" protocol="zookeeper"/> <dubbo:protocol name="dubbo" port="20880" id="mydubbo"/> <dubbo:service interface="com.yesen.service.UserService" ref="userService"/> </beans>
<beans xmlns:dubbo="https://code.alibabatech.com/schema/dubbo"> <dubbo:application name="banksteel-userapp"/> <dubbo:registry address="zookeeper://localhost:2181" protocol="zookeeper"/> <dubbo:reference interface="com.yesen.service.UserService" id="userService" check="false" timeout="10000"/> </beans>
@Controller
public class UserController {
@Autowired private UserService userService;
@RequestMapping("/create")
public String createUser(HttpServletRequest request, Model model) {
User user = new User();
user.setUsername(request.getParameter("username"));
user.setPassword(request.getParameter("password"));
user.setAge(Integer.parseInt(request.getParameter("age")));
userService.insertUser(user);
model.addAttribute("message", user.getUsername());
return "insertSuccess";
}
@RequestMapping("/query")
public String queryUser(String username, Model model) {
List<User> list = userService.getUserByMap(new HashMap<>());
model.addAttribute("userList", list);
return "userInfo";
}
}
cd zookeeper-3.4.6/bin
zkServer.cmd (Windows) 或 ./zkServer.sh start (Linux)
# 驗證:zkCli.cmd → ls /dubbo 應為空

# 在 banksteel-yesen 父項目
mvn clean install -DskipTests
# 複製產出物
cp banksteel-yesen-provider/target/banksteel-yesen-provider-0.0.1-SNAPSHOT.jar D:/
cp -r banksteel-yesen-provider/target/lib D:/
# 執行(Main-Class: com.alibaba.dubbo.container.Main)
java -jar banksteel-yesen-provider-0.0.1-SNAPSHOT.jar

zkCli.cmd
ls /dubbo
# 應看到 [com.yesen.service.UserService] 節點

# 部署 banksteel-userapp.war 到 Tomcat 8
# 訪問 https://localhost:8080/banksteel-user-app/create?username=test&password=123&age=20

# 解壓 dubbo-monitor-simple-2.5.4-SNAPSHOT-assembly.tar.gz
cd conf
# 編輯 dubbo.properties
dubbo.registry.address=zookeeper://localhost:2181
dubbo.protocol.port=7070
cd bin
start.bat (Windows) 或 ./start.sh (Linux)
# 瀏覽器訪問 https://localhost:8080/services.html

| 問題 | 解決方案 |
|---|---|
| 提供者啟動報 ClassNotFound | Maven 打包需配置 maven-dependency-plugin 輸出 lib 目錄,Manifest Class-Path 指向 lib/ |
| 消費者調用超時 | <dubbo:reference timeout="10000"/> 設置合理超時;檢查防火牆 20880 端口 |
| ZK 連接不上 | 確認 zoo.cfg 中 clientPort=2181,Linux 開放端口 |
| 序列化異常 | 實體類必須實現 Serializable,字段類型支援 Dubbo 默認 Hessian2 |
| 監控中心無數據 | 提供者/消費者需配置 <dubbo:monitor protocol="registry"/> 或 JVM 參數 -Ddubbo.monitor.address=... |
maven-assembly-plugin 生成 tar.gz,解壓即運行 ./start.sh「Dubbo 入門易、精通難。關鍵在於理解『接口契約』、『註冊發現』、『負載均衡』、『容錯重試』四大核心機制。」
完整源碼下載:dubbo例子.rar
如有疑問,歡迎留言交流!🤝