SpringCloud(微服务)全套入门教程

源码地址:https://github.com/GeeCoder-zyl/springcloud
请注意:源码与教程有出入,现源码将服务提供者中的mapper、service、serviceImpl包全部移到了api模块中。

#前言#

1、Spring Cloud简介

Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud0 CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目。

2、微服务架构

微服务(Microservices Architecture)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。

微服务的概念源于2014年3月Martin Fowler所写的章“Microservices”http://martinfowler.com/articles/microservices.html

3、微服务设计

那我们在微服务中应该怎样设计呢。以下是微服务的设计指南:

  • 职责单一原则(Single Responsibility Principle):把某一个微服务的功能聚焦在特定业务或者有限的范围内会有助于敏捷开发和服务的发布。
  • 设计阶段就需要把业务范围进行界定。
  • 需要关心微服务的业务范围,而不是服务的数量和规模尽量小。数量和规模需要依照业务功能而定。
  • 于SOA不同,某个微服务的功能、操作和消息协议尽量简单。
  • 项目初期把服务的范围制定相对宽泛,随着深入,进一步重构服务,细分微服务是个很好的做法。

一、服务注册与发现(Eureka)

1、服务治理

由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。

2、Spring Cloud Eureka

Spring Cloud Eureka来实现服务治理。

Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。

3、创建springcloud父项目

创建maven项目

SpringCloud(微服务)全套入门教程_第1张图片

SpringCloud(微服务)全套入门教程_第2张图片

4、添加maven依赖

<!--导入springBoot依赖包 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
    <relativePath/>
</parent>
<properties>
    <java.version>1.8</java.version>
</properties>
<!--依赖管理,用于管理spring-cloud的依赖 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

<dependencies>
    <!--导入springCloudjar包 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream</artifactId>
    </dependency>

    <!--引入springBoot jar包 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!--支持热部署 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
        <version>1.2.8.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>

    <!--整合redis -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
    </dependency>

    <!--导入pojo插件 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--使用druid整合mysql数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!--阿里数据源 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
    </dependency>

    <!--mybatis-plus配置 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.0.6</version>
    </dependency>

    <!--引入springBoot监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

5、创建springcloud-eureka-7000子项目

在springcloud项目上创建新的Modul

SpringCloud(微服务)全套入门教程_第3张图片

父项目选择springcloud

SpringCloud(微服务)全套入门教程_第4张图片

6、添加maven依赖

<dependencies>
    <!--添加 eureka 注册中心 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
</dependencies>

7、创建yml配置文件

SpringCloud(微服务)全套入门教程_第5张图片

server:
  port: 7000                      #定义注册中心端口
eureka:
  server:
    enable-self-preservation: true  #设定自我保护模式 默认值为true 不建议关闭
  instance:
    hostname: localhost        #eureka服务的实例名称
  client:
    register-with-eureka: false   #表示注册中心不会注册自己本身
    fetch-registry: false         #表示自己就是注册中心,不需要检索服务
    service-url:  
      defaultZone: http://${
     eureka.instance.hostname}:${
     server.port}/eureka/     

8、创建服务启动类

在这里插入图片描述

package com.zyl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication(exclude = {
     DataSourceAutoConfiguration.class})
@EnableEurekaServer//定义为Eureka服务端
public class Eureka_7000 {
     

    public static void main(String[] args) {
     

        SpringApplication.run(Eureka_7000.class, args);
    }
}

9、启动服务,访问Eureka页面

SpringCloud(微服务)全套入门教程_第6张图片

10、创建springcloud-api子项目

该项目主要定义公用实体类、公用的对象方法接口、公用fallback类

SpringCloud(微服务)全套入门教程_第7张图片

11、添加maven依赖

<dependencies>
    <!--引入Feign支持  -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

12、创建pojo实体类

SpringCloud(微服务)全套入门教程_第8张图片

通过lombok插件生成实体类的getter和setter方法等,使用前请参照各IED教程安装lombok插件。

package com.zyl.springcloud.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.io.Serializable;

