tags: [dubbo, 分布式]
categories: [dubbo]
前言
关于分布式是什么我们为什么要弄分布式这里不赘述,这里只总结一下分布式项目从0搭建的方法和注意事项,本项目各个模块之间调用是基于Dubbo+Zookeeper来实现的
一般情况下我们都是按照服务来切分的,用以各个服务之间的解耦和切分部署,父项目为普通的Maven项目,删掉了源代码文件夹和资源文件夹,只留下光秃秃的pom.xml,来对各个服务依赖进行统筹管理
这里不使用SpringBoot作为父项项目的原因是因为SpringBoot总会继承自父项SpringBoot,子模块必然会继承相关依赖,建立空的Maven项目更加合适
代码地址
https://github.com/bwensun/Embryo/tree/master/BLOG
项目搭建
项目结构
BLOG├─ .gitignore├─ BLOG_API│ ├─ BLOG_API.iml│ ├─ pom.xml│ ├─ src│ │ └─ main│ │ └─ java├─ BLOG_USER_SERVICE│ ├─ BLOG_USER_SERVICE.iml│ ├─ pom.xml│ ├─ src│ │ ├─ main│ │ │ ├─ java│ │ │ └─ resources│ │ └─ test│ │ └─ java├─ BLOG_WEB│ ├─ BLOG_WEB.iml│ ├─ pom.xml│ ├─ src│ │ └─ main│ │ ├─ java│ │ └─ resources└─ pom.xml
项目建立
建立Maven项目父工程BLOG
正常输入GAV,groupId为项目名,artifactId为倒置的域名,版本号随意,我一般填入1.0,选择默认1.0快照版本也可以的
这里对项目的依赖做了统筹管理,在父pom中规定了依赖的版本,而子模块中只需写入GA信息即可,这样整个工程的依赖版本更迭时只需要修改父工程的依赖版本即可,另外父pom中也规定了整个项目共用了的依赖,通过依赖传递让子模块自动继承
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><packaging>pom</packaging><modules><module>BLOG_API</module><module>BLOG_USER_SERVICE</module><module>BLOG_WEB</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.bwensun</groupId><artifactId>blog</artifactId><version>0.0.1-SNAPSHOT</version><name>blog</name><description>个人博客项目</description><properties><java.version>1.8</java.version><main.class>com.bwensun.blog.BlogApplication</main.class><!--maven依赖版本控制--><mybatis-spring-boot-starter>1.3.0</mybatis-spring-boot-starter><dubbo-spring-boot-starter>0.2.0</dubbo-spring-boot-starter><mybatis-generator-core>1.3.7</mybatis-generator-core><druid-spring-boot-starter>1.1.10</druid-spring-boot-starter><mysql-connector-java>5.1.44</mysql-connector-java><lombok>1.16.18</lombok><pagehelper>5.1.10</pagehelper><springfox-swagger2>2.6.1</springfox-swagger2></properties><dependencyManagement><dependencies><dependency><groupId>com.bwensun</groupId><artifactId>BLOG_API</artifactId><version>${project.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis-spring-boot-starter}</version></dependency><dependency><groupId>com.alibaba.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>${dubbo-spring-boot-starter}</version></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>${mybatis-generator-core}</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid-spring-boot-starter}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector-java}</version></dependency></dependencies></dependencyManagement><!--公有依赖--><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok}</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper}</version></dependency><!-- swagger2 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${springfox-swagger2}</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${springfox-swagger2}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>${main.class}</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
建立BLOG_API模块**
在Dubbo官网服务化最佳实践中有提及,建议将服务接口、服务模型、服务异常等均放在 API 包中,我们也遵循其规范,右键项目New Module -> 名为BLOG_API和父项目类似,注意设置Maven Repository设置,版本号和父项目一致,可以从pom.xml中看到继承自父项目
API模块用于定义一些公有的实体类、工具类、异常类和服务接口,调用方引入该模块,通过接口调用服务而不用关心到底是哪一个Service是实现了该功能
建立完毕后注意执行mvn clean install 安装到本地仓库
<?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"><parent><artifactId>blog</artifactId><groupId>com.bwensun</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>BLOG_API</artifactId></project>
建立BLOG_USER_SERVICE模块和BLOG_Web模块
建立模块过程和之前方法一致
这里需要注意的是这两个项目我重新引入了SpringBoot相关的依赖,标记文件夹,并添加启动类,和配置文件使之成为一个单独的SpringBoot项目,用以启动和调用服务
Zookeeper的安装和启动连接:略
以下是pom.xml和application.yaml配置,启动类略
BLOG_USER_SERVICE模块**
pom.xml
<?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"><parent><artifactId>blog</artifactId><groupId>com.bwensun</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>BLOG_USER_SERVICE</artifactId><dependencies><dependency><groupId>com.bwensun</groupId><artifactId>BLOG_API</artifactId></dependency><dependency><groupId>com.alibaba.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId></dependency><!--druid连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies><build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.7</version><configuration><!--自定义路径,否则会自动识别GeneratorConfig.xml文件--><!-- <configurationFiile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>--><!--是为了运行mvn mybatis-generator:generate -e时显示具体过程--><verbose>true</verbose><!--为了生成文件时后一次生成的文件覆盖前一次生成的同名文件--><overwrite>true</overwrite></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.44</version></dependency></dependencies></plugin></plugins></build></project>
yaml
dubbo:application:name: boot-order-service-consumerregistry:#address: zookeeper://localhost:2181ipaddress: zookeeper://ip:2181?backup=47.103.215.103:2182,47.103.215.103:2183file: dubbo-registry/dubbo-registry.properties# monitor:# protocol: registryserver:port: 8081spring:profiles:include: druidmybatis:mapper-locations: classpath:mapper/*.xml
启动类
注意@EnableDubbo这个注解要加上
@SpringBootApplication@EnableDubbopublic class BlogUserServiceApplication {public static void main(String[] args) {SpringApplication.run(BlogUserServiceApplication.class, args);}}
BLOG_WEB模块
pom.xml
<?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"><parent><artifactId>blog</artifactId><groupId>com.bwensun</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>BLOG_WEB</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId></dependency><dependency><groupId>com.bwensun</groupId><artifactId>BLOG_API</artifactId></dependency></dependencies></project>
yaml
dubbo:application:name: boot-order-service-consumerregistry:address: zookeeper://IP:2181?backup=47.103.215.103:2182,47.103.215.103:2183file: dubbo-registry/dubbo-registry.properties# monitor:# protocol: registryserver:port: 8081
启动类
注意@EnableDubbo这个注解要加上
@SpringBootApplication@EnableDubbopublic class BlogWebApplication {public static void main(String[] args) {SpringApplication.run(BlogWebApplication.class, args);}}
写个Demo
BLOG_API添加实体类、接口
- 添加实体类
@Getter@Setter@ToStringpublic class User implements Serializable {/*** 主键*/private Integer id;/*** 用户名*/private String userName;/*** 密码*/private String password;private static final long serialVersionUID = 1L;}
添加服务接口
@Componentpublic interface UserService {/*** 用户信息分页查询* @return 分页用户对象*/PageInfo<User> getUserList();}
BLOG_USER_SERVICE实现该接口
- 实现该服务接口
注意:
Service为import ``com.alibaba.dubbo.config.annotation.``Service
@Component@Servicepublic class UserServiceImpl implements UserService {@ResourceUserMapper userMapper;@Overridepublic PageInfo<User> getUserList() {PageHelper.startPage(1, 10);List<User> users = userMapper.selectAll();return new PageInfo<>(users);}
- 具体Dao层略
BLOG_WEB添加控制器
@RestController@RequestMapping("user")public class UserController {@ReferenceUserService userService;@RequestMapping("userList")public PageInfo<User> getUserList(){return userService.getUserList();}}
测试
- 启动BLOG_USER_SERVICE项目来注册到ZK之中,控制台打印如下

- 启动BLOG_WEB项目,用于接受客户端的请求,同样他会连接ZK来获取服务

- 访问localhost:8081/user/userList可以发现已经接受了返回的查询结果

问题和解决
事实上,在实际测试中遇到了非常多问题,我把这些都记录下来,放到了
