access ribbon 编程_关于ribbonClient配置的一个坑

不知道从哪个版本起(目测跟版本无关,应该是ribbon.eureka.enabled=true的情况下),给ribbon配置物理的server list起,单纯配置xxx.ribbon.listOfServers不起效果了,于是就开启了埋坑之旅。

目前使用的是Camden.SR6版本

异常

java.lang.IllegalStateException: No instances available for xxx

at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:75)

at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:53)

at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:86)

at org.springframework.cloud.netflix.metrics.MetricsClientHttpRequestInterceptor.intercept(MetricsClientHttpRequestInterceptor.java:68)

at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:86)

at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:70)

at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)

at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)

at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652)

at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)

at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)

at org.springframework.web.client.RestTemplate$$FastClassBySpringCGLIB$$aa4e9ed0.invoke()

at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)

at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)

at org.springframework.cloud.netflix.metrics.RestTemplateUrlTemplateCapturingAspect.captureUrlTemplate(RestTemplateUrlTemplateCapturingAspect.java:33)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629)

at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:618)

at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)

at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)

at org.springframework.web.client.RestTemplate$$EnhancerBySpringCGLIB$$ec1f757d.postForEntity()

复现条件

采用了RibbonClient来指定server list

没有使用@RibbonClients指定,把标注RibbonClient配置类放在了@ComponentScan扫描包下

有多个服务这样指定

而且其中还有一个服务使用load balanced restTemplate的时候,url中的服务名写错了,写成了一个不存在的服务名(当时是把外部的服务名改了导致的)

导致使用到了错误的server list。

问题配置

@RibbonClient(name = "xxx",configuration = XxxRibbonConfig.class)

public class XxxRibbonConfig {

String listOfServers = "http://192.168.99.100:8080,http://192.168.99.101:8080";

@Bean

public ServerList ribbonServerList() {

List list = Lists.newArrayList();

if (!Strings.isNullOrEmpty(listOfServers)) {

for (String s: listOfServers.split(",")) {

list.add(new Server(s.trim()));

}

}

return new StaticServerList(list);

}

}

这个的问题是把这个配置放到了@ComponentScan扫描的包下面

查看/beans

{

"bean": "ribbonServerList",

"aliases": [],

"scope": "singleton",

"type": "org.springframework.cloud.netflix.ribbon.StaticServerList",

"resource": "class path resource [com/xxx/XxxRibbonConfig.class]",

"dependencies": []

}

会发现多个ribbonClient的话,其中一个的ribbonServerList注册为全局的了。(为什么会注册为全局的?)而spring-cloud-netflix-core-1.2.6.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java

@Bean

@ConditionalOnMissingBean

@SuppressWarnings("unchecked")

public ServerList ribbonServerList(IClientConfig config) {

if (this.propertiesFactory.isSet(ServerList.class, name)) {

return this.propertiesFactory.get(ServerList.class, config, name);

}

ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();

serverList.initWithNiwsConfig(config);

return serverList;

}

这里发现已经有了ribbonServerList,而且没有找到指定的服务名的server list配置,于是就采用了全局的。

解决方案

解决方案很简单,就是修改为正确的服务名就可以了。另外一个方案就是不使用RibbonClient配置,最简单的就是配置文件添加NIWSServerListClassName属性:

xxx:

ribbon:

ReadTimeout: 60000

ConnectTimeout: 60000

NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList

listOfServers: http://192.168.99.100:8080,http://192.168.99.101:8080

规避全局ribbonServerList的方案

在不使用NIWSServerListClassName属性配置,使用RibbonClient配置的前提下,如何规避全局ribbonServerList呢?

方案1:使用@RibbonClients配置

@SpringCloudApplication

@RibbonClients(value = {

@RibbonClient(name = "xxx",configuration = XxxRibbonConfig.class),

@RibbonClient(name = "demo",configuration = DemoRibbonConfig.class)

})

public class DemoServiceApplication {

public static void main(String[] args) {

SpringApplication.run(DemoServiceApplication.class, args);

}

}

然后XxxRibbonConfig以及DemoRibbonConfig类上没有任何注解,比如

public class XxxRibbonConfig {

String listOfServers = "http://192.168.99.100:8080,http://192.168.99.101:8080";

@Bean

public ServerList ribbonServerList() {

List list = Lists.newArrayList();

if (!Strings.isNullOrEmpty(listOfServers)) {

for (String s: listOfServers.split(",")) {

list.add(new Server(s.trim()));

}

}

return new StaticServerList(list);

}

}

由于类上没有注解,因而这个时候就跟他们类路径是否在@ComponentScan扫描的包下面没有关系了。

方案2

把标注@RibbonClient的XxxRibbonConfig以及DemoRibbonConfig放到@ComponentScan扫描的包外面即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值