Gradle多模块+SpringCloud微服务实践

Updated on with 0 views and 0 comments

  

1.Project

  REP3_CLOUD

2.Cloud 简单配置

2.1.父模块配置

  主要就是配置一下通用依赖和基本插件

 1buildscript {
 2    ext {
 3        springBootVersion = '2.2.2.RELEASE'
 4        springBootManagementVersion = '1.0.8.RELEASE'
 5        springCloudVersion = 'Hoxton.SR1'
 6    }
 7    repositories {
 8        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
 9        mavenCentral()
10        maven { url 'https://repo.spring.io/snapshot' }
11        maven { url 'https://repo.spring.io/milestone' }
12    }
13    dependencies {
14        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
15        classpath("io.spring.gradle:dependency-management-plugin:${springBootManagementVersion}")
16    }
17}
18
19allprojects {
20    group "com.github.rep3.cloud"
21    version "1.0.0"
22}
23
24subprojects {
25    apply plugin: 'java'
26    apply plugin: 'application'
27    apply plugin: 'idea'
28    apply plugin: 'eclipse'
29    apply plugin: 'war'
30    apply plugin: 'org.springframework.boot'
31    apply plugin: 'io.spring.dependency-management'
32    sourceCompatibility = JavaVersion.VERSION_1_8
33    targetCompatibility = JavaVersion.VERSION_1_8
34    jar {
35        enabled = true
36    }
37    bootJar {
38        classifier = 'boot'
39    }
40    repositories {
41        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
42        mavenCentral()
43        maven { url 'https://repo.spring.io/snapshot' }
44        maven { url 'https://repo.spring.io/milestone' }
45    }
46    dependencies {
47        compile(
48                'org.springframework.boot:spring-boot-starter-web',
49                'org.springframework.boot:spring-boot-starter-tomcat',
50                'org.springframework.boot:spring-boot-starter-actuator',
51                'org.springframework.cloud:spring-cloud-starter',
52                'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client',
53                'com.google.guava:guava:23.0'
54
55        )
56        testCompile(
57                "org.springframework:spring-test",
58                "junit:junit:4.12"
59        )
60    }
61    dependencyManagement {
62        imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}") }
63        imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" }
64    }
65}

2.2.EurekaServer 服务注册中心

  配置一下 EurekaServer 端依赖

 1mainClassName = 'com.github.rep3.cloud.eureka.EurekaApplication'
 2springBoot {
 3    mainClassName = 'com.github.rep3.cloud.eureka.EurekaApplication'
 4    buildInfo {
 5        properties {
 6            artifact = 'eureka'
 7            version = '1.0.0'
 8            group = 'com.github.rep3.cloud'
 9            name = 'eureka'
10        }
11    }
12}
13bootJar {
14    classifier = 'boot'
15}
16dependencies {
17    compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
18}

2.3.Zuul 网关

  配置 zuul 依赖

 1mainClassName = 'com.github.rep3.cloud.zuul.Rep3ZuulApplication'
 2springBoot {
 3    mainClassName = 'com.github.rep3.cloud.zuul.Rep3ZuulApplication'
 4    buildInfo {
 5        properties {
 6            artifact = 'zuul'
 7            version = '1.0.0'
 8            group = 'com.github.rep3.cloud'
 9            name = 'zuul'
10        }
11    }
12}
13bootJar {
14    classifier = 'boot'
15}
16dependencies {
17    compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
18}

  Cloud 基本的依赖就配置完成了,接下来就配置配置 YAML 跑起来试试看

3.Springboot

  SpringBoot 不做过多赘述,主要看一下配置文件加载的优先级
配置加载顺序 1->12 越小优先级越高

 11.命令行传入参数
 22.SPRING_APPLICATION_JSON中的属性
 33.java:comp/env中的JNDI属性
 44.Java的系统属性:System.getProperties()
 55.操作系统环境变量
 66.random*配置的随机属性
 77.位于当前应用jar包之外的application-profile.yaml配置文件
 88.位于当前应用jar包之内的application-profile.yaml配置文件
 99.位于jar包之外的appication.yml配置
1010.位于jar包之内的application.yml配置
1111.@Configuration配置类中
1212.应用默认属性比如port默认8080

4.SpringBootActutor

  微服务的监控和管理,将依赖配置在根模块中,所有的子模块 SpringBoot 就可以使用了

