一、为什么要用微服务网关

在微服务架构中,一般不同的微服务有不同的网络地址,而外部客户端(如手机APP)可能需要调用多个接口才能完成一次业务需求。例如一个电影购票的手机APP,可能会调用多个微服务的接口,才能完成一次购票的业务流程。

电影购票业务

如果让客户端直接与微服务通信会产生以下的问题:
1.客户端会多次请求不同的微服务,增加了客户端的复杂性。
2.存在跨域请求,在一定场景下处理比较复杂。
3.认证复杂,每个服务都需要单独认证。
4.难以重构
5.某些微服务可能使用了防火墙/游览器不友好的协议,直接访问会有一定的困难。
以上问题就可以借助微服务网关解决,微服务网关是介于客户端和服务端之间的中间层,所有的外部请求先经过微服务网关

二、Zuul简介

Zuul是Netflix开源的微服务网关,可以和Eureka,Ribbon,Hystrix等组件配合使用。Zuul的核心是一系列过滤器,这些过滤器可以完成以下功能:
1.身份认证与安全
2.审查与监控
3.动态路由
4.压力测试
5.负载均衡
6.静态响应处理等

三、编写Zuul微服务网关

1.创建一个Maven工程microservice-gateway-zuul,并添加依赖

<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>

2.在启动类添加注解 @EnableZuulProxy声明一个Zuul代理,该代理使用Ribbon来定位注册在Eureka Server中的服务,同时还整合了Hystrix。

  1. @EnableZuulProxy 

  2. @SpringBootApplication 

  3. public class MicroserviceGatewayZuulApplication { 


  4. public static void main(String[] args) { 

  5. SpringApplication.run(MicroserviceGatewayZuulApplication.class, args); 





3.编写配置文件application.yml

server:
port: 8040
spring:
application:
name: microservice-gateway-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/

说明:默认情况Zuul会代理所有注册到Eureka Server上的微服务,并且路由规则如下。
http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的ServiceId/** 会被转发到serviceId对应的微服务。
测试过程省略。

四、路由配置详解

1.自定义指定微服务的访问路径

zuul:
routes:
microservice-provider-user: /user/**

格式zuul.routes.微服务的serviceId = 指定路径,这样microservice-provider-user微服务就会被映射到路径/user/**
2.忽略指定微服务

zuul:
ignored-services: microservice-provider-user,microservice-consumer-movie

用逗号分隔,来指定忽略多个微服务。
3.忽略所有微服务,只路由指定微服务

zuul:
ignored-services: '*'
routes:
microservice-provider-user: /user/**

4.同时指定微服务的serviceId和路径

zuul:
routes:
user-route: ## 这个路由名称可以随意命名
service-id: microservice-provider-user
path: /user/**

这个同示例1是一样的
5.同时指定path和URL

 zuul:
routes:
user-route: ## 这个路由名称可以随意命名
url: http://localhost:8000/ #指定的url
path: /user/** #url对应的路径

但是这样有些问题,这种方式配置的路由不会作为HystrixCommand执行,也不能使用Ribbon来负载均衡多个URL。
6.忽略某些路径

zuul:
routes:
microservice-provider-user: /user/**
ignored-patterns: /**/admin/** #忽略所有包含admin路径的

这样就可以将微服务microservice-provider-user映射到/user/** 路径,同时忽略所有包含/admin/的路径。

五、Zuul的header设置&上传文件&过滤器

5.1敏感header的设置

zuul:
routes:
microservice-provider-user:
path: /users/**
sensitive-headers: Cookie,Set-Cookie,Authorization
url: https://downstream

这样就可以为microservice-provider-user指定敏感header了,不过可以指定全局的。

zuul:
sensitive-headers: Cookie,Set-Cookie,Authorization

5.2忽略header

可以用zuul.ignoredHeaders属性丢弃一些header,例如:

zuul:
ignored-headers: header1,header2

这样设置后,header1和header2就不会传播到其他微服务中。

5.3使用Zuul上传文件

对于小文件(1M以内),无需处理即可上传,对于大文件(10M以上)上传,需要为上传路径添加/zuul前缀,也可以使用zuul.servlet-path自定义前缀。
1.创建一个Maven工程,microservice-file-upload,并添加以下依赖。

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

2.在启动类上添加注解@EnableEurekaClient,@SpringBootApplication
3.编写controller

  1. /** 

  2. * @author ship 

  3. * @Description 文件上传 

  4. * @Date: 2018-07-24 09:43 

  5. */ 

  6. @Controller 

  7. public class FileUploadController { 


  8. @RequestMapping(value = "/upload",method = RequestMethod.POST) 

  9. public String upload(@RequestParam(value = "file",required = true) MultipartFile file)throws IOException{ 

  10. File desFile = new File(file.getOriginalFilename()); 

  11. FileCopyUtils.copy(file.getBytes(),desFile); 

  12. return desFile.getAbsolutePath(); 





4.配置文件application.yml

server:
port: 8050
spring:
application:
name: microservice-file-upload
http:
multipart:
max-file-size: 2000Mb # 默认1M
max-request-size: 2500Mb # 默认10M eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
## 上传大文件将超时时间设置的长一些
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 6000
ribbon:
ConnectTimeOut: 3000
ReadTimeOut: 60000

测试过程省略,文中使用的springboot版本都是1.5.14.RELEASE。

5.4过滤器

Zuul的大部分功能都是通过过滤器实现的,定义了4种标准类型,分别是:
1.PRE:这种过滤器在请求被路由之前调用,常用于身份验证、记录调试信息等。
2.ROUTING:这种过滤器将请求路由到微服务。
3.POST:这种过滤器在路由到微服务后执行。
4.ERROR:在其他阶段发生错误时执行该过滤器。


下面编写一个简单的过滤器,来实现打印请求日志。
1.复制项目microservice-gateway-zuul改为microservice-gateway-zuul-filter
2.编写自定义的Zuul过滤器

/**
* @author ship
* @Description Zuul过滤器打印日志
* @Date: 2018-07-23 14:33
*/
public class PreRequestLogFilter extends ZuulFilter { private static final Logger log = LoggerFactory.getLogger(PreRequestLogFilter.class); @Override
public String filterType() {
//返回过滤器的类型,有pre,route,post,error等几种值
return "pre";
} @Override
public int filterOrder() {
return 1;
} @Override
public boolean shouldFilter() {
return true;
} @Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("send %s request to %s",request.getMethod(),request.getRequestURL().toString()));
return null;
}
}

3.修改启动类,添加以下内容。

    @Bean
public PreRequestLogFilter preRequestLogFilter(){
return new PreRequestLogFilter();
}

测试先依次启动microservice-discovery-eureka,microservice-provider-user,microservice-gateway-zuul-filter,
再访问http://localhost:8040/microservice-provider-user/1,即可获得如下日志。

六、Zuul的容错与回退

在SpringCloud中,Zuul默认已经整合了Hystrix(可自行测试Hystrix监控),下面说说如何实现回退。
为Zuul添加回退主要是实现FallbackProvider接口(ZuulFallbackProvider已经过时),并返回一个ClientHttpResponse对象,下面开始代码编写。
1.复制项目microservice-gateway-zuul更改为microservice-gateway-zuul-fallback
2.编写回退类。

/**
* @author ship
* @Description 在Edgware及更高版本,ZuulFallbackProvider已经过时。
* @Date: 2018-07-23 13:07
*/
@Component
public class UserFallbackProvider implements FallbackProvider { private static final Logger log = LoggerFactory.getLogger(UserFallbackProvider.class); @Override
public ClientHttpResponse fallbackResponse(Throwable cause) {
log.error("微服务回退原因:"+cause.getMessage());
return this.fallbackResponse();
} @Override
public String getRoute() {
//表明为哪个微服务提供回退
return "microservice-provider-user";
} @Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
//fallback时的状态码
return HttpStatus.OK;
} @Override
public int getRawStatusCode() throws IOException {
//返回数字类型的状态码,本例返回的就是200
return this.getStatusCode().value();
} @Override
public String getStatusText() throws IOException {
return this.getStatusCode().getReasonPhrase();
} @Override
public void close() { } @Override
public InputStream getBody() throws IOException {
//响应体
return new ByteArrayInputStream("用户微服务不可用,请稍后再试。".getBytes());
} @Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application","json", Charset.forName("UTF-8"));
headers.setContentType(mediaType);
return headers;
}
};
} }

