(十)spring-cloud入门学习:API服务网关Spring Cloud Zuul

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/guangcaiwudong/article/details/96995954

Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,那外部请求如何调用服务?如何进行路由和过滤?

在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务端。

Spring Cloud Zuul路由是微服务架构的不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。

Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/api/user转发到到user服务,/api/shop转发到到shop服务。zuul默认和Ribbon结合实现了负载均衡的功能。

一、Zuul基础功能:路由和过滤

1.创建eureka_zuul工程,pom.xml如下

<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.kevin</groupId>
  <artifactId>euraka_zuul</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>euraka_zuul</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.4.RELEASE</version>
  </parent>

  <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </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>
  <dependencyManagement>
    <dependencies>
        <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-dependencies</artifactId>
           <version>Greenwich.SR1</version>
           <type>pom</type>
           <scope>import</scope>
        </dependency>
    </dependencies>
  </dependencyManagement>
</project>

2. application.properties定义路由地址

spring.application.name=eurekaZuul
server.port=9301
eureka.client.serviceUrl.defaultZone=http://localhost:9101/eureka/
zuul.routes.ribbon.path=/ribbon/**
zuul.routes.ribbon.serviceId=eurekaRibbon
zuul.routes.feign.path=/feign/**
zuul.routes.feign.serviceId=eurekaFeign

3. Application.java开启zuul代理

package com.kevin.euraka_zuul;

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

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

4. 如果需要进行过滤,可继承ZuulFilter。
Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”;
在这里插入图片描述

TokenFilter.java:

package com.kevin.euraka_zuul.filter;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

@Component
public class TokenFilter extends ZuulFilter{

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

	@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()));
        String accessToken = request.getParameter("token");
        if(StringUtils.isEmpty(accessToken)) {
        	ctx.setSendZuulResponse(false);
        	ctx.setResponseStatusCode(400);
        	ctx.setResponseBody("failed, no token");
        }else {
        	ctx.setSendZuulResponse(true);
        	ctx.setResponseStatusCode(200);
        }
		
		return null;
	}

	@Override
	public String filterType() {
		return "pre";
	}

	@Override
	public int filterOrder() {
		return 0;
	}
}

4. 测试:
1)过滤检查
在这里插入图片描述
2)负载均衡
在这里插入图片描述
在这里插入图片描述

扫描二维码关注公众号,回复: 7592239 查看本文章

3) 路由
在这里插入图片描述

二、熔断

1. 实现熔断类FallbackProvider,需要指定路由应用名和定义熔断返回内容

package com.kevin.euraka_zuul.filter;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

@Component
public class FeignFallback implements FallbackProvider{

	@Override
	public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
		return new ClientHttpResponse() {
			
			@Override
			public HttpHeaders getHeaders() {
				HttpHeaders headers = new HttpHeaders();
                  headers.setContentType(MediaType.APPLICATION_JSON);
              	  return headers;
			}
			
			@Override
			public InputStream getBody() throws IOException {
				return new ByteArrayInputStream("The service is unavailable.".getBytes());
			}
			
			@Override
			public String getStatusText() throws IOException {
				return "OK";
			}
			
			@Override
			public HttpStatus getStatusCode() throws IOException {
				return HttpStatus.OK;
			}
			
			@Override
			public int getRawStatusCode() throws IOException {
				return 200;
			}
			
			@Override
			public void close() {
				
			}
		};
	}

	@Override
	public String getRoute() {
		return "eurekaFeign";
	}
}

2. 当eurekaFeign停止服务后,通过zuul访问,返回熔断信息
在这里插入图片描述

三、超时与重试

1. 可以通过以下配置设置超时时长

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
ribbon.ConnectTimeout=3000
ribbon.ReadTimeout=6000

也可以指定service的超时时长
在这里插入图片描述

2. 重试

<dependency>
	<groupId>org.springframework.retry</groupId>
	<artifactId>spring-retry</artifactId>
</dependency>

配置文件:

#开启重试
zuul.retryable=true
#最大重试次数
client.ribbon.MaxAutoRetries=3
#切换相同Server的次数
client.ribbon.MaxAutoRetriesNextServer=0

参考:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#_router_and_filter_zuul
http://www.ityouknow.com/springcloud/2018/01/20/spring-cloud-zuul.html

猜你喜欢

转载自blog.csdn.net/guangcaiwudong/article/details/96995954