1'org.springframework.boot:spring-boot-starter-actuator'

  启动以后查看 /health 就可以看到监控信息了

  放开所有监控点

1management:
2  endpoints:
3    web:
4      exposure:
5        include: '*'

  查看所有监控点

1http://192.168.0.101:8002/actuator

  返回了所有监控点信息

1{"_links":{"self":{"href":"http://192.168.0.101:8002/actuator","templated":false},"archaius":{"href":"http://192.168.0.101:8002/actuator/archaius","templated":false},"beans":{"href":"http://192.168.0.101:8002/actuator/beans","templated":false},"caches-cache":{"href":"http://192.168.0.101:8002/actuator/caches/{cache}","templated":true},"caches":{"href":"http://192.168.0.101:8002/actuator/caches","templated":false},"health-path":{"href":"http://192.168.0.101:8002/actuator/health/{*path}","templated":true},"health":{"href":"http://192.168.0.101:8002/actuator/health","templated":false},"info":{"href":"http://192.168.0.101:8002/actuator/info","templated":false},"conditions":{"href":"http://192.168.0.101:8002/actuator/conditions","templated":false},"configprops":{"href":"http://192.168.0.101:8002/actuator/configprops","templated":false},"env":{"href":"http://192.168.0.101:8002/actuator/env","templated":false},"env-toMatch":{"href":"http://192.168.0.101:8002/actuator/env/{toMatch}","templated":true},"loggers-name":{"href":"http://192.168.0.101:8002/actuator/loggers/{name}","templated":true},"loggers":{"href":"http://192.168.0.101:8002/actuator/loggers","templated":false},"heapdump":{"href":"http://192.168.0.101:8002/actuator/heapdump","templated":false},"threaddump":{"href":"http://192.168.0.101:8002/actuator/threaddump","templated":false},"metrics-requiredMetricName":{"href":"http://192.168.0.101:8002/actuator/metrics/{requiredMetricName}","templated":true},"metrics":{"href":"http://192.168.0.101:8002/actuator/metrics","templated":false},"scheduledtasks":{"href":"http://192.168.0.101:8002/actuator/scheduledtasks","templated":false},"mappings":{"href":"http://192.168.0.101:8002/actuator/mappings","templated":false},"refresh":{"href":"http://192.168.0.101:8002/actuator/refresh","templated":false},"features":{"href":"http://192.168.0.101:8002/actuator/features","templated":false},"service-registry":{"href":"http://192.168.0.101:8002/actuator/service-registry","templated":false}}}
 11./beans: 所有bean信息
 22./caches:缓存信息
 33./health:服务状态
 44./info:服务自定义信息
 55./configprops:应用配置的属性信息
 66./env:应用所有可用环境信息
 77./mappings:所有SpringMvc映射关系信息
 88./metrics:内存信息,线程信息,垃圾回收信息等
 99./dump:运行中的线程信息
1010./trace:http跟踪信息
11...

5.Eureka 服务治理中心

  服务注册 :主要用来开微服务架构中有多少服务都部署在哪里

  服务发现 :服务之间调用关系的处理,比如 A 服务调用 C 服务,会直接像注册中心发出咨询请求,然后注册中心将 C服务的位置清单 返回给 A 服务,A 便获得了 多个C服务的位置 ,然后就可以调用其一。

  SpringCloudEureka 使用 Netflix Eureka 来实现服务注册与发现,既包括了注册端也包括了服务端

  服务端依赖

1compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
2

  客户端依赖

1compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client',

  服务端 Application 开启 @EnableEurekaServer 注解标识为服务中心
同时要配置配置文件,给出 hostname 地址,客户端策略等

1eureka:
2  instance:
3    hostname: localhost
4  client:
5    register-with-eureka: false
6    fetch-registry: false

  客户端需要开启 @EnableEurekaClient 标示为 Eureka 客户端,同时配置出服务中心的地址

1eureka:
2  client:
3    serviceUrl:
4      defaultZone: http://localhost:8000/eureka/
5

5.1 高可用

  上面搭建的只有一个服务注册中心 1 Eureka : N Springboot ,当这一台 Eureka 崩掉以后,所有服务将不能正常访问

  在 Eureka 中,所有服务既是服务提供者,也是服务消费者,Eureka 本身也不例外,现在放开一下配置,并新建一个 Eureka 服务,两者互相注册成服务

