Spring Cloud Netflix通过自动配置并绑定到Spring Environment和其他Spring编程模型习惯用法,为Spring Boot应用程序提供了Netflix OSS集成。使用一些简单的批注,您可以快速启用和配置应用程序内部的通用模式,并使用经过测试的Netflix组件构建大型分布式系统。提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)。
服务发现:Eureka客户
服务发现是基于微服务的体系结构的关键原则之一。尝试手动配置每个客户端或某种形式的约定可能非常困难并且非常脆弱。Eureka是Netflix Service Discovery服务器和客户端。可以将服务器配置和部署为高可用性,每个服务器将有关已注册服务的状态复制到其他服务器。
在尤里卡注册
当客户端向Eureka注册时,它将提供有关其自身的元数据,例如主机和端口,运行状况指示器URL,主页等。Eureka从属于服务的每个实例接收心跳消息。如果心跳在可配置的时间表上进行故障转移,则通常会将实例从注册表中删除。
尤里卡客户示例:
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
(即完全正常的Spring Boot应用)。在此示例中,我们@EnableEurekaClient明确使用 ,但只有Eureka可用,您也可以使用@EnableDiscoveryClient。需要进行配置才能找到Eureka服务器。例:
application.yml
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
其中,“ defaultZone”是一个魔术字符串后备值,它为任何不表达首选项的客户端提供服务URL(即,这是一个有用的默认值)。
默认的应用程序名称(服务ID),虚拟主机和非安全端口,从拍摄的Environment是,
s
p
r
i
n
g
.
a
p
p
l
i
c
a
t
i
o
n
.
n
a
m
e
,
{spring.application.name},
spring.application.name,{spring.application.name}和${server.port}分别。
@EnableEurekaClient使应用程序同时进入Eureka的“实例”(即,它自己注册)和“客户端”(即,它可以查询注册表以定位其他服务)。实例行为由eureka.instance.*配置键驱动,但是如果确保您的应用程序具有spring.application.name默认值(这是Eureka服务ID或VIP 的默认值),则默认值会很好 。
有关可配置选项的更多详细信息,请参见EurekaInstanceConfigBean和EurekaClientConfigBean。
状态页和健康指示器
Eureka实例的状态页面和运行状况指示器分别默认为“ / info”和“ / health”,它们是Spring Boot Actuator应用程序中有用端点的默认位置。如果您使用非默认上下文路径或servlet路径(例如server.servletPath=/foo)或管理端点路径(例如management.contextPath=/admin),则即使对于Actuator应用程序,也需要更改它们。例:
application.yml
eureka:
instance:
statusPageUrlPath: ${management.context-path}/info
healthCheckUrlPath:
m
a
n
a
g
e
m
e
n
t
.
c
o
n
t
e
x
t
−
p
a
t
h
/
h
e
a
l
t
h
这
些
链
接
显
示
在
客
户
端
使
用
的
元
数
据
中
,
并
在
某
些
情
况
下
用
于
确
定
是
否
将
请
求
发
送
到
您
的
应
用
程
序
,
因
此
,
如
果
请
求
准
确
,
将
很
有
帮
助
。
注
册
安
全
的
应
用
程
序
如
果
您
的
应
用
程
序
希
望
通
过
H
T
T
P
S
与
您
联
系
,
则
可
以
分
别
在
中
设
置
两
个
标
志
E
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
,
即
e
u
r
e
k
a
.
i
n
s
t
a
n
c
e
.
[
n
o
n
S
e
c
u
r
e
P
o
r
t
E
n
a
b
l
e
d
,
s
e
c
u
r
e
P
o
r
t
E
n
a
b
l
e
d
]
=
[
f
a
l
s
e
,
t
r
u
e
]
。
这
将
使
E
u
r
e
k
a
发
布
实
例
信
息
,
显
示
对
安
全
通
信
的
明
确
偏
好
。
S
p
r
i
n
g
C
l
o
u
d
D
i
s
c
o
v
e
r
y
C
l
i
e
n
t
将
始
终
h
t
t
p
s
:
/
/
…
;
为
以
这
种
方
式
配
置
的
服
务
返
回
U
R
I
,
并
且
E
u
r
e
k
a
(
本
地
)
实
例
信
息
将
具
有
安
全
的
运
行
状
况
检
查
U
R
L
。
由
于
E
u
r
e
k
a
在
内
部
工
作
的
方
式
,
它
仍
然
会
发
布
状
态
和
主
页
的
非
安
全
U
R
L
,
除
非
您
也
明
确
地
覆
盖
了
这
些
U
R
L
。
您
可
以
使
用
占
位
符
来
配
置
e
u
r
e
k
a
实
例
网
址
,
例
如
a
p
p
l
i
c
a
t
i
o
n
.
y
m
l
e
u
r
e
k
a
:
i
n
s
t
a
n
c
e
:
s
t
a
t
u
s
P
a
g
e
U
r
l
:
h
t
t
p
s
:
/
/
{management.context-path}/health 这些链接显示在客户端使用的元数据中,并在某些情况下用于确定是否将请求发送到您的应用程序,因此,如果请求准确,将很有帮助。 注册安全的应用程序 如果您的应用程序希望通过HTTPS与您联系,则可以 分别在中设置两个标志EurekaInstanceConfig,即 eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]。这将使Eureka发布实例信息,显示对安全通信的明确偏好。Spring Cloud DiscoveryClient将始终https://…;为以这种方式配置的服务返回URI,并且Eureka(本地)实例信息将具有安全的运行状况检查URL。 由于Eureka在内部工作的方式,它仍然会发布状态和主页的非安全URL,除非您也明确地覆盖了这些URL。您可以使用占位符来配置eureka实例网址,例如 application.yml eureka: instance: statusPageUrl: https://
management.context−path/health这些链接显示在客户端使用的元数据中,并在某些情况下用于确定是否将请求发送到您的应用程序,因此,如果请求准确,将很有帮助。注册安全的应用程序如果您的应用程序希望通过HTTPS与您联系,则可以分别在中设置两个标志EurekaInstanceConfig,即eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]。这将使Eureka发布实例信息,显示对安全通信的明确偏好。SpringCloudDiscoveryClient将始终https://…;为以这种方式配置的服务返回URI,并且Eureka(本地)实例信息将具有安全的运行状况检查URL。由于Eureka在内部工作的方式,它仍然会发布状态和主页的非安全URL,除非您也明确地覆盖了这些URL。您可以使用占位符来配置eureka实例网址,例如application.ymleureka:instance:statusPageUrl:https://{eureka.hostname}/info
healthCheckUrl: https://
e
u
r
e
k
a
.
h
o
s
t
n
a
m
e
/
h
e
a
l
t
h
h
o
m
e
P
a
g
e
U
r
l
:
h
t
t
p
s
:
/
/
{eureka.hostname}/health homePageUrl: https://
eureka.hostname/healthhomePageUrl:https://{eureka.hostname}/
(请注意,这
e
u
r
e
k
a
.
h
o
s
t
n
a
m
e
是
本
机
占
位
符
,
仅
在
更
高
版
本
的
E
u
r
e
k
a
中
可
用
。
您
也
可
以
使
用
S
p
r
i
n
g
占
位
符
来
实
现
相
同
的
目
的
,
例
如
使
用
{eureka.hostname}是本机占位符,仅在更高版本的Eureka中可用。您也可以使用Spring占位符来实现相同的目的,例如使用
eureka.hostname是本机占位符,仅在更高版本的Eureka中可用。您也可以使用Spring占位符来实现相同的目的,例如使用{eureka.instance.hostName}。)
注意 如果您的应用程序在代理后面运行,并且SSL终止在代理中(例如,如果您在
Cloud Foundry或其他平台中作为服务运行),则需要确保代理“转发”标头
被截取并处理应用程序。如果Spring Boot应用程序中的嵌入式Tomcat容器
具有针对’X-Forwarded-\ *'标头的显式配置,则会自动执行此操作。出现此
错误的迹象是,您的应用程序呈现给自身的链接将是错误的(错误的主机,端
口或协议)。
尤里卡的健康检查
默认情况下,Eureka使用客户端心跳来确定客户端是否启动。除非另有说明,否则发现客户端不会根据Spring Boot Actuator传播应用程序的当前运行状况检查状态。这意味着成功注册后,尤里卡将始终宣布该应用程序处于“启动”状态。可以通过启用Eureka运行状况检查来更改此行为,这会导致应用程序状态传播到Eureka。结果,除“ UP”状态外,其他所有应用程序都不会将流量发送到处于其他状态的应用程序。
application.yml
eureka:
client:
healthcheck:
enabled: true
如果您需要对健康检查进行更多控制,则可以考虑实施自己的com.netflix.appinfo.HealthCheckHandler。
实例和客户端的Eureka元数据
值得花费一些时间来了解Eureka元数据的工作原理,因此您可以在平台中使用有意义的方式使用它。对于诸如主机名,IP地址,端口号,状态页和运行状况检查之类的内容,有标准的元数据。这些将发布在服务注册表中,并由客户端用于以直接方式联系服务。可以将其他元数据添加到中的实例注册中eureka.instance.metadataMap,并且可以在远程客户端中访问它,但是除非知道元数据的含义,否则通常不会更改客户端的行为。下文描述了几种特殊情况,其中Spring Cloud已经为元数据映射分配了含义。
在Cloudfoundry上使用Eureka
Cloudfoundry具有全局路由器,因此同一应用程序的所有实例都具有相同的主机名(在具有类似架构的其他PaaS解决方案中也是如此)。这不一定是使用Eureka的障碍,但是如果您使用路由器(推荐,或者甚至取决于平台的设置方式是必选的),则需要显式设置主机名和端口号(安全或不安全) ),以便他们使用路由器。您可能还希望使用实例元数据,以便您可以区分客户端上的实例(例如,在自定义负载平衡器中)。默认情况下eureka.instance.instanceId为vcap.application.instance_id。例如:
application.yml
eureka:
instance:
hostname:
v
c
a
p
.
a
p
p
l
i
c
a
t
i
o
n
.
u
r
i
s
[
0
]
n
o
n
S
e
c
u
r
e
P
o
r
t
:
80
根
据
在
C
l
o
u
d
f
o
u
n
d
r
y
实
例
中
设
置
安
全
规
则
的
方
式
,
您
也
许
可
以
注
册
并
使
用
主
机
V
M
的
I
P
地
址
进
行
直
接
的
服
务
到
服
务
的
调
用
。
P
i
v
o
t
a
l
W
e
b
服
务
(
P
W
S
)
尚
不
提
供
此
功
能
。
在
A
W
S
上
使
用
E
u
r
e
k
a
如
果
计
划
将
应
用
程
序
部
署
到
A
W
S
云
,
则
必
须
将
E
u
r
e
k
a
实
例
配
置
为
可
感
知
A
m
a
z
o
n
,
并
且
可
以
通
过
以
下
方
式
自
定
义
E
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
B
e
a
n
来
实
现
:
@
B
e
a
n
@
P
r
o
f
i
l
e
(
"
!
d
e
f
a
u
l
t
"
)
p
u
b
l
i
c
E
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
B
e
a
n
e
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
(
)
E
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
B
e
a
n
b
=
n
e
w
E
u
r
e
k
a
I
n
s
t
a
n
c
e
C
o
n
f
i
g
B
e
a
n
(
)
;
A
m
a
z
o
n
I
n
f
o
i
n
f
o
=
A
m
a
z
o
n
I
n
f
o
.
B
u
i
l
d
e
r
.
n
e
w
B
u
i
l
d
e
r
(
)
.
a
u
t
o
B
u
i
l
d
(
"
e
u
r
e
k
a
"
)
;
b
.
s
e
t
D
a
t
a
C
e
n
t
e
r
I
n
f
o
(
i
n
f
o
)
;
r
e
t
u
r
n
b
;
更
改
尤
里
卡
实
例
I
D
一
个
普
通
的
N
e
t
f
l
i
x
E
u
r
e
k
a
实
例
注
册
的
I
D
等
于
其
主
机
名
(
即
,
每
个
主
机
仅
提
供
一
项
服
务
)
。
S
p
r
i
n
g
C
l
o
u
d
E
u
r
e
k
a
提
供
了
一
个
明
智
的
默
认
值
,
如
下
所
示
:
{vcap.application.uris[0]} nonSecurePort: 80 根据在Cloudfoundry实例中设置安全规则的方式,您也许可以注册并使用主机VM的IP地址进行直接的服务到服务的调用。Pivotal Web服务(PWS)尚不提供此功能。 在AWS上使用Eureka 如果计划将应用程序部署到AWS云,则必须将Eureka实例配置为可感知Amazon,并且可以通过以下方式自定义EurekaInstanceConfigBean来实现: @Bean @Profile("!default") public EurekaInstanceConfigBean eurekaInstanceConfig() { EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(); AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka"); b.setDataCenterInfo(info); return b; } 更改尤里卡实例ID 一个普通的Netflix Eureka实例注册的ID等于其主机名(即,每个主机仅提供一项服务)。Spring Cloud Eureka提供了一个明智的默认值,如下所示:
vcap.application.uris[0]nonSecurePort:80根据在Cloudfoundry实例中设置安全规则的方式,您也许可以注册并使用主机VM的IP地址进行直接的服务到服务的调用。PivotalWeb服务(PWS)尚不提供此功能。在AWS上使用Eureka如果计划将应用程序部署到AWS云,则必须将Eureka实例配置为可感知Amazon,并且可以通过以下方式自定义EurekaInstanceConfigBean来实现:@Bean@Profile("!default")publicEurekaInstanceConfigBeaneurekaInstanceConfig()EurekaInstanceConfigBeanb=newEurekaInstanceConfigBean();AmazonInfoinfo=AmazonInfo.Builder.newBuilder().autoBuild("eureka");b.setDataCenterInfo(info);returnb;更改尤里卡实例ID一个普通的NetflixEureka实例注册的ID等于其主机名(即,每个主机仅提供一项服务)。SpringCloudEureka提供了一个明智的默认值,如下所示:{spring.cloud.client.hostname}:
s
p
r
i
n
g
.
a
p
p
l
i
c
a
t
i
o
n
.
n
a
m
e
:
{spring.application.name}:
spring.application.name:{spring.application.instance_id:${server.port}}}。例如myhost:myappname:8080。
使用Spring Cloud,您可以通过在中提供唯一的标识符来覆盖它eureka.instance.instanceId。例如:
application.yml
eureka:
instance:
instanceId:
s
p
r
i
n
g
.
a
p
p
l
i
c
a
t
i
o
n
.
n
a
m
e
:
{spring.application.name}:
spring.application.name:{spring.application.instance_id:${random.value}}
有了此元数据,并且在本地主机上部署了多个服务实例,随机值将在其中插入以使实例唯一。在Cloudfoundry中,spring.application.instance_id它将自动填充在Spring Boot Actuator应用程序中,因此将不需要随机值。
使用EurekaClient
一旦有了一个@EnableDiscoveryClient(或@EnableEurekaClient)一个应用程序,就可以使用它从Eureka Server中发现服务实例。一种方法是使用本机 com.netflix.discovery.EurekaClient(与Spring Cloud相反DiscoveryClient),例如
@Autowired
private EurekaClient discoveryClient;
public String serviceUrl() {
InstanceInfo instance = discoveryClient.getNextServerFromEureka(“STORES”, false);
return instance.getHomePageUrl();
}
TIP 不要使用EurekaClientin @PostConstruct方法或in @Scheduled方法
(或ApplicationContext可能尚未开始的任何地方)。它使用SmartLi
fecycle( phase=0)进行了初始化,因此最早可以依靠它的是处于Smart
Lifecycle更高阶段的另一个。
本地Netflix EurekaClient的替代产品
您不必使用原始Netflix EurekaClient,通常在某种包装后使用它会更方便。Spring Cloud支持Feign(REST客户端构建器),并且SpringRestTemplate使用逻辑Eureka服务标识符(VIP)而不是物理URL。要使用固定的物理服务器列表配置Ribbon,您可以简单地将其设置.ribbon.listOfServers为以逗号分隔的物理地址(或主机名)列表,其中为客户端ID。
您还可以使用,org.springframework.cloud.client.discovery.DiscoveryClient 该API为发现客户端提供了一个简单的API,该API不特定于Netflix,例如
@Autowired
private DiscoveryClient discoveryClient;
public String serviceUrl() {
List list = client.getInstances(“STORES”);
if (list != null && list.size() > 0 ) {
return list.get(0).getUri();
}
return null;
}
为什么注册服务这么慢?
成为实例还涉及到注册表的定期心跳(通过客户端serviceUrl),默认持续时间为30秒。直到实例,服务器和客户端在其本地缓存中都具有相同的元数据之前,客户端才可以使用该服务(因此,可能需要3个监听信号)。您可以使用更改时间段eureka.instance.leaseRenewalIntervalInSeconds,这将加快使客户端连接到其他服务的过程。在生产环境中,最好使用默认值,因为服务器内部存在一些计算,它们会假定租约续订期限。
服务发现:Eureka服务器
尤里卡服务器示例(例如,使用spring-cloud-starter-eureka-server设置类路径):
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
该服务器具有一个带UI的主页,以及根据常规Eureka功能的HTTP API端点/eureka/*。
尤里卡背景阅读:请参阅磁通电容器和Google小组讨论。
TIP 由于Gradle的依赖关系解决规则以及缺乏父bom功能,仅依赖
spring-cloud-starter-eureka-server可能会导致应用程序启动失败。
为了解决这个问题,必须添加Spring依赖管理插件,并且必须像
这样导入Spring Cloud Starter父Bom:
build.gradle
buildscript {
dependencies {
classpath “io.spring.gradle:dependency-management-plugin:0.4.0.RELEASE”
}
}
apply plugin: “io.spring.dependency-management”
dependencyManagement {
imports {
mavenBom ‘org.springframework.cloud:spring-cloud-starter-parent:1.0.0.RELEASE’
}
}
高可用性,区域和区域
Eureka服务器没有后端存储,但是注册表中的所有服务实例都必须发送心跳信号以使其注册保持最新(因此可以在内存中完成)。客户端还具有一个尤里卡注册的内存缓存(因此,对于每个对服务的单个请求,他们都不必去注册表)。
默认情况下,每个Eureka服务器也是Eureka客户端,并且需要(至少一个)服务URL来定位对等方。如果您不提供该服务,则该服务将运行并运行,但是它将使您的日志泛滥成灾,无法与对等方注册。
另请参阅以下有关客户端对区域和区域的功能区支持的详细信息。
独立模式
只要有某种监视器或灵活的运行时(例如Cloud Foundry),两个缓存(客户端和服务器)和心跳的组合就可以使独立的Eureka服务器对故障具有相当的弹性。在独立模式下,您可能希望关闭客户端行为,因此它不会继续尝试并无法到达其对等端。例:
application.yml(独立式Eureka服务器)
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://
e
u
r
e
k
a
.
i
n
s
t
a
n
c
e
.
h
o
s
t
n
a
m
e
:
{eureka.instance.hostname}:
eureka.instance.hostname:{server.port}/eureka/
请注意,serviceUrl指向与本地实例相同的主机。
同行意识
通过运行多个实例并要求它们相互注册,可以使Eureka更具弹性并可以使用。实际上,这是默认行为,因此,要使它起作用,您需要做的就是serviceUrl向对等方添加一个有效值,例如
application.yml(两个对等的Eureka服务器)
spring:
profiles: peer1
eureka:
instance:
hostname: peer1
client:
serviceUrl:
defaultZone: http://peer2/eureka/
spring:
profiles: peer2
eureka:
instance:
hostname: peer2
client:
serviceUrl:
defaultZone: http://peer1/eureka/
在此示例中,我们有一个YAML文件,通过在不同的Spring配置文件中运行该服务器,可以在2台主机(peer1和peer2)上运行同一服务器。您可以使用此配置通过操作/etc/hosts解析主机名来测试单个主机上的对等感知(在生产环境中这样做没有太大价值)。实际上,eureka.instance.hostname如果您在知道其主机名的计算机上运行(java.net.InetAddress默认情况下使用它来查找),则不需要 。
您可以将多个对等方添加到系统中,并且只要它们均通过至少一个边缘彼此连接,它们便会在彼此之间同步注册。如果对等方在物理上分开(在一个数据中心内部或在多个数据中心之间),则该系统原则上可以解决裂脑型故障。
首选IP地址
在某些情况下,尤里卡(Eureka)最好公布服务的IP地址而不是主机名。设置eureka.instance.preferIpAddress 为true,当应用程序向eureka注册时,它将使用其IP地址而不是其主机名。
断路器:Hystrix客户
Netflix创建了一个名为Hystrix的库,该库实现了断路器模式。在微服务架构中,通常有多个服务调用层。
图1.微服务图
较低级别的服务中的服务故障可能会导致级联故障,直至用户。当对特定服务的呼叫达到某个阈值时(Hystrix中默认在5秒钟内出现20次故障),电路将断开并且不会进行呼叫。在错误和断路的情况下,开发人员可以提供备用功能。
图2. Hystrix后备可防止级联故障
开路可以停止级联故障,并让不堪重负或服务故障的时间得到修复。回退可以是另一个受Hystrix保护的调用,静态数据或理智的空值。可能会链接回退,因此第一个回退会进行其他一些业务调用,从而又回退到静态数据。
引导应用示例:
@SpringBootApplication
@EnableCircuitBreaker
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
@Component
public class StoreIntegration {
@HystrixCommand(fallbackMethod = "defaultStores")
public Object getStores(Map<String, Object> parameters) {
//do stuff that might fail
}
public Object defaultStores(Map<String, Object> parameters) {
return /* something useful */;
}
}
这@HystrixCommand是由一个名为“ javanica”的Netflix contrib库提供的 。Spring Cloud会自动将带有该批注的Spring bean包装在连接到Hystrix断路器的代理中。断路器计算何时断开和闭合电路,以及在发生故障时应采取的措施。
要配置,@HystrixCommand您可以将commandProperties 属性与@HystrixProperty注释列表一起使用。有关 更多详细信息,请参见 此处。有关 可用属性的详细信息,请参见Hystrix Wiki。
传播安全上下文或使用Spring Scope
如果您希望将某些线程本地上下文传播到@HystrixCommand默认值,则默认声明将不起作用,因为它会在线程池中执行命令(如果超时)。您可以通过使用某些配置将Hystrix切换为使用与调用方相同的线程,或者直接在批注中通过要求它使用不同的“隔离策略”。例如:
@HystrixCommand(fallbackMethod = “stubMyService”,
commandProperties = {
@HystrixProperty(name=“execution.isolation.strategy”, value=“SEMAPHORE”)
}
)
…
如果您使用@SessionScope或,则同样适用@RequestScope。您会知道什么时候需要执行此操作,因为发生了运行时异常,表明它找不到范围内的上下文。
健康指标
连接的断路器的状态也/health显示在调用应用程序的 端点中。
{
“hystrix”: {
“openCircuitBreakers”: [
“StoreIntegration::getStoresByLocationLink”
],
“status”: “CIRCUIT_OPEN”
},
“status”: “UP”
}
Hystrix指标流
要启用Hystrix指标流,请包括对的依赖spring-boot-starter-actuator。这会将公开/hystrix.stream为管理端点。
org.springframework.boot
spring-boot-starter-actuator
断路器:Hystrix仪表板
Hystrix的主要优点之一是它收集的有关每个HystrixCommand的一组度量。Hystrix仪表板以有效的方式显示每个断路器的运行状况。
图3. Hystrix仪表板
要运行Hystrix仪表板,请使用注释您的Spring Boot主类@EnableHystrixDashboard。然后/hystrix,您访问并将仪表板指向/hystrix.streamHystrix客户端应用程序中的单个实例端点。
涡轮
查看单个实例Hystrix数据对于系统的整体运行状况不是很有用。Turbine是一种将所有相关/hystrix.stream端点聚合到一起的应用程序,可/turbine.stream在Hystrix仪表板中使用。个别实例通过Eureka定位。运行Turbine就像用注释对主类进行@EnableTurbine注释一样简单(例如,使用spring-cloud-starter-turbine设置类路径)。Turbine 1 Wiki中记录的所有配置属性均适用。唯一的区别是turbine.instanceUrlSuffix不需要端口,因为除非,否则端口会自动处理turbine.instanceInsertPort=false。
配置密钥turbine.appConfig是涡轮将用于查找实例的eureka serviceId的列表。然后,在Hystrix仪表板中使用如下形式的URL使用涡轮机流:(https://my.turbine.sever:8080/turbine.stream?cluster=;如果名称为“ default”,则可以省略cluster参数)。该cluster参数必须项匹配turbine.aggregator.clusterConfig。从eureka返回的值是大写的,因此,如果在Eureka上注册了一个名为“ customers”的应用程序,则我们希望本示例可以工作:
涡轮:
聚合器:
clusterConfig:客户
appConfig:客户
所述clusterName可以通过SPEL表达定制turbine.clusterNameExpression与根的一个实例InstanceInfo。默认值为appName,这意味着Eureka serviceId最终以集群键结尾(即InstanceInfofor客户appName的“ CUSTOMERS”)。一个不同的示例是turbine.clusterNameExpression=aSGName,它将从AWS ASG名称获得集群名称。另一个例子:
涡轮:
聚合器:
clusterConfig:SYSTEM,USER
appConfig:客户,商店,用户界面,管理员
clusterNameExpression:元数据[‘cluster’]
在这种情况下,来自4个服务的群集名称将从其元数据映射中拉出,并且应具有包含“ SYSTEM”和“ USER”的值。
要将“默认”集群用于所有应用,您需要一个字符串文字表达式(带单引号):
涡轮:
appConfig:客户,商店
clusterNameExpression:‘默认’
Spring Cloud提供了一个spring-cloud-starter-turbine具有运行Turbine服务器所需的所有依赖项。只需创建一个Spring Boot应用程序并使用对其进行注释@EnableTurbine。
涡轮AMQP
在某些环境中(例如,在PaaS设置中),从所有分布式Hystrix命令中提取指标的经典Turbine模型不起作用。在这种情况下,您可能想让Hystrix命令将指标推送到Turbine,而Spring Cloud通过AMQP消息传递来启用它。您需要在客户端上做的就是添加一个依赖项,spring-cloud-netflix-hystrix-amqp并确保有Rabbit代理可用(有关如何配置客户端凭据的详细信息,请参见Spring Boot文档,但是对于本地代理或本地代理,它应该是开箱即用的)。在Cloud Foundry中)。
在服务器端,只需创建一个Spring Boot应用程序并对其进行注释@EnableTurbineAmqp,默认情况下它将出现在端口8989上(将Hystrix仪表板指向该端口,任何路径)。您可以使用server.port或来定制端口turbine.amqp.port。如果你有spring-boot-starter-web和spring-boot-starter-actuator在类路径中,那么你可以通过提供打开一个单独的端口(和Tomcat默认情况下)对执行机构的端点management.port是不同的。
然后,您可以将Hystrix仪表板而不是单个Hystrix流指向Turbine AMQP服务器。如果Turbine AMQP在myhost的端口8989上运行,则将其放入http://myhost:8989Hystrix仪表板的流输入字段中。电路将以其各自的serviceId开头,后跟一个点,然后是电路名称。
Spring Cloud提供了一个spring-cloud-starter-turbine-amqp具有运行Turbine AMQP服务器所需的所有依赖项。您需要Java 8才能运行该应用程序,因为它是基于Netty的。
自定义AMQP ConnectionFactory
如果您使用的是AMQP,则ConnectionFactory在应用程序上下文中需要一个(来自Spring Rabbit)。如果只有一个ConnectionFactory,则使用它;或者,如果有一个 @HystrixConnectionFactory(在客户端上)和@TurbineConnectionFactory(在服务器上)具有以下条件,则它将优先于其他,否则@Primary将使用它。如果有多个不合格的连接工厂,则会出现错误。
需要注意的是启动春季(如1.2.2)创建了一个ConnectionFactory是不是 @Primary,所以如果你想使用总线一个连接工厂和其他业务的消息,您需要同时创建,并注释他们@ConnectionFactory和@Primary分别。
客户端负载均衡器:功能区
Ribbon是客户端负载平衡器,它使您可以对HTTP和TCP客户端的行为进行大量控制。Feign已经使用了Ribbon,因此如果您正在使用,@FeignClient则本节也适用。
Ribbon中的中心概念是指定客户端的概念。每个负载平衡器都是组件的一部分,这些组件可以一起工作以按需联系远程服务器,并且该组件具有一个名称,您可以将其命名为应用程序开发人员(例如,使用@FeignClient 批注)。Spring Cloud ApplicationContext使用来为每个命名客户端按需 创建一个新集合 RibbonClientConfiguration。这包含(除其他事项外)an ILoadBalancer,a RestClient和a ServerListFilter。
自定义功能区客户端
您可以使用中的外部属性来配置Ribbon客户端的某些位.ribbon.,这与本机使用Netflix API没什么不同,除了可以使用Spring Boot配置文件。可以将本机选项检查为CommonClientConfigKey(功能区核心的一部分)中的静态字段。
Spring Cloud还允许您通过使用声明其他配置(位于之上RibbonClientConfiguration)来完全控制客户端@RibbonClient。例:
@Configuration
@RibbonClient(name = “foo”, configuration = FooConfiguration.class)
public class TestConfiguration {
}
在这种情况下,客户端由已包含的组件RibbonClientConfiguration以及任何组件组成 FooConfiguration (其中后者通常会覆盖前者)。
警告 在FooConfiguration必须@Configuration,但要小心,它是不是在
@ComponentScan主应用程序上下文,否则会被所有的共享@RibbonCli
ents。如果您使用@ComponentScan(或@SpringBootApplication),
则需要采取措施避免将其包括在内(例如,将其放在单独的,不重叠的程序
包中,或者在中指定要扫描的程序包@ComponentScan)。
Spring Cloud Netflix默认为功能区(BeanTypebeanName:)提供以下bean ClassName:
• IClientConfig ribbonClientConfig: DefaultClientConfigImpl
• IRule ribbonRule: ZoneAvoidanceRule
• IPing RibbonPing: NoOpPing
• ServerList ribbonServerList: ConfigurationBasedServerList
• ServerListFilter ribbonServerListFilter: ZonePreferenceServerListFilter
• ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer
创建这些类型之一的bean并将其放置在@RibbonClient 配置中(例如FooConfiguration上述配置),您可以覆盖所描述的每个bean。例:
@Configuration
public class FooConfiguration {
@Bean
public IPing ribbonPing(IClientConfig config) {
return new PingUrl();
}
}
这将替换NoOpPing用PingUrl。
将功能区与Eureka一起使用
当Eureka与Ribbon结合使用时ribbonServerList ,DiscoveryEnabledNIWSServerList 它将被覆盖,其扩展名将填充Eureka中的服务器列表。它也取代了 IPing用接口NIWSDiscoveryPing委托给尤里卡以确定服务器是否已启动。该ServerList由默认安装的是一个DomainExtractingServerList和这样做的目的是使身体的元数据提供给负载平衡器,而无需使用AWS AMI元数据(这是Netflix的依赖)。默认情况下,服务器列表将使用实例元数据中提供的“区域”信息(在客户机集上eureka.instance.metadataMap.zone)构造 ,并且,如果缺少该列表,则可以使用服务器主机名中的域名作为区域的代理(如果标志approximateZoneFromHostname已设置)。一旦区域信息可用,就可以在ServerListFilter(默认情况下,它将用于在与客户端相同的区域中定位服务器,因为默认值为a ZonePreferenceServerListFilter)。
示例:如何在没有尤里卡的情况下使用色带
Eureka是一种抽象发现远程服务器的便捷方法,因此您不必在客户端中对它们的URL进行硬编码,但是如果您不愿意使用它,Ribbon和Feign仍然很合适。假设您@RibbonClient为“ stores” 声明了a ,并且Eureka未被使用(甚至不在类路径上)。Ribbon客户端默认为已配置的服务器列表,您可以提供如下配置
application.yml
stores:
ribbon:
listOfServers: example.com,google.com
示例:禁止在功能区中使用尤里卡
设置该属性ribbon.eureka.enabled = false将显式禁用Ribbon中的Eureka。
application.yml
ribbon:
eureka:
enabled: false
直接使用功能区API
您也可以LoadBalancerClient直接使用。例:
public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}
声明式REST客户端:伪装
Feign是声明性Web服务客户端。它使编写Web服务客户端更加容易。要使用Feign,请创建一个接口并对其进行注释。它具有可插入的注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud添加了对Spring MVC注释的支持,并支持使用HttpMessageConvertersSpring Web中默认使用的注释。当使用Feign时,Spring Cloud集成了Ribbon和Eureka以提供负载平衡的http客户端。
春季启动应用程序示例
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
StoreClient.java
@FeignClient(“stores”)
public interface StoreClient {
@RequestMapping(method = RequestMethod.GET, value = “/stores”)
List getStores();
@RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
}
在@FeignClient注释中,String值(上面的“ stores”)是一个任意的客户端名称,用于创建Ribbon负载均衡器(请参见下面的Ribbon支持的详细信息)。您也可以使用url属性(绝对值或仅主机名)指定URL 。
上面的功能区客户端将要发现“商店”服务的物理地址。如果您的应用程序是Eureka客户端,则它将在Eureka服务注册表中解析该服务。如果您不想使用Eureka,则可以在外部配置中简单地配置服务器列表(例如,参见 )。
覆盖伪默认
Spring Cloud的Feign支持中的中心概念是指定客户端的概念。每个虚拟客户端都是组件集合的一部分,这些组件可以一起工作以按需联系远程服务器,并且该集合的名称是您使用@FeignClient注释作为应用程序开发人员提供的。Spring Cloud ApplicationContext使用来为每个命名客户端按需创建一个新集合 FeignClientsConfiguration。这包含(除其他事项外)an feign.Decoder,a feign.Encoder和a feign.Contract。
Spring Cloud,您可以通过声明额外的配置(在顶部取佯客户端的完全控制FeignClientsConfiguration使用)@FeignClient。例:
@FeignClient(name = “stores”, configuration = FooConfiguration.class)
public interface StoreClient {
//…
}
在这种情况下,客户端由已包含的组件FeignClientsConfiguration和任何包含的组件组成FooConfiguration(后者将覆盖前者)。
警告 在FooConfiguration必须@Configuration,但要小心,它是不是在
@ComponentScan主应用程序上下文,否则将被用于每个@FeignClient。
如果您使用@ComponentScan(或@SpringBootApplication),则需要
采取措施避免将其包括在内(例如,将其放在单独的,不重叠的程序包中,
或者在中指定要扫描的程序包@ComponentScan)。
注意 serviceId现在不推荐使用 该属性,而推荐使用该name属性。
警告 以前,使用url属性不需要name属性。name现在需要使用。
name和url属性中支持占位符。
@FeignClient(name = “
f
e
i
g
n
.
n
a
m
e
"
,
u
r
l
=
"
{feign.name}", url = "
feign.name",url="{feign.url}”)
public interface StoreClient {
//…
}
Spring Cloud Netflix默认为伪装提供以下bean(BeanTypebeanName:)ClassName:
• DecoderfeignDecoder :(ResponseEntityDecoder包含SpringDecoder)
• Encoder feignEncoder: SpringEncoder
• Logger feignLogger: Slf4jLogger
• Contract feignContract: SpringMvcContract
• Feign.Builder feignBuilder: HystrixFeign.Builder
默认情况下,Spring Cloud Netflix 不会为伪装提供以下bean,但仍会从应用程序上下文中查找这些类型的bean以创建伪装客户端:
• Logger.Level
• Retryer
• ErrorDecoder
• Request.Options
• Collection
创建这些类型之一的bean并将其放置在@FeignClient配置中(例如FooConfiguration上述配置),您可以覆盖所描述的每个bean。例:
@Configuration
public class FooConfiguration {
@Bean
public Contract feignContractg() {
return new feign.Contract.Default();
}
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("user", "password");
}
}
替换为SpringMvcContract,并向的集合feign.Contract.Default添加。RequestInterceptorRequestInterceptor
可以按照与上述类似的方式在@EnableFeignClients属性defaultConfiguration中指定默认配置。不同之处在于此配置将适用于所有伪客户端。
Feign Hystrix支持
如果Hystrix在类路径中,则默认情况下,Feign将使用断路器包装所有方法。com.netflix.hystrix.HystrixCommand还可以返回a 。这允许您使用反应模式(与以打电话.toObservable()或.observe()或异步使用(通过调用.queue())。
要禁用对Feign的Hystrix支持,请设置feign.hystrix.enabled=false。
要基于每个客户端禁用Hystrix支持,请创建Feign.Builder具有“原型”范围的香草,例如:
@Configuration
public class FooConfiguration {
@Bean
@Scope(“prototype”)
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
假装Hystrix后备
Hystrix支持回退的概念:当它们的电路断开或出现错误时执行的默认代码路径。要为给定@FeignClient集启用后备,该fallback属性应为实现后备的类名称。
@FeignClient(name = “hello”, fallback = HystrixClientFallback.class)
protected interface HystrixClient {
@RequestMapping(method = RequestMethod.GET, value = “/hello”)
Hello iFailSometimes();
}
static class HystrixClientFallback implements HystrixClient {
@Override
public Hello iFailSometimes() {
return new Hello(“fallback”);
}
}
警告 Feign中的后备实现以及Hystrix后备如何工作存在局限性。目前,
返回com.netflix.hystrix.HystrixCommand和的方法不支持
后备rx.Observable。
假继承支持
Feign通过单继承接口支持样板API。这允许将常用操作分组为方便的基本接口。与Spring MVC一起,您可以为REST端点和Feign客户端共享同一合约。
UserService.java
public interface UserService {
@RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
User getUser(@PathVariable("id") long id);
}
UserResource.java
@RestController
public class UserResource implements UserService {
}
UserClient.java
package project.user;
@FeignClient(“users”)
public interface UserClient extends UserService {
}
伪装请求/响应压缩
您可以考虑为您的Feign请求启用请求或响应GZIP压缩。您可以通过启用以下属性之一来做到这一点:
feign.compression.request.enabled=true
feign.compression.response.enabled=true
伪装请求压缩为您提供的设置类似于您为Web服务器设置的设置:
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
这些属性使您可以选择压缩媒体类型和最小请求阈值长度。
伪装伐木
为每个创建的Feign客户端创建一个记录器。默认情况下,记录器的名称是用于创建Feign客户端的接口的全类名称。伪日志仅响应该DEBUG级别。
application.yml
logging.level.project.user.UserClient: DEBUG
Logger.Level您可以为每个客户端配置的对象告诉Feign要记录多少。选择是:
• NONE,不记录(DEFAULT)。
• BASIC,仅记录请求方法和URL以及响应状态代码和执行时间。
• HEADERS,记录基本信息以及请求和响应标头。
• FULL,记录请求和响应的标题,正文和元数据。
例如,以下将将设置Logger.Level为FULL:
@Configuration
public class FooConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
外部配置:Archaius
Archaius是Netflix客户端配置库。它是所有Netflix OSS组件用于配置的库。Archaius是Apache Commons Configuration项目的扩展。它可以通过轮询源更改或源将更改推送到客户端来更新配置。Archaius使用Dynamic Property类作为属性的句柄。
Archaius示例
class ArchaiusTest {
DynamicStringProperty myprop = DynamicPropertyFactory
.getInstance()
.getStringProperty(“my.prop”);
void doSomething() {
OtherClass.someMethod(myprop.get());
}
}
Archaius具有自己的一组配置文件和加载优先级。Spring应用程序通常不应该直接使用Archaius,但是仍然需要本地配置Netflix工具。Spring Cloud具有Spring Environment Bridge,因此Archaius可以从Spring Environment中读取属性。如此一来,Spring Boot项目就可以使用常规配置工具链,同时允许它们在很大程度上配置Netflix工具,如文档所述。
路由器和过滤器:Zuul
在微服务架构的组成部分中进行路由。例如,/可能被映射到您的Web应用程序,/api/users被映射到用户服务以及/api/shop被映射到商店服务。Zuul是Netflix提供的基于JVM的路由器和服务器端负载平衡器。
Netflix将Zuul用于以下用途:
• 认证方式
• 见解
• 压力测试
• 金丝雀测试
• 动态路由
• 服务迁移
• 减载
• 安全
• 静态响应处理
• 主动/主动流量管理
Zuul的规则引擎允许规则和过滤器基本上以任何JVM语言编写,并内置对Java和Groovy的支持。
嵌入式Zuul反向代理
Spring Cloud创建了一个嵌入式Zuul代理,以简化一个UI应用程序想要代理对一个或多个后端服务的调用的非常常见用例的开发。此功能对于用户界面代理所需的后端服务很有用,从而避免了为所有后端独立管理CORS和身份验证问题的需求。
要启用它,请使用注释一个Spring Boot主类 @EnableZuulProxy,这会将本地调用转发到适当的服务。按照约定,具有Eureka ID“用户”的服务将接收来自位于/users(前缀已去除)的代理的请求。代理使用Ribbon通过Eureka定位要转发的实例,并且所有请求均在hystrix命令中执行,因此故障将显示在Hystrix指标中,并且一旦电路断开,代理将不会尝试与服务联系。
要跳过自动添加服务的步骤,请设置 zuul.ignored-services为服务ID模式列表。如果服务与被忽略的模式匹配,但也包含在显式配置的路由映射中,则它将被忽略。例:
application.yml
zuul:
ignoredServices: ‘*’
routes:
users: /myusers/**
在此示例中,除 “用户” 外,所有服务均被忽略。
要扩充或更改代理路由,您可以添加外部配置,如下所示:
application.yml
zuul:
routes:
users: /myusers/**
这意味着将对“ / myusers”的http调用转发到“用户”服务(例如,“ / myusers / 101”转发到“ / 101”)。
要对路由进行更细粒度的控制,可以单独指定路径和serviceId:
application.yml
zuul:
routes:
users:
path: /myusers/**
serviceId: users_service
这意味着对“ / myusers”的http调用将转发到“ users_service”服务。路由必须具有“路径”,可以将其指定为蚂蚁样式模式,因此“ / myusers / ”仅匹配一个级别,而“ / myusers / {asterisk} {asterisk}”则分层匹配。
后端的位置可以指定为“ serviceId”(对于Eureka服务)或“ url”(对于物理位置),例如
application.yml
zuul:
routes:
users:
path: /myusers/*
url: https://example.com/users_service
这些简单的url-routes不会作为HystrixCommand执行,也无法使用Ribbon来负载均衡多个url。为此,请指定一条服务路由并为serviceId配置一个Ribbon客户端(当前需要在Ribbon中禁用Eureka支持:有关更多信息,请参见上文),例如
application.yml
zuul:
routes:
users:
path: /myusers/**
serviceId: users
ribbon:
eureka:
enabled: false
users:
ribbon:
listOfServers: example.com,google.com
您可以使用regexmapper在serviceId和路由之间提供约定。它使用名为group的正则表达式从serviceId中提取变量,并将其注入到路由模式中。
ApplicationConfiguration.java
@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
return new PatternServiceRouteMapper(
“(?^.+)-(?v.+
)
"
,
"
)", "
)","{version}/${name}”);
}
这意味着serviceId“ myusers-v1”将映射到路由“ / v1 / myusers / {asterisk} {asterisk}”。可以接受任何正则表达式,但所有已命名的组都必须同时存在于servicePattern和routePattern中。如果servicePattern与serviceId不匹配,则使用默认行为。在上面的示例中,serviceId“ myusers”将映射到路由“ / myusers / {asterisk} {asterisk}”(未检测到版本)这些功能默认情况下处于禁用状态,仅应用于发现的服务。
要为所有映射添加前缀,请设置zuul.prefix一个值,例如 /api。默认情况下,在转发请求之前,先从请求中删除代理前缀(使用关闭此行为 zuul.stripPrefix=false)。您还可以从单个路由中关闭对特定于服务的前缀的剥离,例如
application.yml
zuul:
routes:
users:
path: /myusers/**
stripPrefix: false
在此示例中,对“ / myusers / 101”的请求将转发到“用户”服务上的“ / myusers / 101”。
这些zuul.routes条目实际上绑定到类型的对象ProxyRouteLocator。如果查看该对象的属性,将会看到它也具有“可重试”标志。将该标志设置为“ true”以使Ribbon客户端自动重试失败的请求(如果需要,您可以使用Ribbon客户端配置来修改重试操作的参数)。
X-Forwarded-Host默认情况下,标头已添加到转发的请求中。要关闭它,请设置zuul.addProxyHeaders = false。默认情况下会删除前缀路径,并且后端请求将选择标头“ X-Forwarded-Prefix”(在上面的示例中为“ / myusers”)。
@EnableZuulProxy如果您设置了默认路由(“ /”),则带有的应用程序可以充当独立服务器,例如,zuul.route.home: /将所有流量(即“ / {asterisk} {asterisk}”)路由到“ home”服务。
如果需要更细粒度的忽略,则可以指定要忽略的特定模式。这些样式将在路线定位过程开始时进行评估,这意味着样式中应包含前缀以保证匹配。被忽略的模式跨越所有服务,并取代任何其他路由规范。
application.yml
zuul:
ignoredPatterns: //admin/
routes:
users: /myusers/**
这意味着诸如“ / myusers / 101”之类的所有调用都将被转发到“用户”服务上的“ / 101”。但是包括“ / admin /”在内的调用将无法解决。
勒索模式和本地前锋
迁移现有应用程序或API时,常见的模式是“勒死”旧的端点,并用不同的实现方式慢慢替换它们。Zuul代理是一个有用的工具,因为您可以使用它来处理来自旧端点客户端的所有流量,但可以将某些请求重定向到新请求。
配置示例:
application.yml
zuul:
routes:
first:
path: /first/**
url: https://first.example.com
second:
path: /second/**
url: forward:/second
third:
path: /third/**
url: forward:/3rd
legacy:
path: /**
url: https://legacy.example.com
在此示例中,我们扼杀了“旧版”应用程序,该应用程序映射到与其他模式之一不匹配的所有请求。输入的路径/first/{asterisk}{asterisk}已使用外部URL提取到新服务中。并且/second/{asterisk}{asterisk}预先考虑了路径,因此可以在本地处理它们,例如,使用常规Spring @RequestMapping。中的路径 /third/{asterisk}{asterisk}也被转发,但是具有不同的前缀(即/third/foo转发到/3rd/foo)。
注意 被忽略的样式不会被完全忽略,它们不会由代理处理(因此它们也可以在
本地有效转发)。
通过Zuul上传文件
如果您@EnableZuulProxy可以使用代理路径上传文件,并且只要文件很小,它就可以正常工作。对于大文件DispatcherServlet,“ / zuul / ”中有一个替代路径绕过Spring (以避免进行多部分处理)。也就是说,如果zuul.routes.customers=/customers/{asterisk}{asterisk}可以,则可以将大文件发布到“ / zuul / customers / ”。servlet路径通过外部化zuul.servletPath。如果代理路由带您通过功能区负载平衡器,则极大的文件也需要提高超时设置,例如
application.yml
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
请注意,要使流式传输与大文件一起使用,您需要在请求中使用分块编码(某些浏览器默认情况下不这样做)。例如在命令行上:
$ curl -v -H “Transfer-Encoding: chunked”
-F “file=@mylarge.iso” localhost:9999/zuul/simple/file
纯色嵌入式Zuul
您也可以在不使用代理的情况下运行Zuul服务器,或者使用@EnableZuulServer(而不是@EnableZuulProxy)有选择地打开代理平台的某些部分。您添加到类型应用程序中的所有bean ZuulFilter 都会自动安装,与一样@EnableZuulProxy,但是不会自动添加任何代理过滤器。
在这种情况下,仍然可以通过配置“ zuul.routes。”来指定进入Zuul服务器的路由,但是由于没有发现服务也没有代理,因此将忽略“ serviceId”和“ url”设置。例如:
application.yml
zuul:
routes:
api: /api/*
将“ / api / {asterisk} {asterisk}”中的所有路径映射到Zuul过滤器链。
禁用Zuul过滤器
Zuul for Spring Cloud随附了许多ZuulFilter在代理和服务器模式下默认启用的Bean。请参阅zuul过滤器包,以了解可能启用的过滤器。如果要禁用一个,只需设置 zuul...disable=true。按照惯例,后面的包filters是Zuul过滤器类型。例如禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFiltersetzuul.SendResponseFilter.post.disable=true。
Sidecar支持多语种
您是否要使用非jvm语言来利用Eureka,Ribbon和Config Server?Spring Cloud Netflix Sidecar的灵感来自 Netflix Prana。它包括一个简单的http api,用于获取给定服务的所有实例(即主机和端口)。您也可以通过嵌入式Zuul代理来代理服务呼叫,该代理从Eureka获取其路由条目。可以通过主机查找或通过Zuul代理直接访问Spring Cloud Config Server。非jvm应用程序应执行运行状况检查,以便Sidecar可以在应用程序启动或关闭时向eureka报告。
要启用Sidecar,请使用创建一个Spring Boot应用程序@EnableSidecar。这个注解包括@EnableCircuitBreaker,@EnableDiscoveryClient,和@EnableZuulProxy。在与非jvm应用程序相同的主机上运行结果应用程序。
要配置车边加sidecar.port和sidecar.health-uri来application.yml。该sidecar.port属性是非jvm应用程序正在侦听的端口。这样,Sidecar可以在Eureka上正确注册该应用程序。这sidecar.health-uri 是在非jvm应用程序上可访问的uri,它模仿Spring Boot运行状况指示器。它应该返回如下的json文档:
health-uri-document
{
“status”:“UP”
}
这是Sidecar应用程序的示例application.yml:
application.yml
server:
port: 5678
spring:
application:
name: sidecar
sidecar:
port: 8000
health-uri: http://localhost:8000/health.json
该DiscoveryClient.getInstances()方法的api 是/hosts/{serviceId}。这是一个示例响应,/hosts/customers该响应返回不同主机上的两个实例。非jvm应用程序(如果sidecar位于端口5678上)可通过访问此api http://localhost:5678/hosts/{serviceId}。
/主机/客户
[
{
“host”: “myhost”,
“port”: 9000,
“uri”: “http://myhost:9000”,
“serviceId”: “CUSTOMERS”,
“secure”: false
},
{
“host”: “myhost2”,
“port”: 9000,
“uri”: “http://myhost2:9000”,
“serviceId”: “CUSTOMERS”,
“secure”: false
}
]
Zuul代理会自动将eureka中已知的每个服务的路由添加到 /,因此可以在上使用客户服务/customers。Non-jvm应用程序可以通过访问访问客户服务http://localhost:5678/customers (假设Sidecar正在监听5678端口)。
如果Config Server已向Eureka注册,则非jvm应用程序可以通过Zuul代理对其进行访问。如果ConfigServer的serviceId为configserver 并且Sidecar在端口5678上,则可以在http:// localhost:5678 / configserver上对其进行访问
非jvm应用程序可以利用Config Server返回YAML文档的功能。例如,调用https://sidecar.local.spring.io:5678/configserver/default-master.yml 可能会导致生成YAML文档,如下所示
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
password: password
info:
description: Spring Cloud Samples
url: https://github.com/spring-cloud-samples
指标:观众,伺服和地图集
当一起使用时,Spectator / Servo和Atlas提供了近实时的操作洞察平台。
Spectator和Servo是Netflix的指标收集库。Atlas是Netflix指标后端,用于管理维度时间序列数据。
Servo为Netflix服务了好几年了,并且仍然可以使用,但是逐渐被Spectator淘汰,而Spectator只能与Java 8一起使用。SpringCloud Netflix为这两者提供了支持,但是鼓励基于Java 8的应用程序使用Spectator 。
维度指标与分层指标
Spring Boot Actuator指标是分层的,指标仅按名称分隔。这些名称通常遵循一种命名约定,该约定将键/值属性对(维度)嵌入由句点分隔的名称中。请考虑以下两个端点(根和星形)的度量标准:
{
“counter.status.200.root”: 20,
“counter.status.400.root”: 3,
“counter.status.200.star-star”: 5,
}
第一个度量为我们提供了单位时间针对根端点的成功请求的标准化计数。但是,如果系统有20个端点,并且您希望针对所有端点获得成功请求的计数,该怎么办?某些分层指标后端允许您指定通配符,例如将读取所有20个指标并汇总结果。另外,您可以提供一个像所有成功请求一样拦截和记录指标的方法,而与端点无关,但是现在您必须编写20 + 1个不同的指标。同样,如果您想知道服务中所有端点的成功请求总数,则可以指定通配符,例如。counter.status.200.HandlerInterceptorAdaptercounter.status.200.allcounter.status.2.*
即使在分层指标后端具有通配符支持,命名一致性也可能很困难。具体来说,这些标签在名称字符串中的位置会随着时间推移而滑动,从而中断查询。例如,假设我们为上述HTTP方法的层次结构指标添加了一个附加维度。然后counter.status.200.root变为counter.status.200.method.get.root等。我们的counter.status.200.*突然之间不再具有相同的语义。此外,如果新维度未在整个代码库中统一应用,则某些查询可能变得不可能。这样很快就会失控。
Netflix指标已标记(又称维度)。每个度量都有一个名称,但是这个单一的命名度量可以包含多个统计信息和“标记”键/值对,从而提供更大的查询灵活性。实际上,统计信息本身记录在特殊标记中。
用Netflix Servo或Spectator记录的上述根端点的计时器每个状态码包含4个统计信息,其中计数统计信息与Spring Boot Actuator的计数器相同。到目前为止,如果遇到HTTP 200和400,将有8个可用数据点:
{
“root(status=200,stastic=count)”: 20,
“root(status=200,stastic=max)”: 0.7265630630000001,
“root(status=200,stastic=totalOfSquares)”: 0.04759702862580789,
“root(status=200,stastic=totalTime)”: 0.2093076914666667,
“root(status=400,stastic=count)”: 1,
“root(status=400,stastic=max)”: 0,
“root(status=400,stastic=totalOfSquares)”: 0,
“root(status=400,stastic=totalTime)”: 0,
}
默认指标集合
无需任何其他依赖项或配置,基于Spring Cloud的服务将自动配置Servo,MonitorRegistry并开始针对每个Spring MVC请求收集指标。默认情况下,rest将为每个MVC请求记录一个名称为Servo的计时器,该计时器带有以下标记:
- HTTP方法
- HTTP状态(例如200、400、500)
- URI(如果URI为空,则为“ root”),已针对Atlas进行了清理
- 异常类名称,如果请求处理程序引发了异常
- 调用方(如果在请求netflix.metrics.rest.callerHeader上设置了具有键匹配的请求标头)。没有的默认密钥netflix.metrics.rest.callerHeader。如果要收集呼叫者信息,必须将其添加到应用程序属性中。
设置netflix.metrics.rest.metricName属性以将度量标准rest的名称从更改为您提供的名称。
如果启用了Spring AOP并org.aspectj:aspectjweaver在您的运行时类路径中提供了Spring AOP ,Spring Cloud还将在每次使用进行的客户端调用上收集指标RestTemplate。restclient对于每个带有标记的MVC请求,将记录一个名称为的伺服计时器。 - HTTP方法
- HTTP状态(例如200、400、500),如果响应返回null,则为“ CLIENT_ERROR”,如果IOException在执行RestTemplate方法期间发生响应,则为“ IO_ERROR”
- URI,已为Atlas消毒
- 客户名称
指标集合:旁观者
要启用观众指标,请包含以下项的依赖关系spring-boot-starter-spectator:
org.springframework.cloud
spring-cloud-starter-spectator
用旁观者的话来说,仪表是一种命名,键入和标记的配置,指标代表某个时间点给定仪表的值。观众仪表是由注册表创建和控制的,注册表目前有几种不同的实现方式。观众提供4种仪表类型:计数器,计时器,仪表和分配摘要。
Spring Cloud Spectator集成com.netflix.spectator.api.Registry为您配置了一个可注入实例。具体来说,它配置了一个ServoRegistry实例,以统一REST指标的集合以及在单个Servo API下将指标导出到Atlas后端的方式。实际上,这意味着您的代码可能会混合使用Servo监视器和Spectreator仪表,并且都将被Spring Boot Actuator MetricReader实例捕获,并且都将被发送到Atlas后端。
观众柜台
计数器用于测量某些事件发生的速率。
// create a counter with a name and a set of tags
Counter counter = registry.counter(“counterName”, “tagKey1”, “tagValue1”, …);
counter.increment(); // increment when an event occurs
counter.increment(10); // increment by a discrete amount
计数器记录单个时间标准化的统计信息。
旁观者计时器
计时器用于测量某个事件花费的时间。Spring Cloud自动记录Spring MVC请求和有条件的RestTemplate请求的计时器,这些计时器以后可用于为与请求相关的指标(例如延迟)创建仪表板:
请求延迟
图片:: RequestLatency.png []
// create a timer with a name and a set of tags
Timer timer = registry.timer(“timerName”, “tagKey1”, “tagValue1”, …);
// execute an operation and time it at the same time
T result = timer.record(() -> fooReturnsT());
// alternatively, if you must manually record the time
Long start = System.nanoTime();
T result = fooReturnsT();
timer.record(System.nanoTime() - start, TimeUnit.NANOSECONDS);
计时器同时记录4个统计信息:count,max,totalOfSquares和totalTime。如果您increment()每次记录一个定时都在计数器上调用一次,则计数统计将始终与计数器提供的单个归一化值相匹配,因此很少需要为单个操作分别计数和计时。
对于长时间运行的操作,旁观者提供了一种特殊的方法LongTaskTimer。
观众仪表
量规用于确定一些当前值,例如队列的大小或处于运行状态的线程数。由于量表是采样的,因此它们不提供有关这些值在样本之间如何波动的信息。
量规的正常使用包括在初始化时使用ID,对要采样的对象的引用以及基于该对象获取或计算数值的函数注册一次量规。对对象的引用将单独传递,并且Spectator注册表将保留对对象的弱引用。如果对象是垃圾回收,那么观众将自动删除注册。如果此API被滥用,请参阅Spectator文档中的注释,以了解潜在的内存泄漏。
// the registry will automatically sample this gauge periodically
registry.gauge(“gaugeName”, pool, Pool::numberOfRunningThreads);
// manually sample a value in code at periodic intervals – last resort!
registry.gauge(“gaugeName”, Arrays.asList(“tagKey1”, “tagValue1”, …), 1000);
观众分布摘要
分发摘要用于跟踪事件的分发。它与计时器类似,但是更通用,因为它的大小不必一定是一段时间。例如,分发摘要可用于衡量命中服务器的请求的有效负载大小。
// the registry will automatically sample this gauge periodically
DistributionSummary ds = registry.distributionSummary(“dsName”, “tagKey1”, “tagValue1”, …);
ds.record(request.sizeInBytes());
指标集合:伺服
警告 如果您的代码是在Java 8上编译的,请使用Spectator而不是Servo,
因为从长远来看Spectator注定要完全替代Servo。
用Servo的话来说,监视器是一种命名,键入和标记的配置,度量标准表示某个时间点给定监视器的值。伺服监视器在逻辑上等效于观众仪表。伺服监控器由来创建和控制MonitorRegistry。尽管有上述警告,但Servo确实比Spectator的仪表具有更多的显示器选项。
Spring Cloud集成com.netflix.servo.MonitorRegistry为您配置了一个可注入实例。一旦Monitor在Servo中创建了适当的类型,记录数据的过程便与Spectator完全相似。
创建伺服监视器
如果您使用的MonitorRegistry是Spring Cloud提供的Servo 实例(特别是的实例DefaultMonitorRegistry),则Servo提供了便利类来检索计数器和计时器。这些便利类确保Monitor名称和标签的每种唯一组合都只注册一个。
要在Servo中手动创建Monitor类型,尤其是对于不提供便捷方法的更特殊的Monitor类型,请通过提供MonitorConfig实例来实例化适当的类型:
MonitorConfig config = MonitorConfig.builder(“timerName”).withTag(“tagKey1”, “tagValue1”).build();
// somewhere we should cache this Monitor by MonitorConfig
Timer timer = new BasicTimer(config);
monitorRegistry.register(timer);
指标后端:地图集
Atlas由Netflix开发,用于管理维度时间序列数据,以实现近乎实时的运营洞察。Atlas具有内存中数据存储功能,可以快速收集和报告大量指标。
Atlas捕获运营情报。商业智能是为分析一段时间内的趋势而收集的数据,而运营智能则提供了系统中当前正在发生的情况的图片。
Spring Cloud提供了一个spring-cloud-starter-atlas具有您所需的所有依赖项的组件。然后,使用属性@EnableAtlas为Spring Boot应用程序添加注释,并为运行中的Atlas服务器提供一个位置netflix.atlas.uri。
全局标签
Spring Cloud使您可以向发送到Atlas后端的每个指标添加标签。全局标记可用于按应用程序名称,环境,区域等分隔度量。
每个实现的bean AtlasTagProvider将有助于全局标记列表:
@Bean
AtlasTagProvider atlasCommonTags(
@Value("${spring.application.name}") String appName) {
return () -> Collections.singletonMap(“app”, appName);
}
使用地图集
要引导内存中的独立Atlas实例,请执行以下操作:
$ curl -LO https://github.com/Netflix/atlas/releases/download/v1.4.2/atlas-1.4.2-standalone.jar
$ java -jar atlas-1.4.2-standalone.jar
TIP 在给定的6小时窗口内,运行在r3.2xlarge(61GB RAM)上的Atlas独立
节点可以每分钟处理大约200万个指标。
运行之后,您已经收集了一些指标,请通过在Atlas服务器上列出标签来验证设置是否正确:
$ curl http://ATLAS/api/v1/tags
TIP 在针对您的服务执行了多个请求之后,您可以通过将以下网址粘贴到浏览器
中来收集有关每个请求的请求延迟的一些非常基本的信息: http://ATLAS/api/v1/graph?q=name,rest,:eq,:avg
Atlas Wiki包含各种情况下的示例查询的汇编。
确保检查警报原理和有关使用双指数平滑生成动态警报阈值的文档。