这个标题有点儿绕,咋 还是服务路由的服务了?
首先,Zuul最后也会做成一个Eureka Client 服务,注册到 Eureka Server 上,所以,后一个服务说的是Zuul 项目本身也是一个 Eureka 服务。
前一个服务,说的是 在Eureka Server 上注册的所有的其他服务。
那个路由是咋回事? 在没有Zuul的时候,访问不同的服务,需要请求不同的 serivceId ,这个好理解吧,在 Eureka 页面上,我们可以看到一个Application 列表,如下:
这个,就是一系列的服务,每个服务都是一个 Eureka Client 应用。
这些主要都是服务提供者。
服务消费者需要调用哪个服务的时候,就访问不同的应用名称+ 其API路径。
这里有没有觉得有点麻烦,你需要记住每个不同的 服务提供者的 serviceId ,这多少有点儿麻烦。
Zuul 的一个工作就是实现所有这些服务提供者的路由,用来Zuul之后, 服务消费者再不需要记住那么多服务的名字了,而只需要知道 Zuul的服务名称即可, 从此只需要调用Zuul这一个服务。然后 Zuul服务会根据消费者请求的路径匹配到最终的服务提供者。
这样,Zuul就实现了路由的功能。
前期准备和说明
本文档依旧是之前文档的延续,项目依旧基于《SpringCloud Eureka测试项目--一个最简单的订单获取功能》。
创建项目
创建一个springboot项目,命名为 test-springcloud-zuul-server8766
pom.xml 文件
该文件增加了一个 spring-cloud-starter-netflix-zuul 依赖。
完整文档如下:
<?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.pingbu</groupId>
<artifactId>test-springcloud</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.pingbu</groupId>
<artifactId>test-springcloud-zuul-server8766</artifactId>
<version>1.0.0</version>
<dependencies>
<!-- eureka client -->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<finalName>test-springcloud-provider-payment8001</finalName>
</build>
</project>
spring-boot main类
package com.wanshi.provider.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
// Eureka客户端
@EnableEurekaClient
@EnableZuulProxy
@SpringBootApplication
public class ZuulServerMain8766 {
public static void main(String[] args) {
SpringApplication.run(ZuulServerMain8766.class, args);
}
}
可以看到,关键多了有一个 @EnableZuulProxy 的注解。
application.yml 文件
server:
port: 8766
spring:
application:
name: zuul-server
eureka:
serverInstance:
hostname: 127.0.0.1
client:
# 表示将自己注册进Eureka Server默认为true
register-with-eureka: true
# 是否从Eureka Server抓去已有的注册信息,默认是true
fetch-registry: true
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://127.0.0.1:8761/eureka
zuul:
routes:
provider-order-key:
path: /provider1/**
serviceId: provider-order
provider-buy-key:
path: /buy1/**
serviceId: provider-buy
比较需要解释的是 zuul 节点
zuul.routes 定义了路由,本例子中定义了两个路由: 这两个路由的命名其实无所谓,自己起的,我这里写了 provider-order-key 和 provider-buy-key , 这个命名没关系。
path节点定义了在 zuul 服务下的地址 。
serviceId节点定义了访问那个地址后,将转发到的服务。
本例子中,zuul 的服务名是 zuul-server ,端口是 8766
本例子中 定义了一个path 命名为 provider-order-key, 这个命名没关系,关键是看path 和 serviceId 。 我们看到这个 path 定义为 /provider1/** ,serviceId 为 provider-order 。
访问流程说明
- 在浏览器输入 http://127.0.0.1:8766/provider1/provider/order/get/1 后,zuul-server 服务将被请求。
- 由于端口指向的是 zuul server 应用,所以 zuul server 收到请求
- zuul server 判断路径为 /provider1/ 开头的,因此根据路由配置,将转发给 provider-order 服务,访问的路径为 /provider/order/get/1
zuul在注册中心
查看 Eureka 注册中心,可以看到该 zuul-server 服务,因此,消费者可以使用 zuul-server 服务。
这样,我们就可以只使用 zuul-server 这一个服务,将所有的服务整合成一个服务了。使用起来就简单多了。
zuul的负载均衡
zuul本身支持 robbin 负载均衡,如果 一个服务有多个点的话,请求zuul 可以看到每次都访问不同点的服务。