其他分享
首页 > 其他分享> > SpingCloud狂神说笔记整理

SpingCloud狂神说笔记整理

作者:互联网

前言

1.1SpringCloud的常用五大组件

1.2常见面试题

一、微服务概述

1.1、什么是微服务

微服务(Microservice Architecture)是近几年流行的一种架构思想,关于它的概念很难一言以蔽之。究竟什么是

微服务呢?我们在此引用 ThoughtWorks 公司的首席科学家 Martin Fowler于2014年提出的一段话:

原文:https://martinfowler.com/articles/microservices.html
汉化:https://www.cnblogs.com/liuning8023/p/4493156.html

我们从技术维度来理解下:

微服务与微服务架构

微服务

强调的是服务的大小,他关注的是某一个点,是具体解决某一个问题/提供落地对应服务的一个服务应用,狭义的看,可以看做是IDEA中的一个个微服务工程,或者Moudel

微服务架构

一种新的架构形式,Martin Fowler,2014提出!

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建。

微服务优缺点

优点

缺点

微服务技术栈

二、SpringCloud入门

1.SpringCloud是什么

Spring官网:https://spring.io/


2.SpringCloud和SpringBoot关系

SpringBoot专注于快速方便的开发单个个体微服务

SpringCloud是关注全局的微服务协调整理治理框架,它将SpringBoot开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等集成服务。

SpringBoot可以离开SpringClooud独立使用,开发项目,但是SpringCloud离不开SpringBoot,属于依赖关系

3.Dubbo 和 SpringCloud 对比

Dubbo SpringCloud
服务注册中心 Zookeeper Spring Cloud Netfilx Eureka
服务调用方式 RPC REST API
服务监控 Dubbo-monitor Spring Boot Admin
断路器 不完善 Spring Cloud Netfilx Hystrix
服务网关 Spring Cloud Netfilx Zuul
分布式配置 Spring Cloud Config
服务跟踪 Spring Cloud Sleuth
消息总栈 Spring Cloud Bus
数据流 Spring Cloud Stream
批量任务 Spring Cloud Task

最大区别:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。

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

品牌机与组装机的区别
很明显,Spring Cloud的功能比DUBBO更加强大,涵盖面更广,而且作为Spring的拳头项目,它也能够与Spring Framework、Spring Boot、Spring Data、Spring Batch等其他Spring项目完美融合,这些对于微服务而言是至关重要的。使用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了,总是让人不怎么放心,但是如果你是一名高手,那这些都不是问题;而Spring Cloud就像品牌机,在Spring Source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了解。

社区支持与更新力度
最为重要的是,DUBBO停止了5年左右的更新,虽然2017.7重启了。对于技术发展的新需求,需要由开发者自行拓展升级(比如当当网弄出了DubboX),这对于很多想要采用微服务架构的中小软件组织,显然是不太合适的,中小公司没有这么强大的技术能力去修改Dubbo源码+周边的一整套解决方案,并不是每一个公司都有阿里的大牛+真实的线上生产环境测试过。

总结:
曾风靡国内的开源 RPC 服务框架 Dubbo 在重启维护后,令许多用户为之雀跃,但同时,也迎来了一些质疑的声音。互联网技术发展迅速,Dubbo 是否还能跟上时代?Dubbo 与 Spring Cloud 相比又有何优势和差异?是否会有相关举措保证 Dubbo 的后续更新频率?

人物:Dubbo重启维护开发的刘军,主要负责人之一

刘军,阿里巴巴中间件高级研发工程师,主导了 Dubbo 重启维护以后的几个发版计划,专注于高性能RPC 框架和微服务相关领域。曾负责网易考拉 RPC 框架的研发及指导在内部使用,参与了服务治理平台、分布式跟踪系统、分布式一致性框架等从无到有的设计与开发过程。

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

4.Dubbo 和 SpringCloud 对比

5.SpringCloud在哪下

官网:http://projects.spring.io/spring-cloud/
这玩意的版本号有点特别

SpringCloud没有采用数字编号的方式命名版本号,而是采用了伦敦地铁站的名称,同时根据字母表的顺序来对应版本时间顺序,比如最早的Realse版本:Angel,第二个Realse版本:Brixton,然后是Camden、Dalston\Edgware,目前最新的是Hoxton SR4 CURRENT GA通用稳定版。

自学参考书:

三、Rest微服务构建

3.1介绍

