⼤家都都知道在微服务架构中,⼀个系统会被拆分为很多个微服务。那么作为客户端要如何去调⽤ 这么多的微服务呢?如果没有⽹关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调
⽤。
这样的架构,会存在着诸多的问题:
- 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
- 认证复杂,每个服务都需要独⽴认证。
- 微服务做集群的情况下,客户端并没有负责均衡的功能
上⾯的这些问题可以借助
API
⽹关
来解决。
所谓的
API
⽹关,就是指系统的
统⼀⼊⼝
,它封装了应⽤程序的内部结构,为客户端提供统⼀服
务,⼀些与业务本身功能⽆关的公共逻辑可以在这⾥实现,诸如认证、鉴权、监控、路由转发等等。
添加上
API
⽹关之后,系统的架构图变成了如下所示:
⽹关是如何知道微服务的地址
?
⽹关如何进⾏负载均衡呢?
⽹关需要将⾃⼰的信息注册到注册中⼼Nacos上并且拉取其他微服务的信息,然后再调⽤的时候基于 Ribbon 实现负载均衡 。
常见网关介绍
Nginx+lua
使⽤
nginx
的反向代理和负载均衡可实现对
api
服务器的负载均衡及⾼可⽤
,lua
是⼀种脚本语⾔
,
可以来编
写⼀些简单的逻辑
, nginx
⽀持
lua
脚本
Kong
基于
Nginx+Lua
开发,性能⾼,稳定,有多个可⽤的插件
(
限流、鉴权等等
)
可以开箱即⽤。 问题:只⽀
持
Http
协议;⼆次开发,⾃由扩展困难;提供管理
API
,缺乏更易⽤的管控、配置⽅式。
Zuul
Netflflix
开源的⽹关,功能丰富,使⽤
JAVA
开发,易于⼆次开发 问题:缺乏管控,⽆法动态配置;依赖
组件较多;处理
Http
请求依赖的是
Web
容器,性能不如
Nginx,Spring Cloud Gateway
Spring
公司为了替换
Zuul
⽽开发的⽹关服务,将在下⾯具体介绍。
注意:
SpringCloud alibaba
技术栈中并没有提供⾃⼰的⽹关,我们可以采⽤
Spring Cloud Gateway
来做⽹关。
Gateway简介
Spring Cloud Gateway
是
Spring
公司基于
Spring 5.0
,
Spring Boot 2.0
和
Project Reactor
等技术
开发的⽹关,它旨在为微服务架构提供⼀种简单有效的统⼀的
API
路由管理⽅式。它的⽬标是替代Netflflix Zuul
,其不仅提供统⼀的路由⽅式,并且基于
Filter
链的⽅式提供了⽹关基本的功能,例如:安全,监控和限流。
优点:
性能强劲:是第⼀代⽹关
Zuul
的
1.6
倍
功能强⼤:内置了很多实⽤的功能,例如转发、监控、限流等
设计优雅,容易扩展
缺点:
其实现依赖
Netty
与
WebFlux
,不是传统的
Servlet
编程模型,学习成本⾼
不能将其部署在
Tomcat
、
Jetty
等
Servlet
容器⾥,只能打成
jar
包执⾏
需要
Spring Boot 2.0
及以上的版本,才⽀持
Gateway快速入门
1.
创建⼀个
api-gateway
的模块
,
导⼊相关依赖
<?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">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>cn.wolfcode</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>
<dependencies>
<!--gateway网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
</dependencies>
</project>
2.
编写启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayServer {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayServer.class,args);
}
}
3.
编写配置⽂件
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true # 让gateway可以发现nacos中的微服务
自定义路由规则
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true # 让gateway可以发现nacos中的微服务
routes:
- id: product_route
uri: lb://product-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
predicates:
- Path=/product-serv/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
- Time=true
Gateway概念
路由
(Route)
是
gateway
中最基本的组件之⼀,表示⼀个具体的路由信息载体。主要定义了下⾯的⼏个
信息
:
- id,路由标识符,区别于其他 Route。
- uri,路由指向的⽬的地 uri,即客户端请求最终被转发到的微服务。
- order,⽤于多个 Route 之间的排序,数值越⼩排序越靠前,匹配优先级越⾼。
- predicate,断⾔的作⽤是进⾏条件判断,只有断⾔都返回真,才会真正的执⾏路由。
- filter,过滤器⽤于修改请求和响应信息。
我们将符合Path
规则的一切请求,都代理到 uri
参数指定的地址。
本例中,我们将 /product-serv/**
开头的请求,代理到lb://product-service
,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。
网关路由的流程图
整个访问的流程如下:
总结:
网关搭建步骤:
创建项目,引入nacos服务发现和gateway依赖
配置application.yml,包括服务基本信息、nacos地址、路由