SpringCloud学习总结

SpringCloud学习总结

微服务架构方案

  1. SpringCloud NetFlix 一站式解决方案
  2. Apache Dubbo + Zookeeper(注册中心) 半自动,
  3. SpringCloud Alibaba 一站式解决方案

SpringCloud NetFlix

总体构建

创建maven总项目,导入依赖,不建议使用springCloud2020.0.*及以后版本,2020.0.*版本做了很大改动Springboot依赖根据官网文档推荐选择

springCloud官网

SpringCloud中文文档

maven仓库

pom文件配置总依赖

		<dependencyManagement>
			<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencyManagement>

版本控制

			<eureka.version>2.2.6.RELEASE</eureka.version>
			<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
                <version>${eureka.version}</version>
            </dependency>

注册中心 Eureka

CAP原则

C - consistency 强一致性
A - availability 可用性
P - partition tolerance 分区容错性

Eureka遵循AP原则

Zookeeper遵循CP原则


配置Eureka服务端

  1. 在工程下新建maven Module作为Eureka服务端

  2. 在新建项目下添加pom依赖(注意这里是Eureka服务端所以pom依赖是*-server)

    	<dependencies>		
    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        <dependencies>
    

    application.yml配置

    server:
      port: 7003
    
    #Eureka配置
    eureka:
      instance:
        hostname: eureka7003.com   #eureka服务端的实例名称
      client:
        register-with-eureka: false  #表示是否向eureka注册中心注册自己
        fetch-registry: false #如果为false则表示自己为注册中心
        service-url:  #监控页面
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    
  3. 新建启动类

    package com.springcloud;
    
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer             //服务端启动类 可以接受别人注册进来
    public class EurekaServer_7001 {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer_7001.class,args);
        }
    
    }		
    

配置消费者

  1. 新建maven Moudle作为生产者,在pom文件中添加依赖

    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
  2. 在父工程pom文件添加版本依赖

    	<properties>
            <eureka.version>2.2.6.RELEASE</eureka.version>
        </properties>
            
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>${eureka.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>${eureka.version}</version>
        </dependency>
    
  3. application.yml配置

    server:
      port: 80
    spring:
      application:
        name: service-ribbon
    #    register-with-eureka: false #消费者不用注册自己
    #Eureka配置
    eureka:
      client:
        register-with-eureka: false
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
        registry-fetch-interval-seconds: 10
      instance:
        instance-id: springcloud-consumer-dept80  #修改Eureka默认描述信息
    

消费者controller
package com.springcloud.controller;


import com.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {

    @Autowired
    DiscoveryClient discoveryClient;
	
    @Bean   //注册一个Bean  RestTemplate...供我们调用   需要注册到spring中
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    @Autowired
    private RestTemplate restTemplate;
    //通过Ribbon 这里应该是一个变量,通过服务名来访问
    private static final String REST_URL_PREFIX = "http://localhost:8001";

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id, Dept.class);
    }

    @RequestMapping("/consumer/dept/add")
    public Boolean add(@RequestBody Dept dept) {

        System.out.println(dept);
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class);
    }

    @RequestMapping("consumer/dept/list")
    public List<Dept> list() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
    }

}