1  client:
2    register-with-eureka: false
3    fetch-registry: false

  EurekaA

 1server:
 2  port:8001
 3spring:
 4  application:
 5    name:eureka1
 6eureka:
 7  instance:
 8    hostname: peer1
 9  client:
10    serviceUrl:
11      defaultZone: http://peer2:8000/eureka

  EurekaB

 1server:
 2  port:8000
 3spring:
 4  application:
 5    name:eureka2
 6eureka:
 7  instance:
 8    hostname: peer2
 9  client:
10    serviceUrl:
11      defaultZone: http://peer1:8001/eureka

  最后将 peer 的 ip 地址解析在/etc/hosts 中即可完成 eureka 高可用部署
高可用服务注册

 1spring:
 2  profiles: dev
 3  application:
 4    name: auth
 5server:
 6  port: 8002
 7eureka:
 8  client:
 9    serviceUrl:
10      defaultZone: http://peer1/eureka/,http://peer2/eureka/
11management:
12  endpoints:
13    web:
14      exposure:
15        include: '*'
16

5.2 负载均衡

  ribbon 已经在 zuul 里了所以不必添加依赖
ribbon 和 eureka 联合使用时,在 eureka 的服务发现基础上实现了一套 服务选择 的策略,从而达到每个服务负载均衡

  将 @EnableEurekaClient 替换为 @EnableDiscoveryClient
当使用服务时,ribbon 会轮询服务从而走负载较低的服务达到负载均衡的效果

5.3 Eureka 基础架构

1服务注册中心: Eureka提供的服务端,提供服务注册与发现功能
2服务提供: Eureka提供的客户端,将自己的服务注册到Eureka中
3服务消费者: 消费者从应用中心获取服务列表,从而使消费者知道到何处调用服务,ribbon来实现服务消费,另外还有Feign消费方式

  image.png

 1服务提供者
 21.服务注册
 3	服务提供者在启动的时候`发送REST`请求到Eureka,其中包含了自身服务的信息
 4Eureka接收到请求后,将元数据信息存储在`双层Map`中,第一层key为服务名称,第二层是具体服务实例名称.
 5
 62.服务同步
 7服务提供者可能注册到了不同的注册中心,他们的信息分别被多个eureka维护
 8所以访问其中一台eureka是无法调用到其余服务的,那么将eureka构建成集群模式
 9当服务提供者发送`REST请求`到其中一个注册中心时
