zl程序教程

您现在的位置是:首页 >  后端

当前栏目

springcloud-模拟消费者-提供者之间调用的微服务(1)

SpringCloud模拟服务 调用 之间 消费者
2023-09-27 14:22:12 时间

一 概述

先创建一个父工程,然后后续的工程都以这个工程为父,实现 maven的聚合。这样可以在一个窗口看到所有工程,方便讲解。 在实际开发中,每个微服务可独立一个工程。

二 搭建工程

2.1 搭建父工程

1.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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 父模块 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
    <relativePath/>
  </parent>
  <!-- 本模块-->
  <groupId>com.scloud</groupId>
  <artifactId>scloud-demo</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>scloud-demo</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    <mapper.starter.version>2.1.5</mapper.starter.version>
    <mysql.version>5.1.46</mysql.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- springCloud -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>${spring-cloud.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <!-- 通用Mapper启动器 -->
    <dependency>
      <groupId>tk.mybatis</groupId>
      <artifactId>mapper-spring-boot-starter</artifactId>
      <version>${mapper.starter.version}</version>
    </dependency>
    <!-- mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
      </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

 2.2 搭建服务提供者

2.2.1 工程结构

2.2.2 配置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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 父模块 -->
   <parent>
     <groupId>com.scloud</groupId>
     <artifactId>scloud-demo</artifactId>
     <version>1.0-SNAPSHOT</version>
   </parent>
  <!-- 本模块-->
  <groupId>com.scloud</groupId>
  <artifactId>scloud-server-provider</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>scloud-server-provider</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <mapper.starter.version>2.1.5</mapper.starter.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 通用Mapper启动器 -->
    <dependency>
      <groupId>tk.mybatis</groupId>
      <artifactId>mapper-spring-boot-starter</artifactId>
      <version>${mapper.starter.version}</version>
    </dependency>
    <!-- mysql驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
  </dependencies>

  <build>
  </build>
</project>

2.2.3 代码编写

1.controller:

package com.scloud.controller;

import com.scloud.model.User;
import com.scloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User queryById(@PathVariable Long id){
        return userService.queryById(id);
    }
}

2.server层

接口:

package com.scloud.service;

import com.scloud.model.User;

public interface UserService {
    public User queryById(Long id);
}

实现类:

package com.scloud.service.impl;

import com.scloud.dao.UserMapper;
import com.scloud.model.User;
import com.scloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @ClassName: UserServiceImpl
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2021/09/12 18:43:05 
 * @Version: V1.0
 **/
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    /**
     * 根据主键查询用户
     * @param id 用户id
     * @return 用户
     */
    public User queryById(Long id){
        return userMapper.selectByPrimaryKey(id);
    }
}

3.dao

package com.scloud.dao;

import com.scloud.model.User;
import org.springframework.stereotype.Repository;
import tk.mybatis.mapper.common.Mapper;
@Repository
public interface UserMapper extends Mapper<User> {
}

4.model层

package com.scloud.model;

import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;

import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

@Data
@Table(name = "tb_user")
public class User{
    // id
    @Id
    //开启主键自动回填
    @KeySql(useGeneratedKeys = true)
    private Long id;

    // 用户名
    private String userName;

    // 密码
    private String password;

    // 姓名
    private String name;

    // 年龄
    private Integer age;

    // 性别,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 创建时间
    private Date created;

    // 更新时间
    private Date updated;

    // 备注
    private String note;
}

2.2.4 启动类

这里mapper用的是tx开头的包

package com.scloud;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

/**
 * Hello world!
 *
 */
@SpringBootApplication
@MapperScan("com.scloud.dao")
public class UserApplication
{
    public static void main(String[] args) {

        SpringApplication.run(UserApplication.class, args);
        System.out.println("服务端启动成功!!!");
    }
}

2.2.5 配置文件

server:
  port: ${port:9091}
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud
    username: root
    password: root
  application:
    name: user-service
mybatis:
  type-aliases-package: com.scloud.model

2.2.6 启动服务,访问

 地址:http://localhost:9091/user/1

2.3  消费者搭建

2.3.1 工程结构

 2.3.2  配置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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 父模块 -->
  <parent>
    <groupId>com.scloud</groupId>
    <artifactId>scloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>com.scloud</groupId>
  <artifactId>scloud-consumer</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>scloud-consumer</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>


</project>

 2.3.3  controller类

在controller类中编写,调用服务端的接口:http://localhost:9091/user/"+id;

package com.scloud.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/{id}")
    public String queryById(@PathVariable Long id){

        String url = "http://localhost:9091/user/"+id;
        return restTemplate.getForObject(url, String.class);
    }

}

 2.3.4  model

package com.scloud.model;

import lombok.Data;

import java.util.Date;

@Data
public class User {
    private Long id;

    // 用户名
    private String userName;

    // 密码
    private String password;

    // 姓名
    private String name;

    // 年龄
    private Integer age;

    // 性别,1男性,2女性
    private Integer sex;

    // 出生日期
    private Date birthday;

    // 创建时间
    private Date created;

    // 更新时间
    private Date updated;

    // 备注
    private String note;
}

 2.3.5  启动类

package com.scloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * Hello world!
 *
 */
//@SpringBootApplication
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class ConsumerApplication
{
    public static void main( String[] args )
    {

        SpringApplication.run(ConsumerApplication.class, args);
    }
    //初始化RestTemplate,后面调用
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

2.4  消费者调用提供者测试

http://localhost:8080/consumer/8

2.5  总结,这种方式的问题

scloud-service-provider :对外提供了查询用户的接口
scloud-consumer :通过 RestTemplate 访问 http://locahost:9091/user/{id} 接口,查询用户数据
存在问题:
1.在 consumer 中,我 们把url地址硬编码到了代码中,不方便后期维护
2.consumer需要记忆scloud-service-provider 的地址,如果出现变更,可能得不到通知,地址将失效
3.con sumer不清楚scloud-service-provider的状态,服务宕机也不知道
4.scloud-service-provider只有1台服务,不具备高可用性 即便scloud-service-provider形成集群, scloud-consumer还需自己实现负载均衡
通过上面的描述其实就是, 是分布式服务必然要面临的问题:
由1.2描述得出:
1. 如何自动注册和发现 2.如何实现状态监管;3.如何实现动态路由
由4得出:服务如何实现负载均衡
由3得出:服务如何解决容灾问题