/**
 * @ClassName: User
 * @Description: 描述
 * @author: ZYL
 * @date: 2020/7/2 17:42
 */
@Data//开启lombok
@Accessors(chain = true)//开启级联操作,为true时setter方法返回当前对象
@ToString//生成toString()方法
@TableName(value = "tb_user")//开始mybatis-plus表映射,当表名与类名不一样时,需要配置value属性
public class User implements Serializable {
     

    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

二、服务提供者

1、创建springcloud-provider-8001子项目

SpringCloud(微服务)全套入门教程_第9张图片

2、添加maven依赖

<dependencies>
    <dependency>
        <groupId>com.zyl.springcloud</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

    <!--添加eureka 客户端地址 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

    <!--添加断路器配置 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

    <!--添加监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

3、创建yml配置文件

server:
  port: 8001
  servlet:
    context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   #引入druid数据源
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: 123456

  application:
    name: provider-user                            #定义服务名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka    #注册到指定的eureka
  instance:
    instance-id: provider-user-8001                #定义微服务的名称
    prefer-ip-address: true                        #是否显示IP和端口

#mybatis-plush配置
mybatis-plus:
  type-aliases-package: com.zyl.springcloud.pojo       #配置别名包路径
    mapper-locations: classpath:/mybatis/mappers/*.xml #添加mapper映射文件
  configuration:
    map-underscore-to-camel-case: true                #开启驼峰映射规则

feign:
  hystrix:
    enabled: true                        #启动熔断器机制

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000  #设定断路器超时时间

4、创建服务启动类

SpringCloud(微服务)全套入门教程_第10张图片

package com.zyl.springcloud;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

/**
 * @className: Provider_8001
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/3 13:55
 */
@SpringBootApplication//声明为SpringBoot应用
@MapperScan("com.zyl.springcloud.mapper")//扫描数据库映射文件
@EnableEurekaClient//注册到Eureka注册中心
@EnableHystrix//开启断路器机制
public class Provider_8001 {
     

    public static void main(String[] args) {
     

        SpringApplication.run(Provider_8001.class, args);
    }
}

5、创建mapper接口

继承mybatis-plus提供的BaseMapper,其提供基本的crud操作

package com.zyl.springcloud.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyl.springcloud.pojo.User;

/**
 * @className: UserMapper
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/3 13:55
 */
public interface UserMapper extends BaseMapper<User>{
     

}

6、创建service接口

package com.zyl.springcloud.service;

import com.zyl.springcloud.pojo.User;

import java.util.List;

/**
 * @className: UserService
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/3 14:03
 */
public interface UserService {
     

    //获取所有用户的信息
    List<User> getAllUser();

    //根据用户名获取用户信息
    User getUserByName(String name);

    //新增用户
    int addUser(User user);

    //删除用户
    int deleteUser(Integer id);

    //修改用户信息
    int updateUser(User user);
}

7、创建serviceImp类

注意QueryWrapper的使用

package com.zyl.springcloud.serviceImp;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyl.springcloud.mapper.UserMapper;
import com.zyl.springcloud.pojo.User;
import com.zyl.springcloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @className: UserServiceImp
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/3 14:04
 */
@Service
public class UserServiceImp implements UserService {
     

    @Autowired(required = false)
    public UserMapper userMapper;

    //获取所有用户的信息
    @Override
    public List<User> getAllUser() {
     
        List<User> userList = userMapper.selectList(null);
        return userList;
    }

    //根据用户名获取用户信息
    @Override
    public User getUserByName(String name) {
     
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        User user = userMapper.selectOne(queryWrapper);
        return user;
    }

    //新增用户
    @Override
    public int addUser(User user) {
     
        int num = userMapper.insert(user);
        return num;
    }

    //删除用户
    @Override
    public int deleteUser(Integer id) {
     
        int num = userMapper.deleteById(id);
        return num;
    }