我们会使用一个Dept部门模块做一个微服务通用案例

Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务。

回忆Spring,SpringMVC,MyBatis等以往学习的知识。。。

Maven的分包分模块架构复习

一个简单的Maven模块结构是这样的:
**
一个简单的Maven模块结构是这样的:**
app-parent: 一个父项目(app-parent)聚合了很多子项目(app-util\app-dao\app-web...)
|-- pom.xml
|
|-- app-core
||---- pom.xml
|
|-- app-web
||---- pom.xml

一个父工程带着多个子Module子模块

SpringCloud父工程(Project)下初次带着3个子模块(Module)

3.2.SpringCloud版本选择

大版本说明

3.3 创建父工程

新建父工程Maven项目 springcloud,切记Packageing是pom模式
主要是定义POM文件,将后续各个子模块公用的jar包等统一提取出来,类似一个抽象父类

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>org.example</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springcloud-api</module>
        <module>springcloud-provider-dept-8001</module>
        <module>springcloud-consumer-dept-80</module>
        <module>springcloud-eureka7001</module>
        <module>springcloud-eureka7002</module>
        <module>springcloud-eureka7003</module>
    </modules>

    <!--打包方式 pom-->
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.12</junit.version>
        <lombok.version>1.16.18</lombok.version>
        <log4j.version>1.2.17</log4j.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencyManagement>
        <dependencies>
            <!--SpringCloud的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--SpringBoot的依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.4.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--数据库-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <!--数据源-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>

            <!--SpringBoot启动器-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>

            <!--=========日志相关=============-->
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <!--logback-->
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!--log4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>

            <!--lombok-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>
</project>

上面是父工程的pom文件,父工程下面有许多子模块

3.4创建api公共模块,里面存放一些公共的实体类

3.5创建provider模块

1,编写pom,xml
2.配置application.yml
3.根据配置新建mybatis-config.xml文件
4.编写部门dao以及对应的mapper
5.编写service接口以及实现类
6.编写controller类提供Rest服务

//提供Restful服务
@RestController
@RequestMapping("/dept")
public class DeptController {

    //获取一些配置信息,得到具体的微服务
    @Autowired
    private DiscoveryClient client;

    @Autowired
    private DeptService service;

    @PostMapping("/add")
    public boolean addDept(Dept dept){
        boolean b = service.addDept(dept);
        return b;
    }

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

    @GetMapping("/list")
    public List<Dept> queryAll(){
        return service.queryAll();
    }
}

7.编写DeptProvider的主启动类

3.6创建Comsumer消费者模块

大致跟上面差不多,具体看代码
例如

@RestController
public class DeptCounsumerController {

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

    private static final String REST_URL_PREFIX="http://springcloud-provider-dept";
   // springcloud-provider-dept  SPRINGCLOUD-PROVIDER-DEPT

    //消费者,不应该有service层
    //RestTemplate....供我们直接调用就可以了,注册到spring中
    //(url,实体:map,Class<T> responseType)
    @Autowired
    private RestTemplate restTemplate;//提供多种便捷访问远程http服务的方法,简单的Restful服务模板

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

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

    @RequestMapping("/consumer/dept/add")
    public boolean addDept(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
    }
}

了解RestTemplate:

四、Eureka服务注册与发现

4.1什么是Eureka

Eureka:怎么读?

Netflix 在设计Eureka 时,遵循的就是AP原则
CAP原则又称CAP定理,指的是在一个分布式系统中

CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾

Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心,比如Zookeeper;

4.2原理讲解

Eureka的基本架构:

Eureka 包含两个组件:Eureka ServerEureka Client

Eureka Server 提供服务注册服务,各个节点启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉(默认周期为90秒)

三大角色

4.3服务构建

1.erueka-server服务端

  1. 建立springcloud-eureka-7001模块
  2. 编辑pom.xml
 <parent>
        <artifactId>springcloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eureka</artifactId>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <!--导包-->
    <dependencies>
         <!--erueka-server服务端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>
  1. application.yml
server:
  port: 7001

#Eureka配置
eureka:
  instance:
    hostname: localhost  #Eureka服务端的实例名称
  client:
    register-with-eureka: false  #表示是否想eureka注册中心注册自己
    fetch-registry: false  #如果为false,则表示自己为注册中心,等别人过来连就好了
    service-url:  #监控页面
     #单机
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
        # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个defaultZone地址
      #  http://localhost:7001/eureka/

