Spring Cloud学习系列第四章:路由与过滤服务Zuul
来源:互联网 发布:扫描仪软件通用版 编辑:程序博客网 时间:2024/06/01 13:24
一、简介
前面讨论的知识基本上都是围绕后台微服务,但是我们的微服务最终是要提供给客户端调用的,例如WEB、Android、IOS,毕竟用户又不关心你的后台服务架构多么优秀。那么问题来了,几十上百个微服务,都要用反向代理服务器配置,那么多服务器ip,那个配置文件我都不忍直视。既然我们的服务都已经注册在Eureka Server中了,那么直接去代理Eureka Server不就好了,but Eureka Server的服务是不能直接反向代理的,所以Netflix又又又提供给我们一个服务路由器Zuul,简单来说,Zuul是Netflix的基于JVM的路由器和服务器端负载均衡器。
一个简单的微服务架构如下图,前端需要访问的接口都通过访问Zuul集群代理的接口去访问,这样反向代理服务器只需要配置zuul集群就行了,易扩展易维护;微服务之间都可以通过Feign等相互调用。
二、Zuul路由功能
创建Zuul项目,首先肯定要依赖Zuul,其次我们要去发现Eureka里面的服务,所以要成为Eureka client,完整pom如下。
<?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"> <modelVersion>4.0.0</modelVersion> <groupId>com.nan</groupId> <artifactId>zuuldemo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>zuuldemo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR2</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
Zuul项目我们也不需要编写自己的业务代码,只需在项目启动入口加上对应的注解即可。
package com.nan.zuuldemo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@SpringBootApplication@EnableEurekaClient@EnableZuulProxypublic class ZuuldemoApplication { public static void main(String[] args) { SpringApplication.run(ZuuldemoApplication.class, args); }}
最后就是配置文件了,新增主要是zuul.routes的配置。每一个服务我们都给它取个名字,配置好访问路径和在Eureka里面注册的服务id。
spring: application: name: ZuulDemoserver: port: 9200eureka: client: service-url: defaultZone: http://node01:8081/eureka/,http://node02:8082/eureka/zuul: routes: api-hello: path: /api-hello/** serviceId: HelloService api-user: path: /api-user/** serviceId: UserService
然后启动Eureka server以及2个service,最后启动zuul项目。在浏览器分别输入http://localhost:9200/api-hello/hello?name=秦始皇和http://localhost:9200/api-user/user/2,可以看到页面回显的内容就是调用了HelloService和UserService的结果,这就是Zuul的路由功能。
三、Zuul过滤功能
Zuul路由功能很酷也很重要,因为是核心嘛,但是还有一个功能也很重要,就是过滤。一般来说我们提供对外的接口是有一定权限控制的,比如微信或支付宝的接口,都有一大推token、appkey之类的,所以我们也实现一下权限过滤,不过我们只实现一下简单的IP过滤,复杂的权限控制,基本也差不多是这个套路,我们只对HelloService进行过滤,代码如下。
package com.nan.zuuldemo.filter;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;import java.util.regex.Pattern;@Componentpublic class IpFilter extends ZuulFilter { Logger logger = LoggerFactory.getLogger(IpFilter.class); @Value("${zuul.routes.api-hello.path}") private String apiHelloPath; /** * 获取过滤器类型,可以返回下面4个字符串之一 * pre:可以在请求被路由之前调用 * route:在路由请求时候被调用 * post:在route和error过滤器之后被调用 * error:处理请求时发生错误时被调用 */ @Override public String filterType() { //ip过滤器,表示是前置过滤器 return "pre"; } @Override public int filterOrder() { //过滤器优先级,数字越大,优先级越低,其实就是过滤器链里面用到的 return 0; } /** * 是否执行该过滤器 * true 过滤 false 不过滤 */ @Override public boolean shouldFilter() { //我们要执行此过滤器,所以返回true return true; } /** * 过滤逻辑方法 */ @Override public Object run() { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); if (request.getRequestURI().startsWith(apiHelloPath.split("\\*")[0])) { String ip = getIpAddress(request); logger.info("Request real ip = " + ip); //ip不是127.0.0.1,禁止访问 if (!ip.equals("127.0.0.1")) { //不路由该请求 requestContext.setSendZuulResponse(false); //设置错误码 requestContext.setResponseStatusCode(401); //设置返回内容 requestContext.setResponseBody("Sorry,request ip forbidden"); } } return null; } /** * 获取真实请求ip */ private String getIpAddress(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; }}
代码里面都有注释,就不啰嗦了,简单继承Zuul提供的抽象类,实现抽象方法。然后重新启动zuuldemo项目,在浏览器输入http://127.0.0.1:9200/api-hello/hello?name=秦始皇,url的hostname一定要用ip哦,不然会有意想不到的效果,页面回显正常;如果用真实ip访问,比如我的是http://192.168.0.104:9200/api-hello/hello?name=秦始皇,页面就会回显Sorry,request ip forbidden,甚至随便输入个地址,http://192.168.0.104:9200/api-hello/9527,正常应该市404错误,但也会被拦截掉。
以上就是笔者目前所学,还是很初级的内容,如果有什么错误和遗漏,还请见谅并指正,不胜感激。
- Spring Cloud学习系列第四章:路由与过滤服务Zuul
- Spring Cloud(八):服务转发路由zuul
- Spring cloud系列十三 服务网关Zuul
- Spring Cloud学习--服务网关(Zuul)
- Spring Cloud学习--服务网关(Zuul 过滤器)
- Spring Cloud----Zuul动态路由
- 【Spring Cloud】Zuul 路由访问
- Spring Cloud Zuul--服务网关
- Spring Cloud Zuul--服务网关
- 服务网关 Spring Cloud Zuul
- 使用Spring Cloud Zuul实现动态路由
- spring cloud整合swagger,通过zuul路由
- Spring Cloud Zuul实现动态路由(zuul设计)
- Spring Cloud Zuul (服务网关)
- spring-cloud-zuul服务网关(五)
- API网关服务:Spring Cloud Zuul
- SpringCloud API网关服务(Spring Cloud Zuul)
- Spring Cloud中的API网关服务Zuul
- java并发工具CyclicBarrier的理解和使用
- 打破 FOXMAIL 疯狂占用磁盘读写资源的魔障
- Java并发编程实战(学习笔记十二 第十三章 显式锁)
- js复制到粘贴板命令及第三方插件 clipboard 、ZeroClipboard
- json dump()参数
- Spring Cloud学习系列第四章:路由与过滤服务Zuul
- 剑指offer:左旋转字符串
- 强大的第三方-轮播图
- lightoj 1234 Harmonic Number
- 目标追踪-meanshift算法
- Armor CEO在2017年黑客大会上的演讲
- scroll连续滚动问题
- 最大熵学习笔记(零)目录和引言
- 关于 ObjectARX 兼容性