springcloud

微服务架构四个核心问题:

  • 服务很多,客户端如何访问?
  • 服务之间如何通信?
  • 服务怎么治理?
  • 服务宕机怎么办?

解决方案:

​ springcloud生态

  1. Spring Cloud NetFlix 一站式解决方案 已停止更新维护 ------2018
  • api网关 ,zuul组件
  • Feign---------------httpclient----http通信方式,同步(主动访问请求结果)阻塞(没有结果前不干其他事)
  • 服务注册发现:Eureka
  • 熔断机制:Hystrix
  1. Apache Dubbo Zookeeper 半自动,需要整合别人的~!
  • API:没有,找第三方组件或者自己实现
  • Dubbo
  • Zookeeper
  • 没有,借助Hystrix

​ dubbo这个方案并不完善!!!!~

  1. Spring Cloud Alibaba 一站式解决,更简单

  2. 新概念:服务网格 Server Mesh ---------------- istio

常见面试题

1、什么是微服务?
2、微服务之间是如何独立通讯的?
3、SpringCloud和Dubbo有什么区别?
4、SpringCloud和SpringBoot请谈谈你对他们的理解?
5、什么是服务熔断?什么是服务降级?
6、微服务的优缺点分别是什么?说下你在项目中遇到的坑?
7、微服务有哪些技术栈?大致列举一下。
8、eureka和zookeeper都可以提供服务注册与发现,请说说两者的区别?

微服务概述

参考

原文:https://martinfowler.com/microservices/

汉化:https://www.cnblogs.com/liuning8023/p/4493156.html

将单一的应用程序划分成一组小的服务

微服务化的核心就是将传统的一站式应用,根据业务拆分成一个个小的服务,彻底的去耦合,每一个微服务提供单个业务功能的服务,一个服务做一个事情,从技术角度看就是一种小而独立的处理过程,类似进程的概念,能够自行单独启动或销毁,拥有自己独立的数据库和开发语言。

微服务技术栈

微服务条目 落地技术栈
服务开发 Springboot、spring、springMVC
服务配置与管理 NetFlix公司的Archaius、阿里的Diamond等
服务注册与发现 Eureka、Consul、Zookeeper、Nacos
服务调用 Rest、RPC、gRPC
服务熔断器 Hystrix、Envoy
负载均衡 Ribbon、Nginx
服务接口调用(客户端调用服务的简化工具) Feign
消息队列 kafka、RabbitMQ、RocketMQ、ActiveMQ、apache pulsar
服务配置中心管理 springcloudconfig、chef、Apollo、disconf
服务路由(API网关) Zuul、gateway
服务监控 Zabbix、Nagios、metrics、specatator
全链路追踪 Zipkin、Brave、Dapper
服务部署 Docker、Openstack、Kubernetes
数据流操作开发包 springcloud stream
事件消息总线 springcloud bus

springcloud是一个有众多独立子项目组成的大型综合项目,每个子项目有不同的发行节奏,都维护这自己的发布版本号。springcloud通过一个资源清单BOM(Bill of Materials)来管理每个版本的子项目清单,为了避免与子项目的发布号混淆,所以没有采用版本号的方式,而是通过命名的方式。

这些版本名称的命名方式采取了伦敦地铁站的名称,同时根据字母表的顺序来对应版本的时间顺序,比如最早的release版本:Angel,到后面的Brixton、Camden、Dalston、Edgware、Finchley等。

参考文档:

springcloud和springboot的关系

  • SpringBoot专注于快速方便的开发单个个体微服务
  • springcloud关注全局的微服务协调整理治理框架,它将springboot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理、服务发现、断路器、路由、微代理、事件总线、全局锁、决策竞选、分布式会话等集成服务
  • springboot可离开springcloud独立使用,开发项目,但是springcloud离不开springboot,属于依赖关系

Dubbo和springcloud的技术选型

