1.springcloud核心组件

1. Eureka注册中心

		注册中心是整个微服务系统的一个核心服务。
		所有服务启动都要向eureka进行注册;

eureka的执行参数:

  1. 注册:服务启动后会向注册中心发起注册,注册失败时会反复尝试注册,直到成功为止。
  2. 拉取:所有服务每30s会拉取更新一次注册表,当一个服务启动后,其他服务不能立马感知到,需最长等待30s才能拉取到最新服务的地址表。
  3. 心跳:每30s会发送一次心跳数据,当连续丢失3次心跳数据,注册中心会删除这个服务的注册信息。
  4. 自我保护模式:(与zk的主要区别)15分钟内,85%的服务出现心跳异常,eureka会认为网络不稳定,会进入自我保护模式,保护所有服务的注册信息不被删除, 直到恢复正常后,会自动退出自我保护模式
    eureka与zookeeper的区别:
    eureka:
    AP-强调可用性和分区容错性,集群:对等结构。
    zookeeper:
    CP -强调一致性和分区容错性 集群:主从结构。

application.yml

spring:
  application:
    name: eureka-server
    
server:
  port: 2001
  
eureka:
  server:
    enable-self-preservation: false   #关闭自我保护模式,开发阶段暂时关闭(服务启停频繁)
  instance:
    hostname: eureka1  #eureka服务名称,eureka 集群服务器之间,通过 hostname 来区分
  client:
    register-with-eureka: false #注册:多台eureka服务器时打开,eureka服务会相互注册相互发现,单台时不必打开,没必要向自己注册或从自身拉取。
    fetch-registry: false #发现

主程序
添加 @EnableEurekaServer

package cn.tedu.sp05;

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

@EnableEurekaServer
@SpringBootApplication
public class Sp05EurekaApplication {

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

启动,并访问测试
http://eureka1:2001

**需要向eureka进行注册的服务需要三步配置:

  1. 在配置文件中添加eureka的服务地址
spring:
  application:
    name: order-service
    
server:
  port: 8201
# order服务向eureka发起注册,必须在该服务配置中添加eureka的注册地址
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka 
  1. 服务主程序需要添加 @EnableDiscoveryClient #启用服务发现

  2. pom文件添加eureka-client依赖

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

2. rebbin

		负载均衡
		重试
		rebbin是对RestTemplate做了增强,添加了负载均衡和重试功能。
		
		eureka-client 中已经包含 ribbon 依赖

2.1Rebbin负载均衡

	RestTempLate设置 @LoadBalanced
	@LoadBalanced 是负载均衡注释,会对RestTemplate 的实例进行封装,创建动态代理对象,并切入(AOP)负载均衡代码,把请求分发到集群中的服务器。
@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {
	
	@LoadBalanced //负载均衡注解
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

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

}
访问路径设置为服务id
@RestController
public class RibbonController {
	@Autowired
	private RestTemplate rt;
	
	@GetMapping("/item-service/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
	    //这里服务器路径用 service-id 代替,ribbon 会向服务的多台集群服务器分发请求
		return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
	}

	/
	
	@GetMapping("/user-service/{userId}")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return rt.getForObject("http://user-service/{1}", JsonResult.class, userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	public JsonResult addScore(
			@PathVariable Integer userId, Integer score) {
		return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score);
	}
	
	/
	
	@GetMapping("/order-service/{orderId}")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId);
	}

	@GetMapping("/order-service")
	public JsonResult addOrder() {
		return rt.getForObject("http://order-service/", JsonResult.class);
	}
}

2.2Ribbon 重试

	重试参数:
		MaxAutoRetries:对单台服务器的重试次数。
		MaxAutoRetriesNextServer:向后更换几台服务器进行重试。
		OkToRetryOnAllOperations=true:默认只对GET请求重试, 当设置为true时, 对POST等所有类型请求都重试。
		ConnectionTimeout:建立连接的超时时间。
		ReadTimeout:接收响应的超时时间。
		两个超时参数不能直接在yml配置中配置,