编写主启动类

//启动之后访问http://localhost:7001
@SpringBootApplication
@EnableEurekaServer  //EnableEurekaServer 服务端的启动类,注册中心,可以接收别人注册进来
public class EurekaServer_7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer_7001.class,args);
    }
}

启动,访问测试:

2.erueka-client客户端
修改之前创建的springcloud-provider-dept-8001模块

  1. 导入Eureka依赖
<!--eureka,注册到服务中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
  1. application.yml中增加eureka支持
#Eureka的配置,注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001   #修改erueka上的默认描述信息

03.主启动类添加注解

@SpringBootApplication
@EnableEurekaClient   //在服务启动后,自动注册到eureka中
public class DeptProvider8001 {
   public static void main(String[] args) {
       SpringApplication.run(DeptProvider8001.class,args);
   }
}

先启动7001服务端后启动8001客户端进行测试,然后访问监控页http://localhost:7001/ 产看结果如图,成功

actuator与注册微服务信息完善

修改springcloud-provider-dept-8001模块中application.yml

#Eureka的配置,注册到哪里
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001   #修改erueka上的默认描述信息

# info配置
info:
  app.name: hejinjie-springcloud
  company.name: blog-hejinjie

重启8001,刷新

如果此时停掉springcloud-provider-dept-8001 等30s后 监控会开启保护机制:

配置关于服务加载的监控信息

pom.xml中添加依赖

<!--完善监控信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

application.yml中添加配置

# info配置
info:
  app.name: hejinjie-springcloud
  company.name: 阜阳师范大学-计信院

此时点击跳转页面如下

Eureka的自我保护机制

自我保护机制:好死不如赖活着
一句话总结:某时刻某一个微服务不可以用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存!

springcloud-provider-dept-8001服务发现 Discovery(团队开发比较常用)

对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息。【对外暴露服务】

修改springcloud-provider-dept-8001工程中的DeptController
新增一个方法

@GetMapping("/discovery")
    public Object discovery(){
        //获得微服务列表清单
        List<String> list = client.getServices();
        System.out.println("client.getServices()==>"+list);
        //得到一个具体的微服务!
        List<ServiceInstance> serviceInstanceList =
                client.getInstances("springcloud-provider-dept");
        for (ServiceInstance serviceInstance : serviceInstanceList) {
            System.out.println(
                    serviceInstance.getServiceId()+"\t"+
                            serviceInstance.getHost()+"\t"+
                            serviceInstance.getPort()+"\t"+
                            serviceInstance.getUri()
            );
        }
        return this.client;
    }

主启动类增加一个注释

@SpringBootApplication
@EnableEurekaClient   //在服务启动后,自动注册到eureka中
@EnableDiscoveryClient  //服务发现
public class DeptProvider8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider8001.class,args);
    }
}

启动Eureka服务,启动8001提供者
访问测试 http://localhost:8001/dept/discovery

consumer访问服务

springcloud-consumer-dept-80
修改DeptConsumerController增加一个方法

 @GetMapping("/consumer/dept/discovery")
    public Object discovery(){
        return
                restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class);
    }

启动80,访问http://localhost/consumer/dept/discovery

4.4 Eureka:集群环境配置


在hosts文件最后加上,要访问的本机名称,默认是localhost

修改3个EurekaServer的yaml文件夹
在集群中使springcloud-eureka-7001关联springcloud-eureka-7002、springcloud-eureka-7003

7001

server:
  port: 7001

#Eureka配置
eureka:
  instance:
    hostname: eureka7001.com  #Eureka服务端的实例名称
  client:
    register-with-eureka: false  #表示是否想eureka注册中心注册自己
    fetch-registry: false  #如果为false,则表示自己为注册中心,等别人过来连就好了
    service-url:  #监控页面
     #单机
      # defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
        # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个defaultZone地址
      #  http://localhost:7001/eureka/
    #集群(关联)
        defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

7002,7003与上面类似

将8001微服务发布到1台eureka集群配置中,发现在集群中的其余注册中心也可以看到,但是平时我们
保险起见,都发布!
通过springcloud-provider-dept-8001下的yml配置文件,修改Eureka配置:配置服务注册中心地址

#Eureka的配置,注册到哪里
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka/
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provider-dept-8001   #修改erueka上的默认描述信息

启动集群测试

访问http://eureka7001.com:7001/