功能 dubbo springcloud
服务注册中心 Zookeeper spring cloud Netflix Eureka
服务调用方式 RPC Rest Api
服务监控 Dubbo-monitor spring boot admin
断路器 不完善 spring cloud Netflix Hystrix
服务网关 spring cloud Netflix Zuul
分布式配置 spring cloud config
服务跟踪 spring cloud Sleuth
消息总线 spring cloud bus
数据流 spring cloud stream
批量任务 spring cloud task

最大的区别:Springcloud摒弃了Dubbo的RPC通道,采用的是基于HTTP的REST方式。

这两种方式各有优劣,后者牺牲了服务调用的性能,但是相应的避免了原生RPC带来的问题,而且更为的灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更加合适。

解决的问题域不一样:

Dubbo的定位是一款RPC框架,Spring Cloud的目标是微服务架构下的一站式解决方案

Spring Cloud版本选择

Spring boot Spring Cloud 关系
1.2.x Angel 兼容springboot1.2.x
1.3.x Brixton 兼容springboot1.3.x,也兼容springboot1.4.x
1.4.x Camden 兼容springboot1.4.x,也兼容springboot1.5.x
1.5.x Dalston 兼容springboot1.5.x,不兼容springboot2.0.x
1.5.x Edgware 兼容springboot1.5.x,不兼容springboot2.0.x
2.0.x Finchley 兼容springboot2.0.x,不兼容springboot1.5.x
2.1.x Greenwich 兼容Spring Boot 2.1.x
2.2-2.4 Hoxton 兼容Spring Boot 2.2.x
2021.0.3 (2022最新正式版)

Eureka

alt

原理

Eureka的基本架构

  • springcloud封装了NetFlix公司开发的Eureka模块来实现服务注册和发现
  • Eureka采用了C-S的架构设计,EurekaServer作为服务注册功能的服务器,它是服务中心
  • 而系统中的其他微服务使用Eureka的客户端连接到EurekaServer并维持心跳连接。这样系统的维护人员就可以通过EurekaServer来监控系统中各个微服务是否正常运行,springcloud的一些其他模块(比如Zuul)就可以通过EurekaServer来发现系统中的其他微服务,并执行相关的逻辑。
  • Eureka包含两个组件:Eureka ServerEureka Client
  • Eureka Server提供服务注册服务,各个节点启动后,会在EurekaServer中进行注册,这样Eureka Server中的服务注册表会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
  • Eureka Client是一个java客户端,用于简化和EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,会将向EurekaServer发送心跳(默认周期30s)。如果EurekaServer在多个心跳周期内没有收到某个节点的心跳,它会从服务注册表中将这个服务节点移除掉(默认周期为90s)。

三大角色

  • Eureka Server:提供服务的注册与发现
  • Eureka Provider:将自身服务注册到Eureka中,从而使消费者能够找到
  • Eureka Consumer:服务消费方从Eureka中获取注册服务列表,从而找到消费服务

搭建Eureka服务

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
</dependencies>
server:
  port: 7001

#Eureka的配置
eureka:
  instance:
    appname: eureka001  #服务端的实例名称  applicationName
    instance-id: eureka001-id  #修改eureka上的默认描述信息
    prefer-ip-address: true # 可以显示服务的ip
  client:
    register-with-eureka: false #表示是否向注册中心注册自己
    fetch-registry: false #false表示自己为注册中心
    service-url: #监控页面
      defaultZone: http://${eureka.instance.appname}/${server.port}/eureka/
@SpringBootApplication
@EnableEurekaServer //核心注解 开启eureka功能
public class SpringCloudEurekaApplication {

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

访问 http://localhost:7001/ 即可进入界面

alt

客户端配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<!-- 完善监控信息 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
#eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: cosumer8080  #修改eureka上的默认描述信息
#info配置
info:
  app.name: kaka-provider
  company.name: kaka
@SpringBootApplication
@EnableEurekaClient  //注册注解
public class DeptProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderApplication.class,args);
    }
}

