zuul

基于Spring的微服务结点在能力上没有高低贵贱之分,但是在角色上会分为边缘服务和内部服务两部分。内部服务顾名思义是为对内暴露服务的结点,供架构内部来调用;边缘服务是对外部网络暴露的服务结点,也就是对外API接口。

开发人员头疼的地方:为了防止我的程序在网络上被人攻击,我们需要写各种权限机制,这些机制在每个微服务结点都要实现一次。一旦鉴权上有什么bug,又要全部节点上推倒重来,噩梦。

运维人员头疼的地方:边缘服务前段都会架一个F5或者Nginx等负载均衡的代理,需要手动维护一份服务列表和服务地址的路由信息,随着结点的扩展或地址调整这份列表要变来变去。

为了解决鉴权重复的问题,使业务结点本身只关心实现自己的业务,将对权限的处理抽离到上层。外部客户先请求到Zuul上,在Zuul服务上对权限进行统一实现和过滤,以实现微服务结点的过滤和验证。

为了解决请求路由和安全过滤,Spring Cloud推出了一个API gateway组件:Spring Cloud Zuul。

在路由方面,Zuul将自己作为一个微服务结点注册到Eureka上,就获取了所有微服务的实例信息,同时又以服务名为ContextPath的方式创建路由映射。

spring cloud 自定义路由 内存消耗_spring

创建工程 eureka-zuul

在parent-clould 项目上新建一个module, 取名eureka-zuul

pom.xml文件内容如下

<?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.could.shj</groupId>
	<artifactId>eureka-zuul</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>eureka-zuul</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>com.could.shj</groupId>
		<artifactId>parent-clould</artifactId>
		<version>1.0-SNAPSHOT</version>
	</parent>



	<dependencies>
		<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>

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



</project>

启动类如下

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableZuulProxy
public class EurekaZuulApplication {

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

配置文件如下

server.port=8787
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
spring.application.name=eureka-zuul
zuul.routes.ribbon.path=/ribbon/**
zuul.routes.ribbon.serviceId=eureka-ribbon
zuul.routes.feign.path=/feign/**
zuul.routes.feign.serviceId=eureka-feign

服务为eureka-zuul,端口为8787,以 /ribbon/开头的请求转发给eureka-ribbon

以/feign/ 开头的请求,转发给 erueka-feign

 

依次启动,server,client,ribbon,feign,zuul,在浏览器中输入:

http://127.0.0.1:8787/ribbon/hello?name=shj

spring cloud 自定义路由 内存消耗_spring_02

http://127.0.0.1:8787/feign/hello?name=shj

spring cloud 自定义路由 内存消耗_spring_03

注意: 刚开始的时候可能会返回一个异常页面,刷新网页就好

spring cloud 自定义路由 内存消耗_spring_04

此时注册的服务有:

spring cloud 自定义路由 内存消耗_微服务_05

zuul过滤

 

写一个过滤类

package com.could.shj.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @version 1.0
 * @className MyFilter
 * @Description
 * @Author shj
 * @Date 2018/7/27、14:19
 */
@Component
public class MyFilter  extends ZuulFilter{

    @Override
    public String filterType() {
        /*filterType 返回一个字符串代表过滤的类型:
        可返回的内容及其含义
        pre:路由之前
        routing:路由之时
        post:路由之后
        error:发送错误调用
        */
        return "pre";
    }

    @Override
    public int filterOrder() {
        //过滤的顺序
        return 0;
    }

    @Override
    public boolean shouldFilter() {
//      可以写逻辑判断,  是否要过滤,true表示需要过滤
        return true;
    }

    @Override
    public Object run() throws ZuulException {
//     过滤的具体内容
//       可以很复杂,包括查sql,nosql去判断该请求到底有没有权限访问。

        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletRequest request=requestContext.getRequest();

        Object token=request.getParameter("token");
        if(token==null){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(401);
            try {
                requestContext.getResponse().getWriter().write("token 为空");
            }catch (Exception e){
                return null;
            }
        }




        return null;
    }
}

然后在浏览器中访问

http://127.0.0.1:8787/ribbon/hello?name=shj

spring cloud 自定义路由 内存消耗_结点_06

 

 

http://127.0.0.1:8787/ribbon/hello?name=shj&token=1

spring cloud 自定义路由 内存消耗_spring_07

注意: 此时可能会访问到error page ,刷新页面就好

 

 

 

完成后项目的路径为:

spring cloud 自定义路由 内存消耗_微服务_08