sping cloud zuul


在微服务架构中,外部的应用如何来访问内部各种各样的服务呢?

后端服务一般不直接提供给调用端,而是通过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-eurekaspring-cloud-producergateway-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默认已经提供了转发功能。


文章作者: coderpwh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 coderpwh !
  目录