alt

alt

自我保护机制

某时刻某一个微服务不可以用了,eureka不会立刻清除,依旧对该微服务的信息进行保存!

alt

在springcloud中可以使用 一下配置禁用自我保护模式(不推荐关闭)

eureka: 
  server:
    enable-self-preservation: false
@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    @Autowired
    private DiscoveryClient discoveryClient;

    //注册进来的微服务  获取一些信息
    @GetMapping("/dept/discovery")
    public Object discovery(){
        //获取微服务列表清单
        List<String> services = discoveryClient.getServices();

        System.out.println(services);
        List<ServiceInstance> instances = discoveryClient.getInstances("SPRING-CLOUD-PROVIDER");

        System.out.println(instances);
        return discoveryClient;
    }
}

//--------------------------控制台打印----------eureka中的注册信息---------------------------------------------
[cosumerapplication, spring-cloud-provider]
[[EurekaDiscoveryClient.EurekaServiceInstance@6a1b35c8 instance = InstanceInfo [instanceId = 
   DESKTOP-386BR9J:spring-cloud-provider:8081, appName = SPRING-CLOUD-PROVIDER, hostName = 
   DESKTOP-386BR9J, status = UP, ipAddr = 169.254.171.253, port = 8081, securePort = 443, 
   dataCenterInfo = com.netflix.appinfo.MyDataCenterInfo@27ca9b6b]]

集群

#服务器
server:
  port: 7001

#Eureka的配置
eureka:
  instance:
    appname: eureka001  #服务端的实例名称
  client:
    register-with-eureka: false #表示是否向注册中心注册自己
    fetch-registry: false #false表示自己为注册中心
    service-url: #监控页面
      #单机版
      #defaultZone: http://${eureka.instance.appname}:${server.port}/eureka/
      #集群,其他几台机器也是一样修改
      defaultZone: http://eureka002.com:7002/eureka/,http://eureka003.com:7003/eureka/
#######################客户端################################      
eureka:
  client:
    service-url:
      #单机
      #defaultZone: http://localhost:7001/eureka/
      #集群
      defaultZone: http://eureka001.com:7001/eureka/,http://eureka002.com:7002/eureka/,http://eureka003.com:7003/eureka/



CAP原则

RDBMS(mysql、oracle、sqlServer)-----------------》ACID

NoSQL(Redis、mongoDB)--------》CAP

ACID

  • 原子性 Atomicity
  • 一致性 Consistency
  • 隔离性 Isolation
  • 持久性 Durability

CAP

  • 强一致性 Consistency
  • 可用性 Availability
  • 分区容错性 Partition tolerance

CAP的三进二:CA 、AP、CP

==CAP理论的核心:==

1. 一个分布式系统不可能同时很好的满足一致性、可用性和分区容错性这三个需求
2. 根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:
	CA:单点集群,满足一致性,可用性的系统,通常可扩展性较差
	CP:满足一致性、分区容错性的系统,通常性能不是特别高
	AP:满足可用性、分区容错性的系统,通常对一致性要求低一点

Eureka和Zookeeper的区别

著名的CAP理论指出:一个分布式系统不可能同时满足CAP。

由于分区容错性P在分布式系统中是必须要保证的,因此我们在A和C之间进行权衡:

  • Zookeeper保证的CP
   当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但是不能接受服务直接宕机不可用。
也就是说服务注册功能对可用性的要求高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联
系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30~120s且选举期间整个zk集群都是不可用的,这
就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得zk集群失去master节点是较大概率的事件,虽然服务最
终能够恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
  • Eureka保证的是AP
   Eureka明白了这一点,因此在设计的时候就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常的工
作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个注册中心注册时,如果发现连接失败,则会自动切换
到其他节点,只要有一台eureka服务能用,就能保证注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,eureka
还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么eureka就认为客户端与注册中心出现了网络故障
此时会出现一下集中情况:
	1、eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务;
	2、eureka依然能够接受新服务的注册和查询请求,但是不会同步到其他节点上(保证当前节点依然可用)
	3、当网络稳定时,当前实例新的注册信息会被同步到其他节点中。

因此,eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使得整个注册服务瘫痪。

Ribbon

  • spring cloud ribbon是基于NetFlix Ribbon实现的一套客户端负载均衡的工具

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

  • LB,负载均衡,在微服务或分布式集群中经常用的一种应用。

  • 负载均衡简单的说就是将用户的请求平均的分配到多个服务上,从而达到系统的HA (高可用)

  • 常见的负载均衡软件由Nginx、Lvs、Appache+tomcat等

  • dubbo和springcloud中给我们提供了负载均衡,springcloud的负载均衡算法可以自定义

  • 负载均衡简单分类

    • 集中式LB:即在服务的消费方和提供方之间使用独立的LB设施,如Nginx反向代理服务器,由该设施负责把访问请求通过某种策略转发至服务的提供方!!

    • 进程式LB

      • 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可以用,然后自己再从这些地址中选出一个合适的服务器
      • Ribbon就是进程内LB,他只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

使用-只在消费者服务

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
server:
  port: 80
#eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://eureka001.com:7001/eureka/,http://eureka002.com:7002/eureka/,http://eureka003.com:7003/eureka/
    register-with-eureka: false #消费方不用把自己注册到Eureka服务
@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced//配置负载均衡实现,新增这个配置即可实现负载均衡
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
  }