10eureka将请求转发给集群中其他的eureka中,从而实现同步
11
123.服务续约
13心跳检测来观测哪些服务死掉,死掉的服务会被剔除出注册中心集群中去
14其中有两个配置项
15服务续约任务调用时间间隔,默认为30秒
16eureka.instance.lease-renewal-interval-in-seconds=30
17服务失效时间默认为90秒
18eureka.instance.lease-expiration-duration-in-seconds=90
19
20服务消费者
211.获取服务
22消费者访问Eureka中的服务时,Eureka会提供一份只读的服务清单,该清单被eureka缓存并每30秒更新一次
23eureka.client.registry-fetch-interval-seconds配置缓存服务清单时间
242.服务调用
25服务消费者获取服务清单后,通过服务名可以获得具体的提供服务的实例名称和服务元数据信息
26客户端决定需要调用哪个服务实例,如果使用ribbon,则使用了轮询方式调用,从而实现客户端的负载均衡
273.服务下线
28正常关闭服务实例时,服务实例发送`REST请求给EurekaServer`告诉服务中心我要下线了,服务中心收到后将服务状态设置为`Down`并传播下线事件
29
30服务注册中心
311.失效剔除
32发生不可预料的错误时导致服务崩溃但eureka没有收到下线消息的时候,由于服务没有及时续约,所以被剔除
332.自我保护
34请求重试,断路器等机制

  部分源码解析

 1//DiscoveryClient 为接口,抽象了一个服务中心基本需要实现的功能
 2// 所以注册中心可以换位任一实现了该接口的类,但不用修改代码
 3public class EurekaDiscoveryClient implements DiscoveryClient {
 4
 5	// 一段描述
 6	public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
 7	// 客户端
 8	private final EurekaClient eurekaClient;
 9	// 客户端配置
10	private final EurekaClientConfig clientConfig;
11
12	// 根据服务ID获取服务实例列表
13	@Override
14	public List<ServiceInstance> getInstances(String serviceId) {
15		List<InstanceInfo> infos = this.eurekaClient.getInstancesByVipAddress(serviceId,
16				false);
17		List<ServiceInstance> instances = new ArrayList<>();
18		for (InstanceInfo info : infos) {
19			instances.add(new EurekaServiceInstance(info));
20		}
21		return instances;
22	}
23
24	//获取服务名称
25	public List<String> getServices() {
26		Applications applications = this.eurekaClient.getApplications();
27		if (applications == null) {
28			return Collections.emptyList();
29		}
30		List<Application> registered = applications.getRegisteredApplications();
31		List<String> names = new ArrayList<>();
32		for (Application app : registered) {
33			if (app.getInstances().isEmpty()) {
34				continue;
35			}
36			names.add(app.getName().toLowerCase());
37
38		}
39		return names;
40	}
41}
42// EurekaClient抽象了许多接口来定义Client的行为
43public interface EurekaClient extends LookupService {
44   // 通过Region获取Applications,Region为yaml中设置的字符串
45   // Applicaions中包含了appNameApplicationMap等
46  // Applications 包装eureka服务器返回的所有注册表信息的类
47    public Applications getApplicationsForARegion(@Nullable String region);
48  // 通过地址获取 服务注册表
49    public Applications getApplications(String serviceUrl);
50  // 注册监听
51    public void registerEventListener(EurekaEventListener eventListener);
52  // 取消监听
53    public boolean unregisterEventListener(EurekaEventListener eventListener);
54  // 心跳检测
55    public HealthCheckHandler getHealthCheckHandler();
56  // 停止服务
57    public void shutdown();
58  // 获取Client的配置
59    public EurekaClientConfig getEurekaClientConfig();
60    public ApplicationInfoManager getApplicationInfoManager();
61}
62........

  EndpointUtils.java

 1// 从属性文件中获取要与eureka客户端对话的所有eureka服务URL的列表。
 2 public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) {
 3        Map<String, List<String>> orderedUrls = new LinkedHashMap<>();
 4        // 从配置文件中读取Region返回
 5	// 通过eureka.client.region属性来定义
 6	String region = getRegion(clientConfig);
 7	// 读取 eureka.client.defaultZone
 8        String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
 9        if (availZones == null || availZones.length == 0) {
10            availZones = new String[1];
11            availZones[0] = DEFAULT_ZONE;
12        }
13        logger.debug("The availability zone for the given region {} are {}", region, availZones);
14        int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones);
15
16        String zone = availZones[myZoneOffset];
17	// 获取zone中所有配置的eurekaServer地址
18        List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
19        if (serviceUrls != null) {
20            orderedUrls.put(zone, serviceUrls);
21        }
22        int currentOffset = myZoneOffset == (availZones.length - 1) ? 0 : (myZoneOffset + 1);
23        while (currentOffset != myZoneOffset) {
24            zone = availZones[currentOffset];
25            serviceUrls = clientConfig.getEurekaServerServiceUrls(zone);
26            if (serviceUrls != null) {
27		// 最后放入 服务列表中 
28                orderedUrls.put(zone, serviceUrls);
29            }
30            if (currentOffset == (availZones.length - 1)) {
31                currentOffset = 0;
32            } else {
33                currentOffset++;
34            }
35        }
36        if (orderedUrls.size() < 1) {
37            throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!");
38        }
39        return orderedUrls;
40    }

  服务注册

  在 DiscoveryClient 的构造函数中调用了 initScheduledTasks 函数,初始化一些任务
image.png
函数中实力化了一个 InstanceInfoReplicator
image.png
该类中的 run 函数,这句就是调用注册了,
image.png
image.png
在往下就是 http 层了,层层专递的 InstanceInfo 就是实例的一些配置信息了
image.png

  服务获取与续约

  还在 initScheduledTasks

  image.png

  registryFetchIntervalSeconds:eureka.client.registry-fetch-interval-seconds
renewalIntervalInSecs:eureka.instance.lease-renewal-interval-in-seconds
其最后也是通过 RestTemplate 去请求服务端

