文 | 平哥 日期 | 20201013java
具体代码详见GitHub仓库:点我跳转git
此项目为本身学习Dubbo+Zookeeper,搭建的第一个项目,主要架构就是一个父项目、三个子Module:dubbo_provider、 dubbo_consumer 和 dubbo_api,三个子Module分别继承父项目。github
Dubbo的远程访问是基于接口的。Consumer和Provider使用同一个接口,能够实现远程访问。web
p.s. 此项目重点是练习Dubbo+Zookeeper,故没有写链接数据库的内容,只是模拟了访问数据库。spring
用IDEA建立项目,建立完项目目录以下:数据库
直接上代码:apache
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.gcp</groupId> <artifactId>dubbo_pro01</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>dubbo_provider</module> <module>dubbo_consumer</module> <module>dubbo_api</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> </parent> <dependencies> <!--springboot 启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--dubbo springboot启动器--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.8</version> </dependency> <!--curator依赖--> <!--Curator提供了一套Java类库, 能够更容易的使用ZooKeeper。 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>5.1.0</version> </dependency> </dependencies> </project>
package com.gcp.pojo; import lombok.Data; @Data public class User { private Long id; private String name; private String password; }
package com.gcp.service; import com.gcp.pojo.User; /** * 用户服务接口 */ public interface UserService { void register(User user); User getUserById(Long id); }
在pom.xml文件中添加依赖:api
<dependencies> <dependency> <groupId>com.gcp</groupId> <artifactId>dubbo_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
UserMapper接口:浏览器
import com.gcp.pojo.User; /** * 模拟数据库访问 */ public interface UserMapper { void insert(User user); User selectById(Long id); }
UserMapperImpl实现类:springboot
@Repository public class UserMapperImpl implements UserMapper { @Override public void insert(User user) { System.out.println("数据库访问:新增用户 - " + user); } @Override public User selectById(Long id) { User user = new User(); user.setId(id); user.setName("name" + id); user.setPassword("password" + id); System.out.println("数据库访问:主键查询用户 - " + user); return user; } }
@DubboService(loadbalance = "roundrobin")
, 其中 loadbalance = "roundrobin"
意思是若是此服务有集群将采用轮询的方式进行负载均衡访问,
默认是 random
:随机
@DubboService(loadbalance = "roundrobin") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public void register(User user) { System.out.println("UserService 实现类中:注册用户"); userMapper.insert(user); } @Override public User getUserById(Long id) { System.out.println("UserService 实现类中:根据id查询用户"); return userMapper.selectById(id); } }
说明:
在 resources 文件夹下建立application.yml:
dubbo: # dubbo配置根节点 registry: # 配置dubbo的注册中心 registry address: zookeeper://192.168.40.170:2181 # 提供注册中心的访问地址。 application: # 配置本dubbo应用信息 name: gcp-dubbo-first-provider # 配置本dubbo的应用名称,名称组成是:字母,数字,'-',字母开头 protocol: # 协议,协议自定义配置的时候,全部的默认值失效。 name: dubbo # 协议名 port: 20880 # 端口,默认20880
如何安装Zookeeper能够详见我另外一篇文章
*
在 com.gcp
包下建立SpringBoot启动类:
@SpringBootApplication @EnableDubbo // @EnableDubboConfig public class DbProviderApplication { public static void main(String[] args) { SpringApplication.run(DbProviderApplication.class,args); } }
此时可启动,测试看Zookeeper中是否成功注册上服务,访问Linux服务器,利用Zookeeper客户端工具查看:
在pom.xml文件中添加依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.gcp</groupId> <artifactId>dubbo_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
有人可能会疑惑,Zookeeper注册中心中已经有提供的Service服务了,怎么本地还须要Service?
说明: 其实,dubbo远程服务调用,是为了 封装通用规则,但各个子项目有本身的个性逻辑
如:用户的注册逻辑,在一个企业中是统一的。提供一个Provider实现注册逻辑;
对于consumer来讲,是不一样的,能够提供若干入口。如腾讯的用户注册,能够经过QQ、QQ音乐、QQ空间等实现注册或登陆。底层的用户是相同的。
LocalUserService接口:
package com.gcp.service; import com.gcp.pojo.User; /** * consumer子Module的本地Service */ public interface LocalUserService { void register(User user); User getById(Long id); }
LocalUserServiceImpl实现类:
@Service public class LocalUserServiceImpl implements LocalUserService { /** * 远程服务的接口。经过注解@DubboReference实现动态代理建立 * 规则: * 一、 通知Dubbo框架,根据配置找注册中心,发现服务的地址。 * 拿接口名称做为zookeeper中节点的命名规则,获取地址。 * 二、 通知Spring,根据Dubbo框架的特性,建立接口的动态代理对象,并维护 * 在Spring容器中。 * 三、 相似@Autowired,把代理对象注入到当前的变量中。 */ @DubboReference private UserService userService; @Override public void register(User user) { System.out.println("准备调用远程服务,服务对象类型是:" + userService.getClass().getName()); System.out.println("注册的用户是: " + user); userService.register(user); } @Override public User getById(Long id) { System.out.println("根据主键查询用户,主键是: " + id); return userService.getUserById(id); } }
UserController类:
@RestController public class UserController { @Autowired private LocalUserService localUserService; @RequestMapping("findUser") public User findUser(Long id){ return localUserService.getById(id); } @RequestMapping("registerUser") public String register(User user){ localUserService.register(user); return "注册用户成功"; } }
在 resources 文件夹下建立 application.yml:
dubbo: registry: address: zookeeper://192.168.40.170:2181
在 com.gcp 包下建立 DbConsumerApplication:
@SpringBootApplication @EnableDubbo public class DbConsumerApplication { public static void main(String[] args) { SpringApplication.run(DbConsumerApplication.class,args); } }
启动consumer的启动类,查看Zookeeper注册中心是否注册成功:
打开浏览器,输入consumer访问地址,测试是否能够正常访问:
后台输出:
consumer 子 Module:
provider 子 Module:
至此,项目搭建建立成功,你们能够本身多复制几个provider和consumer子Module的启动类,把端口都改为不同试试集群轮询、随机访问的效果。
具体代码详见GitHub仓库:点我跳转