//=========================================使用时===========================

@RestController
public class DeptConsumerController {


    @Autowired
    private RestTemplate restTemplate;

    //private static final String URL_PREFIX = "http://localhost:8081";
    private static final String URL_PREFIX = "http://spring-cloud-provider";//这个地方就用应用名称

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

注意:Ribbon和Eureka整合后简化了步骤,客户端可以直接调用,不用关心IP地址和端口号

alt

package com.kaka.springcloud;
@SpringBootApplication
@EnableEurekaClient
//在微服务启动的时候就能加载自定义的Ribbon类,这个写法是官方要求的,自定义的规则类不能在扫包路径下
@RibbonClient(name = "微服务名称", configuration = MyRibbonRule.class)
public class DeptConsumerApplication {

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

//============================================================
package com.kaka.myrule;

@Configuration
public class MyRibbonRule extends AbstractLoadBalancerRule {
    
    //在下面方法体中实现负载均衡算法
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();//获取活着的服务
            List<Server> allList = lb.getAllServers();//获取所有的服务
            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }
            int index = chooseRandomInt(serverCount);//生成区间随机数
            server = upList.get(index);
            if (server == null) {
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            server = null;
            Thread.yield();
        }
        return server;
    }
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }
    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        // TODO Auto-generated method stub
    }
}

Feign负载均衡

简介

Feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似于controller调用service。springcloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

Feign,主要是社区,大家习惯面向接口编程,这个是很多人开发的规范。调用微服务的方式:

  • 微服务名字 【Ribbon】
  • 接口和注解 【Feign】

Feign旨在使编写java http客户端变得更容易

前面在使用ribbon+restTemplate时,利用restTemplate对http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口被多处调用,所以通常会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他帮助我们定义和实现依赖服务接口的定义,在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置(类似于以前dao接口上标注mapepr注解,现在是一个微服务接口上面标注一个Feign注解即可)即可完成对服务提供方的绑定,简化了使用spring cloud ribbon时,自动封装服务调用客户端的开发量。

Feign集成了Ribbon

  • 利用Ribbon维护了微服务的服务列表信息,并且通过轮询时效内了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
// api新增接口Feign
package com.kaka.springcloud.service;

@FeignClient(value = "eureka上服务名称")
public interface DeptClientFeignService {

    @PostMapping("/dept/add")
    public Boolean addDept(Dept dept);

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();

}