主程序设置 RestTemplate 的请求工厂的超时属性

@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {

	@LoadBalanced
	@Bean
	public RestTemplate getRestTemplate() {
		SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
		// 两个超时时间不能在yml里配置,需要在这里设置
		f.setConnectTimeout(1000);
		f.setReadTimeout(1000);
		return new RestTemplate(f);
		
		//RestTemplate 中默认的 Factory 实例中,两个超时属性默认是 -1,
		//未启用超时,也不会触发重试
		//return new RestTemplate();
	}

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

2.3使用Rebbion需要的配置

1.pom需要添加spring-Retry依赖

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>

2.application.yml 配置 ribbon 重试

spring:
  application:
    name: ribbon
    
server:
  port: 3001
  
eureka:
  client:    
    service-url:	# ribbon服务需要注册到注册中心
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

# ribbon的重试配置  
ribbon:
  MaxAutoRetriesNextServer: 2	#更换服务器的次数
  MaxAutoRetries: 1  #单台服务器重试次数
  OkToRetryOnAllOperations: true

3.Hystrix

		降级:当请求后台服务器失败时,可以通过执行当前服务器的一段代码来向客户端返回结果。
		熔断:避免一台服务器故障引起雪崩效应,引起大面积的服务器 瘫痪。
			断路器会在一定条件下触发熔断:
				1.10s内20次请求;
				2.50%失败执行了降级代码。
			半开状态:
				会尝试发送一起请求,如果失败断路器会继续保持打开状态,反之关闭断路器,自动恢复。

3.1 使用Hystrix需要如下配置

3.1.1 添加hystrix起步依赖

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

3.1.2 主程序添加 @EnableCircuitBreaker 启用 hystrix 断路器

启动断路器,断路器提供两个核心功能:

降级,超时、出错、不可到达时,对服务降级,返回错误信息或者是缓存数据

熔断,当服务压力过大,错误比例过多时,熔断所有请求,所有请求直接降级

可以使用 @SpringCloudApplication 注解代替三个注解

3.1.3 使用降级代码

为每个方法添加降级方法,例如 getItems() 添加降级方法 getItemsFB()
添加 @HystrixCommand 注解,指定降级方法名
@RestController
public class RibbonController {
	@Autowired
	private RestTemplate rt;
	
	@GetMapping("/item-service/{orderId}")
	@HystrixCommand(fallbackMethod = "getItemsFB") //指定降级方法的方法名
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
		return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	@HystrixCommand(fallbackMethod = "decreaseNumberFB")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
	}

	/
	
	@GetMapping("/user-service/{userId}")
	@HystrixCommand(fallbackMethod = "getUserFB")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return rt.getForObject("http://user-service/{1}", JsonResult.class, userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	@HystrixCommand(fallbackMethod = "addScoreFB")
	public JsonResult addScore(@PathVariable Integer userId, Integer score) {
		return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score);
	}
	
	/
	
	@GetMapping("/order-service/{orderId}")
	@HystrixCommand(fallbackMethod = "getOrderFB")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId);
	}

	@GetMapping("/order-service")
	@HystrixCommand(fallbackMethod = "addOrderFB")
	public JsonResult addOrder() {
		return rt.getForObject("http://order-service/", JsonResult.class);
	}
	
	/

    //降级方法的参数和返回值,需要和原始方法一致,方法名任意
	public JsonResult<List<Item>> getItemsFB(String orderId) {
		return JsonResult.err("获取订单商品列表失败");
	}
	public JsonResult decreaseNumberFB(List<Item> items) {
		return JsonResult.err("更新商品库存失败");
	}
	public JsonResult<User> getUserFB(Integer userId) {
		return JsonResult.err("获取用户信息失败");
	}
	public JsonResult addScoreFB(Integer userId, Integer score) {
		return JsonResult.err("增加用户积分失败");
	}
	public JsonResult<Order> getOrderFB(String orderId) {
		return JsonResult.err("获取订单失败");
	}
	public JsonResult addOrderFB() {
		return JsonResult.err("添加订单失败");
	}
}

