Gateway 简介
概述
微服务可能分布在不同的主机上,这样有许多缺点:前端需要硬编码调用不同地址的微服务很麻烦;存在跨域访问的问题;微服务地址直接暴露是不安全的。还有所以需要为前端提供一个统一的访问入口。Gateway 就是用于解决以上问题的框架。Gateway 本身是一个微服务,要注册到 Eureka 中。
入门案例
- maven 依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
- 启动类添加 @EnableDiscoveryClient 注解
- 配置文件:基本的 Eureka 配置 + 路由配置
server:
port: 10010
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user-service-route # 路由的标识 ID,任意名称都可以
uri: http://127.0.0.1:9092 # 路由的转发地址
predicates:
- Path=/user/** # 路由的映射范围
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
- 是否配置成功?
启动实例后能在 Eureka 注册中心看到注册,http://localhost:10010/user/**
的请求会被转发到 http://localhost:9092/user/**
。
动态路由
入门案例中使用的是静态IP 地址,下面是用服务名称代替具体 IP,这样避免直接使用 IP,并可以添加负载均衡。
只需要将配置中的 uri 更换为「loadbalance 协议」
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user-service-route # 路由的标识 ID,任意名称都可以
uri: lb://USER-SERVICE # 路由的转发地址
predicates:
- Path=/user/** # 路由的映射范围
路由规则
- 添加前缀:
http://localhost:10010/**
-->lb://USER-SERVICE/user/**
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user-service-route # 路由的标识 ID,任意名称都可以
uri: lb://USER-SERVICE # 路由的转发地址
predicates:
- Path=/** # 路由的映射范围
filters:
- PrefixPath=/user
- 去除前缀:
http://localhost:10010/api/api/user/**
-->lb://USER-SERVICE/user/**
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: user-service-route # 路由的标识 ID,任意名称都可以
uri: lb://USER-SERVICE # 路由的转发地址
predicates:
- Path=/api/api/user/** # 路由的映射范围
filters:
- StripPrefix=2 # 去除两层前缀
过滤器
前面修改请求其实都是通过 Gateway 的过滤器实现的,上面用到的过滤器为 StripPrefixGatewayFilterFactory 产生的过滤器。Gateway 提供了几十种过滤器,过滤器可以过滤指定规则的请求,也可以过滤所有请求。
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=this-is-a-header, Have-Fun
这个过滤器可以为所有请求添加一个响应头,this-is-a-header: Have-Fun
。
路由器分为局部路由和全局路由,局部路由分为两种(上面展示的两种):
- spring.cloud.gateway.routes.- id.filters
- spring.cloud.gateway.default-filters (功能等价于全局过滤器)
全局过滤器:不在配置文件中配置,需要实现 GlobalFilter 接口。
生命周期
过滤器类似于拦截器,但是只在微服务处理前后运作,请求转发不会触发过滤器。
自定义局部过滤器
自定义过滤器需要实现 AbstractGatewayFilterFactory 抽象类。该类使用内部类接受配置文件中的参数,需要给这个内部类的提供 Getter/Setter 方法。
package com.example.gateway.filter;
import java.util.Arrays;
import java.util.List;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
@Component
public class MyMyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyMyGatewayFilterFactory.Config> {
public MyMyGatewayFilterFactory() {
super(Config.class);
}
// 这个方法指定配置文件注入 Config 的哪一个字段
public List<String> shortcutFieldOrder() {
return Arrays.asList("param");
}
// 由于接受配置文件参数
public static class Config {
private String param;
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
}
// 此为过滤器逻辑,返回值是一个过滤方法,可以使用 Lambda 表达式。
// exchange 参数可以获取请求内容。chain 用于执行请求。
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 前置处理
ServerHttpRequest request = exchange.getRequest();
if (request.getQueryParams().containsKey(config.param)) {
request.getQueryParams().get(config.param)
.forEach(o -> System.out.printf("局部过滤器:%s = %s \n", config.param, o));
}
return chain.filter(exchange); // 执行请求
};
}
}
这里我们使用配置文件将 "name" 注入到 Config.param 字段上。注意配置中使用该过滤器类的前缀来注入。比如 MyMyGatewayFilterFactory 的前缀为 MyMy。过滤器类的命名格式是固定的,为 XxxxGatewayFilterFactory,需要使用 @Component 注入到 Spring 容器中,泛型使用 Config 内部类。
spring:
cloud:
gateway:
routes:
- id: user-service-route # 路由的标识 ID,任意名称都可以
uri: lb://USER-SERVICE # 路由的转发地址
predicates:
- Path=/api/api/user/** # 路由的映射范围
filters:
- StripPrefix=2 # 去除两层前缀
- MyMy=name
default-filters:
- AddResponseHeader=this-is-a-header, Have-Fun
自定义全局过滤器
实现 GlobalFilter, Ordered 接口并注入到 Spring 容器中。
package com.example.gateway.filter;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
// 设置执行的优先级,数字越小优先级越高
@Override
public int getOrder() {
return 1;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("自定义全局过滤器 MyGlobalFilter 执行");
String token = exchange.getRequest().getHeaders().getFirst("token");
// 如果没有 token 将响应状态设置为「未验证 401」,并直接返回,不执行后面的操作。
if (StringUtils.isBlank(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
负载均衡和熔断配置
Gateway 默认集成了 Ribbon 和 Hystrix。
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000 #服务降级超时时间
circuitBreaker:
errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50%
sleepWindowInMilliseconds: 10000 # 熔断后休眠时长,默认值5秒
requestVolumeThreshold: 10 # 熔断触发最小请求次数,默认值是20
ribbon:
ConnectTimeout: 1000 # 连接超时时长
ReadTimeout: 2000 # 数据通信超时时长
MaxAutoRetries: 0 # 当前服务器的重试次数
MaxAutoRetriesNextServer: 0 # 重试多少次服务
OkToRetryOnAllOperations: false # 是否对所有的请求方式都重试
跨域访问配置
微服务会面临跨域访问(比如端口不同)的问题,默认情况下服务不允许别的域访问,我们需要在配置中设置「白名单」告知从哪些域来的请求是被允许的。
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]': # 哪些请求可以跨域
allowedOrigins: # 跨域白名单
- "http://docs.spring.io"
allowedMethods: # 允许的请求方式
- GET
一个常见的情况是前后端分离,前端后端部署在不同端口。比如上面配置中 http://docs.spring.io
为前端的域,完成这个配置之后,前端就可以正常使用 Ajax 访问其他域的所有微服务。
Gateway 高可用
启动多个 Gateway 实例,实现微服务内部访问的高可用。但是 Gateway 主要适用于直接暴露给客户端,仅内部高可用并不是想要的,这时候需要使用 Nginx 代理 Gateway。
Gateway 和 Feign 的区别
Gateway 是作为整体微服务暴露给客户端的访问入口,通常用作权限鉴定和流量控制。Feign 是微服务内部之间互相调用的入口。一句话说就是 Gateway、Feign 一外一内。
尊重原创,转载请标明出处。
Gateway 简介的更多相关文章
- 0601-Zuul构建API Gateway-API gateway简介、基础使用、路由配置、负载配置
一.API Gateway简介 参看:http://www.cnblogs.com/bjlhx/p/8794437.html 二.zuul简介[路由器和过滤器:Zuul] 在微服务架构的组成部分进行路 ...
- SAP Gateway简介
SAP Gateway在S4/HANA时代的ABAP开发模型中有着重要的地位.SAP Gateway是什么?它对ABAP开发有怎样的影响?可以为我们提供哪些方便?这篇译文将浅要地讨论这些话题. SAP ...
- 微服务网关1-Spring Cloud Gateway简介
一.网关基本概念 1.API网关介绍 API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各 ...
- 简单尝试Spring Cloud Gateway
简单尝试Spring Cloud Gateway 简介 Spring Cloud Gateway是一个API网关,它是用于代替Zuul而出现的.Spring Cloud Gateway构建于Sprin ...
- SpringCloud Gateway入门
本文是介绍一下SpringCloud Gateway简单路由转发使用. SpringCloud Gateway简介 SpringCloud是基于Spring Framework 5,Project R ...
- eoLinker GoKu Gateway 开源版 V2.1发布,加入UI管理系统等
GoKu API Gateway 是eoLinker旗下的开源版接口网关,支持OpenAPI与微服务管理,支持私有云部署,实现API转发.请求参数转换.数据校验等功能,提供图形化界面管理,能够快速管理 ...
- Qwiklab'实验-API Gateway, AWS Lambda'
title: AWS之Qwiklab subtitle: 2. Qwiklab'实验-API Gateway, AWS Lambda' date: 2018-09-20 17:29:20 --- In ...
- SpringCloud gateway (史上最全)
疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 前言 ### 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家 ...
- Spring Gateway配置使用(一)
参考文档:Spring Gateway官方文档 , 玹霖的博客 1.Spring Gateway简介 Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring ...
随机推荐
- Numpy实现简单BP神经网络识别手写数字
本文将用Numpy实现简单BP神经网络完成对手写数字图片的识别,数据集为42000张带标签的28x28像素手写数字图像.在计算机完成对手写数字图片的识别过程中,代表图片的28x28=764个像素的特征 ...
- 【Java】Super
Super super用于调用父类的属性.方法.构造器,与this相同. super的使用 属性与方法 在子类的方法或构造器中.通过使用"super.属性"或"super ...
- 【解决了一个问题】腾讯云中使用ckafka生产消息时出现“kafka server: Message contents does not match its CRC.”错误
初始化的主要代码如下: config := sarama.NewConfig() config.Producer.RequiredAcks = sarama.WaitForAll // Wait fo ...
- 搭建服务器之文件共享cifs,nfs,samba
cifs: 微软系统中用于网上邻居共享的一个机制,在linux下也可以通过命令mount -t cifs .....来挂载共享的文件目录等. nfs: linux之间的共享文件方式,基于rpc ser ...
- Redisson 实现分布式锁原理分析
Redisson 实现分布式锁原理分析 写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题. 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有 ...
- gin框架中设置信任代理IP并获取远程客户端IP
package main import ( "fmt" "github.com/gin-gonic/gin" ) func main() { gin.SetMo ...
- IoC容器-Bean管理XML方式(自动装配)
IoC操作Bean管理(XML自动装配) 1,什么是自动装配 (1)根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入 2,演示自动装配过程 (1)根据属性名称自动注入 ...
- Mac中显示及隐藏文件和文件夹的方法
一.方法一 直接在文件或文件夹名前面的加一个'.'点号,然后系统会弹出修改确认对话框,点好就行了. 隐藏文件 解除隐藏可以通过方法三显示所有隐藏文件,找到该文件去掉开头的'.',然后通过方法二来解除隐 ...
- Chrome DevTools 面板全攻略
李华西,微医云服务团队前端开发工程师,喜欢瞎折腾,典型猫奴 Console 面板 此章节请打开 devtools/console/console.html 一起食用 一方面用来记录页面在执行过程中的信 ...
- Ubuntu 14.04更换内核
1:查看当前安装的内核 dpkg -l|grep linux-image 2:查看可以更新的内核版本: sudo apt-cache search linux-image 3:安装新内核 sudo a ...