2.微服务介绍与环境搭建

155 阅读4分钟

1. 微服务介绍

以往单体架构问题:

  • 各个模块耦合,一个模块出现问题会影响其他模块
  • 无法针对各个模块做单独优化和水平扩展

微服务架构,就是用来解决上面单体架构的问题。拆分成可独立打包部署运行的多个服务,并且各个服务可以独立优化以及水平扩展。

2. 微服务环境搭建

2.1模块划分

  • smart-parent父工程

  • smart-common公共模块,引入mysql驱动依赖、mybatis-plus依赖

  • smart-business业务微服务【端口:8070】,会调用设备微服务

  • smart-device设备微服务【端口:8080】,被业务服务调用

我们的业务流程:业务微服务订阅MQTT接收设备上报的数据,然后要调用device微服务查询设备绑定的用户,最后记录设备数据(设备mac地址、userId、状态数据)。

2.2 创建父工程

pom.xml文件中添加:

<!--添加spring-boot-starter-parent依赖 -->
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.1.3.RELEASE</version>
</parent>


<groupId>org.example</groupId>
<artifactId>smart-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>smart-parent</name>


<!--定义spring cloud版本、spring cloud alibaba版本-->
<properties>
   <java.version>1.8</java.version>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   <project.reporting.outputEncoding>UTF8</project.reporting.outputEncoding>
   <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
   <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
</properties>


<!--spring cloud依赖、spring cloud alibaba依赖-->
<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-dependencies</artifactId>
         <version>${spring-cloud.version}</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
      <dependency>
         <groupId>com.alibaba.cloud</groupId>
         <artifactId>spring-cloud-alibaba-dependencies</artifactId>
         <version>${spring-cloud-alibaba.version}</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
   </dependencies>
</dependencyManagement>

【注意】:需要注意各个版本对应关系

各个版本对应关系

2.3 创建smart-common公共模块

在pom.xml中添加:

  <!--父级工程-->
  <parent>
    <groupId>org.example</groupId>
    <artifactId>smart-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <!--基础依赖-->
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>smart-common</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>smart-common</name>

  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.56</version>
    </dependency>
    <!--mysql依赖-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
    <!--mybatis-plus依赖-->
     <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.2.0</version>
    </dependency>
  </dependencies>

2.4 创建smart-device业务微服务

pom.xml中添加:

  • smart-common依赖
  • spring-boot-starter-web依赖
<parent>
    <groupId>org.example</groupId>
    <artifactId>smart-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>smart-device</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>smart-device</name>


  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.example</groupId>
      <artifactId>smart-common</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>

创建工程启动类

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

创建配置类,主要是配置DataSource数据源和mybatis-plus

server:
  port: 8080
spring:
  application:
    name: smart-device
  # 配置DataSource数据源
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.56.200:3306/device?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: password


# mybatis-plus配置
# 配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 配置逻辑删除
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
  # 指定mapper.xml文件位置
  mapper-locations: classpath:mapper/*.xml

创建表对应的实体类

/**
 * @description:
 * @author:xg
 * @date: 2024/12/6
 * @Copyright:
 */
@TableName("tb_device")
public class DevicePO {

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 物理地址
     */
    private String physicalAdd;

    /**
     * 设备名称
     */
    private String deviceName;

    /**
     * 设备绑定的用户id
     */
    private Integer userId;

    private Date createTime;

}

创建Mapper接口


/**
 * @description:
 * @author:xg
 * @date: 2024/12/6
 * @Copyright:
 */
@Mapper
public interface DeviceMapper extends BaseMapper<DevicePO> {
}

创建DeviceService接口以及实现类

