SpringCloud Zuul

网关,外界环境访问Cloud服务中心的服务时,都需要通过网关组件进行访问,相当于代理作用。微服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。

在这里插入图片描述
在Spring cloud体系中,一般上选择zuul或者Gateway网关技术。
Spring Cloud Zuul:Zuul是Netflix开源的微服务网关
可以和Eureka、Ribbon、Hystrix等组件配合使用,
Spring Cloud对Zuul进行了整合与增强,Zuul的主要功能是路由转发和过滤器。

Spring Cloud Gateway:是由spring官方基于Spring5.0,Spring Boot2.0,Project Reactor等技术开发的网关,
提供了一个构建在Spring Ecosystem之上的API网关,旨在提供一种简单而有效的途径来发送API,
并向他们提供交叉关注点,例如:安全性,监控/指标和弹性。
目的是为了替换Spring Cloud Netfilx Zuul的。

SpringCloud Zuul网关的搭建过程如下:

  1. 创建一个项目,在pom.xml导入spring-boot-starter-parent、spring-cloud-denpendences、spring-cloud-starter-netflix-eureka-client、spring-cloud-starter-netflix-zuul
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
</parent>

<dependencyManagement>
    <dependencies>
        <!-- spring-cloud-parent -->
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>Finchley.RELEASE</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
    </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>
                spring-cloud-starter-netflix-eureka-client
            </artifactId>
        </dependency>
    </dependencies>
  1. 在application.properties配置文件定义eureka参数
server.port=9999

spring.application.name=ydma-zuul
eureka.client.serviceUrl.defaultZone=http://localhost:3333/eureka
  1. 在启动类前使用@EnableZuulProxy、@EnableDiscoveryClient等
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy//启用zuul代理
public class ZuulRunBoot {

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

}
  1. 外界访问,通过zuul网关访问eureka注册其他的集群服务,访问格式
http://localhost:9999/服务名/请求
提示:服务名用小写

Zuul Filter

SpringCloud提供了很多内置的filter,进行请求处理。
在这里插入图片描述

Zuul过滤器适合做一些权限检查、身份认证等处理。
在这里插入图片描述
ZuulFilter的作用:
编写实现类,继承ZuulFilter,重写约定方法

@Component
public class CheckLoginFilter extends ZuulFilter{

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public boolean shouldFilter() {
        //获取请求URI,不需要登录的就return false;需要登录的return true
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String uri = request.getRequestURI();
        List<String> checkUris = new ArrayList<String>();
        checkUris.add("/ydma-video/chapters");
        System.out.println("检查"+uri+"是否需要进行拦截检查");
        if(checkUris.contains(uri)) {
            return true;//true调用filter
        }
        return false;//false不调用filter
    }

    @Override
    public Object run() throws ZuulException {
        //过滤器执行逻辑
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        String ticket = request.getParameter("ticket");
        if(ticket != null&&!"".equals(ticket)) {
        	//这里是get请求,如果是post请求的话就比较麻烦,需要进行如下操作:
        	//String url = "http://YDMA-USER/user/token";
        	//MultiValueMap<String, String> params= 
        	//		new LinkedMultiValueMap<String, String>();
        	//params.add("token", token);
        	//YdmaResult checkResult = 
        	//	restTemplate.postForObject(url, params, YdmaResult.class);
        	
            YdmaResult checkResult = restTemplate.getForObject(
                    "http://YDMA-USER/user/ticket?ticket="+ticket, YdmaResult.class);
            if(checkResult.getCode()==YdmaConstant.SUCCESS) {
                ctx.setSendZuulResponse(true);//允许继续路由调用服务
                ctx.setResponseStatusCode(200);
                return null;
            }
        }
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST");
        response.setContentType("text/html;charset=utf-8");
        ctx.setSendZuulResponse(false);//阻止继续路由调用服务
        ctx.setResponseStatusCode(401);//response.setStatus(401);
        ctx.setResponseBody("{\"code\":-1,\"msg\":\"用户身份不合法,未登录\"}");//out.println("{\"code\":-1,\"msg\":\"用户身份不合法,未登录\"}");
        return null;
    }

    @Override
    public String filterType() {
        return "pre";//过滤器类型,pre、post、error、route
    }

    @Override
    public int filterOrder() {
        return 0;//过滤器执行顺序... -3、-2、-1、0、1、2、3
    }

}

Zuul Fallback回退机制

我们在项目中使用Spring cloud zuul的时候,在zuul进行路由分发时,如果后端服务没有启动,或者调用超时,这时候我们希望Zuul提供一种hystrix服务降级处理,而不是将异常暴露出来。

Zuul集成了Hystrix,提供一个FallbackProvider回退机制当路由后面的服务发生故障时进行降级处理。

@Component
public class ServiceFallbackProvider implements FallbackProvider {

    @Override
    // 返回值表示需要针对此微服务做回退处理(该名称一定要是注册进入 eureka 微服务中的那个 serviceId 名称)
    public String getRoute() {
        return "*"; // api服务id,如果需要所有调用都支持回退,则return "*"或return null
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK; // 请求网关成功了,所以是ok
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                String msg = "{\"code\":-1,\"msg\":\"服务调用失败\"}";
                return new ByteArrayInputStream(msg.getBytes("UTF-8")); // 返回前端的内容
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); // 设置头
                return httpHeaders;
            }
        };
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值