1、微服务网关介绍和使用场景
简介:讲解网关的作用和使用场景 (画图)
1)什么是网关
API Gateway,是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能
统一接入
智能路由
AB测试、灰度测试
负载均衡、容灾处理
日志埋点(类似Nignx日志)
流量监控
限流处理
服务降级
安全防护
鉴权处理
监控
机器网络隔离
2)主流的网关
zuul:是Netflix开源的微服务网关,和Eureka,Ribbon,Hystrix等组件配合使用,Zuul 2.0比1.0的性能提高很多
kong: 由Mashape公司开源的,基于Nginx的API gateway
nginx+lua:是一个高性能的HTTP和反向代理服务器,lua是脚本语言,让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求
2、SpringCloud的网关组件zuul基本使用
简介:讲解zuul网关基本使用
创建工程
1)在任意工程下,File >> NEW project
2)
3)
1、加入依赖
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>2.0.4.RELEASE</version> 9 <relativePath/> <!-- lookup parent from repository --> 10 </parent> 11 <groupId>com.po</groupId> 12 <artifactId>api-gateway</artifactId> 13 <version>0.0.1-SNAPSHOT</version> 14 <name>api-gateway</name> 15 <description>Demo project for Spring Boot</description> 16 17 <properties> 18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 19 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 20 <java.version>1.8</java.version> 21 <spring-cloud.version>Finchley.SR1</spring-cloud.version> 22 </properties> 23 24 <dependencies> 25 <dependency> 26 <groupId>org.springframework.cloud</groupId> 27 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 28 </dependency> 29 <dependency> 30 <groupId>org.springframework.cloud</groupId> 31 <artifactId>spring-cloud-starter-netflix-zuul</artifactId> 32 </dependency> 33 34 <dependency> 35 <groupId>org.springframework.boot</groupId> 36 <artifactId>spring-boot-starter-test</artifactId> 37 <scope>test</scope> 38 </dependency> 39 </dependencies> 40 41 <dependencyManagement> 42 <dependencies> 43 <dependency> 44 <groupId>org.springframework.cloud</groupId> 45 <artifactId>spring-cloud-dependencies</artifactId> 46 <version>${spring-cloud.version}</version> 47 <type>pom</type> 48 <scope>import</scope> 49 </dependency> 50 </dependencies> 51 </dependencyManagement> 52 53 <build> 54 <plugins> 55 <plugin> 56 <groupId>org.springframework.boot</groupId> 57 <artifactId>spring-boot-maven-plugin</artifactId> 58 </plugin> 59 </plugins> 60 </build> 61 62 63 64 </project>
yml
server: port: 9000 #服务名称 spring: application: name: api-gateway #指定注册中心地址 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
2、启动类加入注解 @EnableZuulProxy
默认集成断路器 @EnableCircuitBreaker
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package org.springframework.cloud.netflix.zuul; 7 8 import java.lang.annotation.ElementType; 9 import java.lang.annotation.Retention; 10 import java.lang.annotation.RetentionPolicy; 11 import java.lang.annotation.Target; 12 import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 13 import org.springframework.context.annotation.Import; 14 15 @EnableCircuitBreaker 16 @Target({ElementType.TYPE}) 17 @Retention(RetentionPolicy.RUNTIME) 18 @Import({ZuulProxyMarkerConfiguration.class}) 19 public @interface EnableZuulProxy { 20 }
默认访问规则
http://gateway:port/service-id/**
例子:默认 /order-service/api/v1/order/save?user_id=2&product_id=1
自定义 /xdclass_order/api/v1/order/save?user_id=2&product_id=1
比如:
http://localhost:8781/api/vi/order/save?product_id=2&user_id=5
数据如下:
{"code":0,"data":{"id":0,"productName":"\"iPhone7data from port = 8771\"","tradeNo":"2ca0043f-b105-4707-9aa5-8f4727a1abf5","price":7999,"createTime":"2019-01-06T09:37:50.100+0000","userId":5,"userName":null}}
现在通过网关访问
http://localhost:9000/order-service/api/vi/order/save?product_id=2&user_id=5
数据如下:
{"code":0,"data":{"id":0,"productName":"\"iPhone7data from port = 8771\"","tradeNo":"a43c4dd2-f978-4612-97aa-abb2fb735dba","price":7999,"createTime":"2019-01-06T09:39:50.436+0000","userId":5,"userName":null}}
同理其他访问
http://localhost:9000/product-service/api/vi/product/findById?id=2
{"id":2,"name":"iPhone7data from port = 8771","price":7999,"store":20}
自定义路由转发:
1 zuul: 2 routes: 3 order-service: /apigateway/**
http://localhost:9000/apigateway/api/vi/order/save?product_id=2&user_id=5
{"code":0,"data":{"id":0,"productName":"\"iPhone7data from port = 8771\"","tradeNo":"30bae8a6-ccef-49a0-b9fd-06f3afaceb28","price":7999,"createTime":"2019-01-06T09:53:54.154+0000","userId":5,"userName":null}}
环境隔离配置:
需求 :不想让默认的服务对外暴露接口
/order-service/api/v1/order/save
配置:
1 #自定义路由映射 2 zuul: 3 routes: 4 order-service: /apigateway/** 5 product-service: /apigateway/** 6 #统一入口为上面的配置,其他入口忽略 7 ignored-patterns: /*-service/** 8 #忽略整个服务,对外提供接口 9 #ignored-services: product-service
分析:
这样配置之后,访问路径含有service都不行了,必须是apigateway前缀
/**是任意内容的:均可以访问
经测试将第二个会覆盖第一个,
也就是http://localhost:9000/apigateway/api/vi/order/save?product_id=2&user_id=5访问失败
http://localhost:9000/apigateway/api/vi/product/list可以访问
所有配置修改:
1 #自定义路由映射 2 zuul: 3 routes: 4 order-service: /apigateway/order/** 5 product-service: /apigateway/product/** #统一入口为上面的配置,其他入口忽略 7 ignored-patterns: /*-service/** 8 #忽略整个服务,对外提供接口 9 #ignored-services: product-service
http://localhost:9000/apigateway/order/api/vi/order/save?product_id=2&user_id=5
http://localhost:9000/apigateway/product/api/vi/product/list
注意:如果知道ip也是可以访问的
http://localhost:8771/api/vi/product/findById?id=2
补充:服务之间的调用都是通过内网访问
3、高级篇幅之Zuul常用问题分析和网关过滤器原理分析
简介:讲解Zuul网关原理和过滤器生命周期,
1、路由名称定义问题
路由映射重复覆盖问题
1 #自定义路由映射 2 zuul: 3 routes: 4 order-service: /apigateway/order/** 5 product-service: /apigateway/product/** #统一入口为上面的配置,其他入口忽略 7 ignored-patterns: /*-service/** 8 #忽略整个服务,对外提供接口 9 #ignored-services: product-service
2、Http请求头过滤问题
1)对order-service服务的save方法进行修改
1 @RequestMapping("save") 2 @HystrixCommand(fallbackMethod = "saveOrderFail")//调用save方法失败则执行saveOrderFail的方法 3 public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id")int productId, HttpServletRequest request){ 4 String token = request.getHeader("token"); 5 String cookie = request.getHeader("cookie"); 6 System.out.println("token= "+token); 7 System.out.println("cookie= "+cookie); 8 Map<String, Object> data = new HashMap<>(); 9 data.put("code",0); 10 data.put("data",productOrderService.save(userId,productId)); 11 return data; 12 }
通过Postman访问,在Headers添加token,cookie
控制台
1 token= sdasdsadasd 2 cookie= null
cookie没有值?
为什么呢?
routes源码下
ZuulProperties类
1 private Set<String> sensitiveHeaders = new LinkedHashSet<>( 2 Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
已经过滤掉cookie,set-cookie,Authorization这三个参数
1 #自定义路由映射 2 zuul: 3 routes: 4 order-service: /apigateway/order/** 5 product-service: /apigateway/product/** 6 #统一入口为上面的配置,其他入口忽略 7 ignored-patterns: /*-service/** 8 #处理http请求头为空的问题 9 sensitive-headers:
注意:其实zuul就是filter结集合
4、自定义Zuul过滤器实现登录鉴权实战
简介:自定义Zuul过滤器实现登录鉴权实战
在api-gateway服务下
1、新建一个filter包
2、新建一个类,实现ZuulFilter,重写里面的方法
ACL访问控制列表,将路径(/apigateway/order/api/vi/order/save)存放到redis里面
3、在类顶部加注解,@Component,让Spring扫描
1 package com.po.apigateway.filter; 2 3 import com.netflix.zuul.ZuulFilter; 4 import com.netflix.zuul.context.RequestContext; 5 import com.netflix.zuul.exception.ZuulException; 6 import org.apache.commons.lang.StringUtils; 7 import org.springframework.http.HttpStatus; 8 import org.springframework.stereotype.Component; 9 import javax.servlet.http.HttpServletRequest; 10 11 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; 12 /* 13 登入过滤器 14 */ 15 @Component 16 public class LoginFilter extends ZuulFilter { 17 18 /* 19 前置过滤器 20 */ 21 @Override 22 public String filterType() { 23 return PRE_TYPE; 24 } 25 /** 26 * 过滤器顺序,越小越先执行 27 * @return 28 */ 29 @Override 30 public int filterOrder() { 31 return 4; 32 } 33 /** 34 * 过滤器是否生效 35 * @return 36 */ 37 @Override 38 public boolean shouldFilter() { 39 RequestContext currentContext = RequestContext.getCurrentContext(); 40 HttpServletRequest request = currentContext.getRequest(); 41 //System.out.println("路径1: "+request.getRequestURL());//http://localhost:9000/apigateway/product/api/vi/product/list 42 // System.out.println("路径2: "+request.getRequestURI());// /apigateway/product/api/vi/product/list 43 if("/apigateway/order/api/vi/order/save".equalsIgnoreCase(request.getRequestURI())){ 44 return true;//拦截 45 }else if("/apigateway/product/api/vi/product/list".equalsIgnoreCase(request.getRequestURI())){ 46 return true; 47 }else if("/apigateway/product/api/vi/product/findById".equalsIgnoreCase(request.getRequestURI())){ 48 return true; 49 } 50 return false; 51 } 52 /** 53 * 业务逻辑 54 * @return 55 */ 56 @Override 57 public Object run() throws ZuulException { 58 59 System.out.println("拦截了 "); 60 RequestContext requestContext = RequestContext.getCurrentContext(); 61 HttpServletRequest request = requestContext.getRequest(); 62 String token = request.getHeader("token"); 63 if(StringUtils.isBlank(token)){//post请求的话 64 token = request.getParameter("token"); 65 } 66 if(StringUtils.isBlank(token)){ //登录校验逻辑 根据公司情况自定义 JWT技术 67 requestContext.setSendZuulResponse(false);//不往下走 68 //响应回去状态码 实际开发中对客户访问会带加密过的token过来,解密再判断是否为null,查数据库太慢了 69 requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); 70 } 71 return null; 72 } 73 }
流程: shouldFilter方法中返回true,才会执行ZuulException 方法。
5、高级篇幅之高并发情况下接口限流特技
简介:谷歌guava框架介绍,网关限流使用
1、nginx层限流
2、网关层限流
在filter包下
1 package com.po.apigateway.filter; 2 3 import com.google.common.util.concurrent.RateLimiter; 4 import com.netflix.zuul.ZuulFilter; 5 import com.netflix.zuul.context.RequestContext; 6 import com.netflix.zuul.exception.ZuulException; 7 import org.springframework.http.HttpStatus; 8 import org.springframework.stereotype.Component; 9 10 import javax.servlet.http.HttpServletRequest; 11 12 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE; 13 /* 14 订单限流 15 */ 16 @Component 17 public class OrderRateLimiter extends ZuulFilter { 18 //每秒产生1000个令牌 19 private static final RateLimiter RATE_LIMITER=RateLimiter.create(1000); 20 21 @Override 22 public String filterType() { 23 return PRE_TYPE; 24 } 25 26 @Override 27 public int filterOrder() { 28 return -4; 29 } 30 31 @Override 32 public boolean shouldFilter() { 33 RequestContext currentContext = RequestContext.getCurrentContext(); 34 HttpServletRequest request = currentContext.getRequest(); 35 if("/apigateway/order/api/vi/order/save".equalsIgnoreCase(request.getRequestURI())){ 36 return true;//拦截 37 } 38 return false; 39 } 40 41 @Override 42 public Object run() throws ZuulException { 43 RequestContext requestContext = RequestContext.getCurrentContext(); 44 if(!RATE_LIMITER.tryAcquire()){//太多请求 45 requestContext.setSendZuulResponse(false); 46 requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); 47 } 48 return null; 49 } 50 }
6、Zuul微服务网关集群搭建
简介:微服务网关Zull集群搭建
1、nginx+lvs+keepalive
https://www.cnblogs.com/liuyisai/p/5990645.html