当microservice-provider-user微服务无法正常响应时,可以在游览器看到用户微服务不可用,请稍后再试。

七、Zuul的高可用

7.1 Zuul客户端也注册到了Eureka Server上

这种情况下,只要将多个zuul节点注册到Eureka Server即可实现高可用。

7.2 Zuul客户端未注册到了Eureka Server上

假如Zuul客户端是一个手机app,我们可以借助一个负载均衡器实现Zuul的高可用,比如Nginx、HAProxy等。

八、小结

关于微服务网关Zuul还有一些内容没有说,比如聚合微服务。代码全部提交在了我的github上,欢迎留言指教。

【SpringCloud构建微服务系列】微服务网关Zuul的更多相关文章

  1. 玩转Windows服务系列——Windows服务小技巧

    伴随着研究Windows服务,逐渐掌握了一些小技巧,现在与大家分享一下. 将Windows服务转变为控制台程序 由于默认的Windows服务程序,编译后为Win32的窗口程序.我们在程序启动或运行过程 ...

  2. 玩转Windows服务系列——Windows服务启动超时时间

    最近有客户反映,机房出现断电情况,服务器的系统重新启动后,数据库服务自启动失败.第一次遇到这种情况,为了查看是不是断电情况导致数据库文件损坏,从客户的服务器拿到数据库的日志,进行分析. 数据库工作机制 ...

  3. 玩转Windows服务系列——Windows服务小技巧

    原文:玩转Windows服务系列——Windows服务小技巧 伴随着研究Windows服务,逐渐掌握了一些小技巧,现在与大家分享一下. 将Windows服务转变为控制台程序 由于默认的Windows服 ...

  4. go微服务系列(二) - 服务注册/服务发现

    目录 1. 服务注册 1.1 代码演示 1.2 在go run的时候传入服务注册的参数 2. 服务发现均衡负载 2.1 均衡负载算法 2.2 服务发现均衡负载的演示 1. 服务注册 1.1 代码演示 ...

  5. go微服务系列(三) - 服务调用(http)

    1. 关于服务调用 2. 基本方式调用服务 3. 服务调用正确姿势(初步) 3.1 服务端代码 3.2 客户端调用(重要) 1. 关于服务调用 这里的服务调用,我们调用的可以是http api也可以是 ...

  6. 干货分享丨玩转物联网IoTDA服务系列四-智能网关

    摘要:该场景主要描述的是设备可以通过MQTT协议与物联网平台进行交互,用户可以在控制台产品详情中自定义Topic,通过应用侧接口或控制台创建数据转发规则,把设备上报的消息转发给其他华为云服务,供应用侧 ...

  7. SpringCloud 2020.0.4 系列之服务降级

    1. 概述 老话说的好:做人要正直,做事要正派,胸怀坦荡.光明磊落,才会赢得他人的信赖与尊敬. 言归正传,之前聊了服务间通信的组件 Feign,今天我们来聊聊服务降级. 服务降级简单的理解就是给一个备 ...

  8. SpringCloud学习系列之六 ----- 路由网关Zuul基础使用教程

    前言 在上篇中介绍了SpringCloud Config的完美使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关 ...

  9. SpringCloud 2020.0.4 系列之服务降级的其他用法与熔断

    1. 概述 老话说的好:控制好自己的情绪,才能控制好自己的人生.冲动是魔鬼,冷静才最重要. 言归正传,之前聊了在 Feign 调用时,如何给整个 Feign接口类 增加降级策略. 今天我们来聊一下 H ...

  10. 玩转Windows服务系列——使用Boost.Application快速构建Windows服务

    玩转Windows服务系列——创建Windows服务一文中,介绍了如何快速使用VS构建一个Windows服务.Debug.Release版本的注册和卸载,及其原理和服务运行.停止流程浅析分别介绍了Wi ...

