本篇依旧是在Spring Cloud系列的博主已经搭建的Spring Cloud微服务模块上进行的,注意,本文依旧适合初学者和或者在Spring Cloud框架了解不是很深入的基础的开发者,本系列说不上有多高大上,博主坚持通过简单的案例,让开发者可以对Spring Cloud的组件进行了解和使用,并在一定程度上介绍这些组件在开发中充当什么样的成分。
依旧是回顾我们在搭建Zuul模块的时候的知识点。
Zuul网关是什么?
Zuul是Spring Cloud提供的一种基于JVM的动态路由和服务网关解决方案。它可以作为微服务架构中的入口点,用于路由和过滤请求,实现负载均衡、认证、授权、监控等功能。
- 动态路由:Zuul可以根据配置的路由规则将请求动态路由到不同的后端服务。
- 过滤器:Zuul提供了过滤器机制,可以在请求的不同生命周期中执行自定义逻辑,例如身份验证、请求日志记录等。
- 负载均衡:Zuul集成了Ribbon负载均衡器,可以实现请求的负载均衡。
- 容错机制:Zuul通过Hystrix实现了容错机制,可以在后端服务不可用时提供服务降级和熔断功能。
- 监控和追踪:Zuul可以与Spring Cloud Sleuth和Zipkin等组件集成,提供请求的监控和追踪功能。
那么我们开始围绕我们的Zuul进行,首先我们创建一个名为ZuulFilter
的过滤器类,用于实现自定义的请求过滤逻辑。你可以根据需要实现ZuulFilter
的run()
方法。我仅仅就是提供一个demo,方便我们在开发中进行改写。
目录结构:
hystrix模块:作为服务名字Application.name就是代表我们的服务名字
@Component
public class CustomFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre"; // 过滤器类型,可以是pre、route、post、error
}
@Override
public int filterOrder() {
return 1; // 过滤器执行顺序,数值越小越先执行
}
@Override
public boolean shouldFilter() {
return true; // 是否启用该过滤器
}
@Override
public Object run() {
// 过滤器逻辑
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println("Request Method : " + request.getMethod() + " Request URL : " + request.getRequestURL().toString());
return null;
}
}
server:
port: 2379
spring:
application:
name: zuul-demo
#路由前缀
zuul:
prefix: /api
routes:
hystrix-demo:
path: /api/**
serviceId: hystrix-demo
# eureka客户端注册到Eureka注册中心,切记需要启动eureka服务
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
配置完毕后,我们去前端执行一下:
http://localhost:2379/api/hystrix-demo
对照一下,我们发现出现了两次,这是因为我触发了两次。
2023-12-19 20:24:44.036 INFO 10376 --- [nio-2379-exec-3] o.apache.tomcat.util.http.parser.Cookie : A cookie header was received [1691633835; NMTID=00OfgHFpVoe_XqS7E1MrMltkHSaK-8AAAGKqC2m5Q; Hm_lvt_fadc1bd5db1a1d6f581df60a1807f8ab=1699003649,1699405659] that contained an invalid cookie. That cookie will be ignored.
Note: further occurrences of this error will be logged at DEBUG level.
Request Method : GET Request URL : http://localhost:2379/api/hystrix-demo
2023-12-19 20:24:44.118 INFO 10376 --- [nio-2379-exec-3] c.netflix.config.ChainedDynamicProperty : Flipping property: hystrix-demo.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2023-12-19 20:24:44.132 INFO 10376 --- [nio-2379-exec-3] c.n.u.concurrent.ShutdownEnabledTimer : Shutdown hook installed for: NFLoadBalancer-PingTimer-hystrix-demo
2023-12-19 20:24:44.133 INFO 10376 --- [nio-2379-exec-3] c.netflix.loadbalancer.BaseLoadBalancer : Client: hystrix-demo instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=hystrix-demo,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2023-12-19 20:24:44.136 INFO 10376 --- [nio-2379-exec-3] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater
2023-12-19 20:24:44.146 INFO 10376 --- [nio-2379-exec-3] c.netflix.config.ChainedDynamicProperty : Flipping property: hystrix-demo.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2023-12-19 20:24:44.148 INFO 10376 --- [nio-2379-exec-3] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client hystrix-demo initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=hystrix-demo,current list of Servers=[danfoo:2383],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:1; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:danfoo:2383; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@359a4984
这就是一个简单的Zuul网关实现案例了。你可以根据实际需求进行更复杂的配置和修改,反正其实在zuul中,我们就采用此种方式进行相关配置。
提及一下,你可能看到我
这里我介绍一下:这个配置主要是围绕:zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.url=http://localhost:8080/
以上的user-service
就是我写的hystrix-demo,这个代表你需要指向的路由服务名称,或者说我们可以改写成:zuul.routes.<route>.path
和 zuul.routes.<route>.url
这样配置主要是围绕对符号/user-service/**
规则的请求路径转发到http://localhost:端口号/
地址的路由规则,比如有一个请求http://localhost:2379/user-service/hello
被发送到API网关上,由于/user-service/hello
能够被上述配置的path规则匹配,所以API网关会转发请求到http://localhost:8080/hello
地址。
这一般是我们的单实例配置方式。
我上边就是采用的单实例配置。
接下来提及一下多实例配置:
zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.serviceId=user-service
ribbon.eureka.enabled=false
user-service.ribbon.listOfServers=http://localhost:8080/,http://localhost:8081/
该配置实现了对符合/user-service/**
规则的请求路径转发到http://localhost:8080/
和http://localhost:8081/
两个实例地址的路由规则。它的配置方式与服务路由的配置方式一样,都采用了zuul.routes.<route>.path
与zuul.routes.<route>.serviceId
参数对的映射方式,只是这里的serviceId
是由用户手工命名的服务名称,配合<serviceId>.ribbon.listOfServers
参数实现服务与实例的维护。由于存在多个实例,API网关在进行路由转发时需要实现负载均衡策略,于是这里还需要Spring Cloud Ribbon
的配合。
-
ribbon.eureka.enabled
:由于zuul.routes.<route>.serviceId
指定的是服务名称,默认情况下Ribbon会根据服务发现机制来获取配置服务名对应的实例清单。但是,该示例并没有整合类似Eureka之类的服务治理框架,所以需要将该参数设置为false,不然配置的serviceId是获取不到对应实例清单的。 -
user-service.ribbon.listOfServers
:该参数内容与zuul.routes.<route>.serviceId
的配置相对应,开头的user-service
对应了serviceId
的值,这两个参数的配置相当于在该应用内部手工维护了服务与实例的对应关系。