Zuul简介及代码示例
程序员文章站
2022-07-12 18:52:29
...
zuul它是一种怪兽,可能是因为长相太可怕了,百度居然搜不到,我们打开Spring Cloud文档
https://cloud.spring.io/spring-cloud-netflix/reference/html/#_router_and_filter_zuul
Router and Filter: Zuul
路由器和过滤器Zuul
在2微服务架构里面呢,路由是微服务架构的一部分,根路径会映射到你的WEB引用,/api/user他可能会映射到用户
微服务,这个路径会映射到你的商店微服务,Zuul是Netflix开发的,基于JVM的,路由器和服务器端的负载均衡器,我们之前
讲过客户端负载均衡机制,Ribbon,Zuul他还是服务端的负载均衡
Routing is an integral part of a microservice architecture. For example, / may be mapped to your
web application, /api/users is mapped to the user service and /api/shop is mapped to the
shop service. Zuul is a JVM-based router and server-side load balancer from Netflix.
认证,压力测试,动态路由,服务的迁移,减轻各个负载,静态的响应处理,还有流量的管理
Netflix uses Zuul for the following:
Authentication
Insights
Stress Testing
Canary Testing
Dynamic Routing
Service Migration
Load Shedding
Security
Static Response handling
Active/Active traffic management
Zuul的规则引擎呢,使用任意的JVM语言写的,内置可以使用JAVA和Groovy,但是理论上所有的JVM语言都可以玩,
Zuul’s rule engine lets rules and filters be written in essentially any JVM language,
with built-in support for Java and Groovy.
这个配置项被两个配置项代替了
The configuration property zuul.max.host.connections has been replaced by two new properties,
zuul.host.maxTotalConnections and zuul.host.maxPerRouteConnections,
which default to 200 and 20 respectively.
隔离一个是SEMAPHORE,一个是THREAD,一个是信号,一个是线程,他在这个里面使用的信号,你也可以使用这个配置,
去把它指定成Thread
The default Hystrix isolation pattern (ExecutionIsolationStrategy) for all routes is SEMAPHORE.
zuul.ribbonIsolationStrategy can be changed to THREAD if that isolation pattern is preferred.
http://www.github.com/netflix/hystrix
我们讲hystrix的时候有讲过他的隔离
https://github.com/netflix/hystrix/wiki
https://github.com/Netflix/Hystrix/wiki/Configuration
一个是THREAD,一个是SEMAPHORE,他说了默认的是Thread
How to Include Zuul
你要在Spring Cloud里面引入某个组建的话,你就要加上某某starter
To include Zuul in your project, use the starter with a group ID of org.springframework.cloud
and a artifact ID of spring-cloud-starter-netflix-zuul.
Spring Cloud创建了一个嵌入式的代理,他去简化了一种非常常见的开发,开发的方式,这种方式是什么呢,
其中UI应用程序想要去代理,一个或者是多个后端的服务的调用,他说这种特性呢,他说这种特性是比较有用的,
对于用户界面他去代理,后端的服务,对于所有后端去处理跨域,和认证的需要,CORS是Cross Orginal Resouce
Sharing,其实就是跨域请求,可以这样理解,如果你想要使用它的话,在你的主类加上@EnableZuulProxy,本地的请求
会转发到相应的服务,按照约定,假设一个服务它的ID是users,它会用这种路径去接收请求,然后他把前缀省略掉了,
Zuul他使用的是Ribbon,通过Ribbon查询服务注册的组件,Eureka转发你要的实例,所有的请求都会在Hystrix Command
里面去执行,我们之前解析过了Hystrix Command是什么东西了,所有使用@HystrixCommand这个注解,这样所有的失败
都会在Hystrix的指标里面去显示,因为断路器都打开了,不会请求远程的服务了,相对于后端的服务Zuul
Spring Cloud has created an embedded Zuul proxy to ease the development of a common use case where
a UI application wants to make proxy calls to one or more back end services. This feature is useful
for a user interface to proxy to the back end services it requires, avoiding the need to manage CORS
and authentication concerns independently for all the back ends.
To enable it, annotate a Spring Boot main class with @EnableZuulProxy. Doing so causes local calls
to be forwarded to the appropriate service. By convention, a service with an ID of users receives
requests from the proxy located at /users (with the prefix stripped). The proxy uses Ribbon to
locate an instance to which to forward through discovery. All requests are executed in a hystrix
command, so failures appear in Hystrix metrics. Once the circuit is open, the proxy does not
try to contact the service.
Zuul其实并没有发现服务发现的客户端,他没有包含Eureka的Client,因此如果你想通过serviceId去路由的话,
你得提供依赖
microservice-gateway-zuul
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
Zuul的依赖加好了,这个时候我们是不是还得加Eureka的依赖
the Zuul starter does not include a discovery client, so, for routes based on service IDs,
you need to provide one of those on the classpath as well (Eureka is one choice).
@EnableZuulProxy
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
@EnableZuulProxy它是一个组合注解
@EnableCircuitBreaker
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyConfiguration.class)
public @interface EnableZuulProxy {
}
这就是为什么,我只要一个注解就可以把它注册到Eureka
localhost:7900/simple/1
localhost:8040/microservice-simple-provider-user/simple/1
所以这个就是Eureka里面的serviceId,
Mapped URL path [/microservice-simple-provider-user/**] onto handler of type
[class org.springframework.cloud.netflix.zuul.web.ZuulController]
他其实是有一个映射的,规则也是非常简单的,比如你在eureka上有一个微服务叫abc,abc的端口
是8000,他有一个接口是/simple/1,我们使用zuul去访问的,abc是应用的名称,这就可以访问了,
但是没有完全达到我的要求,这么长一个我不喜欢,我想要改成user,我想改成这样的
localhost:8040/user/simple/1
zuul:
routes:
user-route: # 该配置方式中,user-route只是给路由一个名称,可以任意起名。
service-id: microservice-provider-user
path: /user/** # service-id对应的路径
zuul.routes.user-route.service-id=microservice-simple-provider-user
zuul.routes.user-route.path=/user/**
假设我现在有个user微服务,有个电影微服务,反向代理微服务,
默认所有注册到Eureka上的微服务
microservice-consumer-movie-ribbon-hystrix
localhost:8040/microservice-consumer-movie-ribbon-hystrix/movie/1
localhost:8010/movie/1
如果我只想代理user微服务,不想代理电影微服务,第一种办法是把所有的微服务ignore,只有你配的微服务才反向代理,
https://cloud.spring.io/spring-cloud-netflix/reference/html/#_router_and_filter_zuul
zuul:
ignoredServices: '*'
routes:
users: /myusers/**
第二种就是配置
zuul.ignoredServices=microservice-consumer-movie-ribbon-hystrix
多个我可以用逗号
/**
* Set of service names not to consider for proxying automatically. By default all
* services in the discovery client will be proxied.
*/
private Set<String> ignoredServices = new LinkedHashSet<>();
他是一个Set,我们可以用逗号分隔开
<?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>
<groupId>com.learn.cloud</groupId>
<artifactId>microservice-gateway-zuul</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>cn.learn</groupId>
<artifactId>microcloud02</artifactId>
<version>0.0.1</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
<!-- 这个插件,可以将应用打包成一个可执行的jar包 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server.port=8040
spring.application.name=microservice-gateway-zuul
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
eureka.client.serviceUrl.defaultZone=http://admin:[email protected]:8761/eureka
eureka.instance.appname=microservice-gateway-zuul
zuul.routes.user-route.service-id=microservice-simple-provider-user
#zuul.ignoredServices=microservice-consumer-movie-ribbon-hystrix
zuul.routes.user-route.path=/user/**
package com.learn.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@SpringBootApplication
public class GateWayZuulApplication {
public static void main(String[] args) {
SpringApplication.run(GateWayZuulApplication.class, args);
}
}