/**
 * @description:
 * @author:xg
 * @date: 2024/12/7
 * @Copyright:
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    @Resource
    private DeviceMapper deviceMapper;

    /**
     * 根据设备mac地址查询
     * @param physicalAdd
     * @return
     */
    @Override
    public DeviceVO findByPhysicalAdd(String physicalAdd) {
        LambdaQueryWrapper<DevicePO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DevicePO::getPhysicalAdd, physicalAdd);
        DevicePO devicePO = deviceMapper.selectOne(lambdaQueryWrapper);
        DeviceVO deviceVO = new DeviceVO();
        BeanUtils.copyProperties(devicePO, deviceVO);
        return deviceVO;
    }
}

创建接口

/**
 * @description:
 * @author:xg
 * @date: 2024/12/7
 * @Copyright:
 */
@RestController
@RequestMapping("/device")
public class DeviceController {

    @Resource
    private DeviceService deviceService;

    /**
     * 根据mac地址,获取设备信息(包括设备绑定的userID)
     * @param physicalAdd
     * @return
     */
    @GetMapping("/get/{physicalAdd}")
    public DeviceVO get(@PathVariable("physicalAdd") String physicalAdd) {

        return deviceService.findByPhysicalAdd(physicalAdd);
    }
}

最后,我们在DB的tb_device表中填充数据,访问device/get接口,查看到结果。

访问device/get接口

2.5 创建业务微服务

新建smart-business模块,在pom.xml中引入common公共依赖

 <parent>
        <artifactId>smart-parent</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>smart-business</artifactId>
    <name>smart-business</name>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>smart-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

创建启动类


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

创建配置文件,配置数据源和mybatis-plus



server:
  port: 8070
spring:
  application:
    name: smart-business
  # 配置数据源地址
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.56.200:3306/business?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: password


# mybatis-plus配置
# 配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 配置逻辑删除
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
  # 指定mapper.xml文件位置
  mapper-locations: classpath:mapper/*.xml

创建mapper接口类

/**
 * @description:
 * @author:xg
 * @date: 2024/12/6
 * @Copyright:
 */
@Mapper
public interface DeviceDataMapper extends BaseMapper<DeviceDataPO> {
}

创建DeviceDataService接口以及实现类,用于存储设备上报的数据。

/**
 * @description:
 * @author:xg
 * @date: 2024/12/7
 * @Copyright:
 */
@Service
public class DeviceDataServiceImpl implements DeviceDataService {

    @Resource
    private DeviceDataMapper deviceDataMapper;

    @Override
    public void save(DeviceDataDTO deviceDataDTO) {
        DeviceDataPO deviceDataPO = new DeviceDataPO();
        BeanUtils.copyProperties(deviceDataDTO, deviceDataPO);
        deviceDataMapper.insert(deviceDataPO);
    }
}

创建RestTemplate,用于调用device服务。

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

    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

创建业务接口,远程调用device服务获取设备绑定的userid,然后在存储设备数据到DB。

/**
 * @description:
 * @author:xg
 * @date: 2024/12/8
 * @Copyright:
 */
@RestController
@RequestMapping("/deviceData")
@Slf4j
public class DeviceDataController {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private DeviceDataService deviceDataService;

    @PostMapping("/save")
    public Boolean save(@RequestBody @Valid DeviceDataDTO deviceDataDTO) {
        // 通过RestTemplate调用device服务获取设备绑定的userId
        DeviceVO deviceVO = restTemplate.getForObject(
                "http://127.0.0.1:8080/device/get/" + deviceDataDTO.getPhysicalAdd(),
                DeviceVO.class);
        log.info("设备信息:{}", JSON.toJSONString(deviceVO));
        // 存储设备数据到DB
        deviceDataDTO.setUserId(deviceVO.getUserId());
        deviceDataService.save(deviceDataDTO);
        return true;
    }
}

调用设备数据存储接口

设备数据存储接口

可以看到业务服务调用设备服务获取到了设备信息

2024-12-08 11:53:16.236  INFO 37100 --- [nio-8070-exec-2] o.e.controller.DeviceDataController      : 设备信息:{"createTime":1733571060000,"deviceName":"设备1","id":1,"physicalAdd":"a1","userId":1}