随机推荐

  1. HDU 2050 【dp】【简单数学】

    题意: 中文. 思路: 不难发现数学规律是这样的,每次增加的划分区域的数量是每次增加的交点的数量再加一.然后就总结出了递推公式. #include<stdio.h> ]; int main ...

  2. [转]JavaEE开发基础

    JavaEE开发基础 1 JavaEE简介 Java平台有三个版本,分别是JavaSE(Java Platform, Standard Edition),JavaEE(Java Platform, E ...

  3. Linux 上运行 mapreduce 类型错误

    1.ClassCastException 错误代码 /** * */ /** * @author hadoop * */ package WordCount; import java.io.IOExc ...

  4. BZOJ 1091([SCOI2003]分割多边形-分割直线)

    1091: [SCOI2003]分割多边形 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 223  Solved: 82 [Submit][id=10 ...

  5. C++开发人脸性别识别教程(8)——搭建MFC框架之读取目录信息

    在上一篇博客中我们已经绘制了MFC界面,在这篇博客中我们将加入响应代码,为MFC框架加入一个最主要的功能:打开一个目录. 一.加入相关头文件 这里头文件主要包括三类:opencv头文件.批量读取文件相 ...

  6. 白话空间统计之四:P值和Z值(上):零如果

    本来今天想要讲讲软件操作的,后来发现好像还有好几个重要的指标没有说,干脆等所有说完在讲操作吧.否则操作出来的结果会发现大量的"不明觉厉". 首先是空间统计里面非常神奇的两个值:P值 ...

  7. Android sdcard读写权限问题之中的一个

    博主在刚刚在学习过程中发现了一个关于android往sdcard读写的问题, 配置了该配置的提示无读写权限. 在AndroidManifest.xml文件里配置清单例如以下 <manifest ...

  8. Unity5的关卡切换

    本文章由cartzhang编写,转载请注明出处. 全部权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/51055584 作者:car ...

  9. web 开发之js---ajax 中的两种提交方式ajax post 和 ajax get 实例

    ()post http://04101334.iteye.com/blog/637695/ ()get function serializeElement(element) { var method ...

  10. Webx框架:依赖注入

    Webx的依赖注入和Spring的依赖注入很像,仅仅是有一点点的差别. 注入的时候仅仅能让生命周期长的注入到生命周期短的对象中,比方requestScope对象注入到singleton时就会错误发生. ...