在微服务架构中,外部的应用如何来访问内部各种各样的服务呢?
后端服务一般不直接提供给调用端,而是通过API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建一面墙,这面墙直接与调用方通信进行权限控制,后讲请求均衡分发给后台服务端。
ZUUL是什么?
sspring cloud zuul是netflix提供的一个组件,功能类似于nginx,用于反向代理,可以提供动态路由、监控、授权、安全、调度等边缘服务。
微服务场景下,每一个微服务对外暴露了一组细粒度的服务。客户端的请求可能会涉及到一串的服务调用,如果将这些微服务都暴露给客户端,那么会增加客户端代码的复杂度。
参考GOF设计模式中的Facade模式,将细粒度的服务组合起来提供一个粗粒度的服务,所有请求都导入一个统一的入口,那么整个服务只需要暴露一个api,对外屏蔽了服务端的实现细节,也减少了客户端与服务器的网络调用次数。这就是api gateway。
ZUUL的作用
- 动态路由
- 监控
- 安全
- 认证鉴权
- 压力测试
- 金丝雀测试
- 审查
- 服务迁移
- 负载剪裁
- 静态应答处理
ZUUL的简单应用
项目图:
gateway-service-zuul-simple 工程
1. pom依赖
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.neo</groupId>
<artifactId>spring-cloud-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</parent>
<groupId>com.neo</groupId>
<artifactId>gateway-service-zuul-simple</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-service-zuul-simple</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.配置文件
server.port=8888
zuul.routes.it.path=/it/**
zuul.routes.it.url=https://coderpwh.com/photos/
zuul.routes.hello.path=/hello/**
zuul.routes.hello.url=http://localhost:9000/
3.启动类
注解 @EnableZuulProxy 网关路由
package com.neo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableZuulProxy
public class GatewayServiceZuulSimpleApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceZuulSimpleApplication.class, args);
}
}
4.测试验证
启动该工程,访问 http://localhost:8888/it
页面返回的消息如图:
由于博客是https,导致效果较差,大家可以换成http的网站测试
现在启动 spring-cloud-producer 工程
server.port=8888
zuul.routes.it.path=/it/**
zuul.routes.it.url=https://coderpwh.com/photos/
zuul.routes.hello.path=/hello/**
zuul.routes.hello.url=http://localhost:9000/
这是simple 工程中的配置,当访问 hello 下面会重定向到 9000那台服务上面去
访问 http://localhost:8888/hello/hello?name=%E5%93%A5%E7%9A%84
返回: 哥的,this is first messge
说明访问 gateway-service-zuul-simple的请求自动转发到了spring-cloud-producer,并且将结果返回。
服务化
通过url映射的方式来实现zull的转发有局限性,比如每增加一个服务就需要配置一条内容,另外后端的服务如果是动态来提供,就不能采用这种方案来配置了。实际上在实现微服务架构时,服务名与服务实例地址的关系在eureka server中已经存在了,所以只需要将Zuul注册到eureka server上去发现其他服务,就可以实现对serviceId的映射。
看工程 gateway-service-zuul-eureka
1.pom依赖
同上面
** 2.配置文件**
spring.application.name=gateway-service-zuul
server.port=8888
zuul.routes.producer.path=/producer/**
zuul.routes.producer.serviceId=spring-cloud-producer
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
3.测试验证
依次启动 spring-cloud-eureka、 spring-cloud-producer、gateway-service-zuul-eureka
访问: http://localhost:8888/producer/hello?name=%E5%93%A5%E7%9A%84
返回 : 哥的,this is first messge
说明访问 gateway-service-zuul-eureka的请求自动转发到了spring-cloud-producer,并且将结果返回。
模拟集群,创建和spring-cloud-producer一样的项目 spring-cloud-producer2 端口改为9001
启动 spring-cloud-producer2 工程,重启一下 gateway-service-zuul-eureka
多次访问 :http://localhost:8888/producer/hello?name=%E5%93%A5%E7%9A%84
返回:
哥的,this is first messge
哥的,this is two messge
哥的,this is two messge
哥的,this is first messge
说明通过zuul成功调用了producer服务并且做了均衡负载。
网关的默认路由规则
但是如果后端服务多达十几个的时候,每一个都这样配置也挺麻烦的,spring cloud zuul已经帮我们做了默认配置。默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路由规则如下:http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务。
我们注销掉gateway-service-zuul-eureka项目中关于路由的配置:
#zuul.routes.api-a.path=/producer/**
#zuul.routes.api-a.serviceId=spring-cloud-producer
重新启动后,访问 http://localhost:8888/spring-cloud-producer/hello?name=%E5%B0%8F%E6%98%8E,测试返回结果和上述示例相同,说明Spring cloud zuul默认已经提供了转发功能。