这就是模拟集群,一个项目搭载到三个服务器上。

4.5 对比和Zookeeper区别---重要

1.回顾CAP原则

RDBMS (Mysql、Oracle、sqlServer)===>ACID

NoSQL(redis、mongdb)===> CAP

2.ACID是什么?

3.CAP是什么?

CAP的三进二:CA、AP、CP

CAP理论的核心

一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求

根据CAP原理,将NoSQL数据库分成了满足CA原则,满足CP原则和满足AP原则三大类:

作为服务注册中心,Eureka比Zookeeper好在哪里?

著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(容错性)。

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

Zookeeper保证的是CP

当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30~120s,且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因为网络问题使得zk集群失去master节点是较大概率会发生的事件,虽然服务最终能够恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。

Eureka保证的是AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其他节点,只要有一台Eureka还在,就能保住注册服务的可用性,只不过查到的信息可能不是最新的,除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

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

五、Ribbon负载均衡(基于客户端)

5.1Ribbon概述

Ribbon是什么?

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

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

Ribbon能干嘛?


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

负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡软件有 Nginx,Lvs 等等

Dubbo、SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义负载均衡简单分类:

Ribbon的github地址 : https://github.com/NetFlix/ribbon

5.2 Ribbon实现负载均衡

Ribbon的初步配置

1.复制springcloud-consumer-dept-80工程 springcloud-consumer-dept-ribbon-80

2.修改pom.xml,添加Ribbon相关的配置

 <!--集成Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

3.修改application.yml , 追加Eureka的服务注册地址

server:
  port: 80
# erueka配置
eureka:
  client:
    register-with-eureka: false  #不向eureka注册自己
    service-url:
      defaultZone: http://eureka7003.com:7003/eureka/,
      http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

4.对里面的ConfigBean方法加上注解@LoadBalanced在 获得Rest时加入Ribbon的配置,开启Ribbon

@Configuration  //相当于spring中的applicationContext.xml

public class DeptConfig {
    //配置负载均衡实现RestTemplate
    @Bean    //原来是<bean></bean>,注入到Spring
    @LoadBalanced  //配置负载均衡实现RestTemplate
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

5.主启动类添加@EnableEurekaClient,开启Eureka客户端

//Ribbon 和 Eureka 整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient //开启Eureka客户端
public class DeptRibbonConsumer80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptRibbonConsumer80.class,args);
    }
}

6.修改DeptConsumerController客户端访问类,之前的写的地址是写死的,现在需要变化!

 //通过Ribbon,这里应该是一个变量,通过服务名来访问
    //private static final String REST_URL_PREFIX="http://localhost:8001";
    private static final String REST_URL_PREFIX="http://springcloud-provider-dept";
   // springcloud-provider-dept  SPRINGCLOUD-PROVIDER-DEPT

7.先启动三个Eureka集群,在启动springcloud-provider-dept-8001,注册进Eureka,启动springcloud-consumer-dept-ribbon-80
测试
http://localhost/consumer/dept/list

小结:Ribbon和Eureka整合后,客户端可以直接调用,而不用关心端口号和ip地址

Ribbon负载均衡

架构图:

Ribbon不用向Eureka注册自己,上图有误

Ribbon在工作时分成两步

其中Ribbon提供了多种策略,比如轮询(默认),随机和根据响应时间加权重,,,等等

1.参考springcloud-provider-dept-8001,新建两份,分别为8002,8003!

2.修改端口号

3.新建8002/8003数据库,各自微服务分别连接各自的数据库,复制DB1!

4.修改各自的Yml文件

instance:
    instance-id: springcloud-provider-dept-8002   #修改erueka上的默认描述信息

#Spring配置
spring:
  application:
    name: springcloud-provider-dept

测试
启动3个Eureka集群,启动3个provider微服务,启动消费者服务
测试三个都通过后
http://localhost:8001/dept/list
http://localhost:8002/dept/list
http://localhost:8003/dept/list
再测试
http://localhost/consumer/dept/list
多刷新几次,并观察结果
每次访问都都是集群中的某个服务者提供者,这种情况叫做轮询,轮询算法还可以自定义

如何自定义轮询算法

Ribbon核心组件IRule
IRule:根据特定算法从服务列表中选取一个要访问的服务!

