0
点赞
收藏
分享

微信扫一扫

2.服务拆分和服务调用


2.1 服务拆分原则

  • 不同微服务,不要重复开发相同业务;
  • 微服务数据独立,不要访问其它微服务的数据库;
  • 微服务可以将自己的业务暴露为接口,供其它微服务调用。

2.服务拆分和服务调用_maven

2.2 服务拆分案例

这里以黑马的微服务cloud-demo为例,进行项目复用。

cloud-demo:父工程,管理依赖

  • order-service:订单微服务,负责订单相关业务;
  • user-service:用户微服务,负责用户相关业务;

要求

  • 订单微服务和用户微服务必须有各自的数据库,相互独立;
  • 订单服务和用户服务都对外暴露Restful的接口;
  • 订单服务如果要查询用户信息,只能调用用户服务的Restful接口,不能查询用户数据库。

2.2.1 从零开始搭建SpringCloud项目

创建项目:

首先在Idea中new一个Maven项目,在GroupId中填入包名,ArtifastId填写项目名,然后选择电脑中一个文件夹来创建该项目。

2.服务拆分和服务调用_maven_02

创建好的项目如下:

2.服务拆分和服务调用_maven_03

由于主项目中,我们是不写代码的,因此将该项目中的src包直接删除,再导入order-service和user-service模块。

2.服务拆分和服务调用_maven_04

导入项目依赖:

导入父项目依赖

<?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.ku</groupId>
    <artifactId>cloud-demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>
    <modules>
        <module>order-service</module>
        <module>user-service</module>
    </modules>

    <!--父依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>

    <!--依赖属性-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <!--<mysql.version>5.1.47</mysql.version>-->
        <!--<mybatis.version>2.1.1</mybatis.version>-->
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--nacos的管理依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.17</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>

</project>

父级依赖

导入order-service项目依赖

<?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>cloud-demo</artifactId>
        <groupId>com.ku</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <!--打包-->
    <build>
        <finalName>order-app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

order-service服务依赖

导入user-service项目依赖

<?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>cloud-demo</artifactId>
        <groupId>com.ku</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <!--打包-->
    <build>
        <finalName>user-app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

user-service服务依赖

创建两个服务模块结构流程:

  • 分别创建OrderServiceApplication和UserServiceApplciation两个启动类
  • 创建order-service和user-service的四层结构(pojo、mapper、service、controller,其中Order类中引入User类,后面会改进)
  • 首先创建两个模块的数据库,然后执行两个模块的SQL语句,生成对应的数据表
  • 分别配置两个模块的application.yml文件

#order-service配置文件
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: com.ku.order.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.ku.order: debug

order-service的application.xml配置文件

#user-service配置文件
server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: cn.ku.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.ku.user: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS

user-service的application.yaml配置文件

在启动多模块项目的时候,会出现以下弹窗,我们点集弹窗,选择第一个,就会出现多模块运行窗口了

2.服务拆分和服务调用_mysql_05

2.服务拆分和服务调用_spring_06

2.服务拆分和服务调用_spring_07

2.3 实现远程调用案例

2.3.1 Order-service查询测试

2.服务拆分和服务调用_maven_08

当我们通过订单号区查询订单信息的时候,由于我们的订单数据库中只存储了用户ID,且每个服务之间是相互独立的,因此无法查询到用户相关信息。

2.3.2 RestTenplate远程调用流程

在上一节中,我们由于服务模块之间相互独立,通过order模块无法查询到用户模块的用户信息,本节我们将通过远程调用,通过user-service暴露的接口查询出订单实体类中的是所有属性信息。

我们需要在order-service中向user-service发起一个http请求,调用http://localhost:8081/user/{userId}这个接口。

  • 注册一个RestTemplate的实例到Spring容器中,即向OrderServiceApplication注册一个RestTemplate的bean;
  • 修改order-service服务中的queryOrderById方法,根据Order对象中的uerId查询User;
  • 将查询的User填充到Order对象中,一起返回。

2.3.3 注册 RestTenplate

我们需要在order-service的OrderServiceApplication启动类中,注册RestTemplate实例

@MapperScan("com.ku.order.mapper")
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

    //远程调用
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
2.3.4 实现远程调用
修改order-service服务中的com.ku.order.service中OrderService类中的queryOrderById()方法

public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起http请求,查询用户
        // 2.1.url路径
        String url = "http://localhost:8081/user/" + order.getUserId();
        // 2.2.发送http请求,实现远程调用
        User user = restTemplate.getForObject(url, User.class);
        // 3.封装user到Order
        order.setUser(user);
        // 4.返回
        return order;
    }

RestTemplate远程调用

上述代码重点在于RestTemplate对象通过传入的url和希望获取的实体类到getForObject()方法从而获取用户模块的用户信息。

测试结果

2.服务拆分和服务调用_mysql_09

小结:

  • 基于RestTemplate发起的Http请求实现远程调用;
  • http请求做远程调用是与语言无关的调用,只要知道对方的ip、端口、接口路径、请求参数即可。

2.4 提供者与消费者

在服务调用关系中,会有两个不同的角色:

服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)

服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)

但是,服务提供者与服务消费者的角色并不是绝对的,而是相对于业务而言。

思考:如果服务A调用了服务B,而服务B又调用了服务C,服务B的角色是什么?

对于A调用B的业务而言:A是服务消费者,B是服务提供者对于B调用C的业务而言:B是服务消费者,C是服务提供者因此,服务B既可以是服务提供者,也可以是服务消费者。

服务调用关系:

  • 服务提供者:暴露接口给其他服务调用
  • 服务消费者:调用其他微服务提供的接口
  • 提供者与消费者是相对的
  • 一个服务可以同时是服务提供者和服务消费者



举报

相关推荐

0 条评论