6.Ribbon

  负载均衡设备/模块 都会维护一个下挂可用的服务清单,发送心跳检测
剔除不可用设备,当客户端发送请求到负载均衡设备时,该设备按照某种
算法,从维护的清单中抽取出一台服务器,并进行转发。

  SpringCloudRibbon 客户端使用负载均衡

11.服务提供者向服务中心注册
22.服务消费者通过@LoadBalanced注解修饰过的RestTemplate访问服务

  @LoadBalanced 注解给 RestTemplate 做标记,以使用负载均衡的客户端来配置它 LoadBalancerClient

  

  

  ServiceInstance choose(String serviceId) 根据传入的服务名,从负载均衡器中挑选一个对应的服务实例

  T execute(String serviceId,LoadBalancerRequest request): 从负载均衡器中提取服务来 执行 request

  URI reconstructURI(ServiceInstance instance,URI original): 拼接请求地址

  

  LoadBalancerInterceptor 的 Bean,用于对客户端发起的请求实时拦截

  RestTemplateCstomizer 的 Bean,用于给 RestTemplate 增加 LoadBalancerInterceptor

  

  维护了一个 RestTemplate 列表,然后给每一个 RestTemplate 实例去初始化拦截器

  

  拦截器中注入了 LoadBalancerClientLoadBalancerRequestFactory
最后交给 LoadBalancerClient 去执行 request
最后走到了 RibbonLoadBalancerClient
image.png
Server server = getServer(loadBalacer,hint);

  getLoadBalancer通过Factory构造了默认的ZoneAwaerLoadBalaner
image.png
然后调用了 ZoneAwaerLoadBalaner 中的 chooseServer 来选择一个服务,继而执行 request,选择策略在 ZoneAwaerLoadBalaner的chooseServer中

  负载均衡器

1AbstractLoadBalancer:
2ILoadBalancer的抽象实现,定义了
3分组枚举:ALL所有服务实例,STATUS_UP正常服务实例,STATUS_NOT_UP停止服务实例.
4实现了一个chooseServer函数,key为null,表示在选择具体服务实例时忽略key的条件判断.
5getServerList(ServerGroup goup): 根据不同的分组选择不同的服务实例列表.
6getLoadBalancerStats():获取LoadBalancerStats对象,储存负载均衡器中各个服务实例当前的属性和统计信息.
1BaseLoadBalancer:Ribbon负载均衡器的基础实现类
2定义并维护了两个存储服务实例Server的对象列表,分别存储了所有服务实例和所有正常运行服务实例
3定义了LoadBalancerStats
4定义了IPing检查服务是否运行正常
5定义了IPingStrategy Iping的执行策略对象
6定义了IRule负载均衡的处理规则
7...服务实例列表相关函数
1DynamicServerListLoadBalancer继承BaseLoadBalancer,扩展了基础负载均衡器

  负载均衡策略

1AbstractLoadBalancerRule
2RandomRule:随机选择策略
3RoundRobinRule:线性轮询策略
4RetryRule:重试机制策略
5WeightedResponseTimeRule:权重计算策略

7.Hystrix 服务容错保护

  单个服务出错断路

1'org.springframework.cloud:spring-cloud-starterhystrix:1.4.7.RELEASE',  

  SpringCloudApplication 注解聚合了,服务注册负载均衡熔断机制等注解,可以直接标示到 Application 上面

1@SpringBootApplication
2@EnableDiscoveryClient
3@EnableCircuitBreaker
 1@Service
 2public class DemoService {
 3
 4    @Autowired
 5    RestTemplate restTemplate;
 6	// 如果函数出现错误,或者请求超时,那么将会出发熔断请求,并调用callback,返回结果
 7    @HystrixCommand(fallbackMethod = "helloFallback")
 8    public String toAuth() {
 9        return restTemplate.getForEntity("http://auth/home", String.class).getBody();
10    }
11
12    public String helloFallback(){
13        return "error";
14    }
15
16}

  工作流程

 11.创建HystrixCommand/HystrixObservbleCommand Bean,用来表示对依赖服务的操作请求,同时传递所有需要的参数.
 22.命令执行,execute同步执行,queue异步执行,observe()HotOb返回Ob对象,toObServable返回Ob对象ColdOb
 33.结果是否被缓存
 44.断路器是否打开
 55.线程池/请求队列是否被占满
 66.HystrixCommand.run()返回单一结果或跑一场
 7HystrixObservableCommand.construct()返回一个Ob来发射多个结果/通过onError发送错误通知
 87.计算断路器健康程度,根据健康程度熔断/断路服务
 98.fallback处理