4.Feign 整合ribbon、hystrix

feign作用:
	1.声明式客户端
	2.整合ribbon
	3.整合hystrix

1.声明式客户端

只需定义一个接口,就可以通过接口访问后台服务器。
// feign的声明式客户端样例  (远程调用)
@FeignClient("item-service")   // 该注解指定调用的服务名称
public interface ItemFeignService {
	@GetMapping("/{orderId}")	// 指定调用路径
	JsonResult<List<Item>> getItems(@PathVariable String orderId);

	@PostMapping("/decreaseNumber")
	JsonResult decreaseNumber(@RequestBody List<Item> items);
}

5. OpenFeign服务接口调用

5.1 OpenFeign是什么

Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可

SpringCloud对Feign进行了封装,使其支持了SpringMVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign
https://github/spring-cloud/spring-cloud-openfeign

5.2 Feign能干什么?

Feign旨在使用编写Java Http客户端变得更容易。
前面在使用Ribbon+RestTemplate时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。
但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对	每个微服务自行封装一些客户端类来包装这些依赖服务端额调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。
在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是DAO接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。

5.3 Feign和OpenFeign两者区别

1.底层都是内置了Ribbon,去调用注册中心的服务。
2.Feign是Netflix公司写的,是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端,是SpringCloud中的第一代负载均衡客户端。
3.OpenFeign是SpringCloud自己研发的,在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。是SpringCloud中的第二代负载均衡客户端。
4.Feign本身不支持Spring MVC的注解,使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
5.OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 

5.4 OpenFeign微服务调用样例

【cloud-consumer-feign-order80服务 调用 cloud-payment-service服务接口】
新建cloud-consumer-feign-order80服务
POM文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache/POM/4.0.0"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache/POM/4.0.0 http://maven.apache/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-consumer-feign-order80</artifactId>

    <dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project> 

YML文件如下:

server:
  port: 80
spring:
  application:
    name: cloud-consumer-feign-order80
eureka:
  client:
register-with-eureka: true  #开启服务注册,该服务注册到注册中心
fetch-registry: true  #开启服务注册列表拉取
    service-url:
      defaultZone: http://localhost:7001/eureka  #注册中心地址

编辑主启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient  // 开启服务注册
@EnableFeignClients  // OpenFeign注解 (重要)
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class,args);
    }
}

业务逻辑类:
1. 业务逻辑接口+@FeignClient配置调用provider服务
2. 新建PaymentFeignService接口并新增注解@FeignClient

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "cloud-payment-service") // 指定要调用的服务名称
public interface PaymentFeignService {
    /**
     * 通过OpenFeign 远程调用  cloud-payment-service 中的 getPaymentById方法
     * 次处写法照搬 cloud-payment-service 中getPaymentById 方法写法即可
     * @param id
     * @return
     */
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
}

Contorller层如下:

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

@RestController
public class OrderFeignController {

    @Autowired
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return paymentFeignService.getPaymentById(id);
    }

}

服务提供者(cloud-payment-service)代码如下:
服务提供者controller层:

@RestController
@Slf4j
public class PaymentController {
    @Autowired
    private PaymentService paymentService;

    @PostMapping(value = "/payment/create")
    public CommonResult<Payment> create(@RequestBody Payment payment) { //埋雷
        int result = paymentService.create(payment);
        log.info("*****插入结果:" + result);
        if (result > 0) {  //成功
            return new CommonResult(200, "插入数据库成功", result);
        } else {
            return new CommonResult(444, "插入数据库失败", null);
        }
    }

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        Payment payment = paymentService.getPaymentById(id);
        log.info("*****查询结果:" + payment);
        if (payment != null) {  //说明有数据,能查询成功
            return new CommonResult(200, "查询成功", payment);
        } else {
            return new CommonResult(444, "没有对应记录,查询ID:" + id, null);
        }
    }

}

5.5 OpenFeign日志打印功能

Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中Http请求的细节。说白了就是对Feign接口的调用情况进行监控和输出。

