您的位置:首页 > 编程语言 > Java开发

SpringCloud微服务实战-Zuul-APIGateway(十)

2017-07-25 15:10 495 查看

本文转自:http://blog.csdn.net/qq_22841811/article/details/67637786#准备工作

1APIGateway

2Zuul介绍

2.1zuul的功能

Routinginanintegralpartofamicroservicearchitecture.Forexample,/maybemappedtoyourwebapplication,/api/usersismappedtotheuserserviceand/api/shopismappedtotheshopservice.ZuulisaJVMbasedrouterandserversideloadbalancerbyNetflix.

路由在微服务架构的一个组成部分。例如,/可以映射到您的Web应用程序,/api/users映射到用户服务,并且/api/shop映射到商店服务。Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。

其功能包括

验证

见解

压力测试

金丝雀测试

动态路由

服务迁移

减载

安全

静态响应处理

主动/主动流量管理

Zuul的规则引擎允许规则和过滤器基本上用任何JVM语言编写,内置支持Java和Groovy。

2.2Zuul的配置简述

配置属性zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,默认分别为200和20。

所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE。如果首选此隔离模式,则可以将zuul.ribbonIsolationStrategy更改为THREAD。

2.3在springcloud中使用zuul

SpringCloud创建了一个嵌入式Zuul代理,以简化一个非常常见的用例开发,即UI应用程序想要代理对一个或多个后端服务的调用。此功能对于用户界面代理所需的后端服务非常有用,从而避免了对所有后端独立管理CORS和身份验证问题。

要启用它,使用@EnableZuulProxy注释一个SpringBoot主类,并将本地调用转发到相应的服务。按照惯例,ID为“users”的服务将从位于/users处的代理(带有前缀剥离)接收请求。代理使用Ribbon来定位要通过发现转发的实例,并且所有请求都在hystrix命令中执行,因此故障将显示在Hystrix指标中,一旦电路打开,代理将不会尝试联系服务。

注意:Zuul启动器不包括发现客户端,因此对于基于服务ID的路由,您需要在类路径中提供其中一个(例如Eureka是一个选择)。

3Zuul的基本使用

maven依赖

<?xmlversion="1.0"encoding="UTF-8"?>
<projectxmlns="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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent>
<artifactId>spring-cloud-microservice-study</artifactId>
<groupId>com.clsaa.learn.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>microservice-gateway-zuul</artifactId>

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


启动类

packagecom.clsaa.learn.zuul;

importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
使用@EnableZuulProxy注解激活zuul。
*跟进该注解可以看到该注解整合了@EnableCircuitBreaker、@EnableDiscoveryClient,是个组合注解,目的是简化配置。
*CreatedbyEggon2017/7/25
*/
@SpringBootApplication
@EnableZuulProxy
publicclassZuulApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(ZuulApplication.class,args);
}
}


配置文件:application.yml

spring:
application:
name:microservice-gateway-zuul
server:
port:8040
eureka:
instance:
hostname:localhost#指定该Eureka实例的主机名
prefer-ip-address:true
client:
serviceUrl:
defaultZone:'target='_blank'>http://username:password@localhost:8761/eureka[/code]

3.1测试

启动microservice-api-gateway项目。还记得我们之前访问通过http://localhost:8000/1去访问microservice-provider-user服务中id=1的用户信息吗?

我们现在访问http://localhost:8050/microservice-provider-user/1试试。会惊人地看到:

{"id":1,"username":"Tom","age":12}


这不正是microservice-provider-user服务中id=1的用户信息吗?

所以我们可以总结出规律:访问

http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**
将会访问到
http://想要访问的Eureka服务id的小写:该服务端口/**

4自定义配置Zuul路由

上文我们已经完成了通过APIGateway去访问微服务的目的,是通过
http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**
的形式访问的,那么如果我们想自定义在APIGateway中的路径呢?譬如想使用
http://localhost:8050/user/1
就能够将请求路由到http://localhost:8000/1呢?

只需要做一点小小的配置即可:

