SpringCloud微服务注册调用入门-路由网关

1 . 路由网关的介绍

    路由网关(Zuul)的主要功能是路由转发和过滤器 . 路由功能是微服务的一部分 , 比如/service/user转发到到用户服务 , /service/shop转发到到商店服务等 .  zuul默认和Ribbon结合实现了负载均衡的功能

2 . 路由实现

2.1 与之前类似 , 新建模块zuul , 引入路由依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-zuul</artifactId>
	<version>1.4.4.RELEASE</version>
</dependency>

2.2 在其启动applicaton类加上注解@EnableZuulProxy,开启zuul的功能

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApplication {

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

2.3 yml配置文件 , 配置路由路径

spring:
  application:
    name: szuul
server:
  port: 8950

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9999/eureka/

zuul:
  routes:
    api-a:
      path: /service-a/**
      serviceId: client-ribbon # 表示/service-a/路径下的请求分发到client-ribbon服务
    api-b:
      path: /service-b/**
      serviceId: client-feign # 表示/service-b/路径下的请求分发到client-feign服务

2.4 结果测试

    依次启动eurekraserver , service-hello , client-ribbon , client-feign , zuul 6个模块 , 访问网址 http://localhost:8950/service-a/hello?id=123 , http://localhost:8950/service-b/hello?id=123 , 可以看到执行结果(因为我们未启动service-hello , 由于负载均衡的请求分发 , 所以正常会出现交替出现一次成功一次失败的情况) , 能够访问成功 . 

    接下来 , 我们停掉client-ribbon , 再访问 http://localhost:8950/service-a/hello?id=123 , 页面就无法访问了 , 而 http://localhost:8950/service-b/hello?id=123 不受影响 , 这说明路由起到了作用  , 以/service-a/ 开头的请求都转发给client-ribbon服务 , 以/service-b/开头的请求都转发给client-feign服务 . 

3 . 服务过滤

zuul不仅只是路由,并且还能过滤,做一些安全验证 . 为了演示 , 接下来我们继续改造工程

3.1 增加自定义过滤器 继承 ZuulFilter

package com.xbz.zuul.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;

@Component
public class MyZuulFilter extends ZuulFilter {

    /**
     * 返回过滤器类型
     * @return
     *  pre:可以在请求被路由之前调用
     *  routing:在路由请求时候被调用
     *  post:在routing和error过滤器之后被调用
     *  error:处理请求时发生错误时被调用
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 通过int值来定义过滤器的执行顺序 , 数字越小优先级越高
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 判断过滤器是否执行 , 返回false则不执行该过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器的具体逻辑
     *  ctx.setSendZuulResponse(false)令zuul不允许请求,
     *  ctx.setResponseStatusCode(401)设置了其返回的错误码
     *  ctx.setResponseBody(body)编辑返回body内容
     * @return
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if (accessToken == null) {
            System.out.println("error ! no token !");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("error ! no token !");
            } catch (Exception e) {
            }
            return null;
        }
        System.out.println("~ ok ~");
        return null;
    }
}

3.2 启动类中加入MyZuulFilter

package com.xbz.zuul;

import com.xbz.zuul.filter.MyZuulFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApplication {

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

    @Bean
    public MyZuulFilter getZuulFilter(){
        return new MyZuulFilter();
    }
}

3.3 结果测试

重启zuul模块 , 再次访问 http://localhost:8950/service-a/hello?id=123 , 会看到如下信息

error ! no token !error ! no token !
这说明我们配置的过滤器已经生效 , 必须有token参数才可以正常请求 . 访问  http://localhost:8950/service-a/hello?id=123&token=456 , 得到正常结果
hello 123 , service-hello , I am from port:8900

猜你喜欢

转载自blog.csdn.net/xingbaozhen1210/article/details/79805769