//======================消费方 controller==========================
@RestController
public class DeptConsumerController {
    /**
     * Feign
     */
    @Autowired
    private DeptClientFeignService service;
    
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        return service.queryById(id);
    }
    @RequestMapping("/consumer/dept/add")
    public Boolean add(Dept dept){
        return service.addDept(dept);
    }
}
//=====================消费方启动类======================
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.kaka.springcloud"})
public class DeptConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerApplication.class,args);
    }
}

Hystrix

分布式系统面临的问题

复杂分布式体系结构中的应用程序由数十个依赖关系,每个依赖关系在某些时候将不可避免的失败!

  1. 为什么需要断路器

在分布式架构中,一个应用依赖多个服务是非常常见的,如果其中一个依赖由于延迟过高发生阻塞,调用该依赖服务的线程就会阻塞,如果相关业务的QPS较高,就可能产生大量阻塞,从而导致该应用/服务由于服务器资源被耗尽而拖垮。 另外,故障也会在应用之间传递,如果故障服务的上游依赖较多,可能会引起服务的雪崩效应。就跟数据瘫痪,会引起依赖该数据库的应用瘫痪是一样的道理。 当一个应用依赖多个外部服务,一切都正常的情况下,如下图:

alt

如果其中一个依赖发生延迟,当前请求就会被阻塞

alt

出现这种情况后,如果没有应对措施,后续的请求也会被持续阻塞

alt

每个请求都占用了系统的CPU、内存、网络等资源,如果该应用的QPS较高,那么该应用所有的服务资源会被快速消耗完毕,直至应用死掉。如果这个出问题的依赖,不止这一个应用,亦或是受影响的应用上层也有更多的依赖,那就会带来我们前面所提到的服务雪崩效应。 所以,为了应对以上问题,就需要有支持服务隔离、熔断等操作的工具。

  1. 什么是Hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整个服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障后,通过断路器的故障监控(类似于熔断保险丝),向调用方返回一个服务预期的。可处理的备选响应(Fallback),而不是长时间的等待或者抛出调用方法处理的异常,这样就可以保证服务调用方的线程不会长时间被不必要的占用,从而避免了故障在分布式系统中的蔓延,直至雪崩。

官网:https://github.com/NetFlix/Hystrix/wiki

服务熔断

熔断机制是应对雪崩效应的一种微服务链路保护机制。

当筛出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在springcloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand

<!-- 熔断机制- 服务提供者  -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
@RestController
public class DeptController {
    @GetMapping("/dept/list")
    @HystrixCommand(fallbackMethod = "hystrixQueryAll")  //熔断的注解以及回调的方法
    public List<Dept> queryAll(){
        return deptService.queryAll();
    }
    
    //备用方法
    public List<Dept> hystrixQueryAll(){
        return new ArrayList<>();
    }
 
//=======================启动类================================    
@SpringBootApplication
@EnableEurekaClient //服务启动注册到eureka中
@EnableDiscoveryClient  //服务发现
@EnableCircuitBreaker  //打开对熔断的支持
public class DeptProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderApplication.class,args);
    }
}

真实环境中接口不会直接返回Dept这种业务对象,而是封装后的Dto对象,里面包含了返回状态、返回码、返回信息等,对异常情况的封装比较友好

服务降级

如果是整个类的话需要工厂实现

package com.kaka.springcloud.service;

import com.kaka.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;

public class DeptClientServiceFallbackFactory implements FallbackFactory {
    @Override
    public DeptClientFeignService create(Throwable throwable) {
        return new DeptClientFeignService(){
            @Override
            public Boolean addDept(Dept dept) {
                return null;
            }
            @Override
            public Dept queryById(Long id) {
                return null;
            }
            @Override
            public List<Dept> queryAll() {
                return null;
            }
        };
    }
}
//在上面重写的方法里编写熔断逻辑

