概述

微服务可能分布在不同的主机上,这样有许多缺点:前端需要硬编码调用不同地址的微服务很麻烦;存在跨域访问的问题;微服务地址直接暴露是不安全的。还有所以需要为前端提供一个统一的访问入口。Gateway 就是用于解决以上问题的框架。Gateway 本身是一个微服务,要注册到 Eureka 中。

入门案例

  1. 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>
  1. 启动类添加 @EnableDiscoveryClient 注解
  2. 配置文件:基本的 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
  1. 是否配置成功?

启动实例后能在 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

路由器分为局部路由和全局路由,局部路由分为两种(上面展示的两种):

  1. spring.cloud.gateway.routes.- id.filters
  2. 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 简介的更多相关文章

  1. 0601-Zuul构建API Gateway-API gateway简介、基础使用、路由配置、负载配置

    一.API Gateway简介 参看:http://www.cnblogs.com/bjlhx/p/8794437.html 二.zuul简介[路由器和过滤器:Zuul] 在微服务架构的组成部分进行路 ...

  2. SAP Gateway简介

    SAP Gateway在S4/HANA时代的ABAP开发模型中有着重要的地位.SAP Gateway是什么?它对ABAP开发有怎样的影响?可以为我们提供哪些方便?这篇译文将浅要地讨论这些话题. SAP ...

  3. 微服务网关1-Spring Cloud Gateway简介

    一.网关基本概念 1.API网关介绍 ​ API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各 ...

  4. 简单尝试Spring Cloud Gateway

    简单尝试Spring Cloud Gateway 简介 Spring Cloud Gateway是一个API网关,它是用于代替Zuul而出现的.Spring Cloud Gateway构建于Sprin ...

  5. SpringCloud Gateway入门

    本文是介绍一下SpringCloud Gateway简单路由转发使用. SpringCloud Gateway简介 SpringCloud是基于Spring Framework 5,Project R ...

  6. eoLinker GoKu Gateway 开源版 V2.1发布,加入UI管理系统等

    GoKu API Gateway 是eoLinker旗下的开源版接口网关,支持OpenAPI与微服务管理,支持私有云部署,实现API转发.请求参数转换.数据校验等功能,提供图形化界面管理,能够快速管理 ...

  7. Qwiklab'实验-API Gateway, AWS Lambda'

    title: AWS之Qwiklab subtitle: 2. Qwiklab'实验-API Gateway, AWS Lambda' date: 2018-09-20 17:29:20 --- In ...

  8. SpringCloud gateway (史上最全)

    疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -25[ 博客园 总入口 ] 前言 ### 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家 ...

  9. Spring Gateway配置使用(一)

    参考文档:Spring Gateway官方文档 , 玹霖的博客 1.Spring Gateway简介 Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring ...

随机推荐

  1. Android官方文档翻译 十 2.3Styling the Action Bar

    Styling the Action Bar 设计菜单栏的样式 This lesson teaches you to 这节课教给你 Use an Android Theme 使用一个Android主题 ...

  2. 《剑指offer》刷题目录

    <剑指offer>刷题目录 面试题03. 数组中重复的数字 面试题04. 二维数组中的查找 面试题05. 替换空格 面试题06. 从尾到头打印链表 面试题07. 重建二叉树 面试题09. ...

  3. Microsoft Store 桌面应用发布流程(一)之打包应用

    这篇博客主要是介绍桌面应用打包的流程,应用发布流程请看 Microsoft Store 桌面应用发布流程(二)之提交应用 1. 创建打包项目 打开现有的桌面应用项目.选择解决方案项目,右键选择 添加新 ...

  4. ctfshow web2 web3

    ctfshow web2 1.手动注入题.先用万能密码admin' or 1=1%23,有回显 2.union select注入,2处有回显 3.依次查找数据库.表.字段 得到flag ctfshow ...

  5. 阐述JDBC操作数据库的步骤

    1. 加载驱动. Class.forName("oracle.jdbc.driver.OracleDriver"); (注意:加载驱动在JDBC 4.0中是可以省略的,自动从类路径 ...

  6. vue学习7-v-show和v-if

    1. v-show:这个是一次性会把所有的都渲染出来,然后通过简单的切换display值来修改是否需要被渲染.所以在需要频繁切换的情况下推荐使用.v-show不能在template标签上使用. 2. ...

  7. python14day

    昨日回顾 匿名函数:一句话函数 内置函数II 闭包: 内层函数对外层函数非全局变量的引用 一定存在于嵌套函数中 作用:保护数据安全,自由变量不会在内存中消失,而且全局还引用不到 今日内容 装饰器: 装 ...

  8. Android开发-记账本布局-实现记账页面功能选择

    记账页面需要软件盘的弹出,时间的显示和记账类型的选择.为了实现选择的效果,点击图片图片发生变化. 需要制作记账类型数据库,并设置单机事件,单机图片,图片变色,代表选中. 至于软键盘的制作,我直接拿来用 ...

  9. ESP32:蓝牙BLE控制M3508电机

    ESP32:蓝牙BLE控制M3508电机 先给各位朋友拜个年,祝大家新春快乐,事事顺利,身体健康啊! 还是熟悉的3508,内容概述: ESP32主控 蓝牙BLE通信 使用实时系统(FreeRTOS) ...

  10. Git使用教程(超全,看一篇就够了)

    目录 Git介绍 Git安装 Git使用 问题与解决 推荐学习网址 Git介绍 Git是什么? Git是目前世界上最先进的分布式版本控制系统. SVN与Git的最主要的区别? SVN是集中式版本控制系 ...