分布式--使用Dubbo搭建分布式项目

2022-06-19 14:47:42 浏览数 (1)

在分布式架构中,我们会将不同功能模块化,部署到不同的服务器上,这时不同模块之间的通讯就由RPC框架完成,上次介绍了Dubbo的基本使用,知道了它基于Spring容器,因此在SpringBoot项目中可以很方便的使用

一、项目配置

还是利用经典的oracle部门员工表,MyBatis--初入MyBatis中可以找到创建表和数据的sql,实现mapper层和service层的分布式架构

项目依赖关系如下:

consumer最终通过Dubbo进行RPC通讯,调用provider提供的方法

创建Maven聚合项目,设置父Maven模块的pom文件为:

代码语言:javascript复制
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.7.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.7.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>2.7.8</version>
            </dependency>
            <dependency>
                <groupId>org.apache.curator</groupId>
                <artifactId>curator-recipes</artifactId>
                <version>4.2.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>  
1. bean模块

公共的模块,被所有模块引用

导入lombok依赖:

代码语言:javascript复制
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

创建包:

2. mapper模块

用于编写mapper层相关的代码

2.1 依赖

pom文件中导入bean模块Mybatis相关依赖

代码语言:javascript复制
        <!--mybatis启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--mysql jdbc-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.9</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!--bean模块-->
        <dependency>
            <groupId>com.aruba</groupId>
            <artifactId>bean</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
2.2 springboot配置文件

resources目录下创建application-mybatis.yml:

代码语言:javascript复制
# 使用mybatis-plus配置类别名
mybatis-plus:
  type-aliases-package: com.aruba.bean
  configuration:
    map-underscore-to-camel-case: true

spring:
  datasource:
    # 使用阿里的Druid连接池
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 填写你数据库的url、登录名、密码和数据库名
    url: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
  druid:
    # 连接池的配置信息
    # 初始化大小,最小,最大
    initial-size: 5
    min-idle: 5
    maxActive: 20
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,slf4j
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    # 配置DruidStatFilter
    web-stat-filter:
      enabled: true
      url-pattern: "/*"
      exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
    # 配置DruidStatViewServlet
    stat-view-servlet:
      url-pattern: "/druid/*"
      # IP白名单(没有配置或者为空,则允许所有访问)
      allow: 127.0.0.1,192.168.8.109
      # IP黑名单 (存在共同时,deny优先于allow)
      deny: 192.168.1.188
      #  禁用HTML页面上的“Reset All”功能
      reset-enable: false
      # 登录名
      login-username: admin
      # 登录密码
      login-password: 123456
2.3 日志配置

resources目录下创建logback.xml:

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="${catalina.base}/logs/"/>
    <!-- 控制台输出 -->
    <appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 日志输出格式 -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
            </pattern>
        </layout>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <layout class="ch.qos.logback.classic.PatternLayout">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
            </pattern>
        </layout>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!-- 日志输出级别 -->
    <root level="info">
        <appender-ref ref="Stdout"/>
        <!--暂时不需要输出到文件-->
        <!--<appender-ref ref="RollingFile"/>-->
    </root>

    <logger name="com.aruba.mapper" level="DEBUG"></logger>


    <!--日志异步到数据库 -->
    <!--<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
            日志异步到数据库
            <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
               连接池
               <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
                  <driverClass>com.mysql.jdbc.Driver</driverClass>
                  <url>jdbc:mysql://127.0.0.1:3306/databaseName</url>
                  <user>root</user>
                  <password>root</password>
                </dataSource>
            </connectionSource>
      </appender> -->

</configuration>

创建包:

3. api模块

用于定义Provider的对外接口

导入bean模块依赖:

代码语言:javascript复制
        <dependency>
            <groupId>com.aruba</groupId>
            <artifactId>bean</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
4. provider模块

远程对象提供者

4.1 依赖

导入mapper模块、api模块、dubbo相关依赖:

代码语言:javascript复制
        <!--springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--dubbo-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!--zookeeper-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>
        <!--mapper模块-->
        <dependency>
            <groupId>com.aruba</groupId>
            <artifactId>mapper</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--api模块-->
        <dependency>
            <groupId>com.aruba</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