109.返回成功的Response

  断路器原理

  image.png

  HystrixCircuitBreaker 维护了三个抽象函数和三个类

 1allowRequest():每个Hystrix命令的请求通过该函数判断是否被执行
 2
 3isOpen():断路器是否打开
 4
 5markSuccess():闭合断路器
 6
 7Factory:维护了一个Hystrix命令和HystrixCircuitBreaker的关系集合,key
 8通过HystrixCommandKey定义,每一个Hystrix命令都有一个key标识,同时一个Hystrix命令也会在该集合中找到它对应的断路器HystrixCirucuitBreaker
 9
10NoOpCirutiBreaker定义了一个什么都不做的断路器实现,允许所有请求,断路器始终闭合
11
12HystrixCircuitBreakerImpl是本接口实现,定义了4个核心对象
13HystrixCommandProperties:对应实例对象
14HystrixCommandMetrics:记录度量指标对象
15circuitOpen:是否打开标志
16circuitOpenedOrLastTestedTime:打开或是上一次测试的时间

  HystrixCircuitBreakerImpl 的 isOpen
image.png
HystrixCircuitBreakerImpl 的 allowRequest,通过 isOpen 判断是否允许被请求
image.png
!isOpen()||allowSingleTest() 通过配置文件中的 circuiBreakerSleepWindowInMilliseconds 属性休眠时间,对比时间戳判断请求是否可以访问,如果休眠时间到达后请求访问失败,则断路器再次进入打开状态,如果成功,断路器关闭,这句是切换断路器打开关闭状态的切换的实现。
image.png

8.Zuul 路由管理

  单独使用可以进行路由转发,类似 nginx

1zuul:
2  routes:
3    {serviceId}:
4       path: /user/**
5       url: http://www.baidu.com/user/

  上面将 /user 的路由全部转发到下面对应的 url 中

  多实例配置

 1zuul:
 2  routes:
 3    {serviceId}:
 4       path: /user/**
 5       serviceId: {serviceId}
 6// 没有整合eureka这里应该关闭
 7ribbon:
 8  eureka:
 9    enabled: false
10{serviceId}:
11  ribbon:
12    listOfServers:  http://www.baidu1.com/,http://www.baidu2.com/

  忽略路由

1zuul.ignored.parttens=/**/hello/**

  本地跳转

1zuul.routes.{serviceId}.url=forward:/local

  传递 Http Header 信息

1zuul:
2  routes:
3    {router}:
4      // 对制定路由开启自定义敏感头信息
5      customSenstiveHeaders:true
6      // 将制定路由敏感信息头设置为空
7      senstiveHeaders

  当遇到 302 跳转到具体微服务而不是网关时

1zuul:
2  // 跳转时设置Host为zuul
3  addHostHeader : true

8.1 四个阶段的核心过滤器

  image.png

  Pre: 路由转发之前

name index desc
ServletDetectionFilter -3 检测当前请求为 DispatcherServelet/ZuulServlet 处理运行
Servlet30WrapperFilter -2 HttpServletRequest->Servlet30RequestWrapper
FormBodyWrapperFillter -1 将 ContentType 为 x-www-form-urlencoded/multipart-form-data 请求->FormBodyRequestWrapper
DebugFilter 1 debug 信息
PreDecorationFilter 5 设置请求信息,进行路由匹配

  route:路由转发中

name index desc
RibbonRouterFilter 10 通过 serviceId 和 Ribbon/Hystrix 对应用实例发起请求并将结果返回
SimpleHostRoutingFiler 100 通过 routesHost 和路由规则向物理机器发送请求
SendForwardFillter 500 对 forward.to 参数的请求进行处理,forward 跳转

  post route 和 error 过滤器调用之后进入

name index desc
SendErrorFillter 0 包装错误信息组成 forward 发送给网关来报错
SendResponseFiller 1000 返回响应发送给客户端

标题:Gradle多模块+SpringCloud微服务实践
作者:fe
地址:https://blog.eiyouhe.com/articles/2020/01/06/1578318104295.html