SpringCloud微服务实战-Zuul-APIGateway(十)
本文转自:http://blog.csdn.net/qq_22841811/article/details/67637786#准备工作
1 API Gateway
2 Zuul介绍
2.1 zuul的功能
- Routing in an integral part of a microservice architecture. For example, / may be mapped to your web application, /api/users is mapped to the user service and /api/shop is mapped to the shop service. Zuul is a JVM based router and server side load balancer by Netflix.
- 路由在微服务架构的一个组成部分。 例如,/可以映射到您的Web应用程序,/ api / users映射到用户服务,并且/ api / shop映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。
- 其功能包括
- 验证
- 见解
- 压力测试
- 金丝雀测试
- 动态路由
- 服务迁移
- 减载
- 安全
- 静态响应处理
- 主动/主动流量管理
- Zuul的规则引擎允许规则和过滤器基本上用任何JVM语言编写,内置支持Java和Groovy。
2.2 Zuul的配置简述
- 配置属性zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,默认分别为200和20。
- 所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE。 如果首选此隔离模式,则可以将zuul.ribbonIsolationStrategy更改为THREAD。
2.3 在springcloud中使用zuul
- Spring Cloud创建了一个嵌入式Zuul代理,以简化一个非常常见的用例开发,即UI应用程序想要代理对一个或多个后端服务的调用。此功能对于用户界面代理所需的后端服务非常有用,从而避免了对所有后端独立管理CORS和身份验证问题。
- 要启用它,使用@EnableZuulProxy注释一个Spring Boot主类,并将本地调用转发到相应的服务。按照惯例,ID为“users”的服务将从位于/ users处的代理(带有前缀剥离)接收请求。代理使用Ribbon来定位要通过发现转发的实例,并且所有请求都在hystrix命令中执行,因此故障将显示在Hystrix指标中,一旦电路打开,代理将不会尝试联系服务。
- 注意:Zuul启动器不包括发现客户端,因此对于基于服务ID的路由,您需要在类路径中提供其中一个(例如Eureka是一个选择)。
3 Zuul的基本使用
- maven依赖
<?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">
<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>
- 启动类
package com.clsaa.learn.zuul; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; /**
使用@EnableZuulProxy注解激活zuul。
* 跟进该注解可以看到该注解整合了@EnableCircuitBreaker、@EnableDiscoveryClient,是个组合注解,目的是简化配置。
* Created by Egg on 2017/7/25
*/
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(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: http://username:password@localhost:8761/eureka
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路由
上文我们已经完成了通过API Gateway去访问微服务的目的,是通过http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**的形式访问的,那么如果我们想自定义在API Gateway中的路径呢?譬如想使用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: http://example.com/users_service
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
public PatternServiceRouteMapper serviceRouteMapper() {
return new PatternServiceRouteMapper(
"(?<name>^.+)-(?<version>v.+$)",
"${version}/${name}");
}
- 这意味着serviceId“myusers-v1”将映射到路由“/ v1 / myusers / ”。 接受任何正则表达式,但所有命名组必须同时存在于servicePattern和routePattern中。 如果servicePattern与serviceId不匹配,则使用缺省行为。 在上面的示例中,serviceId“myusers”将映射到路由“/ myusers / ”(未检测到任何版本)。此功能默认情况下处于禁用状态,仅适用于发现的服务。
zuul:
ignoredPatterns: /**/admin/**
routes:
users: /myusers/**
This means that all calls such as “/myusers/101” will be forwarded to “/101” on the “users” service. But calls including “/admin/” will not resolve.
如果你需要你的路由以保留它们的顺序,你需要使用YAML文件,因为使用属性文件将会丢失顺序。 例如:如果要使用属性文件,则旧路径可能会在用户路径前面显示,导致用户路径无法访问。
8 zuul.prefix
- 要向所有映射添加前缀,请将zuul.prefix设置为一个值,例如/ api。 默认情况下,在转发请求之前,从请求中删除代理前缀(使用zuul.stripPrefix = false关闭此行为)。
- prefix和stripPrefix(依赖于prefix的使用)连用影响是全局的
- path和stripPrefix连用影响是局部的
9 细节知识
9.1 routes
- 如果使用@EnableZuulProxy与Spring Boot Actuator,您将启用(默认情况下)一个额外的端点,通过HTTP作为/ routes可用。 到此端点的GET将返回映射路由的列表。 POST将强制刷新现有路由(例如,如果服务目录中有更改)。
9.2 Strangulation Patterns (绞杀者模式)
- 迁移现有应用程序或API时的常见模式是“扼杀”旧的端点,慢慢地用不同的实现替换它们。 Zuul代理是一个有用的工具,因为可以使用它来处理来自旧端点的客户端的所有流量,但重定向一些请求到新的端点。
zuul:
routes:
first:
path: /first/**
url: http://first.example.com
second:
path: /second/**
url: forward:/second
third:
path: /third/**
url: forward:/3rd # 本地的转发
legacy:
path: /**
url: http://legacy.example.com
9.3 fallback
- 在类中定制http返回的属性
package com.clsaa.learn.zuul.fallback; import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
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; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; @Component
public class MyFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
//route 如
return "microservice-provider-user";
} @Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
} @Override
public int getRawStatusCode() throws IOException {
return 200;
} @Override
public String getStatusText() throws IOException {
return "OK";
} @Override
public void close() { } @Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(("fallback"+MyFallbackProvider.this.getRoute()).getBytes());
} @Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
9.4 使用sidecar支持异构语言
10过滤器
10.1过滤器类型与请求生命周期
Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
- PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。
- 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
10.2 编写zuul过滤器
- 过滤器类
package com.clsaa.learn.zuul; import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Component
public class PreZuulFilter extends ZuulFilter{
private final static Logger LOGGER = LoggerFactory.getLogger(PreZuulFilter.class); @Override
public String filterType() {
return "pre";
} @Override
public int filterOrder() {
return 1;//数字越大越靠后
} @Override
public boolean shouldFilter() {
return true;
} @Override
public Object run() {
HttpServletRequest servletRequest = RequestContext.getCurrentContext().getRequest();
String host = servletRequest.getRemoteHost();
PreZuulFilter.LOGGER.info("request host : " + host);
return null;
}
}
10.3 禁用过滤器
479/5000
Zuul for Spring Cloud在代理和服务器模式下默认启用了一些ZuulFilter bean。 有关已启用的可能过滤器,请参阅zuul过滤器包。 如果你想禁用一个,只需设置:
zuul.<SimpleClassName>.<filterType>.disable=true
按照惯例,过滤器之后的包是Zuul过滤器类型。 例如,禁用
org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter set zuul.SendResponseFilter.post.disable = true
SpringCloud微服务实战-Zuul-APIGateway(十)的更多相关文章
- springcloud微服务实战--笔记
目前对Springcloud对了解仅限于:“用[注册服务.配置服务]来统一管理其他微服务” 这个水平.有待提高 Springcloud微服务实战这本书是翟永超2017年5月写的,时间已经过去了两年,略 ...
- SpringCloud学习(SPRINGCLOUD微服务实战)一
SpringCloud学习(SPRINGCLOUD微服务实战) springboot入门 1.配置文件 1.1可以自定义参数并在程序中使用 注解@component @value 例如 若配置文件为a ...
- 【SpringCloud微服务实战学习系列】服务治理Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix微服务中的一部分,它基于NetFlix Sureka做了二次封装,主要负责完成微服务架构中的服务治理功能. 一.服务治理 ...
- SpringCloud微服务实战——第三章服务治理
Spring Cloud Eureka 服务治理 是微服务架构中最核心最基本的模块.用于实现各个微服务实例的自动化注册与发现. 服务注册: 在服务治理框架中,都会构建一个注册中心,每个服务单元向注册中 ...
- Spring-cloud微服务实战【八】:API网关zuul
在前面的文章中,我们先后使用了eureka/ribbon/feign/hystrix搭建了一个看似完美的微服务了,那是否还有值得继续优化的地方呢?答案肯定是有的,如果从整个微服务内部来看,基本已经 ...
- SpringCloud微服务实战——搭建企业级开发框架(四十四):【微服务监控告警实现方式一】使用Actuator + Spring Boot Admin实现简单的微服务监控告警系统
业务系统正常运行的稳定性十分重要,作为SpringBoot的四大核心之一,Actuator让你时刻探知SpringBoot服务运行状态信息,是保障系统正常运行必不可少的组件. spring-b ...
- SpringCloud微服务实战——搭建企业级开发框架(三十四):SpringCloud + Docker + k8s实现微服务集群打包部署-Maven打包配置
SpringCloud微服务包含多个SpringBoot可运行的应用程序,在单应用程序下,版本发布时的打包部署还相对简单,当有多个应用程序的微服务发布部署时,原先的单应用程序部署方式就会显得复杂且 ...
- SpringCloud微服务实战——搭建企业级开发框架(三十五):SpringCloud + Docker + k8s实现微服务集群打包部署-集群环境部署
一.集群环境规划配置 生产环境不要使用一主多从,要使用多主多从.这里使用三台主机进行测试一台Master(172.16.20.111),两台Node(172.16.20.112和172.16.20.1 ...
- SpringCloud微服务实战——搭建企业级开发框架(三十六):使用Spring Cloud Stream实现可灵活配置消息中间件的功能
在以往消息队列的使用中,我们通常使用集成消息中间件开源包来实现对应功能,而消息中间件的实现又有多种,比如目前比较主流的ActiveMQ.RocketMQ.RabbitMQ.Kafka,Stream ...
- SpringCloud微服务实战——搭建企业级开发框架(四十):使用Spring Security OAuth2实现单点登录(SSO)系统
一.单点登录SSO介绍 目前每家企业或者平台都存在不止一套系统,由于历史原因每套系统采购于不同厂商,所以系统间都是相互独立的,都有自己的用户鉴权认证体系,当用户进行登录系统时,不得不记住每套系统的 ...
随机推荐
- max number of clients reached Redis测试环境报错
现象:测试服务是去redis循环取数据,早上发现服务挂了,手动登陆redis 无法输入命令,报错:max number of clients reached Redis
- Daily Scrumming* 2015.10.26(Day 7)
一.总体情况总结 今天我们开会具体讨论了一下接下来的任务.还详细讨论了一下分数的分配,具体分数分配我们会在下一篇博客中详细说明. 我们下一周大致的工作安排如下: 1.UI:完成社团后台界面的设计,以及 ...
- Java实验五(客户端)
一. 实验内容 1. 运行教材上TCP代码,结对进行,一人服务器,一人客户端: 2. 利用加解密代码包,编译运行代码,客户端加密,服务器解密: 3. 客户端加密明文后将密文通过 ...
- eclipse异常关闭,而Tomcat然在运行解决方法
1.eclipse异常关闭,而Tomcat然在运行,再启动tomcat会出现端口冲突 解决方法:打开任务管理器,找到javaw.exe,点击关闭,就可以了
- 作业45//Calculator::3.0
计算器 github 我的天我到底要写什么 一,2.0及2.6的改动 做了计算部分 加入了判断输入是否合法 合法的定义是算式符合`数字+运算符+数字+运算符+数字`的格式 其中`"-&quo ...
- B3
吴晓晖(组长) 过去两天完成了哪些任务 一些细节的debug,部分优化,算法中有关记录的部分 展示GitHub当日代码/文档签入记录 接下来的计划 推荐算法 还剩下哪些任务 组员:刘帅珍 过去两天完成 ...
- MYSQL-不能创建表
Can't create table '.\ticket\user_role.frm' (errno: 121) 语法是对的,但显示上面的错误 原因有三种 1.表名重复 2.以该名字命名的表之前创建过 ...
- vs2010调试-尝试调试dll源码。
第一步: 打开“调试”——“选项和设置”——点击调试下“常规”——设置启用“启用.NET Framework源代码单步执行 ” 第二步 选择“符号”——选择Microsoft符号服务器——设置符号缓存 ...
- Internet History, Technology and Security (Week8)
Week 8 This week we start two weeks of Internet Security. It is a little technical but don't worry - ...
- angularJS1笔记-(19)-angular异步加载包的方式
我们平时写的导入包的方式都是同步方式,有时候会显得过于卡顿,这样我们就可以使用异步加载的方式. script.js方式: 执行结果为: 异步加载还可以加载多个即为script([,,,],functi ...