之前的内容在这就不一一写了,请看之前的博文进行衔接。
首先我们来看这里的第一个部分
eureka-provider集群
在写这个的时候第一步改变pom文件,继承主模块,除必要内容其余都可以不用要,如果有自行要加的自行进行增加,这里只进行一个简单的配置
eureka-provider 的pom文件如下,除了以下内容其余删掉,如有需要则另加,基本依赖继承主模块
记得去主模块的pom文件中进行配置
后面凡是有关继承父类或在父类进行配置则根据以上剩下内容不再显示pom文件内容
改变application.yml文件
---
server:
port: 7201
spring:
profiles: provider1
application:
name: eureka-provider
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
---
server:
port: 7202
spring:
profiles: provider2
application:
name: eureka-provider
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
这样eureka-provider集群就完毕了
第二个部分
Hystrix
Hystrix,中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。
而本章中提到的Hystrix是Netflix开源的一款容错框架,实现容错和自我保护。
Hystrix设计原则
1.防止单个服务的故障,耗尽整个系统服务的容器(比如tomcat)的线程资源,避免分布式环境里大量级联失败。
通过第三方客户端访问(通常是通过网络)依赖服务出现失败、拒绝、超时或短路时执行回退逻辑
2.用快速失败代替排队(每个依赖服务维护一个小的线程池或信号量,当线程池满或信号量满,
会立即拒绝服务而不会排队等待)和优雅的服务降级;当依赖服务失效后又恢复正常,快速恢复
3.提供接近实时的监控和警报,从而能够快速发现故障和修复。监控信息包括请求成功,失败(客户端抛出的异常),
超时和线程拒绝。如果访问依赖服务的错误百分比超过阈值,断路器会跳闸,此时服务会在一段时间内停止对特定服务的所有请求
4.将所有请求外部系统(或请求依赖服务)封装到HystrixCommand或HystrixObservableCommand对象中,
然后这些请求在一个独立的线程中执行。使用隔离技术来限制任何一个依赖的失败对系统的影响。
每个依赖服务维护一个小的线程池(或信号量),当线程池满或信号量满,会立即拒绝服务而不会排队等待
启动hystris
1.修改子模块eureka-consumer中的application.yml文件启动熔断器
feign:
hystrix:
enabled: true
2.pom文件不需修改,因为spring-cloud-starter-openfeign已经自带了Hystrix。
3.新增HelloServiceFallback类,用来实现TestFeginService接口
4.修改TestFeginService,在@FeignClient注解中指定降级接口
第三个部分可视化熔断器监控
Hystrix Dashboard 是 Hystrix 的仪表盘组件,提供了数据监控,可以实时监控 Hystrix 的各个指标,例如:
各Hystrix Command的请求响应时间, 请求成功率等数据,然后通过图形化界面展示出来
1.修改子模块hystrix-dashboard与springcloud04添加父子模块引用
注1:hystrix-dashboard是个独立的服务,不用注册到 Eureka server
(也就是继承主模块,看上面)
2.添加依赖,添加到主模块中
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3.启动类添加如下注解
@EnableHystrixDashboard//启用熔断器仪表盘
4.修改application.yml
server:
port: 7501
spring:
application:
name: hystrix-dashboard
对eureka-consumer服务进行监控
5~6步骤是在子模块eureka-consumer中操作
5.添加依赖,此依赖是打开Actuator(但此依赖已在步骤2被导入父模块springcloud04,所以可省略)
org.springframework.boot
spring-boot-starter-actuator
6.启动类添加如下注解
@EnableCircuitBreaker//启动断路器
然后对注册机,提供者,消费者,可视化熔断器依次执行即可
第四部分
配置中心
springcloud05 主模块 quickstart项目
eureka-server-cluster 子模块 springboot项目
eureka-cluster1/eureka-cluster1(2个注册中心集群)
eureka-provider 子模块 springboot项目
生产者集群(provider1/provider2),同时此生产者也访问了配置中心里面的配置信息
eureka-consumer 子模块 springboot项目
Feign访问生产集群,Feign默认集成了Ribbon,默认实现了负载均衡的效果。
config-server 子模块 springcloud的配置中心
config-server1/config-server1(2个配置中心集群)
随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,
需要的配置文件随着服务增加而不断增多。某一个基础服务信息变更,都会引起一系列的更新和重启,
运维苦不堪言也容易出错,配置中心便是解决此类问题的灵丹妙药。
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,
server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。
Spring cloud使用git或svn存放配置文件,默认情况下使用git,我们先以git为例做一套示例
创建springcloud配置中心
1.在GitHub中创建仓库(这里都是使用ssh)
创建一个仓库springcloud_config_server_public(公库)(供测试使用)
注1:如果是真正的项目,会用公库吗?
创建一个仓库springcloud_config_server_private(私库)
2。在各个仓库中添加一下文件
spring-cloud-config-dev.yml
spring-cloud-config-test.yml
spring-cloud-config-prod.yml
3.编辑子模块config-server
1.编辑父子模块关系
注1:暂时不继承父模块~暂时不继承父模块~暂时不继承父模块~~~
2.添加pom(这里已经是里面的了,不需要另外找)
<dependency>
<!-- 不用添加到父模块 -->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
注1:通过start.spring.io创建,dependencies要选择Config Server,会有两个选项,要先其中带有git/svn的
4.修改application.yml,这里我是先用的公库,后面再改成的私库
server:
port: 8001
spring:
profiles: configserver1
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/swaily/springcloud_config_server_public.git ##去github当中去复制改路径ssh方式
search-paths:
5.在启动类添加注解
@EnableConfigServer
6.测试
http://localhost:8001/spring-cloud-config-dev.yml
http://localhost:8001/spring-cloud-config-test.yml
http://localhost:8001/spring-cloud-config-prod.yml
如果显示yml文件中的内容,则表示配置中心启动成功且连接上远程Git仓库的配置文件
server搞起来之后,最终还是要在业务项目中去获取server端的配置信息
配置client端,用于测试,后续可删除
创建及编辑子模块config-client,它其实就是一个普通springboot项目,只不过添加了spring-cloud-config-client依赖,
可以访问springcloud配置中心里面的配置信息
1.编辑父子模块关系
注1:不需要继承父模块~不需要继承父模块~不需要继承父模块~
2.添加依赖在主模块当中,因为在其他文件当中也要使用,这里自身也要添加,因为这里并没有继承主模块
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
注1:通过start.spring.io创建,dependencies要选择Config Client
注2:入了两个坑:
坑一:网上大部分帖子导入依赖均为:“spring-cloud-config-client”,新版中其实是“spring-cloud-starter-config”,
最后还是通过start.spring.io查找生成pom,对比后才发现问题
坑二:start.spring.io生成的依赖中少了spring-boot-starter-web,tomcat无法启动
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
注3:此模块不要引入spring-cloud-config-server依赖
3.创建及编辑配置文件bootstrap.yml和application.yml
bootstrap.yml文件
spring:
cloud:
config:
name: spring-cloud-config #对应spring-cloud-config-dev.yml的{spring-cloud-config}部分
profile: prod #对应spring-cloud-config-dev.yml的{dev}部分
uri: http://localhost:8001/ #配置中心的具体地址
label: master #对应git的分支。如果配置中心使用的是本地存储,则该参数无用
application.yml文件
server:
port: 8002
spring:
application:
name: config-client
注1:配置文件优先级 bootstrap.yml>application.yml>git 文件里的 yml
4.创建HelloController,通过@Value注解读取配置信息
##这个根据你里面写的内容来进行依次点
如果你是在github文件中的内容写的是以下内容
config:
hello:spring-cloud-dev
@Value("${config.hello}")
private String msg = null;
5.启动类不用附加注解,直接可以启动
6.测试
http://localhost:8002/hello
SpringCloud高可用配置中心
将config-server进行集群设置
1.配置高可用的双注册中心
2.创建生产者
3.创建消费者
## 以上配置均为之前内容,启动各子模块并测试:注册中心(2)/生产者(2)/消费者(1)
4.创建配置中心模块server-config,完成后并测试(单机版/未向注册中心注册)
注1:不需要继承父模块~不需要继承父模块~不需要继承父模块~~~
5.在之前server-config的pom的基础上添加eureka组件
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
6.修改server-config的application.yml,向注册中心注册(单机版),启动并测试(这里使用了私库方式(公库就是以上的application.yml文件))注意以下需要自己的私钥可以在以下找到
7.server-config修改为高可用双配置中心,启动并测试
---
server:
port: 8001
spring:
profiles: configserver1
application:
name: config-server
cloud:
config:
server:
git:
uri: git@github.com:llssdsq/springcloud_config_server_private.git
search-paths:
lable: master
ignore-local-ssh-settings: true
private-key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA44acF/U6vtK+z7vmvUvYaspZFFXDh5g0uVdQ8l6o9WHccFaN
FIEwHr1qcQMvoUyJGfzCj0AZx2+FugxgQxTvqhZKN3M4+/Pzbdze063TtssnQOvQ
1TBMzB7n/rs3i7YlyGvPJejxqmKhcgNyWNQRzNKloLsoHlmKu2iPvfDK/+G0shuQ
GCsbRkeTxh6mPeAElKjT7vy3+VjKHBD6KgQtnNdS6sMJQv9H2MV6SpppJyHqRsIS
tfP6p2wIUjJqrts/MMCpJGrSUlXpUqiu+dKGnNhpcZB8c2GVuhv8EJzsA1eS0ac1
IT/TWRk3JVT/FdWxiqLYHKBYd7yphQoUsfUafwIDAQABAoIBAGsT/8Q6siH6Vri3
Krltx3VCs7ehQTtAQ5fyYvMd35BUNQVdhlnfDsF4zW5QXIsh1Og5D2uRdFBqyNmt
V2Rapww6H0WHYYsZ3TeYGfovNZMyes/P62FZsNrjtLUqcNK8r31qV3v07D8O2gIp
Yxgw/guSG0bQrenSpDrc08FFYJQZRt/S1SFTLuUBvsYNSzKwodWR7yKJlP5y66uf
x45D4lUHQ+PyKIxZv19HMjn4KKUV9WL30391RkXU9BIP+YX7U9Bct+H2HcxABaRA
bzeoPBSz/qdpcrXtnTpXnrk+izaTV25xqSfPybGiPP6uWoj9gHzXFg9G0YbYQmbU
7hPB6NECgYEA80u5l9/2hnoRQdbph9t114E65bZBkYb72/hS0L+pqo+Bdt71TZyN
zwOUP5JQ3nExAE9BEamnH0XAubLA5SZfV2f6R57B17QbSH1egrEwT//ZLX9q/FBw
FXtJ/jbg1gO9KSC0k1oROmR5FH+lEXN16cURdIfzabA6pSQbsA15Q6cCgYEA72gU
DpQmvB87l6pMrBvZRMEgppibnRrOU0FWVZaUxg89TNv8gh4x1EIX3C4rn4ib9V8r
oBm7TwJj87QRng1PzwT0XIlSB3SOQs6upm1f2zAse7yxZ/BG398Hs3U1wNjDLLIP
KaezQPiTslKXjq/DC6wKVKEX7lNbqQkHyK2MLWkCgYEA7qqgW+5mhjEE8NOEr7OH
/GpXfrS1ya7jLzyA8SqzpA+27wd1GDe1nRhju6ErF6tuaGFW8Z69xR3GG+TQ+XoV
GUd07AE/Iv0Zrpjdt9NeE3xmbg2KxA2chlY1ld373bY5QDlHKy21rNSXOpalNWNQ
joy1vN0I2er4/LtZNfFhvg0CgYAvgsooMoKVZuVere9VYJl3qZQfO732KbG0mAzY
I3AW9kNGE4pDEFb3Nr6hdZA2stewlFiGB1VC0sifPqcYZK/n96W/D4l17U2mOHo0
kRQq3Z6WV9YlOGv4VbyjgqlOQjZJknSr4ZoTVMGK7BUjvgHJOTU7olSreWOBYkdn
LfnZsQKBgQDLazmrstVaoNMa+sCU5bIzZeIHqp/r/NuTdEhxEh+v0ozkjebP9YlZ
ghEGUnChyJrNLoqURIWfzirlrLLYvDlMWCiJE61AgSFoScYaTC25kRHwtkRrMTqj
p0xEDa4f96FHywJj0+y3q2uZMHyg1D9YqdZiyVU9XrHZVeozPcOnLA==
-----END RSA PRIVATE KEY-----
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
---
server:
port: 8002
spring:
profiles: configserver2
application:
name: config-server
cloud:
config:
server:
git:
uri: git@github.com:llssdsq/springcloud_config_server_private.git
search-paths:
lable: master
ignore-local-ssh-settings: true
private-key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA44acF/U6vtK+z7vmvUvYaspZFFXDh5g0uVdQ8l6o9WHccFaN
FIEwHr1qcQMvoUyJGfzCj0AZx2+FugxgQxTvqhZKN3M4+/Pzbdze063TtssnQOvQ
1TBMzB7n/rs3i7YlyGvPJejxqmKhcgNyWNQRzNKloLsoHlmKu2iPvfDK/+G0shuQ
GCsbRkeTxh6mPeAElKjT7vy3+VjKHBD6KgQtnNdS6sMJQv9H2MV6SpppJyHqRsIS
tfP6p2wIUjJqrts/MMCpJGrSUlXpUqiu+dKGnNhpcZB8c2GVuhv8EJzsA1eS0ac1
IT/TWRk3JVT/FdWxiqLYHKBYd7yphQoUsfUafwIDAQABAoIBAGsT/8Q6siH6Vri3
Krltx3VCs7ehQTtAQ5fyYvMd35BUNQVdhlnfDsF4zW5QXIsh1Og5D2uRdFBqyNmt
V2Rapww6H0WHYYsZ3TeYGfovNZMyes/P62FZsNrjtLUqcNK8r31qV3v07D8O2gIp
Yxgw/guSG0bQrenSpDrc08FFYJQZRt/S1SFTLuUBvsYNSzKwodWR7yKJlP5y66uf
x45D4lUHQ+PyKIxZv19HMjn4KKUV9WL30391RkXU9BIP+YX7U9Bct+H2HcxABaRA
bzeoPBSz/qdpcrXtnTpXnrk+izaTV25xqSfPybGiPP6uWoj9gHzXFg9G0YbYQmbU
7hPB6NECgYEA80u5l9/2hnoRQdbph9t114E65bZBkYb72/hS0L+pqo+Bdt71TZyN
zwOUP5JQ3nExAE9BEamnH0XAubLA5SZfV2f6R57B17QbSH1egrEwT//ZLX9q/FBw
FXtJ/jbg1gO9KSC0k1oROmR5FH+lEXN16cURdIfzabA6pSQbsA15Q6cCgYEA72gU
DpQmvB87l6pMrBvZRMEgppibnRrOU0FWVZaUxg89TNv8gh4x1EIX3C4rn4ib9V8r
oBm7TwJj87QRng1PzwT0XIlSB3SOQs6upm1f2zAse7yxZ/BG398Hs3U1wNjDLLIP
KaezQPiTslKXjq/DC6wKVKEX7lNbqQkHyK2MLWkCgYEA7qqgW+5mhjEE8NOEr7OH
/GpXfrS1ya7jLzyA8SqzpA+27wd1GDe1nRhju6ErF6tuaGFW8Z69xR3GG+TQ+XoV
GUd07AE/Iv0Zrpjdt9NeE3xmbg2KxA2chlY1ld373bY5QDlHKy21rNSXOpalNWNQ
joy1vN0I2er4/LtZNfFhvg0CgYAvgsooMoKVZuVere9VYJl3qZQfO732KbG0mAzY
I3AW9kNGE4pDEFb3Nr6hdZA2stewlFiGB1VC0sifPqcYZK/n96W/D4l17U2mOHo0
kRQq3Z6WV9YlOGv4VbyjgqlOQjZJknSr4ZoTVMGK7BUjvgHJOTU7olSreWOBYkdn
LfnZsQKBgQDLazmrstVaoNMa+sCU5bIzZeIHqp/r/NuTdEhxEh+v0ozkjebP9YlZ
ghEGUnChyJrNLoqURIWfzirlrLLYvDlMWCiJE61AgSFoScYaTC25kRHwtkRrMTqj
p0xEDa4f96FHywJj0+y3q2uZMHyg1D9YqdZiyVU9XrHZVeozPcOnLA==
-----END RSA PRIVATE KEY-----
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
或者使用公库方式
---
server:
port: 8001
spring:
profiles: configserver1
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/swaily/springcloud_config_server_public.git
search-paths:
##配置中心向注册中心进行服务注册
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
---
server:
port: 8002
spring:
profiles: configserver2
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/swaily/springcloud_config_server_public.git
search-paths:
##配置中心向注册中心进行服务注册
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
8.eureka-provider生产者访问配置中心,将原application.yml复制到
1.在父模块添加配置中心客户端依赖
org.springframework.cloud
spring-cloud-starter-config
2.修改bootstrap.yml文件,添加注册中心->配置中心的配置
注1:入的坑
eureka.client.serviceUrl.defaultZone=http://peer1:7101/eureka/,http://peer2:7102/eureka/
此项虽然在application.yml中配置过了,但在bootstrap.yml要重新配置一次,因为bootstrap.yml比application.yml加载要早
但bootstrap.yml配置后,application.yml中可以不配置了
注2:第一,注释了配置中心的URL,第二,添加了配置中心的应用名
## add
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
spring:
cloud:
config:
name: spring-cloud-config #对应spring-cloud-config-dev.yml的{spring-cloud-config}部分
profile: dev #对应spring-cloud-config-dev.yml的{dev}部分
## remove 下面代码已注释,因为不再通过URL直接访问配置中心,而是生产者->注册中心->配置中心->获得Git中的配置信息
#spring.cloud.config.uri = http://localhost:8001/ #配置中心的具体地址()
label: master #对应git的分支。如果配置中心使用的是本地存储,则该参数无用
## add
discovery:
enabled: true #true是从配置中心读取文件
## add
service-id: config-server #指定配置中心的service-id,便于扩展为高可用配置集群(目前已启用)
SpringCloud Config(配置中心)实现配置自动刷新,此时config-client可删除
注1:项目端口号的设计
71XX 注册中心
72XX 生产者
73XX 消费者
74XX 熔断器仪表板
800X 配置中心-服务端(8001/8002)
75XX 服务网关
第五部分
网关
为什么需要API Gateway
Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,
Spring Cloud Config服务集群配置中心,似乎一个微服务框架已经完成了。我们还是少考虑了一个问题,
外部的应用如何来访问内部各种各样的微服务呢?
外部的应用如何来访问内部各种各样的微服务呢?在微服务架构中,后端服务往往不直接开放给调用端,
而是通过一个API网关根据请求的url,路由到相应的服务。当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,
这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务端。
Spring Cloud Zuul
Spring Cloud Zuul路由是微服务架构的不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务。
Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
Spring Cloud Zuul的简单使用
1.新建gateway子模块编辑springcloud06父子关系,并继承springcloud06
2.子模块gateway修改pom,添加zuul依赖(不添加到父模块中添加到子本模块中的pom文件即可)
org.springframework.cloud
spring-cloud-starter-netflix-zuul
注1:使用“https://start.spring.io/”搜索zuul,生成pom
3.配置文件
spring:
application:
name: gateway
server:
port: 7501
eureka:
client:
serviceUrl:
defaultZone: http://peer1:7101/eureka/,http://peer2:7102/eureka/,http://peer3:7103/eureka/
zuul:
FormBodyWrapperFilter:
pre:
disable: true
## api-aaa指模块名
## 这里的配置表示(用于测试后面再更改),访问/mv/** 直接重定向到
https://mvnrepository.com/**
(自己添加到里面,这里就不另行写了,因为这个到最后可删除,用以上的即可,怕出错就先加上以下的内容先测试使用)
zuul.routes.api-aaa.path=/mv/**
zuul.routes.api-aaa.url=https://mvnrepository.com/
4.修改启动类,添加@EnableZuulProxy,支持网关路由
5.测试:浏览器地址栏输入如下URL
http://localhost:7501/mv/aaa
http://localhost:7501/mv/artifact/junit/junit
服务化,Spring Cloud Zuul向注册中心注册并配置路由访问eureka-consumer
1.创建注册中心(双注册中心)并启动
2.创建消费者,启动后并测试
CalController
以下步骤均在子模块gateway中修改
3.添加与springcloud06的父子关系,并继承pom
4.修改application.yml向注册中心注册
spring.application.name=gateway
server.port=7501
## 向注册中心注册
eureka.client.serviceUrl.defaultZone=http://peer1:7101/eureka/,http://peer2:7102/eureka/
## 配置子模块eureka-consumer的路由规则(将以上的内容修改为以下的内容,用来测试使用最后也可删除)
zuul.routes.api-cons.path=/cons/**
zuul.routes.api-cons.serviceId=eureka-consumer
4.子模块gateway修改启动类,添加@EnableEurekaClient
5.测试子模块eureka-consumer路由配置,浏览器地址栏输入如下URL
http://localhost:7501/cons/htllo/add
网关的默认路由规则
通过url映射的方式来实现zull的转发有局限性,
第一:如果后端服务多达十几个的时候,每一个服务都要配置一次,这样相当麻烦!
第二:如果后端的服务是动态添加的,难道每添加一个服务就修改配置文件,添加一个路由规则么!
实际上在实现微服务架构时,服务名与服务实例地址的关系在eureka server中已经存在了,
所以,我们只需要将Zuul注册到eureka server上去发现其他服务,就可以实现对serviceId的映射
默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并按如下规则进行配置:
http://zuul_host:zuul_port/serviceId/(最后可根据这个去访问即http://localhost:7501/serviceId(可以使eureka-provider也可以是eureka-consumer等)/(里面的方法)**))
这样,所有的请求会被转发到serviceId对应的微服务。
测试:
1.将application.yml中如下配置删除或注释(其实不删除或注释也是可以的,就相当于给eureka-consumer服务多配置了一条路由)
zuul.routes.api-cons.path=/cons/**
zuul.routes.api-cons.serviceId=eureka-consumer
2.浏览器地址栏输入如下URL
http://localhost:7501/eureka-consumer/cal/add?num1=10&num2=20
最终发现在访问的效果是一样的
Zuul的核心
Zuul大部分功能都是通过过滤器来实现的,Filter是Zuul的核心,用来实现对外服务的控制。
1.Filter生命周期
Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”
2.Filter类型
过滤器类型对应于Filter的生命周期
PRE:
这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING:
这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务
POST:
这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等
ERROR:
在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务
注1:如何禁用指定的Filter
zuul:
FormBodyWrapperFilter:
pre:
disable: true
zuul自定义filter
Zuul中有默认实现的Filter,当然也可以实现自己的自定义Filter,用来完成一些鉴权、流量转发、请求统计等工作。
我们来实现一个自定义过滤器TokenFilter,实现令牌验证功能,
实现自定义Filter步骤
1.继承ZuulFilter的类,并覆盖其中的4个方法
public class XxxFilter extends ZuulFilter {
@Override
String filterType() {
return "pre"; //定义filter的类型,有pre、route、post、error四种
}
@Override
int filterOrder() {
return 0; //定义filter的顺序,数字越小表示顺序越高,越先执行
}
@Override
boolean shouldFilter() {
return true; //表示是否需要执行该filter,true表示执行,false表示不执行
}
@Override
Object run() {
// 如可添加以下内容,用于测试
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String uname=request.getParameter("uname");
if(null==uname||"".equals(uname.trim())){
ctx.setSendZuulResponse(false); //不对其进行路由
ctx.setResponseStatusCode(400);
ctx.setResponseBody("token is empty");
ctx.set("isSuccess", false);
}else{
ctx.setSendZuulResponse(true); //对请求进行路由
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);
}
return null; //filter需要执行的具体操作
}
}
2.将TokenFilter加入到请求拦截队列,在启动类中添加以下代码
@Bean
public TokenFilter tokenFilter() {
return new TokenFilter();
}
3.测试
http://localhost:7501/eureka-consumer/cal/add?num1=10&num2=20 返回token is empty
http://localhost:7501/eureka-consumer/cal/add?num1=10&num2=20&token=abc 正常执行,并返回结果
注1:自定义路由中常用的类或API
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
ctx.setSendZuulResponse(true); //对请求进行路由
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);
ctx.setSendZuulResponse(false); //不对其进行路由
ctx.setResponseStatusCode(400);
ctx.setResponseBody("token is empty");
ctx.set("isSuccess", false);