首页 > 编程语言 > 详细

SpringCloud之服务网关

时间:2020-04-12 16:36:24      阅读:45      评论:0      收藏:0      [点我收藏+]

1.zuul

1.1定义

zuul叫路由网关,它包含对请求的路由和过滤的功能。

路由负责将外部的请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。而过滤是负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能基础。

1.2项目开发

源代码:https://github.com/zhongyushi-git/cloud-zuul.git

1)参考ribbon的项目新建一个项目cloud-zuul,把eureka集群、api以及服务提供者8001拿过来

2)在pom中导入依赖  

技术分享图片
    <!--web-->
        <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>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- zuul路由网关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
View Code

3)配置yml

技术分享图片
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway


#把客户端注册到服务列表中
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/, http://eureka7002.com:7002/eureka/, http://eureka7003.com:7003/eureka/
  #设置入驻的服务的名称,是唯一的
  instance:
    instance-id: gateway-9527.com
    #访问路径显示ip
    prefer-ip-address: true
View Code

4)在hosts文件添加映射

127.0.0.1  myzuul.com

5)在com.zys.cloud包下创建启动类并添加注解@EnableZuulProxy

技术分享图片
package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

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

6)启动测试

先启动eureka集群,然后启动微服务提供者8001,最后启动路由9527。

不用路由访问:http://localhost:8001/user/get/1
使用路由访问: http://myzuul.com:9527/cloud-provider/user/get/1,其中cloud-provider是微服务提供者的名称
在使用路由访问的时候,暴露出了微服务的名称,但是一般情况下是不会这样做的,因此需要对微服务名称进行代理。

7)配置服务代理

在路由的yml配置代理的名称并设置不能使用微服务名进行访问。

技术分享图片
#配置微服务代理
zuul:
 
  routes:
    #指定要代理的微服务名称
    myuser.serviceId: cloud-provider
    #指定代理的路径
    myuser.path: /myuser/**
  #忽略真实的服务名,即不能使用服务名访问,只能通过代理访问以保证安全
  #忽略单个微服务
  ignored-services: cloud-provider
  #批量忽略微服务
#  ignored-services: "*"
View Code

重启路由的服务,访问http://myzuul.com:9527/myuser/user/get/1是没有问题的,访问http://myzuul.com:9527/cloud-provider/user/get/1出现404,已达到效果。

实例中设置忽略了单个微服务,如果要批量忽略微服务,给ignored-services设置为"*"即可。

8)设置统一前缀

有时候多个系统之间访问的路径需要相同的前缀,这个时候只需要在yml配置即可。

技术分享图片
zuul:
  #设置统一的前缀
  prefix: /springcloud
View Code

然后访问的时候都需要加这个前缀,访问路径是http://myzuul.com:9527/springcloud/myuser/user/get/1。

2.gateway

2.1定义

旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤功能,如熔断、限流、重试等。三大核心概念如下:

Route(路由):是构建网关的基本模块,由ID、URL、一系列断言和过滤器组成。
Predicate(断言):用于匹配Http请求中的所有内容,如果匹配则进行路由。
Filter(过滤):指的是Spring框架中GatewayFilter的实例

2.2zuul与gateway的区别

它是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor模式通信框架Netty,是基于异步非阻塞模型开发的。而zuul使用的是阻塞框架。

2.3项目开发

源代码:https://github.com/zhongyushi-git/cloud-gateway.git

2.3.1环境搭建

1)创建maven的父工程cloud-gateway,导入依赖

技术分享图片
<!--统一管理jar包版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
    </properties>

    <!--  依赖管理,父工程锁定版本-->
    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
View Code

2)创建eureka服务子模块cloud-eureka-server7001,导入依赖

技术分享图片
<dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--boot web actuator-->
        <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>

    </dependencies>
View Code

3)eureka的yml配置

技术分享图片
server:
  port: 7001

eureka:
  instance:
    #eureka服务端的实例名称
    hostname: localhost
  client:
    #false表示不向注册中心注册自己
    register-with-eureka: false
    #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
View Code

4)创建eureka启动类

技术分享图片
package com.zys.cloud;

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

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}
View Code

5)创建服务提供者子模块cloud-provider8001,导入依赖

技术分享图片
 <dependencies>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--boot web actuator-->
        <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>
    </dependencies>
View Code

6)8001的yml配置

技术分享图片
server:
  port: 8001

spring:
  application:
    name: cloud-provider



#把客户端注册到服务列表中
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka/
  #设置入驻的服务的名称,是唯一的
  instance:
    instance-id: cloud-provider8001
    #访问路径显示ip
    prefer-ip-address: true
View Code

7)创建8001启动类

技术分享图片
package com.zys.cloud;

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

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

8)创建8001的controller接口

技术分享图片
package com.zys.cloud.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

@RestController
@RequestMapping("/user")
public class UserController {

    @Value("${server.port}")
    private String port;

    @Value("${eureka.client.service-url.defaultZone}")
    private String eureka;

    @GetMapping("/get")
    public String get(){
        return "server port is \t"+port+".\t\t\t\t time:"+new Date();
    }

    @GetMapping("/get2")
    public String get2(){
        return "eureka server is \t"+eureka+".\t\t\t\t time:"+new Date();
    }


}
View Code

9)创建服务提供者子模块cloud-provider8002,方式同8001,只是端口号不同。创建完成后先启动eureka,然后启动8001和8002,在浏览器测试接口。

2.3.2创建路由子模块cloud-gateway9527

1)导入依赖

技术分享图片
  <dependencies>
        <!--eureka client-->
        <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>
    </dependencies>
View Code

需要注意的是,这里不需要导入web。

2)yml配置

技术分享图片
server:
  port: 9527

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

        - id: provider_routh   #路由的ID,没有固定规则但要求唯一,简易配合服务名
          uri: lb://cloud-provider     #匹配后提供服务的路由地址
          predicates:
            - Path=/user/get2/**             #断言,路径相匹配的进行路由
           
eureka:
  instance:
    hostname: cloud-gateway-service
    instance-id: cloud-gateway
    #访问路径显示ip
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka/
View Code

3)创建启动类

技术分享图片
package com.zys.cloud;

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

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

4)启动测试

先启动eureka,然后启动8001和8002,最后启动9527。浏览器输入http://127.0.0.1:9527/user/get2就可以正常访问了。多刷新几次,可以看出是8001和8002轮询的。

2.3.3动态路由配置

除了2.3.2中使用yml的方式配置路由外,还可以通过编码方式配置。

新建配置类GateWayConfig 

技术分享图片
package com.zys.cloud.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 编码方式配置路由
 */
@Configuration
public class GateWayConfig {
    /**
     * 配置一个id为route-name的路由规则,
     * 当访问地址http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei
     * @param routeLocatorBuilder
     * @return
     */
    @SuppressWarnings("JavaDoc")
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_route1",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();
        return routes.build();
    }
}
View Code

重启9527,访问地址http://localhost:9527/guonei时会自动转发到地址:http://news.baidu.com/guonei。

2.3.4断言配置

有时候为了进行配置,就可以配置断言。

例如:配置get2请求在某个时间后生效。只需要在yml的predicates设置After即可。

技术分享图片
predicates:
    - Path=/user/get2/**             #断言,路径相匹配的进行路由
    - After=2020-04-09T21:15:28.872+08:00[Asia/Shanghai]
View Code

后面的时间格式必须正确,获取格式时间的方法

技术分享图片
public static void  getTime(){
        ZonedDateTime zbj = ZonedDateTime.now();
        System.out.println(zbj);
    }
View Code

又如设置请求的方法必须为get

技术分享图片
predicates:
    - Path=/user/get2/**             #断言,路径相匹配的进行路由
    - After=2020-04-09T21:15:28.872+08:00[Asia/Shanghai]
    - Method=GET
View Code

2.3.5过滤器配置

自定义一个过滤器,只有在请求中包含unmae且不为null时才能访问。创建过滤器类MyLogGateWayFilter 

技术分享图片
package com.zys.cloud.filter;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 自定义过滤器
 */
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //每次进来后判断带不带uname这个key
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        //uname为null非法用户
        if(uname == null){
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        return 0;
    }
}
View Code

重启9527,访问地址http://127.0.0.1:9527/user/get2时无法访问,而http://127.0.0.1:9527/user/get2?uname=1可以正常访问。

  

SpringCloud之服务网关

原文:https://www.cnblogs.com/zys2019/p/12656029.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!