SpringCloud学习-SpringCloudNetfix
Posted wu6660563
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud学习-SpringCloudNetfix相关的知识,希望对你有一定的参考价值。
Netfix组件是涵盖了构建大型分布式系统的一整套方案。提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载均衡(Ribbon)
服务发现:Eureka客户端
Netfix服务发现服务器和客户端都是Eureka,可以将服务器配置和部署为高可用性,每个服务器将注册服务的状态复制到其他服务器
- 通过使用
org.springframework.cloud
和spring-cloud-starter-eureka
的库 - Eureka从属于服务的每个实例接收心跳信息。如果心跳失败超过可配置的时间,直接从注册表删除。客户端加入
@EnableEurekaClient
,也可以使用@EnableDiscoveryClient
,但需要配置serviceUrl.defaultZone
,从Environment获取的默认应用程序名称(服务ID),虚拟主机和非安全端口分别为$spring.application.name
,$spring.application.name
和$server.port
Eureka进行身份验证
可以使用eureka.client.serviceUrl.defaultZone
加入凭证http://user:password@localhost:8761/eureka
状态页和健康指标
指定状态指标,如下:
eureka:
instance:
statusPageUrlPath: $management.context-path/info
healthCheckUrlPath: $management.context-path/health
注册安全应用程序
使用https,可以分别在EurekaInstanceConfig
,即eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]
eureka:
instance:
statusPageUrl: https://$eureka.hostname/info
healthCheckUrl: https://$eureka.hostname/health
homePageUrl: https://$eureka.hostname/
Eureka的健康检查
如果需要让Eureka自动检测心跳,可以把检测心跳设置为true
eureka:
client:
healthcheck:
enabled: true
如果需要更多的控制健康检测,可以实现接口com.netflix.appinfo.HealthCheckHandler
AWS云上部署Eureka
如果应用程序要部署到AWS云,必须配置为AWS可以识别到,可以通过EurekaInstanceConfigBean
@Bean
@Profile("!default")
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils)
EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(inetUtils);
AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka");
b.setDataCenterInfo(info);
return b;
如果Eureka实例注册了其主机相同的ID,可以如下配置
$spring.cloud.client.hostname:$spring.application.name:$spring.application.instance_id:$server.port
,如:myhost:myappname:8080
使用EurekaClient
一旦有通过@EnableDiscoveryClient
注解的程序,可以通过Eureka服务器发现服务实例。
@Autowired
private EurekaClient discoveryClient;
public String serviceUrl()
InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false);
return instance.getHomePageUrl();
注册的维持时间为30s,可以通过修改配置eureka.instance.leaseRenewalIntervalInSeconds
更改周期
服务发现:Eureka服务器
要使用Eureka服务器,使用group为org.springframework.cloud
和artifactId为spring-cloud-starter-eureka-server
运行Eureka服务器
@SpringBootApplication
@EnableEurekaServer
public class Application
public static void main(String[] args)
new SpringApplicationBuilder(Application.class).web(true).run(args);
断路器:Hystrix客户端
断路器就是,当一个请求超时,启用短路以后的策略或者路由逻辑
要在项目中支持Hystrix
,使用groupId为org.springframework.cloud
和artifactId为spring-cloud-starter-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)
//失败的操作返回
public Object defaultStores(Map<String, Object> parameters)
return new Object();
传播安全上下文或使用Spring范围
如果希望某些线程传播到@HystrixCommand
,默认声明不起作用,因为默认线程已经超时了。
可以使用hystrix.shareSecurityContext
设置为true
健康指标
可以通过访问http://ip:port/health来访问健康指标
"hystrix":
"openCircuitBreakers": [
"StoreIntegration::getStoresByLocationLink"
],
"status": "CIRCUIT_OPEN"
,
"status": "UP"
Hystrix指标流
要用Hystrix的话,需要加入spring-boot-starter-actuator
的依赖,将使用/hystrix.stream
作为管理端点
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
断路器:Hystrix仪表板
Hystrix的优点是收集每个HystrixCommand
的指标,可以有效管理每个断路器的运行状态
Hystrix超时和Ribbon
导入groupId=org.springframework.cloud
和artifactId=spring-cloud-starter-hystrix-dashboard
即可使用仪表盘
在SpringBoot的主类中注解@EnableHystrixDashboard
,然后访问/hystrix
即可
Turbine
Hystrix在系统整体健康方面不是非常有用。在Maven中引入spring-cloud-starter-turbine
,Turbine
将所有/hystrix.stream
聚合到/turbine.stream
中。需要使用@EnableTurbine
注释主类。区别在于trubine.instanceUrlSuffix
不需要预先添加端口,除非turbine.instanceInsertPort=false
自动处理
可以通过如下配置重新定义hystrix的端口
eureka:
instance:
metadata-map:
management.port: $management.port:8081
客户端负载均衡器:Ribbon
Ribbon主要的6个组件是:IRule、IPing、ServerList、ServerListUpdater、ILoadBalancer
Ribbon的主要功能:
- 支持DNS和IP和服务端通信
- 根据算法从多个服务中选取一个服务进行访问
- 通过对客户端和服务器分成几个区域(zone)来建立客户端和服务端之间的关系,客户端尽量访问和自己的相同区域的zone服务。减少服务的延迟
- 保留服务器的统计信息,ribbon可以实现用于避免高延迟或者频繁访问故障的服务器
- 保留区域的统计数据,ribbon可以实现避免可能访问实现的zone
Ribbon是一个客户端负载均衡器,Feign已经使用Ribbon,所以可以直接使用@FeignClient
如果要使用Ribbon,需要在Maven或者Gradle中加入groupId=org.springframework.cloud
和artifactId=spring-cloud-starter-ribbon
,即可完成依赖加入
自定义Ribbon客户端
可以用<client>.ribbon.*
来配置Ribbon客户端。允许使用@RibbonClient
声明其他配置
@Configuration
@RibbonClient(name = "foo", configuration = FooConfiguration.class)
public class RibbonConfiguration
默认提供一下Bean:
IClientConfig ribbonClientConfig:DefaultClientConfigImpl
IRule ribbonRule:ZoneAvoidanceRule
IPing ribbonPing:NoOpPing
ServerList<Server> ribbonServerList:ConfigurationBasedServerList
ServerListFilter<Server> ribbonServerListFilter:ZonePreferenceServerListFilter
ILoadBalancer ribbonLoadBalancer:ZoneAwareLoadBalancer
ServerListUpdater ribbonServerListUpdater:PollingServerListUpdater
@Configuration
public class FooConfiguration
@Bean
public IPing ribbonPing(IClientConfig config)
return new PingUrl();
这时就是用PingUrl
代替NoOpPing
IPing
用于检测服务器是否已经存活,相当于心跳检测
NIWSDiscoveryPing
不执行真正的PING,如果DiscoveryClient
认为是在线,则程序认为本次心跳成功,服务活着PingUrl
组成一个HttpClient调用一个服务的URL,如果调用成功,则认为本次心跳成功,表示此服务活着NoOpPing
永远返回true,认为服务永远活着DummyPing
默认实现,默认返回true,即认为服务永远活着
ServerList
功能:存储服务列表。分为静态和动态,后台有个线程来定时刷新和过滤服务
有以下几种实现:
ConfigurationBasedServerList
从配置文件中获取所有服务列表,如:sample-client.ribbon.listOfServers=www.xxx.com,www.xxx.com
DiscoveryEnabledNIWSServerList
从Eureka获取服务列表。此值必须通过属性中VipAddress
来标识DomainExtractingServerList
代理类,根据ServerList的值实现具体的逻辑
ServerListFilter
该接口允许过滤配置或者动态获取具有特性的服务器列表。ServerListFilter是DynamicServerListLoadBalancer用于过滤ServerList实现返回的服务器组件
ZoneAffinityServerListFilter
: 过滤掉所有的不和客户端在相同zone的服务,如果和客户端相同的zone不存在,才不过滤服务,通过<clientName>.ribbon.EnableZoneAffinity=true
ZonePreferenceServerListFilter
: 和ZoneAffinityServerListFilter
相似,但是比较的zone是发布环境的zoneServerListSubsetFilter
: 此过滤器确保客户端仅能看到由ServerList实现返回的整个服务器的固定子集。可以定期用新服务器替代可用性差的子集中的服务器
<clientName>.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# the server must register itself with Eureka server with VipAddress "myservice"
<clientName>.ribbon.DeploymentContextBasedVipAddresses=myservice
<clientName>.ribbon.NIWSServerListFilterClassName=com.netflix.loadbalancer.ServerListSubsetFilter
# only show client 5 servers. default is 20.
<clientName>.ribbon.ServerListSubsetFilter.size=5
ServerListUpdater
被DynamicServerListLoadBalancer
用于动态的更新服务列表
具体的实现有:
PollingServerListUpdater
默认的实现策略。此对象会启动一个定时线程池,定时执行更新策略
EnrekaNotificationServerListUpdater
当收到缓存刷新的通知,会更新服务列表
IClientConfig
定义各种配置信息,用来初始化ribbon客户端和负载均衡器
常用的IClientConfig有以下几种实现:
DefaultClientConfigImpl
ILoadBalancer
定义软件负载平衡器操作的接口。动态更新一组服务列表及根据指定算法及从现有的服务器列表中选择一个服务
DynamicServerListLoadBalancer
ZoneAwareLoadBalancer
声明式REST客户端:Feign
Feign是一个声明式的Web服务客户端,封装了HTTP请求,默认使用HttpMessageConverters
使用groupId=org.springframework.cloud
和artifactId=spring-cloud-starter-feign
的启动器,在启动主类中添加@EnableFeignClients
注解
客户端主要代码
@FeignClient("stores")
public interface StoreClient
@RequestMapping(method = RequestMethod.GET, value = "/stores")
List<Store> getStores();
@RequestMapping(method = RequestMethod.POST, value = "/stores/storeId", consumes = "application/json")
Store update(@PathVariable("storeId") Long storeId, Store store);
SpringCloud可以通过FeignClientsConfiguration
来声明额外的配置,包括feignDecoder
、feignEncoder
、feignContract
serviceId
属性已经弃用,有利于name
属性。以前用url
属性,不需要name
属性。现在需要使用name
name
、url
支持占位符
@FeignClient(name = "$feign.name", url = "$feign.url")
public interface StoreClient
//..
Spring Cloud Netflix默认为feign(BeanType beanName:ClassName)提供以下bean:
- Decoder feignDecoder:ResponseEntityDecoder(其中包含SpringDecoder)
- Encoder feignEncoder:SpringEncoder
- Logger feignLogger:Slf4jLogger
- Contract feignContract:SpringMvcContract
- Feign.Builder feignBuilder:HystrixFeign.Builder
- Client feignClient:如果Ribbon启用,则为LoadBalancerFeignClient,否则将使用默认的feign客户端。
可以通过将feign.okhttp.enabled或feign.httpclient.enabled设置为true,并将它们放在类路径上来使用OkHttpClient和ApacheHttpClient feign客户端。
Spring允许你放置在@FeignClient
配置,允许覆盖每个Bean,如:
@Configuration
public class FooConfiguration
@Bean
public Contract feignContract()
return new feign.Contract.Default();
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor()
return new BasicAuthRequestInterceptor("user", "password");
这将SpringMvcContract替换为feign.Contract.Default,并将RequestInterceptor添加到RequestInterceptor的集合中。
可以在@EnableFeignClients属性defaultConfiguration中以与上述相似的方式指定默认配置。不同之处在于,此配置将适用于所有假客户端。
手动创建Feign客户端
在某些情况下,可能需要手动创建Feign客户端。下面是创建两个具有相同接口的Feign客户端的例子。
@Import(FeignClientsConfiguration.class)
class FooController
private FooClient fooClient;
private FooClient adminClient;
@Autowired
public FooController(
Decoder decoder, Encoder encoder, Client client)
this.fooClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
.target(FooClient.class, "http://PROD-SVC");
this.adminClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
.target(FooClient.class, "http://PROD-SVC");
断路器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");
当服务降级,有两个实现类的时候,需要标记@Primary
,某些情况下,又需要关闭,需要设置@FeiignClient
的primary=false
@FeignClient(name = "hello", primary = false)
public interface HelloClient
// methods here
Feign请求/响应压缩
可以给请求启动和响应GZIP压缩,通过配置如下:
feign.compression.request.enabled=true
feign.compression.response.enabled=true
# 压缩相关配置,配置压缩类型,最小请求阈值长度
feign.compression.request.enabled=true
feign.compression.request.mime-types=text/xml,application/xml,application/json
feign.compression.request.min-request-size=2048
Feign日志记录
logging.level.project.user.UserClient: DEBUG
NONE
,无记录(Default)BASIC
,只记录请求方法和请求和响应头HEADERS
,记录基本的信息以及请求和响应头FULL
,记录请求和响应头,正文和元数据
@Configuration
public class FooConfiguration
@Bean
Logger.Level feignLoggerLevel()
return Logger.Level.FULL;
Zuul路由
在整个微服务体系中,可以通过/api/users
映射到用户服务,/api/shop
映射到商店服务,可以通过zuul
来实现
zuul实现以下操作:
- 认证
- 洞察
- 压力测试
- 金丝雀测试
- 动态路由
- 服务迁移
- 负载脱落
- 安全
- 静态响应处理
- 主动/主动流量管理
配置属性zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,分别默认为200和20。
所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE。如果此隔离模式是首选,则zuul.ribbonIsolationStrategy可以更改为THREAD。
- 使用
groupId=org.springframework.cloud
和artifactId=spring-cloud-starter-zuul
加入zuul组件 - 使用
@EnableZuulProxy
来启动zuul代理,可以不用给每个服务单独CORS处理和验证
默认情况下,将X-Forwarded-Host标头添加到转发的请求中。关闭set zuul.addProxyHeaders = false
。默认情况下,前缀路径被删除,对后端的请求会拾取一个标题“X-Forwarded-Prefix”(上述示例中的“/ myusers”)
通过Zuul上传文件
如果您@EnableZuulProxy
您可以使用代理路径上传文件,只要文件很小,它就应该工作。对于大文件,有一个替代路径绕过“/ zuul / *”中的Spring DispatcherServlet
(以避免多部分处理)。也就是说,如果zuul.routes.customers=/customers/**
则可以将大文件发送到“/ zuul / customers / *”。servlet路径通过zuul.servletPath进行外部化。如果代理路由引导您通过Ribbon负载均衡器,例如,超大文件也将需要提升超时设置
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
ZuulServlet
Zuul实现了Servlet接口,Zuul嵌入到Spring调度机制。可以使用zuul.servlet-path
来更改路径
ZuulRequestContext
如果想要过滤器之间传递信息,Zuul使用RequestContext
。按照每个请求的ThreadLocal
进行。关于路由请求,根据实际的HttpServletRequest
和HttpServletResponse
的路由信息。RequestContext
扩展ConcurrentHashMap
,所有的东西都存储在上下文中。
@EnableZuulProxy
与@EnableZuulServer
@EnableZuulServer
过滤器
创建从SpringBoot配置文件中加载路由定义的SimpleRouteLocator
前置过滤器
:
ServletDetectionFilter
:检测请求是否通过Spring调度程序。使用键FilterConstants.IS_DISPATCHER_REQUEST_KEY
设置布尔值。FormBodyWrapperFilter
:解析表单数据,对下游请求进行重新编码。DebugFilter
:如果设置了debug
请求参数,则此过滤器将RequestContext.setDebugRouting()
和RequestContext.setDebugRequest()
设置为true
路由过滤器
:
SendForwardFilter
:此过滤器使用ServletRequestDispatcher
转发请求。转发位置存储在RequestContext
属性FilterConstants.FORWARD_TO_KEY
。对于转发在端点很有用。
过滤器
:
SendResponseFilter
:将代理请求的响应放入当前响应。
错误过滤器
:
SendErrorFilter
:如果RequestContext.getThrowable()
部位null,则转发到/
错误(默认情况下)。如果设置为error.path
属性来更改默认转发路径/error
@EnableZuulProxy过滤器
创建从DiscoveryClient
以及属性加载路由定义的DiscoveryClientRouterLocator
。每个serviceId
从DiscoveryClient
创建路由。
前置路由器
:
PreDecorationFilter
:此过滤器根据提供的RouteLocator
确定在哪和如何路由。为下游请求设置各种代理相关的头
路由过滤器
:RibbonRoutingFilter
:此过滤器使用Ribbon,Hystrix等发送请求,有HttpClient
、OkHttpClient
v3(类路径设置com.squareup.okhttp3:okhttp
设置ribbon.okhttp.enabled=true
)、Ribbon Http客户端(通过设置ribbon.restclient.enabled=true
启动)SimpleHostRoutingFilter
:此过滤器通过HttpClient发送请求到预定的URL
以上是关于SpringCloud学习-SpringCloudNetfix的主要内容,如果未能解决你的问题,请参考以下文章
springcloud学习02-对springcloud的理解的记录
如何学习SpringCloud?(SpringCloud模板)