@FeignClient(value = "eureka上服务名称", fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientFeignService {

    @PostMapping("/dept/add")
    public Boolean addDept(Dept dept);

    @GetMapping("/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();
}
###客户端application.yml
#开启降级
feign:
  hystrix:
    enabled: true

服务熔断:服务器,某个服务超时或者异常,引起熔断

服务降级:客户端,从整体网站请求负载考虑,当某个服务熔断或者关闭之后服务将不再调用~

此时客户端可以准备一个FallBackFactory,返回一个缺省值。

DashBoard流监控

<!--- 消费者   -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>


<!--- 被监控的微服务 服务提供者--->
<!-- 完善监控信息 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.kaka.springcloud"})
@EnableHystrixDashboard  //消费者开启监控服务
public class DeptConsumerApplication {

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

访问 localhost:9001/hystrix 豪猪

alt

提供服务方,增加一个servlet

SpringBootApplication
@EnableEurekaClient //服务启动注册到eureka中
@EnableDiscoveryClient  //服务发现
@EnableCircuitBreaker  //打开对熔断的支持
public class DeptProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderApplication.class,args);
    }
    
    
    //增加一个servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());

        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
    
}

alt

alt

Zuul

Zuul包含了对请求的路由和过滤两个最主要的功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,以后的访问服务都是通过Zuul跳转后获得。

注意:Zuul最终还是会注册进Eureka

提供:代理+路由+过滤三大功能

官网:https://github.com/Netflix/zuul

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
server:
  port: 9527

spring:
  application:
    name: springcloud-zuul

#eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://eureka001.com:7001/eureka/,http://eureka002.com:7002/eureka/,http://eureka003.com:7003/eureka/
  instance:
    instance-id: zuul9527.com
    prefer-ip-address: true

#info配置
info:
  app.name: zuul
  company.name: kaka.com
    
zuul:
  routes:
    mydept.serviceId: spring-cloud-provider
    mydept.path: /mydept/**
  ignored-services: spring-cloud-provider #不能在使用这个路径访问了 也可以用通配符  "*" 以后会有很多歌服务
  prefix: /kaka  #设置公共的访问路径前缀

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication.class,args);
    }
}

访问 localhost:9527/kaka/mydept/dept/get/1 即可

SpringCloud Config

一套集中式、动态的配置管理设施

spring cloud config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。

分服务端和客户端两部分

  • 服务端:也成为分布式配置中心,他是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息、加密、解密信息等访问接口
  • 客户端:通过指定的配置中心来管理应用资源,以及业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就把有助于对环境配置进行版本管理。并且可以通过git客户端工具来方便的管理和访问配置内容。

作用

  • 集中管理配置文件
  • 不同环境,不同配置,动态化的配置更新,分环境部署
  • 运行期间动态调整配置,不再需要在服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
  • 当配置发生变动时,服务不再重启,即可感知到配置的变化,并应用新的配置
  • 将配置信息以rest接口的形式暴露

由于springcloud config默认使用git来存储配置文件

服务端

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 完善监控信息-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
spring:
  application:
    name: cosumerApplication
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/xxx/xxx.git    #仓库地址  要用https的
@EnableConfigServer   //添加支持注解
public class DeptConsumerApplication {

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

客户端

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
# bootstrap.yml文件(系统级别的配置,而application.yml是用户级别的配置)
spring:
  cloud:
    config:
      uri: http:localhost:8080  #服务端地址
      name: application  #需要从git上获取的资源名称,不需要后缀
      profile: dev
      label: master


#application.yml
spring:
  application:
    name: cosumerApplication
/**
在配置类中使用注解读取远程的配置信息
*/

@Value("${spring.application.name}")
private String appName;

套路

  • 导入依赖
  • 编写配置
  • 加注解@EnabledXXXXXXX

以上内容如有错误之处,欢迎指正!!!

学习源为:https://space.bilibili.com/95256449/channel/seriesdetail?sid=393820&ctype=0