配置生产者

  1. 新建maven Moudle作为生产者,在pom文件中添加依赖

    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
  2. application.yml配置

    server:
      port: 8003
    
    #mybatis配置
    mybatis:
      type-aliases-package: com.springcloud.pojo
      mapper-locations: classpath:mapper/*.xml
    
    
    #spring配置
    spring:
      application:
        name: springcloud-provider-dept
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db03?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
        username: root
        password: tiger
    #Eureka服务注册地址
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/,http://eureka7002.com:7002/eureka/
        register-with-eureka: true
        fetch-registry: true
      instance:
        prefer-ip-address: true
        instance-id: springcloud-provider-dept8003  #修改Eureka默认描述信息
    #info配置
    info:
      app.name: 8888
      company.name: 8888
    
  3. 在启动类添加 @EnableEurekaClient 开启Eureka服务

负载均衡 ribbon

问题

  1. 有些教程在这里要导入ribbon包不过 ,在Netflix-eureka-client2.2.6.RELEASE版本已经集成了ribbon所以不用导入

  2. SpringCloud2020.0.0开始删除了ribbon,还不清楚如何应用,所以建议使用2020.0.0之前的版本,不过,Netflix-eureka-client3.0.0可以

    直接配合SpringCloud2020.0.0使用,并且依然支持轮询负载均衡,只是不清楚如何再自定义。如果强行导入其他版本ribbon,会出现找不到

    服务的情况 :No instance.....。或者ServerPropertiesAutoConfiguration.class找不到

配置ribbon

ribbon是配置在客户端,也就是消费者端youyu

因为创建消费者时的是eureka-client 而这个包已经包含了ribbon,所以此时不用导入依赖

![](D:\Project\MarkDown\屏幕截图 2021-02-01 174643.png)

默认轮询

在注册的给刚刚的Bean添加一个注解

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
更改均衡配置

再添加一个Bean ribbon默认有几个配置方案,下面这个是随机

    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
自定义均衡配置
  1. 在启动类添加注解@RibbonClient(name = "服务名",configuration = 自定义的配置类.class)
  2. 创建配置类,添加@Configuration 注解,规则可以自己定制
  3. 注意自己定制的配置不可放到项目启动类同级

服务熔断与降级 Hystrix

服务熔断

服务端,某个服务超时或异常,引起熔断,保险丝功能

配置服务熔断
  1. 生产者添加pom依赖

    		<dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
  2. 启动类添加注解 @EnableCircuitBreaker //添加断路器

  3. controller 给原方法添加备选方案

        @GetMapping("/dept/get/{id}")
        @HystrixCommand(fallbackMethod = "hystrixGet")
        public Dept get(@PathVariable("id") int id) {
            Dept dept = service.queryById(id);
            if (dept == null) {
                throw new RuntimeException("id=>" + id + ",不存在该用户,或信息无法查到");
            }
            return dept;
        }
    
        //备选方法
        public Dept hystrixGet(@PathVariable("id") int id) {
            return new Dept()
                    .setDeptno(id)
                    .setDname("id=>" + id + ",不存在该用户,或信息无法查到")
                    .setDb_source("没有该数据库");
        }
    

服务降级

客户端,从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时,在客户端,我们准备一个 FallbackFactory返回一个默认的值,整体服务水平下降。

服务降级实现方式
  1. 通过Feign
  2. Zuul网关方式

网关路由 Zuul

  1. 创建一个新的maven Module 作为网关服务
  2. 添加pom依赖
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
            
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  1. application.yml

    server:
      port: 9527
    spring:
      application:
        name: springcloud-zuul
    eureka:
      client:
        service-url:
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/,http://eureka7002.com:7002/eureka/
      instance:
        instance-id: zuul9527.com
        prefer-ip-address: true
    
    
    
    info:
      app.name: mao-springcloud
      company.name: blog.mao.com
    zuul:
      routes:
        mydept.serviceId: springcloud-provider-dept
        mydept.path: /mydept/**   #可以用这个路径访问
      ignored-services: "*"    #不能使用这个路径访问
      prefix: /mao   #路由前缀
    
    
  2. 编写启动类 添加@EnableZuulProxy 注解

接口编程 Feign

  1. 面向接口编程

  2. 添加服务接口 也就是对应生产者的controller,再创建实体类

    package com.springcloud.service;
    
    import com.springcloud.pojo.Dept;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.List;
    
    @Component
    public interface DeptClientService {
    
        @GetMapping("/dept/list")
        List<Dept> queryAll();
    
        @RequestMapping("/dept/get/{id}")
        Dept get(@PathVariable("id") Integer id);
    
        @RequestMapping("/dept/add")
        Boolean add(@RequestBody Dept dept);
    }
    
    
  3. 修改controller 不再使用RestFul

    package com.springcloud.controller;
    
    import com.springcloud.pojo.Dept;
    import com.springcloud.service.DeptClientService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    public class DeptConsumerController {
    
        @Autowired
        private DeptClientService service;
    
        @RequestMapping("/consumer/dept/get/{id}")
        public Dept get(@PathVariable("id") Integer id){
            return service.get(id);
        }
        @RequestMapping("/consumer/dept/add")
        public Boolean add(@RequestBody Dept dept){
            return null;
        }
        @RequestMapping("consumer/dept/list")
        public List<Dept> list(){
            return this.service.queryAll();
        }
    
    }
    
    

服务降级配置

  1. 在服务接口类添加注解 @FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)

  2. 可以删除实现类,正常情况下即使在有@Component注解的情况下也不能将接口类注入到Bean,前面建实体类就是为了实现自动注入 但是@FeignClient可以将接口注入到Bean

  3. 创建FallbackFactory实现类

    package com.springcloud.service;
    
    import com.springcloud.pojo.Dept;
    import feign.hystrix.FallbackFactory;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    //降级
    @Component
    public class DeptClientServiceFallbackFactory implements FallbackFactory {
        @Override
        public DeptClientService create(Throwable throwable) {
            return new DeptClientService() {
                @Override
                public List<Dept> queryAll() {
                    List<Dept> deptList = new ArrayList<>();
                    Dept dept = new Dept().setDeptno(0).setDname("没有找到(服务降级返回)");
                    deptList.add(dept);
                    return deptList;
                }
    
                @Override
                public Dept get(Integer id) {
                    return new Dept().setDeptno(id).setDname("没有找到(服务降级返回),这个服务已经被关闭");
                }
    
                @Override
                public Boolean add(Dept dept) {
                    return null;
                }
            };
        }
    }
    
    
posted @ 2021-02-01 20:09  Apoint  阅读(70)  评论(0)    收藏  举报