Spring Cloud系列教程的所有博客均在下方的目录链接中,方便大家查找和阅读。建议按照顺序学习,对于项目搭建有疑问的可以着重看目录里的第二篇博客。
Spring cloud学习专栏目录
API Gateway也就是服务网关,在微服务架构中,每个客户端需要调用一个或者多个API。有了API Gateway之后,用户的所有请求都直接发送到这个服务网关上,再由它进行转发,API Gateway起到了对服务进行聚合的作用。
API Gateway负责请求转发、组合及协议转换。客户端的所有请求都要先经过API Gateway,然后由它将请求路由到对应的微服务。API Gateway经常通过调用多个微服务并合并结果来处理一个请求。它可以在web协议(如Http与WebSocket)与内部使用的非Web友好型协议间进行转换。
API Gateway还可以为每个客户端提供一个定制的API。通常他会向移动客户端暴露一个粗粒度的API。例如查询商品信息时,API Gateway只需要提供一个接口,用户只需要调用这一个接口就可以获取商品的详细信息。但此时API Gateway其实是通过调用多个服务(如商品服务、评论服务、详情服务)并合并他们的结果来处理这一个请求。
它封装了应用的内部结构,客户端直接跟网关交互,而不必调用特定的服务。如果没有网关,前端页面就需要自己关心后端各个服务模块的地址,如果服务发布多个节点,或者发布地址变更后,前端页面要对应改过来,这就会很复杂。有了网关后,前端只需要向网关发起请求,不需要关心服务地址是否变动,屏蔽后端的复杂性,它还能将多个API调用逻辑进行聚合,从而减少客户端的请求数。
我们需要开发这样一个高可用的组件,它的开发、部署和管理都要耗费成本。还有一个问题,它可能成为开发的一个瓶颈。为了暴露每个微服务的端点,开发者必须更新API Gateway。API Gateway的更新过程要尽可能的简单,否则为了更新网关开发者将不得不排队等待。不过虽然有这些不足,但对于大部分的应用,采用API Gateway的方式都是合理有效的。
当时我们学习Hystrix时隔离模式的默认值是Thread。而在这里所有路由的默认Hystrix隔离模式是信号量(SEMAPHORE)。如果首选隔离模式,则可以将zuul.ribbonIsolationStrategy更改为THREAD。
选中刚创建好的zuul-parent父工程,右键–>new project–>maven module
找到zuul-parent的pom文件导入依赖,主要是eureka的依赖和zuul的依赖。运行后zuul-server如果报错只需要右键–>maven–>update project即可。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud</groupId>
<artifactId>zuul-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<!-- 导入Spring Cloud的依赖管理 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- eureka依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>
<modules>
<module>zuul-server</module>
</modules>
</project>
在zuul-server下新建一个包com.spring.zuulserver,创建启动类ZuulServerApplication,多添加一个@EnableZuulProxy注解。
package com.spring.zuulserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}
# 配置api端口号
server.port=8040
# tomcat
server.tomcat.uri-encoding=UTF-8
# 服务名称
spring.application.name=zuul-server
# 服务注册中心的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
启动eureka服务、zuul服务、用户微服务。
我们先访问一下用户微服务中的接口,可以看到现在可以正常请求。
———————————————————————————————————
接下来我们试一下是否可以通过zuul来对用户微服务中的接口进行请求,我们将请求的url中的端口改为zuul的端口8040,后面多加上一个用户微服务配置中命名的application.name。也就是将路径改为:http://localhost:8040/microservice-provide-user/getUserInfo/1。可以看到依旧可以正常访问,说明我们已经通过zuul这个网关请求到了用户微服务中的接口。(默认情况下注册在eureka上的服务都会被Zuul创建映射关系来进行路由)
刚才我们已经实现了通过zuul对用户微服务进行访问,但是我们可以发现一个问题那就是路径中服务名称(microservice-provide-user)太长了,所以我们这里要做一些优化,通过路由配置来改变地址的映射如下所示。
# 配置api端口号
server.port=8040
# tomcat
server.tomcat.uri-encoding=UTF-8
# 服务名称
spring.application.name=zuul-server
# 服务注册中心的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
#配置zuul的路由规则,将microservice-provide-user微服务映射到/user/**路径
#也就是以后我们请求/user时,请求就会被转发到/microservice-provide-user
zuul.routes.microservice-provide-user.service-id=microservice-provide-user
zuul.routes.microservice-provide-user.path=/user/**
这里解释一下zuul的默认配置是如下这样的,所以我们其实就是对path进行了修改,来改变它的请求路径。
zuul.routes.microservice-provide-user.service-id=microservice-provide-user
zuul.routes.microservice-provide-user.path=/microservice-provide-user/**
重新启动一下zuul服务
将刚才的路径http://localhost:8040/microservice-provide-user/getUserInfo/1
改为http://localhost:8040/user/getUserInfo/1进行测试,可以看到访问成功,说明我们的自定义路由配置起了作用。
默认情况下注册在eureka上的服务都会被Zuul创建映射关系来进行路由,也就是这些服务的接口都可以通过 ip + zuul的端口号 + 微服务的application.name + 接口地址来访问。如果我们不希望zuul代理所有的微服务只代理指定的微服务那我们就需要做一些配置。
这里我们配置zuul只代理用户微服务而不代理车票微服务。
我们加上如下所示配置,让zuul忽略车票微服务
# 配置api端口号
server.port=8040
# tomcat
server.tomcat.uri-encoding=UTF-8
# 服务名称
spring.application.name=zuul-server
# 服务注册中心的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
#配置zuul忽略所有的服务
zuul.ignored-services=microservice-consumer-ticket
#配置zuul的路由规则,将microservice-provide-user微服务映射到/user/**路径
#也就是以后我们请求/user时,请求就会被转发到/microservice-provide-user
zuul.routes.microservice-provide-user.service-id=microservice-provide-user
zuul.routes.microservice-provide-user.path=/user/**
启动eureka服务、zuul服务、用户微服务、车票微服务
访问:http://localhost:8040/microservice-consumer-ticket/getTicketInfo/1进行测试,发现404报错说明zuul没有对车票微服务进行路由。也就是说我们的ignored-services配置是生效的。
上面已经提到了怎么忽略服务也就是使用 zuul.ignored-services,如果你需要更细粒度的控制,如你需要Zuul代理微服务但是又需要保护这个微服务的某些敏感路径,那么就需要使用ignored-Patterns。
#忽略所有包含admin的路径
zuul.ignored-patterns=/**/admin/**
首先你需要去配置文件中将 /routes端点开放出来
加上management.endpoints.web.exposure.include=routes
———————————————————————————————————
然后只需要访问Zuul服务下的/actuator/routes即可,就可以看到路由配置了。 http://localhost:8040/actuator/routes
当外部HTTP请求到达AP网关服务的时候,首先它会进入第一个阶段pre,在这里它会被pre类型的过滤器进行处理,该类型过滤器的主要目的是在进行请求路由之前做一些前置加工,比如请求的校验等。在完成了pre类型的过滤器处理之后,请求进入第二个阶段 routing,也就是之前说的路由请求转发阶段,请求将会被routing类型过滤器处理。这里的具体处理内容就是将外部请求转发到具体服务实例上去的过程,当服务实例将请求结果都返回之后, routing阶段完成,请求进入第三个阶段post,此时请求将会被post类型的过滤器处理,这些过滤器在处理的时候不仅可以获取到请求信息,还能获取到服务实例的返回信息,所以在post类型的过滤器中,我们可以对处理结果进行一些加工或转换等内容。另外,还有一个特殊的阶段 error,该阶段只有在上述三个阶段中发生异常的时候才会触发,但是它的最后流向还是post类型的过滤器,因为它需要通过post过滤器将最终结果返回给请求客户端
实现过滤器需要继承 ZuulFilter这个类,并且实现里面的四个方法