查看分析源码:

  1. IRule
  2. ILoadBalancer
  3. AbstractLoadBalancer
  4. AbstractLoadBalancerRule:这个抽象父类十分重要!核心
  5. RoundRobinRule
    省略。。。。

切换为随机策略实现试试,在ConfigBean中添加方法

public IRule myRule(){
	//使用我们重新选择的随机算法,替代默认的轮询!
	return new RandomRule();
}

...........................................................

六、Feign负载均衡

6.1 Feign概述

feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。

Spring Cloud集成了Ribbon和Eureka,可在使用Feign时提供负载均衡的http客户端。

只需要创建一个接口,然后添加注解即可!

feign ,主要是社区,大家都习惯面向接口编程。这个是很多开发人员的规范。调用微服务访问两种方法

Feign能干什么?

Feign集成了Ribbon

6.2Feign使用步骤

1、参考springcloud-consumer-dept-ribbon-80
2、新建springcloud-consumer-dept-feign-80

3、springcloud-consumer-dept-feign-80修改pom.xml , 添加对Feign的支持。

<!--Feign相关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

4、修改springcloud-api工程

@Service  //注入到Spring,方便调用
//微服务客户端注解,value:指定微服务的名字,这样就可以使Feign客户端直接找到对应的微服务
@FeignClient(value = "springcloud-provider-dept")
public interface DeptClineService {
    @PostMapping("/dept/add")
    public boolean addDept(Dept dept);
    @GetMapping("/dept/get/{id}")
    public Dept queryById(Long deptno);
    @GetMapping("/dept/list")
    public List<Dept> queryAll();
}

5.修改springcloud-consumer-dept-feign
原本是


@RestController
public class DeptCounsumerController {

    /**
     * 理解:消费者,不应该有service层
     * RestTemplate....供我们直接调用就可以了,注册到spring中
     * (url,实体:map,Class<T> responseType)
     * 提供多种便捷访问远程http服务的方法,简单的Restful服务模板
     * */
   

    
	/**
     * 服务提供方前缀
     * 通过Ribbon,这里应该是一个变量,通过服务名来访问
     * */
    private static final String REST_URL_PREFIX="http://springcloud-provider-dept";
    // private static final String REST_URL_PREFIX="http://localhost:8001";


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

    @RequestMapping("/consumer/dept/list")
    public List<Dept> queryAll(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
        //getForObject:(服务提供方地址(接口),参数实体,返回类型.class)
    }

    @RequestMapping("/consumer/dept/add")
    public boolean addDept(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
        // postForObject:(服务提供方地址(接口),参数实体,返回类型.class)
    }

    @GetMapping("/consumer/dept/discovery")
    public Object discovery(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery",Object.class);
    }

}

修改后

@RestController
public class DeptCounsumerController {

    /**
     * 理解:消费者,不应该有service层
     * RestTemplate....供我们直接调用就可以了,注册到spring中
     * (url,实体:map,Class<T> responseType)
     * 提供多种便捷访问远程http服务的方法,简单的Restful服务模板
     * */
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    DeptClineService service=null;

    /**
     * 服务提供方前缀
     * 通过Ribbon,这里应该是一个变量,通过服务名来访问
     * */
    private static final String REST_URL_PREFIX="http://springcloud-provider-dept";
    // private static final String REST_URL_PREFIX="http://localhost:8001";

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept queryById(@PathVariable("id") Long id){
        return this.service.queryById(id);
    }

    @RequestMapping("/consumer/dept/list")
    public List<Dept> queryAll(){
        return this.service.queryAll();
    }

    @RequestMapping("/consumer/dept/add")
    public boolean addDept(Dept dept){
        return this.service.addDept(dept);
    }

}

6.修改主启动类DeptConsumerFeign,增加一个注解

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.hejinjie"})

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

测试
http://localhost/consumer/dept/list
结果:Feign自带负载均衡配置项

小结
Feign通过接口的方法调用Rest服务 ( 之前是Ribbon+RestTemplate )