    //修改用户信息
    @Override
    public int updateUser(User user) {
     
        int num = userMapper.updateById(user);
        return num;
    }
}

8、创建controller类

package com.zyl.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zyl.springcloud.pojo.User;
import com.zyl.springcloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @className: UserController
 * @description: 服务提供者控制器
 * @author: ZYL
 * @date: 2020/7/3 14:11
 */
@RestController//使用RESTful风格    
public class UserController {
     

    @Autowired
    private UserService userService;

    //获取所有用户的信息
    @GetMapping("/getAllUser")
    @HystrixCommand(fallbackMethod = "getAllUser")
    public List<User> getAllUser() {
     
        List<User> userList = userService.getAllUser();
        return userList;
    }

    //根据用户名获取用户信息
    @GetMapping("/getUserByName/{name}")
    @HystrixCommand(fallbackMethod = "getUserByName")
    public User getUserByName(@PathVariable String name) {
     
        User user = userService.getUserByName(name);
        return user;
    }

    //新增用户
    @PostMapping("/addUser/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod = "addUser")
    public int addUser(User user) {
     
        int num = userService.addUser(user);
        return num;
    }

    //删除用户
    @DeleteMapping("/deleteUser/{id}")
    @HystrixCommand(fallbackMethod = "deleteUser")
    public int deleteUser(@PathVariable Integer id) {
     
        int num = userService.deleteUser(id);
        return num;
    }

    //修改用户信息
    @PutMapping("/updateUser/{id}/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod = "updateUser")
    public int updateUser(User user) {
     
        int num = userService.updateUser(user);
        return num;
    }

}

9、启动提供者服务,访问服务提供者页面

SpringCloud(微服务)全套入门教程_第11张图片

得到后端返回的json数据

SpringCloud(微服务)全套入门教程_第12张图片

三、服务消费者(Feign方式实现)

1、Ribbon简介

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。

2、Ribbon的核心组件

均为接口类型,有以下几个

ServerList

  • 用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

ServerListFilter

  • 仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

IRule

  • 选择一个最终的服务地址作为LB结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。

Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

3、Ribbon提供的主要负载均衡策略介绍

简单轮询负载均衡(RoundRobin)

以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。

随机负载均衡 (Random)

随机选择状态为UP的Server

加权响应时间负载均衡 (WeightedResponseTime)

根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。

区域感知轮询负载均衡(ZoneAvoidanceRule)

复合判断server所在区域的性能和server的可用性选择server

4、Feign简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。

使用Feign,只需要创建一个接口并注解,它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解,Feign支持可插拔的编码器和解码器,Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

Feign 具有如下特性:

  • 可插拔的注解支持,包括Feign注解和JAX-RS注解
  • 支持可插拔的HTTP编码器和解码器
  • 支持Hystrix和它的Fallback
  • 支持Ribbon的负载均衡
  • 支持HTTP请求和响应的压缩Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。它整合了RibbonHystrix,从而不再需要显式地使用这两个组件。Feign还提供了HTTP请求的模板,通过编写简单的接口和注解,就可以定义好HTTP请求的参数、格式、地址等信息。接下来,Feign会完全代理HTTP的请求,我们只需要像调用方法一样调用它就可以完成服务请求。

简而言之:Feign能干RibbonHystrix的事情,但是要用RibbonHystrix自带的注解必须要引入相应的jar包才可以。

5、创建springcloud-consumer-8020子项目

SpringCloud(微服务)全套入门教程_第13张图片

6、添加maven依赖

<dependencies>
    <dependency>
        <groupId>com.zyl.springcloud</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

    <!--Eureka客户端配置 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--引入Feign支持 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!--添加断路器配置 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--添加监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

7、创建yml配置文件

server:
  port: 8020
  servlet:
    context-path: /

spring:
  application:
    name: consumer-user                          #定义服务名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka #链接注册中心集群
  instance:
    instance-id: consumer-user-8020             #定义微服务的名称
    prefer-ip-address: true                     #是否显示IP和端口

feign:
  hystrix:
    enabled: true                               #启动熔断器机制

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000        #设定断路器超时时间

8、创建服务启动类

package com.zyl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @className: Consumer_8020
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/3 15:40
 */
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//排除数据源
@EnableEurekaClient//链接注册中心
@EnableFeignClients//添加feign的支持
public class Consumer_8020 {
     

    public static void main(String[] args) {
     

        SpringApplication.run(Consumer_8020.class, args);
    }
}

9、在springcloud-api子项目中创建Feign客户端接口

package com.zyl.springcloud.client;

import com.zyl.springcloud.fallback.UserFeignClientFallbackFactory;
import com.zyl.springcloud.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * @className: UserService
 * @description: Feign客户端
 * @author: ZYL
 * @date: 2020/7/3 15:40
 */
@FeignClient(value = "provider-user", fallbackFactory = UserFeignClientFallbackFactory.class)//指定服务提供者的服务名称和fallback类
public interface UserFeignClient {
     

    //查询所有用户的信息
    @GetMapping("/getAllUser")
    List<User> getAllUser();

    //根据用户名获取用户信息
    @GetMapping("/getUserByName/{name}")
    User getUserByName(@PathVariable String name);

    //新增用户
    @PostMapping("/addUser/{name}/{age}/{sex}")
    String addUser(@PathVariable String name, @PathVariable Integer age, @PathVariable String sex);

    //删除用户
    @DeleteMapping("/deleteUser/{id}")
    String deleteUser(@PathVariable Integer id);

    //修改用户信息
    @PutMapping("/updateUser/{id}/{name}/{age}/{sex}")
    String updateUser(@PathVariable Integer id, @PathVariable String name, @PathVariable Integer age, @PathVariable String sex);
}

10、创建controller类

package com.zyl.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zyl.springcloud.client.UserFeignClient;
import com.zyl.springcloud.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @className: UserController
 * @description: 服务消费者控制器
 * @author: ZYL
 * @date: 2020/7/3 15:43
 */
@RestController
public class UserController {
     

    @Autowired
    private UserFeignClient userFeignClient;

    //查询所有用户的信息
    @GetMapping("/getAllUser")
    @HystrixCommand(fallbackMethod="getAllUser")
    public List<User> getAllUser() {
     
        return userFeignClient.getAllUser();
    }

    //根据用户名获取用户信息
    @GetMapping("/getUserByName/{name}")
    @HystrixCommand(fallbackMethod="getUserByName")
    public User getUserByName(@PathVariable String name) {
     
        return userFeignClient.getUserByName(name);
    }

    //新增用户
    @PostMapping("/addUser/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod="addUser")
    public String addUser(User user) {
     
        return userFeignClient.addUser(user.getName(), user.getAge(), user.getSex());
    }

    //删除用户
    @DeleteMapping("/deleteUser/{id}")
    @HystrixCommand(fallbackMethod="deleteUser")
    public String deleteUser(@PathVariable Integer id) {
     
        return userFeignClient.deleteUser(id);
    }

    //修改用户信息
    @PutMapping("/updateUser/{id}/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod="updateUser")
    public String updateUser(User user) {
     
        return userFeignClient.updateUser(user.getId(), user.getName(), user.getAge(), user.getSex());
    }

}

11、创建负载均衡配置类

SpringCloud(微服务)全套入门教程_第14张图片

package com.zyl.springcloud.config;

import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @className: UserService
 * @description: 服务调用策略配置
 * @author: ZYL
 * @date: 2020/7/3 15:40
 */
@Configuration
public class RestTemplateConfig {
     

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

    @Bean
    public RoundRobinRule myRule() {
     
        return new RoundRobinRule();//轮询策略
//        return new RandomRule();//随机策略
//        return new AvailabilityFilteringRule();//首先会过滤掉故障机或者并发链接数超过阈值的服务器.剩余的机器轮询配置
//        new WeightedResponseTimeRule();//服务器影响时间越快,则权重越高
//        new BestAvailableRule();//最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的
    }
}

12、启动消费者服务,访问服务消费者页面

SpringCloud(微服务)全套入门教程_第15张图片
在这里插入图片描述

四、断路器监控(Hystrix Dashboard)

1、为什么需要断路器

在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

针对上述问题,在Spring Cloud Hystrix中实现了线程隔离、断路器等一系列的服务保护功能。它也是基于Netflix的开源框架 Hystrix实现的,该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等强大功能。

2、什么是断路器

断路器模式源于Martin Fowler的Circuit Breaker一文。“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。

在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延。

3、断路器示意图

SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图:

SpringCloud(微服务)全套入门教程_第16张图片

一个微服务的超时失败可能导致瀑布式连锁反映,下图中,Hystrix通过自主反馈实现的断路器, 防止了这种情况发生。

SpringCloud(微服务)全套入门教程_第17张图片

图中的服务B因为某些原因失败,变得不可用,所有对服务B的调用都会超时。当对B的调用失败达到一个特定的阀值(5秒之内发生20次失败是Hystrix定义的缺省值), 链路就会被处于open状态, 之后所有所有对服务B的调用都不会被执行, 取而代之的是由断路器提供的一个表示链路open的Fallback消息. Hystrix提供了相应机制,可以让开发者定义这个Fallbak消息.

open的链路阻断了瀑布式错误, 可以让被淹没或者错误的服务有时间进行修复。这个fallback可以是另外一个Hystrix保护的调用, 静态数据,或者合法的空值. Fallbacks可以组成链式结构,所以,最底层调用其它业务服务的第一个Fallback返回静态数据.

4、添加maven依赖

<!--添加断路器配置 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

5、在springcloud-api子项目中创建fallback类

package com.zyl.springcloud.fallback;

import java.util.ArrayList;
import java.util.List;

import com.zyl.springcloud.client.UserFeignClient;
import org.springframework.stereotype.Component;

import com.zyl.springcloud.pojo.User;

import feign.hystrix.FallbackFactory;

/**
 * @ClassName: UserFeignClientFallbackFactory
 * @Description: 用户服务返回预期错误信息
 * @author: ZYL
 * @date: 2020/7/2 17:42
 */
@Component
public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
     

    @Override
    public UserFeignClient create(Throwable cause) {
     

        return new UserFeignClient() {
     

            @Override
            public List<User> getAllUser() {
     
                User user = new User();
                user.setId(0).setName("后台服务器异常,查询用户失败").setAge(0).setSex("");
                List<User> userList = new ArrayList<User>();
                userList.add(user);
                return userList;
            }

            @Override
            public User getUserByName(String name) {
     
                User user = new User();
                user.setId(0).setName("后台服务器异常,查询用户失败").setAge(0).setSex("");
                return user;
            }

            @Override
            public String updateUser(Integer id, String name, Integer age, String sex) {
     
                return "后台服务器异常,更新用户失败";
            }

            @Override
            public String addUser(String name, Integer age, String sex) {
     
                return "后台服务器异常,新增用户失败";
            }

            @Override
            public String deleteUser(Integer id) {
     
                return "后台服务器异常,删除用户失败";
            }
        };
    }
}

6、创建dashboard配置类

package com.zyl.springcloud.config;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Servlet;

@Configuration
public class DashboardConfig {
     
   
   @Bean
   public ServletRegistrationBean<Servlet> getServlet(){
     
      HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean<Servlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
   }
}

7、在消费者主启动类上添加@EnableHystrix注解

SpringCloud(微服务)全套入门教程_第18张图片

8、在controller方法上添加@HystrixCommand注解,并指明断路方法

package com.zyl.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zyl.springcloud.client.UserFeignClient;
import com.zyl.springcloud.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @className: UserController
 * @description: 服务消费者控制器
 * @author: ZYL
 * @date: 2020/7/3 15:43
 */
@RestController
public class UserController {
     

    @Autowired
    private UserFeignClient userFeignClient;

    //查询所有用户的信息
    @GetMapping("/getAllUser")
    @HystrixCommand(fallbackMethod="getAllUser")
    public List<User> getAllUser() {
     
        return userFeignClient.getAllUser();
    }

    //根据用户名获取用户信息
    @GetMapping("/getUserByName/{name}")
    @HystrixCommand(fallbackMethod="getUserByName")
    public User getUserByName(@PathVariable String name) {
     
        return userFeignClient.getUserByName(name);
    }

    //新增用户
    @PostMapping("/addUser/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod="addUser")
    public String addUser(User user) {
     
        return userFeignClient.addUser(user.getName(), user.getAge(), user.getSex());
    }

    //删除用户
    @DeleteMapping("/deleteUser/{id}")
    @HystrixCommand(fallbackMethod="deleteUser")
    public String deleteUser(@PathVariable Integer id) {
     
        return userFeignClient.deleteUser(id);
    }

    //修改用户信息
    @PutMapping("/updateUser/{id}/{name}/{age}/{sex}")
    @HystrixCommand(fallbackMethod="updateUser")
    public String updateUser(User user) {
     
        return userFeignClient.updateUser(user.getId(), user.getName(), user.getAge(), user.getSex());
    }

}

6、重启消费者服务、启动dashboard服务

SpringCloud(微服务)全套入门教程_第19张图片

7、访问图形化监控界面

SpringCloud(微服务)全套入门教程_第20张图片

刷新服务消费者页面,当后台服务器出现异常时,显示fallback方法返回的错误提示信息

SpringCloud(微服务)全套入门教程_第21张图片

图形化展示方法的连通情况

SpringCloud(微服务)全套入门教程_第22张图片

五、服务网关(Zuul)

1、服务网关的作用

服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。

路由在微服务体系结构的一个组成部分。例如,/可以映射到您的Web应用程序,/api/users映射到用户服务,并将/api/shop映射到商店服务。ZuulNetflix的基于JVM的路由器和服务器端负载均衡器。

Netflix使用Zuul进行以下操作:

  • 认证
  • 洞察
  • 压力测试
  • 金丝雀测试
  • 动态路由
  • 服务迁移
  • 负载脱落
  • 安全
  • 静态响应处理
  • 主动/主动流量管理

Zuul的规则引擎允许基本上写任何JVM语言编写规则和过滤器,内置JavaGroovy

2、什么是服务网关

服务网关 = 路由转发 + 过滤器

1、路由转发:接收一切外界请求,转发到后端的微服务上去;

2、过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。

3、创建springcloud-zuul-9050子项目

SpringCloud(微服务)全套入门教程_第23张图片

4、添加maven依赖

<!--导入springBoot依赖包 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/>
</parent>
<properties>
    <java.version>1.8</java.version>
</properties>
<!--依赖管理,用于管理spring-cloud的依赖 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.SR2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>com.zyl.springcloud</groupId>
        <artifactId>springcloud-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <!--导入springCloudjar包 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-stream</artifactId>
    </dependency>

    <!--引入springBoot jar包 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!--支持热部署 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
        <version>1.2.8.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>

    <!--引入springBoot监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!--添加eureka 客户端地址 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!--添加zuul支持-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>

    <!--添加断路器配置 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
</dependencies>

5、创建yml配置文件

server:
  port: 9050
  servlet:
    context-path: /
spring:
  application:
    name: zuul                          #定义服务名称
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka
  instance:
    instance-id: zuul-9050              #定义微服务的名称
    prefer-ip-address: true             #是否显示IP和端口

zuul:
  prefix: /api                          #通过统一的公共前缀访问
#  ignored-services: springcloud-user   #禁止通过某个服务名访问
  ignored-services: "*"                 #禁止通过全部服务名访问
  routes:
    user-service:
      serviceId: consumer-user          #映射的服务名称
      path:      /user/**               #浏览器输入地址

management:                             #路由映射显示
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: ALWAYS

6、创建路由服务主启动类

package com.zyl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableZuulProxy
public class Zuul_9050 {
     

    public static void main(String[] args) {
     

        SpringApplication.run(Zuul_9050.class, args);
    }

    @Bean
    public TokenFilter tokenFilter() {
     
        return new TokenFilter();
    }

    @Bean
    public PasswordFilter PasswordFilter() {
     
        return new PasswordFilter();
    }
}

7、创建路由fallback类

package com.zyl.springcloud;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * @className: ZuulFallback
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/6 17:14
 */
@Component
public class ZuulFallback implements FallbackProvider {
     
    @Override
    public String getRoute() {
     
        return "*";//对所有服务调用支持回退
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
     
        return new ClientHttpResponse() {
     
            @Override
            public HttpStatus getStatusCode() throws IOException {
     
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
     
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
     
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {
     

            }

            @Override
            public InputStream getBody() throws IOException {
     
                return new ByteArrayInputStream("服务不可用".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
     
                HttpHeaders headers = new HttpHeaders();
                MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
                headers.setContentType(mt);
                return headers;
            }
        };
    }
}

8、创建路由token过滤器类

package com.zyl.springcloud;

import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

/**
 * @className: TokenFilter
 * @description: 过滤器token
 * @author: ZYL
 * @date: 2020/7/7 9:33
 */
public class TokenFilter extends com.netflix.zuul.ZuulFilter {
     

    private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);

    @Override
    public String filterType() {
     
        return "pre";//在请求通过路由之前调用
    }

    @Override
    public int filterOrder() {
     
        return 0;// filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
    }

    @Override
    public boolean shouldFilter() {
     
        return true;// 是否执行该过滤器,此处为true,说明需要过滤
    }

    @Override
    public Object run() {
     
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        LOGGER.info("TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString());
        String token = request.getParameter("token");// 获取请求的参数
        if (StringUtils.isNotBlank(token)) {
     
            ctx.setSendZuulResponse(true); //对请求进行路由
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);
            return null;
        } else {
     
            ctx.setSendZuulResponse(false); //不对其进行路由
            ctx.setResponseStatusCode(400);
            ctx.setResponseBody("token is empty");
            ctx.set("isSuccess", false);
            return null;
        }
    }
}

9、创建路由password过滤器类

package com.zyl.springcloud;

import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

/**
 * @className: PasswordFilter
 * @description: 过滤器password
 * @author: ZYL
 * @date: 2020/7/7 10:12
 */
public class PasswordFilter extends com.netflix.zuul.ZuulFilter {
     

    private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);

    @Override
    public String filterType() {
     
        return "post"; //请求处理完成后执行过滤器
    }

    @Override
    public int filterOrder() {
     
        return 1; //优先级为1,数字越大,优先级越低
    }

    @Override
    public boolean shouldFilter() {
     
        RequestContext ctx = RequestContext.getCurrentContext();
        return (boolean) ctx.get("isSuccess");//判断上一个过滤器结果是否为true,否则就不走下面过滤器,直接跳过后面的所有过滤器并返回
    }

    @Override
    public Object run() throws ZuulException {
     
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        LOGGER.info("PasswordFilter {},{}", request.getMethod(), request.getRequestURL().toString());
        String password = request.getParameter("password");
        if (null != password && password.equals("123456")) {
     
            ctx.setSendZuulResponse(true);
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);
            return null;
        } else {
     
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(400);
            ctx.setResponseBody("The password cannot be empty");
            ctx.set("isSuccess", false);
            return null;
        }
    }
}

10、启动路由服务,通过路由访问服务

SpringCloud(微服务)全套入门教程_第24张图片

在地址栏输入token的值和password的值

SpringCloud(微服务)全套入门教程_第25张图片

六、服务端配置中心(Config Service)

1、springcloud config简介

中心服务器,从而能够提供更好的管理、发布能力。SpringCloudConfig分服务端和客户端,服务端负责将git svn中存储的配置文件发布成REST接口,客户端可以从服务端REST接口获取配置。但客户端并不能主动感知到配置的变化,从而主动去获取新的配置,这需要每个客户端通过POST方法触发各自的/refresh

SpringCloudBus通过一个轻量级消息代理连接分布式系统的节点。这可以用于广播状态更改(如配置更改)或其他管理指令。SpringCloudBus提供了通过POST方法访问的endpoint/bus/refresh,这个接口通常由git的钩子功能调用,用以通知各个SpringCloudConfig的客户端去服务端更新配置。

注意:这是工作的流程图,实际的部署中SpringCloudBus并不是一个独立存在的服务,这里单列出来是为了能清晰的显示出工作流程。

下图是SpringCloudConfig结合SpringCloudBus实现分布式配置的工作流

SpringCloud(微服务)全套入门教程_第26张图片

2、为什么需要springcloud config

在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client,业界也有些知名的同类开源产品,比如百度的disconf

相比较同类产品,SpringCloudConfig最大的优势是和Spring无缝集成,支持Spring里面EnvironmentPropertySource的接口,对于已有的Spring应用程序的迁移成本非常低,在配置获取的接口上是完全一致,结合SpringBoot可使你的项目有更加统一的标准(包括依赖版本和约束规范),避免了应为集成不同开软件源造成的依赖版本冲突。

3、创建git远程仓库文件

SpringCloud(微服务)全套入门教程_第27张图片
SpringCloud(微服务)全套入门教程_第28张图片

4、创建springcloud-config-service-9080子项目

SpringCloud(微服务)全套入门教程_第29张图片

5、添加maven依赖

<dependencies>
    <!--springcloud配置中心  -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>

    <!--引入springBoot监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!--添加eureka 客户端地址 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

6、添加yml配置文件

server:
  port: 9080
  servlet:
    context-path: /

spring:
  application:
    name: config-service   #定义服务名称
  config:
    name: config-service   #定义配置文件名
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/geecoder/springcloud-config #连接远程git账户
          search-paths: /** #查找git仓库的路径
          label: master #查找的git分支
#          username: #私有仓库需要配置用户名和密码
#          password:

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka
  instance:
    instance-id: config-service-9080   #定义微服务的名称
    prefer-ip-address: true            #是否显示IP和端口

7、创建主启动类

package com.zyl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication(exclude= {
     DataSourceAutoConfiguration.class})//排除数据源启动,否则会报错
@EnableConfigServer//开启配置中心设置
public class ConfigService_9080 {
     
   
   public static void main(String[] args) {
     
      SpringApplication.run(ConfigService_9080.class, args);
   }
}

8、启动服务,访问服务端配置中心地址

SpringCloud(微服务)全套入门教程_第30张图片

http请求地址和资源文件映射如下:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

SpringCloud(微服务)全套入门教程_第31张图片

七、客户端配置中心(Config Client)

1、创建springcloud-config-client-9090子项目

SpringCloud(微服务)全套入门教程_第32张图片

2、添加maven依赖

<dependencies>
    <!--springcloud客户端配置  -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>

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

    <!--引入springBoot监控 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!--添加eureka 客户端地址 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
</dependencies>

3、创建两个yml配置文件

bootstrao.yml会在程序引导时执行,应用于更加早期配置信息读取。

SpringCloud(微服务)全套入门教程_第33张图片

application.yml:

server:
  port: 9090
  servlet:
    context-path: /

spring:
  application:
    name: config-client   #定义服务名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka
  instance:
    instance-id: config-client-9090    #定义微服务的名称
    prefer-ip-address: true            #是否显示IP和端口

bootstrap.yml:

spring:
  cloud:
    config:
      name: springcloudconfig     #对应config server Url中的{
     application}
      profile: dev                #动态加载开发环境配置文件
      label: master               #获取master默认分支
      uri: http://localhost:9080/ #配置服务中心地址

4、创建主启动类

package com.zyl.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ConfigClient_9090 {
     

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

5、创建controller类

package com.zyl.springcloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @className: ConfigController
 * @description: 描述
 * @author: ZYL
 * @date: 2020/7/7 15:50
 */
@RestController
public class ConfigController {
     

    @Value("${content}")//content是git文件中的key
    String content;

    @GetMapping("/config")
    public String config() {
     
        return "content: " + content;
    }
}

6、启动服务,访问客户端配置中心页面

SpringCloud(微服务)全套入门教程_第34张图片
SpringCloud(微服务)全套入门教程_第35张图片

你可能感兴趣的:(微服务,springcloud,spring,java,spring,boot)