4.2 springboot配置文件

配置dubbo相关,以及引入mapper模块中的配置:

代码语言:javascript复制
dubbo:
  application:
    name: dubbo-provider
  registry:
    address: zookeeper://192.168.42.4:2181

# 加载其他配置文件,加载其他application-*.yml文件,多个名称之间使用逗号分隔
spring:
  profiles:
    active: mybatis
4.3 SpringBoot启动类

创建包:

创建启动类,开启Dubbo、Mapper扫描:

代码语言:javascript复制
@SpringBootApplication
@EnableDubbo
@MapperScan("com/aruba/mapper")
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

}
5. 项目结构

完成上面步骤后,项目结构如下:

二、实现分布式项目RPC通讯

实现查询部门信息,并展示到网页上

1. bean模块下创建部门类

内容为:

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept implements Serializable {
    /**
     * 部门编号
     */
    private Integer deptno;
    /**
     * 部门名称
     */
    private String dname;
    /**
     * 地址
     */
    private String loc;
}
2. api模块中新增查询接口

内容为:

代码语言:javascript复制
public interface DubboDeptService {
    public List<Dept> findAllDept();
}
3. mapper模块中新增DeptMapper

内容为:

代码语言:javascript复制
public interface DeptMapper extends BaseMapper<Dept> {
}
4. provider模块中实现对外接口

内容为:

代码语言:javascript复制
@DubboService
public class DubboDeptServiceImpl implements DubboDeptService {

    @Autowired
    private DeptMapper deptMapper;

    @Override
    public List<Dept> findAllDept() {
        Wrapper<Dept> queryWrapper = new QueryWrapper<>();

        return deptMapper.selectList(queryWrapper);
    }

}

注意需要@DubboService注解,表示注册到Dubbo中

5. 新建dept模块

业务模块代码编写

5.1 依赖

导入springweb依赖、dubbo、api模块等:

代码语言:javascript复制
        <!--web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--dubbo-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <!--zookeeper-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--api模块-->
        <dependency>
            <groupId>com.aruba</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
5.2 springboot配置文件

配置dubbo:

代码语言:javascript复制
dubbo:
  application:
    name: dubbo-dept-consumer
  registry:
    address: zookeeper://192.168.42.4:2181
5.3 springboot启动类

开启dubbo:

代码语言:javascript复制
@SpringBootApplication
@EnableDubbo
public class DeptApplication {

    public static void main(String[] args) {
        SpringApplication.run(DeptApplication.class, args);
    }

}
5.4 service层代码

定义接口:

代码语言:javascript复制
public interface DeptService {

    public List<Dept> findAllDept();

}

实现接口,使用provider对外对象进行调用获取部门信息:

代码语言:javascript复制
@Service
public class DeptServiceImp implements DeptService {

    @DubboReference
    private DubboDeptService dubboDeptService;

    @Override
    public List<Dept> findAllDept() {
        return dubboDeptService.findAllDept();
    }
    
}
5.5 controller层代码
代码语言:javascript复制
@Controller
public class DeptController {

    @Autowired
    private DeptService deptService;


    @RequestMapping("dept")
    public String dept(Model model) {
        model.addAttribute("deptList", deptService.findAllDept());
        return "dept";
    }

}
5.6 html展示

resources目录下新建templates文件夹,并创建一个html文件:

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    #tb {
        border: burlywood 1px solid;
        width: 50%;
        margin: 0 auto;
    }

    #tb th, td {
        border: 1px solid bisque;
        text-align: center;
    }
</style>
<body>
<table id="tb" cellpadding="0px" cellspacing="0px">
    <tr>
        <th>编号</th>
        <th>部门名称</th>
        <th>地址</th>
    </tr>
    <tr th:each="dept : ${deptList}">
        <td th:text="${dept.deptno}"></td>
        <td th:text="${dept.dname}"></td>
        <td th:text="${dept.loc}"></td>
    </tr>
</table>
</body>
</html>

启动provider和dept的springboot,并进行浏览器访问:

数据库日志打印是provider输出的:

项目地址:

https://gitee.com/aruba/dubbo.git

0 人点赞