日志级别:
NONE:默认的,不显示任何日志
BASIC:仅记录请求方法、RUL、响应状态码及执行时间
HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息
FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据

配置日志bean


import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {
 
    @Bean
    public Logger.Level feignLoggerLevel(){ // 实例化feign日志对象
        return Logger.Level.FULL;
    }
}

YML文件里需要开启日志的Feign客户端

logging:
  level:
    com.**.**.**.PaymentFeignService: debug  # 前边是包路径 

5.6 补充OpenFeign远程调用样例

现有如下两个服务,我想member服务调用coupon服务的接口

第一步,A调用B,需要给A添加OpenFeign依赖,即,需要给member服务新增OpenFeign依赖。

第二步,编写一个接口,告诉springcloud需要远程调用其他服务
当调用时先根据FeignClient后的服务名称去nocas找对应服务,再去找调用的是具体的哪一个接口

第三步,开启远程调用权限,member服务启动类添加注解@EnableFeignClients

第四步,新增调用方法测试是否调用成功。

【问题记录】

解决方法:
解决这个报错的方法参考链接

6.GateWay 网关

Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关https://github/Netflix/zuul/wiki
但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关代替Zull,那就是SpringCloud Geteway;

Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
主要作用:
 反向代理
 鉴权
 流量控制
 熔断
 日志监控
 。。。。。。

6.1 网关的三大核心概念

6.1.1 Route(路由)

路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由

6.1.2 Predicate(断言)

参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由

6.1.3 Filter(过滤)

指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

6.1.4总体

Web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
Predicate就是我们的匹配条件: 而Filter,就是可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。

6.2 Gateway工作流程


客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求匹配的路由,将其发送到Gateway Web Handler.
Handler再通过指定的过滤器链来将请求发送给我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Filter在"pre"类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在"post"类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量控制等有着非常重要的作用

6.3 入门Demo

6.3.1 新建Module:cloud-gateway-gateway9527
POM如下:【gateway依赖添加】

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache/POM/4.0.0"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache/POM/4.0.0 http://maven.apache/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-gateway-gateway9527</artifactId>

    <dependencies>
        <!--新增gateway,不需要引入web和actuator模块-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

YML如下:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:    # 新增GateWay配置
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001   #匹配后提供服务的路由地址(方法1:通过IP+port路由)
          uri: lb://cloud-payment-service  #方法2:通过服务名称路由 (lb:负载均衡)
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由
 
        - id: payment_routh2
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由

eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://localhost:7001/eureka


默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。
需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。

6.4 Predicate的使用

6.4.1 是什么?

启动我们的gatewat9527,查看启动日志

6.4.2 常用的Route Predicate

1.After Route Predicate (指定时间之后才可以访问)


ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
 - After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
• 测试:没到时间进行测试报错

2. Before Route Predicate

• YML
 - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]

3.Between Route Predicate

• YML
 - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]

4.Cookie Route Predicate


• YML
 - Cookie=username,atguigu #并且Cookie是username=zhangshuai才能访问
• 不带cookies访问

• 带上cookies访问
 curl下载地址:https://curl.haxx.se/download.html

• 加入curl返回中文乱码(帖子): https://blog.csdn/leedee/article/details/82685636

5.Header Route Predicate


• YML

  • Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式

6Host Route Predicate

YML: - Host=**.atguigu

7.Method Route Predicate

YML:- Method=GET

8.Path Route Predicate

YML:

9. Query Route Predicate

YML: - Query=username, \d+ #要有参数名称并且是正整数才能路由

6.5 小结

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/get/**   #断言,路径相匹配的进行路由

        - id: payment_routh2
          #uri: http://localhost:8001   #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service
          predicates:
            - Path=/payment/lb/**   #断言,路径相匹配的进行路由
            #- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
            #- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
            #- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
            #- Host=**.atguigu
            #- Method=GET
            #- Query=username, \d+ #要有参数名称并且是正整数才能路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://localhost:7001/eureka

更多推荐

SpringCloud 核心组件知识点总结-面试必备