springcloud(十)-Zuul微服务网关

时间:2023-01-09 05:08:57

为什么要使用微服务网关

前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个微服务框架已经完成了。

我们还是少考虑了一个问题,外部的应用如何来访问内部各种各样的微服务呢?

如果让客户端直接与各个微服务通信,会有以下问题:

  • 客户端会多次请求不同的微服务,增加了客户端的复杂性。
  • 存在跨域请求,在一定的场景下处理相对复杂。
  • 认证复杂,每个服务都需要独立认证。
  • 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个微服务拆分成多个。如果客户端直接与微服务通信,那么重构将很难实施。
  • 某些微服务可能使用了对防火墙/浏览器不友好的协议,直接访问时会有一定的困难。

以上问题可借助微服务网关解决。微服务网关时介于客户端和服务端之间的中间层,所有的外部请求都会先经过微服务网关。使用微服务网关后,架构为:

springcloud(十)-Zuul微服务网关

微服务网关封装了应用程序的内部结构,客户端只用跟网关交互,而无须直接调用特定的微服务接口。这样,开发就可以得到简化。不仅如此,使用微服务网关还有一下优点:

  • 易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
  • 易于认证。可在微服务网关上进行认证,然后再将请求转发到后端的微服务。
  • 减少了客户端与各个微服务之间的交互次数。

编写Zuul

1.创建一个Maven工程,ArtifactId是microservice-gateway-zuul,配置pom.xml文件

<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">
<modelVersion>4.0.0</modelVersion> <groupId>com.itmuch.cloud</groupId>
<artifactId>microservice-gateway-zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>microservice-gateway-zuul</name>
<url>http://maven.apache.org</url> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 用于监控spring boot 端点 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!-- <scope>provided</scope> -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> <!-- 这个需要为 true 热部署才有效 -->
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies> <!-- 引入spring cloud 的依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement> <!-- 添加spring-boot 的maven插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2.在启动类上添加注解@EnableZuulProxy,声明一个Zuul代理。该代理使用Ribbon来定位注册在Eureka Server中的微服务;同时,该代理还整合了Hystrix,从而实现了容错,所有经过zuul的请求都会在Hystrix命令中执行。

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication { public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}

3.编写配置文件application.yml.

server:
port: 8040
spring:
application:
name: microservice-gateway-zuul
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8083/eureka
management:
security:
enabled: false

这样,一个简单的微服务网关就编写完了。从配置可知,此时仅添加了Zuul的依赖,并将Zuul注册到EurekaServer上。

测试1

启动项目microservice-discovery-eureka.

启动项目microservice-provider-user.

启动项目microservice-consumer-movie-ribbon。

启动项目microservice-gateway-zuul。

访问http://localhost:8040/microservice-consumer-movie/user/1,请求会被转发到http://loclahost:8010/user/1.

访问http://localhost:8040/microservice-provider-user/1,请求会被转发到http://localhost:8081/1。

说明在默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:

http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务。

测试2

启动项目microservice-discovery-eureka.

启动多个microservice-provider-user实例。

启动项目microservice-gateway-zuul。此时,Eureka Server首页如下:

springcloud(十)-Zuul微服务网关

多次访问http://localhost:8040/microservie-provider-user/1,会发现两个用户微服务节点都会打印类似如下日志。

Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?
2019-04-29 19:30:48.253 TRACE 9536 --- [nio-8081-exec-5] o.h.type.descriptor.sql.BasicBinder : binding parameter [] as [BIGINT] - []
2019-04-29 19:30:48.257 TRACE 9536 --- [nio-8081-exec-5] o.h.type.descriptor.sql.BasicExtractor : extracted value ([age2_0_0_] : [INTEGER]) - []
2019-04-29 19:30:48.257 TRACE 9536 --- [nio-8081-exec-5] o.h.type.descriptor.sql.BasicExtractor : extracted value ([balance3_0_0_] : [NUMERIC]) - [98.23]
2019-04-29 19:30:48.257 TRACE 9536 --- [nio-8081-exec-5] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name4_0_0_] : [VARCHAR]) - [张三]
2019-04-29 19:30:48.257 TRACE 9536 --- [nio-8081-exec-5] o.h.type.descriptor.sql.BasicExtractor : extracted value ([username5_0_0_] : [VARCHAR]) - [account1]

说明Zuul可以使用Ribbon达到负载均衡的效果。

另外,Zuul也整合了Hystrix.这里不再演示。