该请求发送给Eureka服务器 (http://MICROSERVICECLOUD-PROVIDER-DEPT/dept/list)

通过Feign直接找到服务接口,由于在进行服务调用的时候融合了Ribbon技术,所以也支持负载均衡作用!
feign其实不是做负载均衡的,负载均衡是ribbon的功能,feign只是集成了ribbon而已,但是负载均衡的功能还是feign内置的ribbon再做,而不是feign。
feign的作用的替代RestTemplate,性能比较低,但是可以使代码可读性很强。

Feign和Ribbon的比较

Ribbon:Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡器它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载它在联合 Eureka 使用时ribbonServerList 会被 DiscoveryEnabledNIWSServerList 重写,扩展成从 Eureka 注册中心获取服务端列表同时它也会用 NIWSDiscoveryPing 来取代 IPing,它将职责委托给 Eureka 来确定服务端是否已经启动。 使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。

用法:

1.RestTemplate注入到容器中,@LoadBalanced注解使用默认负载均衡算法(可以使用自定义)
2.用** REST_URL_PREFIX** 指定请求地址 , 使用 restTemplate 模拟 http 请求。@RestController

Feign :是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,面向接口;然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写 客户端变得非常容易。类似于 mybatis 的 @Mapper注解 。

用法:

在上面

七、Hystrix断路器,服务熔断

Hystrix概述

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

服务雪崩
多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B 和微服务C又调用其他的微服务,这就是所谓的 “扇出”、如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的 “雪崩效应”。


多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B 和微服务C又调用其他的微服务,这就是所谓的 “扇出”、如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的 “雪崩效应”

我们需要 ·弃车保帅·

什么是Hystrix?
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级
联故障,以提高分布式系统的弹性。
“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩.

有什么用?

当许多后端系统中有一个潜在阻塞服务时,它可以阻止整个用户请求:

随着大容量通信量的增加,单个后端依赖项的潜在性会导致所有服务器上的所有资源在几秒钟内饱和。

应用程序中通过网络或客户端库可能导致网络请求的每个点都是潜在故障的来源。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,从而备份队列、线程和其他系统资源,从而导致更多跨系统的级联故障。

当使用Hystrix包装每个基础依赖项时,上面的图表中所示的体系结构会发生类似于以下关系图的变化。每个依赖项是相互隔离的,限制在延迟发生时它可以填充的资源中,并包含在回退逻辑中,该逻辑决定在依赖项中发生任何类型的故障时要做出什么样的响应:


官网资料:https://github.com/Netflix/Hystrix/wiki

服务熔断

什么是服务熔断

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

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

熔断机制的注解是 @HystrixCommand

服务熔断可以解决的问题:

入门案例

1.参考springcloud-provider-dept-8001,新建springcloud-provider-dept-hystrix-8001
将之前8001的所有东西拷贝一份

2.修改pom文件,添加依赖

<!--Hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

3.修改yml配置文件,修改eureka实例的id

#Eureka的配置,注册到哪里
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka/
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-provide-dept-hystric-8001  #修改erueka上的默认描述信息
    prefer-ip-address: true  #改为true默认显示的是ip地址,而不是Localhost

prefer-ip-address: true:

4.修改Controller

@RestController
@RequestMapping("/dept")
public class DeptController {

    //获取一些配置信息,得到具体的微服务
    @Autowired
    private DiscoveryClient client;

    @Autowired
    private DeptService service;

    /**
     * 根据id查询部门信息
     * HystrixCommand:一旦调用该方法发生异常后,就执行hystrixGet方法中的代码
     * @Param:id
     */
    @HystrixCommand(fallbackMethod = "hystrixGet")
    @GetMapping("/get/{id}")//根据id查询
    public Dept queryById(@PathVariable("id") Long id){
        Dept dept = service.queryById(id);
        if(dept==null){
            throw new RuntimeException("该id:"+id+"没有对应的的信息");
        }
        return dept;
    }

    /**
     * 根据id查询备选方案(熔断)
     * @Param:id
     * @return
     * */
    public Dept hystrixGet(@PathVariable("id") Long id){
        return new Dept().setDeptno(id).setDname("这个id=>"+id+",没有对应的信息,null---@Hystrix~").setDb_source("在Mysql中没有这个数据库");
    }

}

5.为主启动类添加熔断注解

@SpringBootApplication
@EnableEurekaClient   //在服务启动后,自动注册到eureka中
@EnableDiscoveryClient  //服务发现
@EnableCircuitBreaker //添加对熔断支持的注解
public class DeptProvider8001hysric {
    public static void main(String[] args) {
        SpringApplication.run(DeptProvider8001hysric.class,args);
    }
}

测试
1、启动Eureka集群
2、启动主启动类 DeptProviderHystrix8001
3、启动客户端 springcloud-consumer-dept-80
4、访问 http://localhost/consumer/dept/get/111

使用熔断后,当访问一个不存在的id时,显示如下

不使用熔断的话

因此,为了避免因某个微服务后台出现异常或错误而导致整个应用或网页报错,使用熔断是必要的

服务降级

1.什么是服务降级?

整体资源快不够了,忍痛先将某些服务关闭,等度过难关,再开启回来

服务降级是指当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务

资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证核心功能服务的可用性,都要对某些服务降级处理。比如当双11活动时,把交易无关的服务统统降级,如查看蚂蚁深林,查看历史订单等等。

服务降级主要用于什么场景呢?当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,可以将一些 不重要或不紧急的服务或任务进行服务的延迟使用或暂停使用。

降级的方式可以根据业务来,可以延迟服务,比如延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行 ;或者在粒度范围内关闭服务,比如关闭相关文章的推荐。


如上图,当某一时间内。A的访问量暴增,而B和C的访问量较少,这时候就要B和C关闭一些服务功能,去承担A的部分服务,从而为A分担压力,这叫做服务降级

2.服务降级需要考虑的问题
1)那些服务是核心服务,哪些服务是非核心服务
2)那些服务可以支持降级,那些服务不能支持降级,降级策略是什么
3)除服务降级之外是否存在更复杂的业务放通场景,策略是什么?