spring:
application:
name:microservice-api-gateway
server:
port:8050
eureka:
instance:
hostname:gateway
client:
serviceUrl:
defaultZone:http://discovery:8761/eureka/#下面整个树都非必须,如果不配置,将默认使用http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**路由到:http://想要访问的Eureka服务id的小写:该服务端口/**
zuul:
routes:
user:#可以随便写,在zuul上面唯一即可;当这里的值=service-id时,service-id可以不写。
path:/user/**#想要映射到的路径
service-id:microservice-provider-user#Eureka中的serviceId


5如何忽略某些服务

准备工作

启动服务:microservice-discovery-eureka

启动服务:microservice-provider-user

启动服务:microservice-consumer-movie-ribbon

如果我们现在只想将microservice-consumer-movie-ribbon服务暴露给外部,microservice-provider-user不想暴露,那么应该怎么办呢?

依然只是一点小小的配置即可:

spring:
application:
name:microservice-api-gateway
server:
port:8050
eureka:
instance:
hostname:gateway
client:
serviceUrl:
defaultZone:http://discovery:8761/eureka/zuul:
ignored-services:microservice-provider-user#需要忽视的服务(配置后将不会被路由)
routes:
movie:#可以随便写,在zuul上面唯一即可;当这里的值=service-id时,service-id可以不写。
path:/movie/**#想要映射到的路径
service-id:microservice-consumer-movie-ribbon-with-hystrix#Eureka中的serviceId


也可使用ignoredServices:服务名

路由必须有一个“路径”,可以指定为ant样式模式,所以“/myusers/”只匹配一个级别,但“/myusers/*”分层匹配。

后端的位置可以被指定为“serviceId”(对于来自发现的服务)或“url”(对于物理位置),例如。

zuul:
routes:
users:
path:/myusers/**
url:'target='_blank'>http://example.com/users_service[/code]

6启动Hystrixcommand

这些简单的url路由不会作为HystrixCommand执行,也不能使用Ribbon来平衡多个URL。要实现此目的,请指定服务路由并为serviceId配置功能区客户端(这当前需要禁用功能区中的Eureka支持:有关详细信息,请参阅上文)。

zuul:
routes:
users:
path:/myusers/**
serviceId:users

ribbon:
eureka:
enabled:false

users:#这是ribion要请求的serviceID
ribbon:
listOfServers:http://localhost:7900,http://localhost:7901


7使用正则表达规则路由

可以使用regexmapper在serviceId和路由之间提供约定。它使用正则表达式命名的组从serviceId提取变量并将它们注入到路由模式中。

regexmapper:用于routepattern转换为servicePattern

routepattern:路由正则表达式

servicePattern:service正则表达式

@Bean
publicPatternServiceRouteMapperserviceRouteMapper(){
returnnewPatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}


这意味着serviceId“myusers-v1”将映射到路由“/v1/myusers/”。接受任何正则表达式,但所有命名组必须同时存在于servicePattern和routePattern中。如果servicePattern与serviceId不匹配,则使用缺省行为。在上面的示例中,serviceId“myusers”将映射到路由“/myusers/”(未检测到任何版本)。此功能默认情况下处于禁用状态,仅适用于发现的服务。

zuul:
ignoredPatterns:/**/admin/**
routes:
users:/myusers/**


Thismeansthatallcallssuchas“/myusers/101”willbeforwardedto“/101”onthe“users”service.Butcallsincluding“/admin/”willnotresolve.

如果你需要你的路由以保留它们的顺序,你需要使用YAML文件,因为使用属性文件将会丢失顺序。例如:如果要使用属性文件,则旧路径可能会在用户路径前面显示,导致用户路径无法访问。

8zuul.prefix

要向所有映射添加前缀,请将zuul.prefix设置为一个值,例如/api。默认情况下,在转发请求之前,从请求中删除代理前缀(使用zuul.stripPrefix=false关闭此行为)。

prefix和stripPrefix(依赖于prefix的使用)连用影响是全局的

path和stripPrefix连用影响是局部的

9细节知识

9.1routes

如果使用@EnableZuulProxy与SpringBootActuator,您将启用(默认情况下)一个额外的端点,通过HTTP作为/routes可用。到此端点的GET将返回映射路由的列表。POST将强制刷新现有路由(例如,如果服务目录中有更改)。

9.2StrangulationPatterns(绞杀者模式)

迁移现有应用程序或API时的常见模式是“扼杀”旧的端点,慢慢地用不同的实现替换它们。Zuul代理是一个有用的工具,因为可以使用它来处理来自旧端点的客户端的所有流量,但重定向一些请求到新的端点。

zuul:
routes:
first:
path:/first/**
url:http://first.example.comsecond:
path:/second/**
url:forward:/second
third:
path:/third/**
url:forward:/3rd#本地的转发
legacy:
path:/**
url:'target='_blank'>http://legacy.example.com[/code]

9.3fallback

在类中定制http返回的属性

packagecom.clsaa.learn.zuul.fallback;

importorg.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
importorg.springframework.http.HttpHeaders;
importorg.springframework.http.HttpStatus;
importorg.springframework.http.MediaType;
importorg.springframework.http.client.ClientHttpResponse;
importorg.springframework.stereotype.Component;

importjava.io.ByteArrayInputStream;
importjava.io.IOException;
importjava.io.InputStream;

@Component
publicclassMyFallbackProviderimplementsZuulFallbackProvider{
@Override
publicStringgetRoute(){
//route如
return"microservice-provider-user";
}

@Override
publicClientHttpResponsefallbackResponse(){
returnnewClientHttpResponse(){
@Override
publicHttpStatusgetStatusCode()throwsIOException{
returnHttpStatus.OK;
}

@Override
publicintgetRawStatusCode()throwsIOException{
return200;
}

@Override
publicStringgetStatusText()throwsIOException{
return"OK";
}

@Override
publicvoidclose(){

}

@Override
publicInputStreamgetBody()throwsIOException{
returnnewByteArrayInputStream(("fallback"+MyFallbackProvider.this.getRoute()).getBytes());
}

@Override
publicHttpHeadersgetHeaders(){
HttpHeadersheaders=newHttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
returnheaders;
}
};
}
}


9.4使用sidecar支持异构语言

10过滤器

10.1过滤器类型与请求生命周期

Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用ApacheHttpClient或NetfilxRibbon请求微服务。

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTPHeader、收集统计信息和指标、将响应从微服务发送给客户端等。

ERROR:在其他阶段发生错误时执行该过滤器。

除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。



10.2编写zuul过滤器

过滤器类

packagecom.clsaa.learn.zuul;

importcom.netflix.zuul.ZuulFilter;
importcom.netflix.zuul.context.RequestContext;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.stereotype.Component;

importjavax.servlet.http.HttpServletRequest;

@Component
publicclassPreZuulFilterextendsZuulFilter{
privatefinalstaticLoggerLOGGER=LoggerFactory.getLogger(PreZuulFilter.class);

@Override
publicStringfilterType(){
return"pre";
}

@Override
publicintfilterOrder(){
return1;//数字越大越靠后
}

@Override
publicbooleanshouldFilter(){
returntrue;
}

@Override
publicObjectrun(){
HttpServletRequestservletRequest=RequestContext.getCurrentContext().getRequest();
Stringhost=servletRequest.getRemoteHost();
PreZuulFilter.LOGGER.info("requesthost:"+host);
returnnull;
}
}


10.3禁用过滤器

479/5000
ZuulforSpringCloud在代理和服务器模式下默认启用了一些ZuulFilterbean。有关已启用的可能过滤器,请参阅zuul过滤器包。如果你想禁用一个,只需设置:

zuul.<SimpleClassName>.<filterType>.disable=true


按照惯例,过滤器之后的包是Zuul过滤器类型。例如,禁用

org.springframework.cloud.netflix.zuul.filters.post.SendResponseFiltersetzuul.SendResponseFilter.post.disable=true



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: