Fork me on GitHub

SpringCloud个人笔记-05-Zuul初体验

  • sb_cloud_zuul

 

  1.为什么需要网关呢?

    1.1 我们知道我们要进入一个服务本身,很明显我们没有特别好的办法,直接输入IP地址+端口号,我们知道这样的做法很糟糕的,这样的做法大有问题,首先暴露了我们实体机器的IP地址,别人一看你的IP地址就知道服务部署在哪里,让别人很方便的进行攻击操作

 

    1.2

我们这么多服务,我们是不是要挨个调用它呀,我们这里假设做了个权限认证,我们每一个客户访问的都是跑在不同机器上的不同的JVM上的服务程序,我们每一个服务都需要一个服务认证,这样做烦不烦呀,明显是很烦的。

那么我们这时候面临着这两个极其重要的问题,这时我们就需要一个办法解决它们。首先,我们看IP地址的暴露和IP地址写死后带来的单点问题,我是不是对这么服务本身我也要动态的维护它服务的列表呀,我需要调用这服务本身,是不是也要一个负载均衡一样的玩意,还有关于IP地址暴露的玩意,我是不是需要做一个代理呀,像Nginx的反向代理一样的东西,还有这玩意上部署公共的模块,比如所有入口的权限校验的东西。

 

因此我们现在需要Zuul API网关。它就解决了上面的问题,你想调用某个服务,它会给你映射,把你服务的IP地址映射成

某个路径,你输入该路径,它匹配到了,它就去替你访问这个服务,它会有个请求转发的过程,像Nginx一样,服务机器的具体实例,它不会直接去访问IP,它会去Eureka注册中心拿到服务的实例ID,即服务的名字。我再次使用客户端的负载均衡ribbon访问其中服务实例中的一台

 

  


 

 

<?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.huarui</groupId>
    <artifactId>sb_cloud_zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sb_cloud_zuul</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.19.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Edgware.SR3</spring-cloud.version>
    </properties>

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

        <!-- config依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!-- zuul依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>

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

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.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>
pom.xml

 

spring:
  application:
    name: sb-cloud-zuul
  cloud:
    config:
      discovery:
        enabled: true
        service-id: SB-CLOUD-CONFIG
      profile: dev
      #uri: http://localhost:9002/

eureka:
  client:
    serviceUrl:
      defaultZone: http://39.108.85.204:8761/eureka/
  #instance:
    #注册时使用ip而不是主机名
    #prefer-ip-address: true
    #指定ip
    #ip-address: ip
server:
  port: 9005


zuul:
  routes:
    sb-product: #随意取
      path: /sb-product/** # 真实访问路径 /sb-product/** -> sb-cloud-product/**
      serviceId: sb-cloud-product
      sensitiveHeaders:
# ignored-patterns: /sb-cloud-order/order/getProduct,/sb-cloud-product/product/getMsg
#  简洁写法
#zuul:
#  routes:
#    sb-cloud-product: sb-product

management:
  security:
    enabled: false
bootstrap.yml

 

@SpringBootApplication
@EnableZuulProxy
public class SbCloudZuulApplication {

	/**
	 *
	 * http://localhost:9005/sb-cloud-product/product/getMsg
	 *
	 * http://localhost:9005/sb-cloud-order/order/getProduct
	 *
	 * localhost:9005/application/routes
	 * @param args
        */
	public static void main(String[] args) {
		SpringApplication.run(SbCloudZuulApplication.class, args);
	}

}

  

启动sb_cloud_zuul     默认端口9005

启动sb_cloud_product     默认端口9000

 

直接访问 商品服务 : http://39.108.85.204:9000/product/getMsg  可以返回数据

通过zuul路由访问  :  http://localhost:9005/sb-cloud-product/product/getMsg 也可以返回数据

 

规则就是 服务的名字/服务的请求路径

 

 

  • 我想配置个性化的路径路由到我想要去的服务
zuul:
  routes:
    sb-product: #路由规则名 可随意取
      path: /sb-product/** # 真实访问路径 /sb-product/** -> sb-cloud-product/**
      serviceId: sb-cloud-product # 要路由的服务名
      sensitiveHeaders:

  

  配置后 ,表现为 http://localhost:9005/sb-product/product/getMsg  也可以返回数据

  

 

  • 我想过滤特定的路径不让别人访问

 

zuul:
  routes:
    sb-product: #路由规则名 可随意取
      path: /sb-product/** # 真实访问路径 /sb-product/** -> sb-cloud-product/**
      serviceId: sb-cloud-product # 要路由的服务名
      #sensitiveHeaders:
  #要过滤的路径(可配置多个 , 分割)
  ignored-patterns: /sb-cloud-order/order/getProduct,/sb-cloud-product/product/getMsg

  

 

zuul组件包含了对请求的路由和过滤两个功能

1.其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础

2.而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础

  每一个进入zuul的http请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端

 

zuul中实现的过滤器必须包含4个基本特征:过滤类型,执行顺序,执行条件,具体操作

String filterType();

filterType:该函数需要返回一个字符串代表过滤器的类型,而这个类型就是在http请求过程中定义的各个阶段。在zuul中默认定义了4个不同的生命周期过程类型,具体如下

  • pre:可以在请求被路由之前调用
  • routing: 路由请求时被调用
  • post:在routing和error过滤器之后被调用
  • 处理请求时发生错误时被调用
int filterOrder();

通过int值来定义过滤器的执行顺序,数值越小优先级越高。

boolean shouldFilter();

返回一个boolean值来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。

Object run();

过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。

 

过滤器实现

package com.huarui.filter;

import com.google.common.util.concurrent.RateLimiter;
import com.huarui.exception.RateLimitException;
import com.netflix.zuul.ZuulFilter;
import org.springframework.stereotype.Component;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;


/**前置
 * 限流
 * 令牌桶规则
 * Created by lihui on 2019/3/2.
 *
 */
@Component
public class RateLimitFilter extends ZuulFilter {

    /**
     * 每秒钟10个令牌
     */
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(10);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return SERVLET_DETECTION_FILTER_ORDER - 2;
    }

   
    @Override
    public boolean shouldFilter() {
        return true;
    }

  /** * 具体实现 * @return */ @Override public Object run() { if (!RATE_LIMITER.tryAcquire()){//如果没有取到令牌则无法访问 throw new RateLimitException(); } return null; } }

 

package com.huarui.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;


/**
 * 后置过滤器
 * Created by lihui on 2019/3/2.
 */
@Component
public class addRespHeaderFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {//给访问的请求加上请求头信息
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        response.setHeader("lihui", "youxiu326"+UUID.randomUUID().toString());
        return null;
    }
}

 

 

测试:请求头中携带了参数

 

 测试:限流

posted @ 2019-03-05 18:33  youxiu326  阅读(193)  评论(0编辑  收藏  举报