3.自动降级分类

服务降级处理是在客户端实现完成的,与服务端没有关系
入门案例
修改springcloud-api工程,根据已经有的DeptClientService接口新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory

/**
 * 服务降级
 * */

@Component//千万不能忘记
public class DeptClientServiceFallbackFactory implements FallbackFactory {
    @Override
    public DeptClineService create(Throwable throwable) {
        return new DeptClineService() {
            @Override
            public boolean addDept(Dept dept) {
                return false;
            }

            @Override
            public Dept queryById(Long id) {
                 return new Dept()
                        .setDeptno(id)
                        .setDname("id=>" + id + "没有对应的信息,客户端提供了降级的信息,这个服务现在已经被关闭")
                        .setDb_source("没有数据~");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }
        };
    }
}


修改springcloud-api工程,DeptClientService接口在注解 @FeignClient中添加fallbackFactory属性值

import java.util.List;
@Service  //注入到Spring,方便调用
//@FeignClient:服务客户端注解,value:指定微服务的名字,这样就可以让Feign客户端直接找到对应的微服务
@FeignClient(value = "springcloud-provider-dept",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClineService {
    @PostMapping("/dept/add")
    public boolean addDept(Dept dept);
    @GetMapping("/dept/get/{id}")
    public Dept queryById(Long deptno);
    @GetMapping("/dept/list")
    public List<Dept> queryAll();
}

修改spring-cloud-consumer-feign中yml.开启降级

server:
  port: 80
# erueka配置
eureka:
  client:
    register-with-eureka: false  #不向eureka注册自己
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
feign:
  hystrix:
    enabled: true

测试

  1. 启动eureka集群
  2. 启动 springcloud-provider-dept-hystrix-8001
  3. 启动 springcloud-consumer-dept-feign-80
  4. 正常访问测试
    http://localhost/consumer/dept/get/1
  5. 故意关闭微服务启动 springcloud-provider-dept-hystrix-8001
  6. 客户端自己调用提示
    http://localhost/consumer/dept/get/1
    此时服务端provider已经down了,但是我们做了服务降级处理,让客户端在服务端不可用时
    也会获得提示信息而不会挂起耗死服务器。

小结
服务熔断-->服务端:一般是某个服务故障或者异常引起,类似现实世界中的 “保险丝” , 当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时!
服务降级-->客户端:所谓降级,一般是从整体负荷考虑,就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。

熔断,降级,限流:

3.服务监控 hystrixDashboard
除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等等。

Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控SpringCloud也提供了HystrixDashboard的整合,对监控内容转化成可视化界面!

入门案例
新建工程springcloud-consumer-hystrix-dashboard-9001
1.pom.xml 复制之前的80依赖,再添加两个依赖

<dependencies>

        <!--Hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--实体类和web-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

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

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

        <!--集成Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    </dependencies>

2.主启动类改名 + 新注解@EnableHystrixDashboard
3.所有的Provider微服务提供类(8001/8002/8003) 都需要监控依赖配置
4.在 springcloud-provider-dept-hystrix-8001 启动类中增加一个bean,添加监控

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

    //增加一个Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //访问该页面就是监控页面
        registration.addUrlMappings("/actuator/hystrix.stream");
        return registration;
    }
}

