目录

  • SpringCloud简介
  • SpringCloud的场景模拟
  • 创建父工程
  • 创建服务提供者
  • 创建服务调用者
  • 发现问题


SpringCloud简介

  • SpringCloud是Spring旗下的项目之一,官网地址:http://projects.spring.io/spring-cloud/Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。
  • SpringCloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等等功能。其主要涉及的组件包括:
  • Eureka:注册中心
  • Zuul:服务网关
  • Ribbon:负载均衡
  • Feign:服务调用
  • Hystix:熔断器
  • SpringCloud的版本命名比较特殊,因为它不是一个组件,而是许多组件的集合,它的命名是以A到Z的为首字母的一些单词组成:
  • spring el引擎 spring ul_spring el引擎

SpringCloud的场景模拟

创建父工程

  1. 创建一个新的工程
  2. 填写信息,然后核对,没有问题就一直next
  3. 创建成功后在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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lwb</groupId>
    <artifactId>cloud_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.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>Finchley.SR1</spring-cloud.version>
        <mapper.starter.version>2.0.3</mapper.starter.version>
        <mysql.version>5.1.32</mysql.version>
        <pageHelper.starter.version>1.2.5</pageHelper.starter.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--springCloud-->
            <dependency>
                <groupId>org.springfamework.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>
            <!--分页助手-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pageHelper.starter.version}}</version>
            </dependency>
            <!--mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <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>

创建服务提供者

  • 对外提供一个查询服务
  1. 点击父工程,右键,选择new module,创建子工程
  2. 点击next,填写子工程名称
  3. 点击next,查看路径是否正确,看一看子工程是否在父工程下面
  4. 点击finish
  5. 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>cloud_demo</artifactId>
        <groupId>com.lwb</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>userservice</artifactId>

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


</project>
  1. 在resource下创建springboot的配置文件application.yml
server:
  port: 8081
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/class
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 20
      minimum-idle: 10
mybatis:
  type-aliases-package: com.lwb.userservice.domain
  1. 在java文件下配置启动类
@SpringBootApplication
@MapperScan("com.lwb.userservice.mapper")//扫描指定包中的接口
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class);
    }
}
  1. 并且将配置和启动类中的包创建出来
  2. 创建实体类
@Table(name = "user")
public class User implements Serializable{

    @Id
    private String id;

    private String name;
    private String password;
    private String email;
    private String telephone;
    private Integer root;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Integer getRoot() {
        return root;
    }

    public void setRoot(Integer root) {
        this.root = root;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", telephone='" + telephone + '\'' +
                ", root=" + root +
                '}';
    }
}
  1. 创建UserMapper接口(内置了增删改查的接口)
@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User>{
}
  1. 创建service对象
@Service
public class UserService {

    @Autowired
    public UserMapper userMapper;

    public User findById(String id){
        return userMapper.selectByPrimaryKey(id);
    }
}
  1. 创建Controller对象
//如果在Controller添加了@RestController注解,那么Controller层的方法中无法重定向到jsp或者html页面,其返回的内容就是自定义的内容。
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/{id}")
    public User findById(@PathVariable("id")String id){
        return userService.findById(id);
    }
}
  1. 启动测试

创建服务调用者

  • 创建工作与上述差不多
  1. pom.xml的配置,因为是调用,所以只需要注入web依赖
<?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.lwb</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer</artifactId>

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


</project>
  1. 创建启动类
@SpringBootApplication
public class ConsumeApplication {


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

    public static void main(String[] args) {
        SpringApplication.run(ConsumeApplication.class);
    }
}
  1. 创建实体类
public class User implements Serializable{

    private String id;

    private String name;
    private String password;
    private String email;
    private String telephone;
    private Integer root;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Integer getRoot() {
        return root;
    }

    public void setRoot(Integer root) {
        this.root = root;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                ", telephone='" + telephone + '\'' +
                ", root=" + root +
                '}';
    }
}
  1. 创建controller对象远程调用userservice
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("{id}")
    public User findById(@PathVariable("id")String id){
        String url = "http://localhost:8081/user"+id;
        User user = restTemplate.getForObject(url,User.class);
        return user;
    }
}
  1. 启动测试

发现问题

  1. 回顾一下,刚才的流程:
  • use-service-demo:一个提供根据id查询用户的微服务
  • consumer-demo:一个服务调用者,通过RestTemplate远程调用user-service-demo
  1. 发现存在一些问题
  • 在consumer中,我们把url地址硬编码到了代码中,不方便后期维护
  • consumer需要记忆user-service的地址,如果出现变更,可能得不到通知,地址将失效
  • consumer不清楚user-service的状态,服务宕机也不知道
  • user-service只有1台服务,不具备高可用性
  • 即便user-service形成集群,consumer还需自己实现负载均衡
  1. 将问题整合,主要分为以下几类
  • 服务管理
  • 如何自动注册和发现
  • 如何实现状态监管
  • 如何实现动态路由
  • 服务如何实现负载均衡
  • 服务如何解决容灾问题
  • 服务如何实现统一配置