精华内容
下载资源
问答
  • springCloud+SpringBoot+eureka+gateway+JWT实现:注册中心,网关,token,服务之间调用

    springCloud+SpringBoot+eureka+gateway+JWT实现:注册中心,网关,token,服务之间调用

    github链接

    展开全文
  • SpringCloud 服务之间调用

    千次阅读 2018-11-21 21:58:10
    Spring cloud 中服务之间通过restful方式调用有两种方式: 1.restTemplate+Ribbon 2.feign Ribbon 是客户端负载均衡器,Zuul网关负载均衡器 针对外部请求做负载。 客户端ribbon的负载均衡,解决的是服务发起方...

    Spring cloud 中服务之间通过restful方式调用有两种方式:

    1.restTemplate+Ribbon

    2.feign

    Ribbon 是客户端负载均衡器,Zuul网关负载均衡器 针对外部请求做负载。

    客户端ribbon的负载均衡,解决的是服务发起方(在Eureka注册的服务)对被调用的服务的负载,比如我们查询商品服务要调用显示库存和商品明细服务,通过商品服务的接口将两个服务组合,可以减少外部应用的请求

     

    ribbon是对服务之间调用做负载,是服务之间的负载均衡,zuul是可以对外部请求做负载均衡。

    Feign http负载平衡客户端:1、Feign采用的是接口加注解;2、Feign 整合了ribbon

    1.首先创建一个eureka客户端工程

    2.启动类上增加客户端注解

    3.添加yml配置信息

    4.增加一个服务类

    5.启动 工程测试如下

    6.添加一个客户端类实现服务调用,RestTemplate 的三种使用方式:

    6.1 直接new一个RestTemplate 

    这种的缺点是地址是写死的,在实际的为服务中我们是不知道对方的地址的。

    6.2利用loadBalanceerClient通过应用名获取url

    6.3首先创建一个RestTemplate配置类

    在控制层注入RestTemplate  使用restTemplate+应用名的方式访问注册服务。注意ribbon发现服务时服务名称中不能含有"_"。

     

    展开全文
  • 1.简介 微服务架构服务实例众多,服务服务之间如何调用,Spring Cloud提供了解决方案:伪装者 Feign...第一步:服务之间调用 本例需要创建三个工程: eureka-server 注册中心服务(项目创建参照第三节网关) product-

    1.简介

    微服务架构服务实例众多,服务与服务之间如何调用,Spring Cloud提供了解决方案:伪装者 Feign。

    Feign 是 Spring Cloud 的一个组件,也是一个WebService客户端,用于服务之间的调动。


    2. 如何使用

    第一步:服务之间调用

    本例需要创建三个工程:

    eureka-server 注册中心服务(项目创建参照第三节网关)

    product-service 产品服务(最基础的客户端服务,提供一个rest接口即可。前面第三节已创建,可参考,不需要做任何修改)

    order-service-feignclient  订单服务(测试服务调用)

    order-service-feignclient 工程目录如下图:


    (1)pom.xml增加依赖

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

    (2)增加接口和 @FeignClient 注解

    package com.hole.feign;
    
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    /**
     * Created by helei on 2017/7/16.
     */
    @FeignClient(value = "product-service",fallback = ProductServiceFeignDaoHystrix.class)
    public interface ProductServiceFeignDao {
    
        @RequestMapping(value = "/hello",method = RequestMethod.GET)
        String hello();
    }
    

    @FeignClient(value = "product-service"
    value设置要调用服务的服务名。Feign会根据服务名去注册中心查找服务url

    (3)启动类增加 @EnableFeignClient开启Feign功能,新增Rest接口用于调用产品服务。

    package com.hole;
    
    import com.hole.feign.ProductServiceFeignDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @EnableDiscoveryClient
    @SpringBootApplication
    @RestController
    @EnableFeignClients
    public class OrderServiceFeignclientApplication {
    	@Autowired
    	private ProductServiceFeignDao productServiceFeignDao;
    
    	public static void main(String[] args) {
    		SpringApplication.run(OrderServiceFeignclientApplication.class, args);
    	}
    
    	@RequestMapping(value = "/product/hello",method = RequestMethod.GET)
    	public String getHelloFromProductService(){
    		return productServiceFeignDao.hello();
    	}
    }
    

    (4)启动服务验证

    启动成功后请求 /product/hello,结果成功调用产品服务并返回结果。



    第二步:增加 Hystrix 断路熔断机制

    (1)增加 Feign接口实现类,实现方法作为断路器的回调方法。

    package com.hole.feign;
    
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    
    /**
     * Created by helei on 2017/7/16.
     */
    @Component
    public class ProductServiceFeignDaoHystrix implements ProductServiceFeignDao {
    
        @Override
        public String hello() {
            return "服务不见鸟,稍后再试!";
        }
    }
    
    (2)Feign接口的 @FeignClient注解增加 fallback参数,指向接口的实现类。

    package com.hole.feign;
    
    import org.springframework.cloud.netflix.feign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    /**
     * Created by helei on 2017/7/16.
     */
    @FeignClient(value = "product-service",fallback = ProductServiceFeignDaoHystrix.class)
    public interface ProductServiceFeignDao {
    
        @RequestMapping(value = "/hello",method = RequestMethod.GET)
        String hello();
    }
    

    (3)启动服务验证。

    启动成功后将 product-sevice 服务关闭,再次请求 /product/hello,结果发现报异常。


    发现断路器并没有起作用,而是直接抛异常。

    带着疑惑查了下官方API,官方文档中大致意思是feign默认是启用hystrix的,然而测试的结果是并没有。但发现了一段配置

    feign.hystrix.enabled=false

    这个配置意思很明确了吧,将false改为true,试试又不犯法,结果。。。

    对,就是你认为的那样,成功了!



    还有一个地方要补充下:

    FigenClient已经包含了Hystrix,所有启动类不需要再开启 @EnableCircuitBreaker。


    展开全文
  • SpringCloud之服务网关Gateway

    万次阅读 多人点赞 2019-06-30 22:02:38
    前言 SpringCloud 是微服务中的翘楚,... 前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度;具体作用就是转发服务,接收并转发所有内外 部的客户端调用;其他常见的功能还有权限认证,限流控制等等。 ...

    前言

      SpringCloud 是微服务中的翘楚,最佳的落地方案。

      Spring Cloud Gateway 是 Spring Cloud 新推出的网关框架,之前是 Netflix Zuul。网关通常在项目中为了简化

      前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度;具体作用就是转发服务,接收并转发所有内外

      部的客户端调用;其他常见的功能还有权限认证,限流控制等等。

      本博客会提到网关的基本转发功能熔断功能限流功能以及功能的综合使用

    源码

      GitHub地址:https://github.com/intomylife/SpringCloud

    环境

    • JDK 1.8.0 +
    • Maven 3.0 +
    • SpringBoot 2.0.3
    • SpringCloud Finchley.RELEASE
    • Redis 3.0 +

    开发工具

    • IntelliJ IDEA

    正文

    commons 工程

    commons 工程 - POM 文件

    <?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>com.zwc</groupId>
        <artifactId>springcloud-gateway-commons</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称和描述 -->
        <name>springcloud-gateway-commons</name>
        <description>公用工程</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties 下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- 编码 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <!-- jdk -->
            <java.version>1.8</java.version>
    
            <!-- SpringBoot -->
            <platform-bom.version>Cairo-SR3</platform-bom.version>
    
            <!-- SpringCloud -->
            <spring-cloud-dependencies.version>Finchley.RELEASE</spring-cloud-dependencies.version>
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
    
        </dependencies>
    
        <!-- 依赖 jar 包版本管理的管理器 -->
        <!-- 如果 dependencies 里的 dependency 自己没有声明 version 元素,那么 maven 就此处来找版本声明。 -->
        <!-- 如果有,就会继承它;如果没有就会报错,告诉你没有版本信息 -->
        <!-- 优先级:如果 dependencies 里的 dependency 已经声明了版本信息,就不会生效此处的版本信息了 -->
        <dependencyManagement>
            <dependencies>
                <!-- SpringBoot -->
                <dependency>
                    <groupId>io.spring.platform</groupId>
                    <artifactId>platform-bom</artifactId>
                    <version>${platform-bom.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!-- SpringCloud -->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud-dependencies.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 配置一些共用依赖

    commons 工程 - 项目结构

     

    service 工程

      ① 此工程下有四个模块:一个注册中心,一个网关以及两个提供者

      ② 两个提供者除端口不一致以外,其他代码基本一致

     

    registry-service(注册中心)

    registry-service - POM 文件

    <?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>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-registry-service</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-registry-service</name>
        <description>注册中心</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
    
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 服务注册中心 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 主要加入 spring-cloud-starter-netflix-eureka-server 依赖

    registry-service - application.yml 配置文件

    # 端口
    server:
      port: 8761
    
    # 应用名称
    spring:
      application:
        name: eureka-server
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        # 是否向注册中心注册自己
        registerWithEureka: false
        # 是否向注册中心获取注册信息
        fetchRegistry: false
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    • 这里使用了默认的 8761 端口,当然也可以更改,不过在发现调用服务端的注册中心地址端口要与它一致

    registry-service - 启动类

    package com.zwc;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class SpringcloudGatewayRegistryServiceApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayRegistryServiceApplication.class, args);
        }
    
    }
    
    • 在启动类中添加 @EnableEurekaServer 注解表示此工程是注册中心

    registry-service - 启动项目

      1. 项目启动成功后访问 http://localhost:8761/ 即可看到 eureka-server 主页面

     

      注:由于服务工程 A 和服务工程 B 除端口不一致以外,其他代码基本一致,所以服务工程 B 不再赘述

    a-service(服务工程 A)

    a-service - POM 文件

    <?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>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-a-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-a-service-core</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-a-service-core</name>
        <description>服务工程 - A 核心</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
    
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- commons工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-commons</artifactId>
                <version>1.0</version>
            </dependency>
    
            <!-- api工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-a-service-api</artifactId>
                <version>1.0</version>
            </dependency>
    
            <!-- springboot web 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖

    a-service - application.yml 配置文件

    # 端口
    server:
      port: 9000
    
    # 应用名称
    spring:
      application:
        name: gateway-service
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    • 注意此处配置注册中心地址的端口为 8761 也就是上面注册中心工程配置的端口

    a-service - controller 前端控制器(提供服务)

    package com.zwc.a.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /*
     * @ClassName ASayHelloController
     * @Desc TODO   Say Hello
     * @Date 2019/5/20 23:24
     * @Version 1.0
     */
    @RestController
    public class ASayHelloController {
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   读取配置文件中的端口
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @Value("${server.port}")
        private String port;
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   Say Hello
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @RequestMapping("/hello")
        public String hello(){
            return "Hello!I'm a. port:" + port;
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:28
         * @Version 1.0
         */
        @RequestMapping("/name")
        public String name(String name){
            return "My name is " + name + ". aaa";
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:52
         * @Version 1.0
         */
        @RequestMapping("/age")
        public String age(String age){
            return "I am " + age + " years old this year. aaa";
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/29 22:00
         * @Version 1.0
         */
        @RequestMapping("/routeAll")
        public String routeAll(String pass) {
            return "Can I pass? " + pass + "! port:" + port;
        }
    
    }
    
    • 提供输出字符串服务,供网关调用

    a-service - 启动类

    package com.zwc;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient
    public class SpringcloudGatewayAServiceCoreApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayAServiceCoreApplication.class, args);
        }
    
    }
    
    • 添加 @EnableEurekaClient 注解表示此工程可以向注册中心提供服务

    a-service - 启动项目

      1. 刷新 http://localhost:8761/(注册中心)可以看到服务已经被注册进来了

      2. 项目启动成功后访问:http://localhost:9000/hello

      3. 输出内容:'Hello!I'm a. port:9000'

      4. 同样启动服务工程 B后,刷新 http://localhost:8761/(注册中心)

      5. 项目启动成功后访问:http://localhost:9001/hello

      6. 输出内容:'Hello!I'm b. port:9001'

      7. 其他接口是下面网关服务启动后转发调用的,也是本博客的重头戏

     

    master-service(网关)

    master-service - POM 文件

    <?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>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-master-service</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-master-service</name>
        <description>Spring Cloud Gateway 服务网关</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- ali json -->
            <fastjson.version>1.2.47</fastjson.version>
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <!-- gateway -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
    
            <!-- redis -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            </dependency>
    
            <!-- hystrix -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
            <!-- ali json依赖 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖:提供和注册服务
    • 加入 spring-cloud-starter-gateway 依赖:gateway
    • 加入 spring-boot-starter-data-redis-reactive 依赖:结合 Redis 限流
    • 加入 spring-cloud-starter-netflix-hystrix 依赖:熔断器

    master-service - application.yml 配置文件

    # 端口
    server:
      port: 8000
    
    spring:
      profiles:
        # 指定配置
        # route_simple:简单尝试
        # route_stripPrefix:截取请求
        # route_uri:转发指定地址并传入参数
        # route_addRequestParameter:转发指定服务并传入参数
        # route_hystrix:熔断
        # route_requestRateLimiter:限流
        # route_all:综合
        active: route_simple
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    • 注意配置注册中心地址的端口都为 8761 也就是上面注册中心工程配置的端口
    • 每一对 '---' 符号中的配置文件都是单独的,使用 spring.profiles.active 指定
    • 每一对 '---' 符号中的配置文件都只配置了一个 route(路由)
    • route(路由)由四部分组成,其中 filters 不是必须参数
    • 唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)

     

    master-service - 简单尝试

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive

      1. 停止注册中心工程(registry-service)、服务工程 A 和服务工程 B

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_simple

      3. 上面配置文件内容意思是当访问 http://localhost:8000/archive (网关地址/archive)

          会被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明服务转发成功

     

    master-service - 截取请求

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    

      1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_stripPrefix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/str/archive (网关地址/str/archive)截取 /str 部分,

          截取后被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/str/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明路径被截取并服务转发成功

     

    master-service - 转发指定地址并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_uri

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/name (网关地址/name)

          会被转发到 http://localhost:9000/name(uri/name),并传入 'name=zwc' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      5. 项目启动成功后访问:http://localhost:8000/name

      6. 输出内容:'My name is zwc. aaa'(通过网关转发 - 参数有值)

      7. 打开新页面访问:http://localhost:9000/name

      8. 输出内容:'My name is null. aaa'(直接访问 - 参数没有值)

      9. 证明转发指定地址并传入参数成功

     

    master-service - 转发指定服务并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_addRequestParameter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      6. 项目启动成功后访问:http://localhost:8000/age

      7. 这时可能会报错 500.错误信息为 'Unable to find instance for gateway-service'

      8. 这种情况不要慌张,只是服务还没有被注册到注册中心,稍等片刻再访问

      9. 多次访问:http://localhost:8000/age

     10. 轮流输出内容:'I am three years old this year. aaa'  'I am three years old this year. bbb'

     11. 此时还通过网关达到了负载均衡的效果

     12. 证明转发指定服务并传入参数成功

     

    master-service - 熔断

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_hystrix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 此处还多配置了一个过滤器 '- name: Hystrix'(熔断)

      6. 当请求服务出错时,会调用 fallback,路径为:http://localhost:8000/fallback (网关地址/fallback)

      7. 此时就需要如下前端控制器

    master-service - 熔断 - controller

    package com.zwc.gateway.hystrix;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @ClassName FallbackController
     * @Desc TODO   网关断路器
     * @Date 2019/6/23 19:33
     * @Version 1.0
     */
    @RestController
    public class FallbackController {
    
        /*
         * @ClassName FallbackController
         * @Desc TODO   网关断路器
         * @Date 2019/6/23 19:35
         * @Version 1.0
         */
        @RequestMapping("/fallback")
        public String fallback() {
            return "I'm Spring Cloud Gateway fallback.";
        }
    
    }
    

      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      9. 项目启动成功后访问:http://localhost:8000/age

     10. 输出内容:'I'm Spring Cloud Gateway fallback.'

     11. 证明熔断成功

     

    master-service - 限流(重点,解决不生效问题)

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_requestRateLimiter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处还需要配置 redis 的连接信息

      5. 注意此处是结合 redis 实现的限流,所以 filter 过滤器的 name 必须为 RequestRateLimiter

      6. 并且通过实现 KeyResolver 类来自定义限流策略,如下

    master-service - 限流 - 策略

    package com.zwc.gateway.config.filters;
    
    import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    /**
     * @ClassName UriKeyResolver
     * @Desc TODO   Spring Cloud Gateway 网关限流过滤器
     * @Date 2019/6/23 17:59
     * @Version 1.0
     */
    public class UriKeyResolver implements KeyResolver {
    
        /*
         * @ClassName UriKeyResolver
         * @Desc TODO   根据请求的 uri 限流
         * @Date 2019/6/29 17:25
         * @Version 1.0
         */
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            return Mono.just(exchange.getRequest().getURI().getPath());
        }
    
    }
    

      7. 启动本地 redis(redis-server.exe) 服务

      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      9. 项目启动成功后访问:http://localhost:8000/age

     10. 此时限流却无论如何都不生效,原因有如下两点

    ① redis-server 版本过低!我 Windows 本地是 redis-2.4.2 版本的,要用 3 以上的版本!!!

    ② 数据在 redis 中存储的时间只有几秒,所以得使用 monitor 指令来动态的观察!!!

     11. 打开 redis-cli.exe,输入命令 monitor 

     12. 快速刷新地址:http://localhost:8000/age

     13. 页面上会出现 429,redis-cli.exe 中会出现很多数据交互(request_rate_limiter.xxx 开头的 key)

     14. 证明限流成功

     

    master-service - 综合

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_all

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/all/routeAll (网关地址/all/routeAll)截取 /all 部分,

          会被转发到 http://gateway-service/routeAll(uri/routeAll),并传入 'pass=yes' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      5. 项目启动成功后访问:http://localhost:8000/all/routeAll

      6. 首先会返回 'I'm Spring Cloud Gateway fallback.',因为服务还未被注册到注册中心

      7. 然后会返回 '{"msg":"缺少凭证","code":-1}',因为配置了全局过滤器,如下

    package com.zwc.gateway.config.filters;
    
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    import org.springframework.core.io.buffer.DataBuffer;
    
    import java.net.InetSocketAddress;
    import java.nio.charset.StandardCharsets;
    
    /**
     * @ClassName TokenFilter
     * @Desc TODO   请求认证过滤器
     * @Date 2019/6/29 17:49
     * @Version 1.0
     */
    public class TokenFilter implements GlobalFilter{
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 请求对象
            ServerHttpRequest request = exchange.getRequest();
            // 响应对象
            ServerHttpResponse response = exchange.getResponse();
    
            // 只有综合路由才添加这个全局过滤器(routesId:route_all)
            // 如果请求路径中不存在 routeAll 字符串
            if(request.getURI().toString().indexOf("routeAll") == -1){
                System.out.println("filter -> return");
                // 直接跳出
                return chain.filter(exchange);
            }
    
            // 从请求中获取 token 参数
            String token = exchange.getRequest().getQueryParams().getFirst("token");
            // 如果为空,那么将返回 401
            if (token == null || token.isEmpty()) {
    
                // 响应消息内容对象
                JSONObject message = new JSONObject();
                // 响应状态
                message.put("code", -1);
                // 响应内容
                message.put("msg", "缺少凭证");
                // 转换响应消息内容对象为字节
                byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
                DataBuffer buffer = response.bufferFactory().wrap(bits);
                // 设置响应对象状态码 401
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // 设置响应对象内容并且指定编码,否则在浏览器中会中文乱码
                response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
                // 返回响应对象
                return response.writeWith(Mono.just(buffer));
            }
            // 获取请求地址
            String beforePath = request.getPath().pathWithinApplication().value();
            // 获取响应状态码
            HttpStatus beforeStatusCode = response.getStatusCode();
            System.out.println("响应码:" + beforeStatusCode + ",请求路径:" + beforePath);
            // 请求前
            System.out.println("filter -> before");
            // 如果不为空,就通过
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 获取请求地址
                String afterPath = request.getPath().pathWithinApplication().value();
                // 获取响应状态码
                HttpStatus afterStatusCode = response.getStatusCode();
                System.out.println("响应码:" + afterStatusCode + ",请求路径:" + afterPath);
                // 响应后
                System.out.println("filter -> after");
            }));
        }
    
    }
    

      8. 全局过滤器,不需要配置在配置文件中,作用于所有路由;只是这里在处理前做了判断,只有路径中存在

          routeAll 字符串才到后续处理;并且处理分为请求前的处理,和响应后的处理

      9. 此时在地址:http://localhost:8000/all/routeAll 中添加 token 参数

     10. 访问:http://localhost:8000/all/routeAll?token=123

     11. 轮流输出内容:'Can I pass? yes! port:9000' 和 'Can I pass? yes! port:9001'

     12. 观察 gateway 工程的控制台,会有如下内容输出

    响应码:null,请求路径:/routeAll
    filter -> before
    响应码:200,请求路径:/routeAll
    filter -> after

     13. 证明全局过滤器过滤成功

     

    service 工程 - 项目结构

     

    把多工程项目使用 IntelliJ IDEA 打开

    1. 把项目从 GitHub 中下载到你的本地
    2. 打开 IntelliJ IDEA 
    3. 点击 File -> Open
    4. 打开你下载到本地的项目目录
    5. springcloud-gateway -> springcloud-gateway-service(选择打开此工程)
    6. 打开 service 工程后
    7. 再次点击 File -> Project Structrue
    8. 选择 Modules,点击 '+' 符号
    9. 点击 Import  Module
    10. 还是打开你下载到本地的项目目录
    11. springcloud-gateway -> springcloud-gateway-commons -> pom.xml
    12. 点击 OK
    13. 点击 Next,Finish
    14. 点击 Apply,OK

     


     

    希望能够帮助到你

    over

     

     

     

    展开全文
  • SpringCloud各服务之间调用过程原理

    千次阅读 2020-05-21 17:47:44
    1.用户针对一个订单完成支付之后,会寻找订单服务更新订单状态为“已支付”; 2.库存服务进行扣减库存操作 3.通知仓库服务进行发货 4.给用户的这次购物进行相应的积分增加 下图为个服务的图解 二、Spring ...
  • 当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务端。1.pom文件配置&lt;dependency&gt; &lt;groupId&gt;org....
  • 原创文章 如有侵权联系删除 ...访问网关服务18084->访问到provider会不会经过consumer? 如果走consumer 整个访问路径是怎样的?如果经过consumer需要解决问题1 问题2 如果不走consumer 就不会有熔断...
  • 场景:项目在网关Zuul中对请求Request进行了处理,(包括添加修改...可当服务A调用服务B时,服务B的Request就把之前网关Zuul做的处理数据都丢失了。 解决: 在子服务里添加如下代码,防止丢失处理过后的Reques...
  • 一、什么是服务网关 服务网关 = 路由转发 + 过滤器 1、路由转发:接收一切外界请求,转发到后端的微服务上去; 2、过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等, 这些都可以...
  • 上篇写了 nacos 的安装,这篇写一下以nacos为注册中心,进行服务调用网关路由等的使用,首先看下各版本之间的对应关系
  • 在分布式架构的系统中,每个服务都有自己的一套API提供给别的服务调用,如何保证每个服务相互之间安全调用? 思路 1、所有接口都要通过认证才能访问,有时候又有需求,不需要认证就可以访问。 ...
  • 场景和网关之间同步消息,再发到玩家。 1、场景服务器发送消息到网关服务器 2、场景服务器发送消息到网关服务器,网关服务器查找对应网关玩家,并发送消息。 (1)单个玩家的消息发送 (2)多玩家的广播发送  3、...
  • 微服务中 Feign调用以及网关Zuul的请求头与字段相关问题 文章目录微服务中 Feign调用以及网关Zuul的请求头与字段相关问题前言1. Feign远程调用请求头丢失1.1 原因分析1.2 解决方案11.3 解决方案22. Zuul对请求头的...
  • 一.背景微服务架构下,我们的系统根据...需要注意的是我们这边讲的是微服务之间调用的安全认证,不是统一的在API官网认证,需求不一样,API网关处的统一认证是和业务挂钩的,我们这边是为了防止接口被别人随便调用。
  • 微服务间的调用(Dubbo和SpringCloud)需要走网关层吗?
  • 业界普遍采用的做法是,内部系统之间调用用 RPC,对外用 REST,因为内部系统之间可能调用很频繁,需要 RPC 的高性能支撑。对外用 REST 更易理解,更通用些。 API网关内部和外部通讯方式 在进行协议转换前我们要先...
  • 网关服务架构

    千次阅读 2018-11-29 17:17:08
    一、要做一个网关服务的架构 网关具备哪些功能 隔绝网站应用服务与外部服务商应用的直接访问 限流 限定访问,ip、域名、请求等非法信息拦截 日志记录 不会因为业务增加而导致网关系统重启 二、要怎么设计  ...
  • spring cloud整合dubbo组件实现服务调用,以及dubbo调用服务和springcloud的feign调用服务的区别
  • SpringCloud底层服务之间是怎么相互调用的?

    万次阅读 多人点赞 2018-11-22 16:41:10
    :如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务 以上就是我们通过一个电商业务场景,阐述了Spring Cloud微服务架构几个核心组件的底层原理。 **文字总结还不够直观?...
  • 客户端与服务器之间消息交互通过网关服进行转发,客户端与网关服通过TCP进行连接,网关服将客户端消息发送对应服务器(登陆服、广场服、游戏服),对应服务器收到消息之后进行处理,处理完再通过网关服将消息发送给...
  • 自己动手写一个服务网关

    千次阅读 2018-11-25 01:16:18
    当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制。 本文所实现的网关源码抄袭了---Oh,不对,是借鉴。借鉴了Zuul网关的源码,提炼出其核心思路,实现了一套简单...
  • 来源:Java爱好者社区前言公司内考虑到服务器资源成本的问题,目前业务上还在进行服务的容器化改造和迁移,计划将容器化后的服务,以及一些中间件(MQ、DB、ES、Redis等)尽量都迁移到...
  • 微服务之间通过Ribbon或Feign实现服务之间调用以及负载均衡;通过Spring Cloud Config实现了应用多环境的外部化部署以及版本管理;为了使微服务集群更加健壮,使用hystrix的熔断机制避免某些服务出故障后引发的...
  • Spring Cloud Gateway服务网关

    千次阅读 热门讨论 2021-05-18 14:04:36
    Spring Cloud Gateway服务网关一、 概述1.1 Gateway是什么1.2 Gateway网关能做什么1.3 我们为什么选择Gatway1.4 SpringCloud Gateway 具有如下特性1.5 SpringCloud Gateway与Zuul的区别1.6 Zuul 1 模型1.7 WebFlux是...
  • 什么是网关: 网关就是架设在前端浏览器和后端微服务之间的一层服务,用于转发请求,微服务的接口不再暴露给前端页面,前端只了解网关的地址. 为什么需要网关: 其实不要也可以,加了网关就是可以做一些服务限流,统计比较...
  • Zuul:如果前端、移动端要调用后端系统,统一从Zuul网关进入,由Zuul网关转发请求给对应的服务   以上就是我们通过一个电商业务场景,阐述了Spring Cloud微服务架构几个核心组件的底层原理。   文字...
  • 五:对微服务API服务网关的理解

    万次阅读 2018-07-27 21:43:02
    通过以下几个问题去理解微服务中的一个重要组件:API网关。 1. 什么是API网关 2. 为什么需要API网关 3. API网关在微服务架构体系中处于什么位置 4. 网关技术实现有哪些 5. zuul网关工作原理是什么样的 6. 技术上...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,194
精华内容 24,877
关键字:

服务之间调用网关