注:springcloud-provide-dept-hystric-8001中的yml里添加

hystrix:
  dashboard:
    proxy-stream-allow-list: "localhost"
#暴露全部的监控信息
management:
  endpoints:
    web:
      exposure:
        include: "*"

测试一

  1. 启动eureka集群
  2. 启动springcloud-consumer-hystrix-dashboard-9001
  3. 在 springcloud-provider-dept-hystrix-8001 启动类中增加一个bean
@SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard
public class DeptConsumer80dashboard {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer80dashboard.class,args);
    }

    //增加一个Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        //访问该页面就是监控页面
        registration.addUrlMappings("/actuator/hystrix.stream");
        return registration;
    }

}

测试一

  1. 启动eureka集群
  2. 启动springcloud-consumer-hystrix-dashboard-9001
  3. 在 springcloud-provider-dept-hystrix-8001 启动类中增加一个bean
  4. 启动 springcloud-provider-dept-hystrix-8001
  5. http://localhost:8001/dept/get/1
  6. http://localhost:8001/actuator/hystrix.stream 【查看1秒一动的数据流】



八、Zuul路由网关

Zull概述

1.什么是Zull
Zuul包含了对请求的路由和过滤两个最主要的功能:

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


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

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

2.Zull能干嘛

官方文档:https://github.com/Netflix/zuul/

入门案列
1.新建springcloud-zuul模块,并导入依赖

<dependencies>

        <!--Hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--实体类和web-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

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

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

        <!--集成Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
    </dependencies>

2.配置yml

server:
  port: 9527

  #spring相关配置
spring:
  application:
    name: springcloud-zuul
    #erueka配置
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: hejinjie.com  #实例的id
    prefer-ip-address: true    #可以显示ip

    #info配置
info:
  app.name: springcloud-zuul-hejinjie
  company.name: 阜阳师范大学

3.创建主启动类

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

4.hosts修改
路径:C:\Windows\System32\drivers\etc\hosts

测试
启动
Eureka集群
一个服务提供类:springcloud-provider-dept-8001
zuul路由
访问 :http://localhost:7001/ 可以看到Zuul路由被注册到网关中心了

测试
不用路由 :http://localhost:8001/dept/get/1

使用路由 :http://myzuul.com:9527/springcloud-provider-dept/dept/get/1

网关 / 微服务名字 / 具体的服务

路由访问映射规则

问题:http://myzuul.com:9527/springcloud-provider-dept/dept/get/2 这样去访问的话,就暴露了我们真实微服务的名称!这不是我们需要的!怎么处理呢?

修改:springcloud-zuul-9527 工程
修改yml

#Zuul路由映射
zuul:
	routes:
		mydept.serviceId: springcloud-provider-dept
		mydept.path: /mydept/**

配置前访问:http://myzuul.com:9527/springcloud-provider-dept/dept/get/1

配置后访问:http://myzuul.com:9527/mydept/dept/get/1

问题,现在访问原路径依旧可以访问!这不是我们所希望的!

原真实服务名忽略

# Zuul路由映射
zuul:
	ignored-services: springcloud-provider-dept # 不能再使用这个服务名访问;
ignored:忽略
	routes:
		mydept.serviceId: springcloud-provider-dept
		mydept.path: /mydept/**

测试:现在访问http://myzuul.com:9527/springcloud-provider-dept/dept/get/1 就访问不了了
上面的例子中,我们只写了一个,那要是有多个需要隐藏,怎么办呢?

#Zuul路由映射
zuul:
	ignored-services: "*" # 通配符 * , 隐藏全部的!
	routes:
		mydept.serviceId: springcloud-provider-dept
		mydept.path: /mydept/**

设置统一公共前缀

#Zuul路由映射
zuul:
	prefix: /kuang
	ignored-services: springcloud-provider-dept
	routes:
		mydept.serviceId: springcloud-provider-dept
		mydept.path: /mydept/**

访问:http://myzuul.com:9527/he/mydept/dept/get/1 ,加上统一的前缀!he,否则,就访问不了了!

九、Spring Cloud Config 分布式配置

标签:服务,SpingCloud,springcloud,笔记,Eureka,dept,http,狂神,eureka
来源: https://www.cnblogs.com/hejinjie-blog/p/15100340.html