Ribbon采用客户端负载均衡。与服务端负载均衡对应,比如我们访问baidu.com, 域名解析器后转向某个负载均衡设备来决定我们的请求打到哪台机器上,对于我们请求者来说是透明的,我们不知道负载信息。
而Ribbon则是自己维护所有可用的服务列表,根据某种策略,去选择请求哪个服务实例。比如随机选取,线性轮询选取,在线性轮询的基础上重试选取,权重选取,Zone优先选取等。
在Feign集成Ribbon的时候,把两个超时时间委托给Ribbon。
public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) { super(lb, clientConfig); this.setRetryHandler(RetryHandler.DEFAULT); this.clientConfig = clientConfig; this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout); this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout); this.serverIntrospector = serverIntrospector; }在不和Ribbon集成的时候,OpenFeign会设置连接超时和读取超时
feign.Client.Default#convertAndSend
final HttpURLConnection connection = (HttpURLConnection) new URL(request.url()).openConnection(); if (connection instanceof HttpsURLConnection) { HttpsURLConnection sslCon = (HttpsURLConnection) connection; if (sslContextFactory != null) { sslCon.setSSLSocketFactory(sslContextFactory); } if (hostnameVerifier != null) { sslCon.setHostnameVerifier(hostnameVerifier); } } connection.setConnectTimeout(options.connectTimeoutMillis()); connection.setReadTimeout(options.readTimeoutMillis());而和Ribbon集成后,Feign会读取ribbon的两个时间设置,即
# ribbon全局默认连接和等待时间 ribbon.ConnectTimeout: 1000 ribbon.ReadTimeout: 10000 # ribbon指定service的连接和等待时间,注意service的名称要和在FeignClient注解里标注的内容一致, 要大写 PROVIDER-DEMO.ribbon.ConnectTimeout: 1 PROVIDER-DEMO.ribbon.ReadTimeout: 1关于单独执行某个服务的超时配置,区别Ribbon全局时间配置,这个idea没有自动提示,debug了半天源码,找到配置为服务名大写+.ribbon.ConnectTimeout
com.netflix.client.config.DefaultClientConfigImpl#getInstancePropName(java.lang.String, java.lang.String)
public String getInstancePropName(String restClientName, String key) { return restClientName + "." + this.getNameSpace() + "." + key; }这里设置为1只是为了测试超时设置。debug追踪发现,确实如此。这种最佳实践真的只能自己去实践。
调优由于http rest请求的复杂性,可能需要调整超时时间,心跳时间,甚至根据当前服务的请求速率设置线程池大小和排队大小,设置熔断条件等。这个只能在监控上线后,根据监控信息去对应修改需要的配置。目前我还没有最佳实践,不乱说了。
结尾到这里,在启动了eureka,provider之后,启动consumer就可以实现远程调用了。嗯,基本满足开发需求了。访问feign的接口,观察admin里两个provider的请求,可以发现我们的请求确实负载到不同的instance上了。访问fallback接口,可以看到失败的时候会执行我们的降级策略。
Miao语基础很重要,基础很重要,基础非常重要。