1.如何用Qt实现Ribbon风格?附源码
2.SpringCloud原理OpenFeign原来是码分这么基于Ribbon来实现负载均衡的
3.netflix已经有了feign这个httpclient,为什么还要开发ribb
4.Ribbon负载均衡分析
5.ribbonè´è½½å衡详解
6.一个注解@LoadBalanced就能让RestTemplate拥有负载均衡的能力?「扩展点实战系列」- 第443篇
如何用Qt实现Ribbon风格?附源码
为在Qt中实现Ribbon风格进行探索,操作环境为win bit搭配VS更新至5版本和Qt5.6.0 bit。码分首选组件是码分Qt的widget和scrollArea。新创建的码分Qt程序中,将默认菜单栏和工具栏去除,码分以便为Ribbon风格定制空间。码分采集文章的源码通过添加一个widget和一个scrollArea至UI界面,码分这两个控件布局采用垂直排列,码分进一步在widget内部放置了一个pushButton和TabWidget,码分其排列形式为水平方向。码分在scrollArea内部,码分同样采用水平排列方式放置widget。码分设计布局完成后,码分整体展现的码分界面结构符合Ribbon风格预期。
在实现过程中,码分首先确定界面的布局边界设为0,同时间距设置为0,以优化视觉效果。对所有元素进行样式调整,freemat源码按钮和TabWidget的文字进行了个性化修改。对scrollArea内部的widget背景颜色设定为白色,并指定一个适合宽度,随后调整scrollArea背景颜色,达到与整体风格一致的效果。
要将左侧的文件菜单置于主界面之上,并确保其他标签向右顺序排列,通过按钮的绝对定位方法能够解决文件菜单的定位问题。然而,对于TabWidget的标签移动问题,借助QSS(CSS扩展)实现更高效的调整。具体代码编写用于执行这一操作。实现后,界面布局的各个元素位置得到精确调整。
为了增强Ribbon风格的直观性,对按钮和Tabbar的样式进行细致设计,使界面更加美观和实用。在文件菜单实现阶段,cfrunloop 源码直接应用QMenu进行菜单创建可能受限,而利用Qt提供的QWidgetAction来创建自定义菜单widget,并结合QSS进行个性化设计,提供了灵活的实现方法。通过编写适用于QWidgetAction的类并重写paintEvent函数,可以顺利应用QSS样式。对文件按钮菜单进行具体配置,以达到理想的功能效果。
接下来,对Tabwidget内的groupBox通过QSS进行定制,以塑造更专业的外观与风格。随着对各个组件的逐步优化,界面呈现的美观与功能并重特点逐步显现。最终的界面设计融入了微软雅黑字体风格,对TabWidget背景色进行设定,并隐藏文件按钮菜单的小按钮,使界面在美观与功能性上达到和谐统一。
通过以上步骤,lftp源码已实现并展示了基于Qt实现Ribbon风格的完整过程与细节。包括界面布局、组件样式调整、功能性实现及最终美化等环节,旨在提供一种兼具美观与实用性,符合Ribbon风格要求的界面设计方法。
SpringCloud原理OpenFeign原来是这么基于Ribbon来实现负载均衡的
欢迎来到本篇文章,之前我们已经深入探讨了OpenFeign的动态代理生成原理和Ribbon的运行机制。若要对OpenFeign的动态代理生成原理和Ribbon的运行原理有更深入的了解,可关注微信公众号“三友的java日记”,通过菜单栏查看整理的相关内容。接下来,我们将继续深入SpringCloud组件原理,探讨OpenFeign是如何利用Ribbon实现负载均衡的,以及两组件如何协同工作的。
一、Feign动态代理调用实现rpc流程解析
我们从Feign客户端接口的动态代理生成原理出发,了解到动态代理基于JDK实现,abslistview源码所有方法调用最终都会调用到InvocationHandler接口的实现,即ReflectiveFeign.FeignInvocationHandler。接下来,我们将深入探讨FeignInvocationHandler如何实现rpc调用。
FeignInvocationHandler通过invoke方法实现动态代理功能,其主要逻辑如下:
1. 对于调用的方法是否为equals、hashCode、toString等特殊方法进行判断,若为则无需走rpc调用。
2. 从dispatch获取调用方法对应的MethodHandler,然后调用MethodHandler的invoke方法。
3. MethodHandler在构建动态代理时生成,作用是最终实现rpc调用,每个方法有对应的MethodHandler。
4. SynchronousMethodHandler是实现rpc调用的关键类,通过构造RequestTemplate、Options和重试组件,发起.netflix.client.conf.CommonClientConfigKeyã
<clientName>.<nameSpace>.NFLoadBalancerClassName=xx
<clientName>.<nameSpace>.NFLoadBalancerRuleClassName=xx
<clientName>.<nameSpace>.NFLoadBalancerPingClassName=xx
<clientName>.<nameSpace>.NIWSServerListClassName=xx
<clientName>.<nameSpace>.NIWSServerListFilterClassName=xx
com.netflix.client.config.IClientConfigï¼Ribbonç客æ·ç«¯é ç½®ï¼é»è®¤éç¨com.netflix.client.config.DefaultClientConfigImplå®ç°ã
com.netflix.loadbalancer.IRuleï¼Ribbonçè´è½½åè¡¡çç¥ï¼é»è®¤éç¨com.netflix.loadbalancer.ZoneAvoidanceRuleå®ç°ï¼è¯¥çç¥è½å¤å¨å¤åºåç¯å¢ä¸éåºæä½³åºåçå®ä¾è¿è¡è®¿é®ã
com.netflix.loadbalancer.IPingï¼Ribbonçå®ä¾æ£æ¥çç¥ï¼é»è®¤éç¨com.netflix.loadbalancer.NoOpPingå®ç°ï¼è¯¥æ£æ¥çç¥æ¯ä¸ä¸ªç¹æ®çå®ç°ï¼å®é ä¸å®å¹¶ä¸ä¼æ£æ¥å®ä¾æ¯å¦å¯ç¨ï¼èæ¯å§ç»è¿åtrueï¼é»è®¤è®¤ä¸ºæææå¡å®ä¾é½æ¯å¯ç¨çã
com.netflix.loadbalancer.ServerListï¼æå¡å®ä¾æ¸ åçç»´æ¤æºå¶ï¼é»è®¤éç¨com.netflix.loadbalancer.ConfigurationBasedServerListå®ç°ã
com.netflix.loadbalancer.ServerListFilterï¼æå¡å®ä¾æ¸ åè¿æ»¤æºå¶ï¼é»è®¤éorg.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilterï¼è¯¥çç¥è½å¤ä¼å è¿æ»¤åºä¸è¯·æ±æ¹å¤äºååºåçæå¡å®ä¾ã
com.netflix.loadbalancer.ILoadBalancerï¼è´è½½åè¡¡å¨ï¼é»è®¤éç¨com.netflix.loadbalancer.ZoneAwareLoadBalancerå®ç°ï¼å®å ·å¤äºåºåæç¥çè½åã
ä¸é¢çé ç½®æ¯å¨é¡¹ç®ä¸æ²¡æå¼å ¥spring Cloud Eurekaï¼å¦æå¼å ¥äºEurekaåRibbonä¾èµæ¶ï¼èªå¨åé ç½®ä¼æä¸äºä¸åã
éè¿èªå¨åé ç½®çå®ç°ï¼å¯ä»¥è½»æ¾çå®ç°å®¢æ·ç«¯çè´è½½åè¡¡ãåæ¶ï¼é对ä¸äºä¸ªæ§åéæ±ï¼æ们å¯ä»¥æ¹ä¾¿çæ¿æ¢ä¸é¢çè¿äºé»è®¤å®ç°ï¼åªéè¦å¨springbootåºç¨ä¸å建对åºçå®ç°å®ä¾å°±è½è¦çè¿äºé»è®¤çé ç½®å®ç°ã
@Configuration
public class MyRibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
è¿æ ·å°±ä¼ä½¿ç¨P使ç¨äºRandomRuleå®ä¾æ¿ä»£äºé»è®¤çcom.netflix.loadbalancer.ZoneAvoidanceRuleã
ä¹å¯ä»¥ä½¿ç¨@RibbonClient注解å®ç°æ´ç»ç²åº¦ç客æ·ç«¯é ç½®
对äºRibbonçåæ°é常æäºç§æ¹å¼ï¼å ¨å±é 置以åæå®å®¢æ·ç«¯é ç½®
å ¨å±é ç½®çæ¹å¼å¾ç®å
åªéè¦ä½¿ç¨ribbon.<key>=<value>æ ¼å¼è¿è¡é ç½®å³å¯ãå ¶ä¸ï¼<key>代表äºRibbon客æ·ç«¯é ç½®çåæ°åï¼<value>å代表äºå¯¹åºåæ°çå¼ãæ¯å¦ï¼æ们å¯ä»¥æ³ä¸é¢è¿æ ·é ç½®Ribbonçè¶ æ¶æ¶é´
ribbon.ConnectTimeout=
ribbon.ServerListRefreshInterval= ribbonè·åæå¡å®æ¶æ¶é´
å ¨å±é ç½®å¯ä»¥ä½ä¸ºé»è®¤å¼è¿è¡è®¾ç½®ï¼å½æå®å®¢æ·ç«¯é ç½®äºç¸åºçkeyçå¼æ¶ï¼å°è¦çå ¨å±é ç½®çå 容
æå®å®¢æ·ç«¯çé ç½®æ¹å¼
<client>.ribbon.<key>=<value>çæ ¼å¼è¿è¡é ç½®.<client>表示æå¡åï¼æ¯å¦æ²¡ææå¡æ²»çæ¡æ¶çæ¶åï¼å¦Eurekaï¼ï¼æ们éè¦æå®å®ä¾æ¸ åï¼å¯ä»¥æå®æå¡åæ¥å详ç»çé ç½®ï¼
user-service.ribbon.listOfServers=localhost:,localhost:,localhost:
对äºRibbonåæ°çkey以åvalueç±»åçå®ä¹ï¼å¯ä»¥éè¿æ¥çcom.netflix.client.config.CommonClientConfigKeyç±»ã
å½å¨spring Cloudçåºç¨åæ¶å¼å ¥Spring cloud RibbonåSpring Cloud Eurekaä¾èµæ¶ï¼ä¼è§¦åEurekaä¸å®ç°ç对Ribbonçèªå¨åé ç½®ãè¿æ¶çserverListçç»´æ¤æºå¶å®ç°å°è¢«com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerListçå®ä¾æè¦çï¼è¯¥å®ç°ä¼è®²æå¡æ¸ åå表交ç»Eurekaçæå¡æ²»çæºå¶æ¥è¿è¡ç»´æ¤ãIPingçå®ç°å°è¢«com.netflix.niws.loadbalancer.NIWSDiscoveryPingçå®ä¾æè¦çï¼è¯¥å®ä¾ä¹å°å®ä¾æ¥å£çä»»å¡äº¤ç»äºæå¡æ²»çæ¡æ¶æ¥è¿è¡ç»´æ¤ãé»è®¤æ åµä¸ï¼ç¨äºè·åå®ä¾è¯·æ±çServerListæ¥å£å®ç°å°éç¨Spring Cloud Eurekaä¸å°è£ çorg.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerListï¼å ¶ç®çæ¯ä¸ºäºè®©å®ä¾ç»´æ¤çç¥æ´å éç¨ï¼æ以å°ä½¿ç¨ç©çå æ°æ®æ¥è¿è¡è´è½½åè¡¡ï¼èä¸æ¯ä½¿ç¨åççAWS AMIå æ°æ®ãå¨ä¸Spring cloud Eurekaç»å使ç¨çæ¶åï¼ä¸éè¦åå»æå®ç±»ä¼¼çuser-service.ribbon.listOfServersçåæ°æ¥æå®å ·ä½çæå¡å®ä¾æ¸ åï¼å 为Eurekaå°ä¼ä¸ºæ们维æ¤æææå¡çå®ä¾æ¸ åï¼è对äºRibbonçåæ°é ç½®ï¼æ们ä¾ç¶å¯ä»¥éç¨ä¹åç两ç§é ç½®æ¹å¼æ¥å®ç°ã
æ¤å¤ï¼ç±äºspring Cloud Ribboné»è®¤å®ç°äºåºå亲åçç¥ï¼æ以ï¼å¯ä»¥éè¿Eurekaå®ä¾çå æ°æ®é ç½®æ¥å®ç°åºååçå®ä¾é ç½®æ¹æ¡ãæ¯å¦å¯ä»¥å°ä¸åæºæ¿çå®ä¾é ç½®æä¸åçåºåå¼ï¼ä½ä¸ºè·¨åºåç容å¨æºå¶å®ç°ãèå®ç°ä¹é常ç®åï¼åªéè¦æå¡å®ä¾çå æ°æ®ä¸å¢å zoneåæ°æ¥æå®èªå·±æå¨çåºåï¼æ¯å¦ï¼
eureka.instance.metadataMap.zone=shanghai
å¨Spring Cloud Ribbonä¸Spring Cloud Eurekaç»åçå·¥ç¨ä¸ï¼æ们å¯ä»¥éè¿åæ°ç¦ç¨Eureka对Ribbonæå¡å®ä¾çç»´æ¤å®ç°ãè¿æ¶åéè¦èªå·±å»ç»´æ¤æå¡å®ä¾å表äºã
ribbon.eureka.enabled=false.
ç±äºSpring Cloud Eurekaå®ç°çæå¡æ²»çæºå¶å¼ºè°äºcapåççapæºå¶ï¼å³å¯ç¨æ§åå¯é æ§ï¼ï¼ä¸zookeeperè¿ç±»å¼ºè°cpï¼ä¸è´æ§ï¼å¯é æ§ï¼æå¡è´¨éæ¡æ¶æ大çåºå«å°±æ¯ï¼Eureka为äºå®ç°æ´é«çæå¡å¯ç¨æ§ï¼çºç²äºä¸å®çä¸è´æ§ï¼å¨æ端æ åµä¸å®æ¿æ¥åæ éå®ä¾ä¹ä¸è¦ä¸¢å¼"å¥åº·"å®ä¾ã
æ¯å¦è¯´ï¼å½æå¡æ³¨åä¸å¿çç½ç»åçæ éæå¼æ¶åï¼ç±äºææçæå¡å®ä¾æ æ³ç»´æ¤ç»çº¦å¿è·³ï¼å¨å¼ºè°apçæå¡æ²»çä¸å°ä¼ææææå¡å®ä¾åé¤æï¼èEurekaåä¼å ä¸ºè¶ è¿%çå®ä¾ä¸¢å¤±å¿è·³è触åä¿æ¤æºå¶ï¼æ³¨åä¸å¿å°ä¼ä¿çæ¤æ¶çææèç¹ï¼ä»¥å®ç°æå¡é´ä¾ç¶å¯ä»¥è¿è¡äºç¸è°ç¨çåºæ¯ï¼å³ä½¿å ¶ä¸æé¨åæ éèç¹ï¼ä½è¿æ ·åå¯ä»¥ç»§ç»ä¿é大å¤æ°æå¡çæ£å¸¸æ¶è´¹ã
å¨Camdençæ¬ï¼æ´åäºspring retryæ¥å¢å¼ºRestTemplateçéè¯è½åï¼å¯¹äºæ们å¼åè æ¥è¯´ï¼åªéè¦ç®åé ç½®ï¼å³å¯å®æéè¯çç¥ã
spring.cloud.loadbalancer.retry.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
user-service.ribbon.ConnectTimeout=
user-service.ribbon.ReadTimeout=
user-service.ribbon.OkToRetryOnAllOperations=true
user-service.ribbon.MaxAutoRetriesNextServer=2
user-service.ribbon.maxAutoRetries=1
spring.cloud.loadbalancer.retry.enabled:该åæ°ç¨æ¥å¼å¯éè¯æºå¶ï¼å®é»è®¤æ¯å ³éçã
hystrix.command.default.execution.isolation.thread.timeoutInMillisecondsï¼æè·¯å¨çè¶ æ¶æ¶é´éè¦å¤§äºRibbonçè¶ æ¶æ¶é´ï¼ä¸ç¶ä¸ä¼è§¦åéè¯ã
user-service.ribbon.ConnectTimeoutï¼è¯·æ±è¿æ¥è¶ æ¶æ¶é´ã
user-service.ribbon.ReadTimeoutï¼è¯·æ±å¤ççè¶ æ¶æ¶é´
user-service.ribbon.OkToRetryOnAllOperationsï¼å¯¹æææä½è¯·æ±é½è¿è¡éè¯ã
user-service.ribbon.MaxAutoRetriesNextServerï¼åæ¢å®ä¾çéè¯æ¬¡æ°ã
user-service.ribbon.maxAutoRetriesï¼å¯¹å½åå®ä¾çéè¯æ¬¡æ°ã
æ ¹æ®ä»¥ä¸é ç½®ï¼å½è®¿é®å°æ é请æ±çæ¶åï¼å®ä¼åå°è¯è®¿é®ä¸æ¬¡å½åå®ä¾ï¼æ¬¡æ°ç±maxAutoRetriesé ç½®ï¼ï¼å¦æä¸è¡ï¼å°±æ¢ä¸ä¸ªå®ä¾è¿è¡è®¿é®ï¼å¦æè¿æ¯ä¸è¡ï¼åæ¢ä¸ä¸ªå®ä¾è®¿é®ï¼æ´æ¢æ¬¡æ°ç±MaxAutoRetriesNextServeré ç½®ï¼ï¼å¦æä¾ç¶ä¸è¡ï¼è¿å失败
项ç®å¯å¨çæ¶åä¼èªå¨ç为æ们å è½½LoadBalancerAutoConfigurationèªå¨é 置类ï¼è¯¥èªå¨é 置类åå§åæ¡ä»¶æ¯è¦æ±classpathå¿ é¡»è¦æRestTemplateè¿ä¸ªç±»ï¼å¿ é¡»è¦æLoadBalancerClientå®ç°ç±»ã
LoadBalancerAutoConfiguration为æ们干äºäºä»¶äºï¼ç¬¬ä¸ä»¶æ¯å建äºLoadBalancerInterceptoræ¦æªå¨beanï¼ç¨äºå®ç°å¯¹å®¢æ·ç«¯å起请æ±æ¶è¿è¡æ¦æªï¼ä»¥å®ç°å®¢æ·ç«¯è´è½½åè¡¡ãå建äºä¸ä¸ª
RestTemplateCustomizerçbeanï¼ç¨äºç»RestTemplateå¢å LoadBalancerInterceptoræ¦æªå¨ã
æ¯æ¬¡è¯·æ±çæ¶åé½ä¼æ§è¡org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptorçinterceptæ¹æ³ï¼èLoadBalancerInterceptorå ·æLoadBalancerClientï¼å®¢æ·ç«¯è´è½½å®¢æ·ç«¯ï¼å®ä¾çä¸ä¸ªå¼ç¨ï¼
å¨æ¦æªå¨ä¸éè¿æ¹æ³è·åæå¡åç请æ±urlï¼æ¯å¦/p/1bddb5dc
Spring cloudç³»åå Ribbonçåè½æ¦è¿°ã主è¦ç»ä»¶åå±æ§æ件é ç½®
/p/faffa
æ¬äººæéäºç¬è®°ä¸è®°å½çåèæç«
ææ¡£ï¼_ribbon è´è½½åè¡¡.note
é¾æ¥ï¼/noteshare?id=efc3efbbefd8ed0b9&sub=B0E6DFEEBDAF
一个注解@LoadBalanced就能让RestTemplate拥有负载均衡的能力?「扩展点实战系列」- 第篇
在系列文章《国内最全的Spring Boot系列》中,我们探讨了多个主题,如扩展点的应用实践:《扩展点实战系列》的第篇到第篇,其中包括CommandLineRunner和ApplicationRunner的缓存预热,初始化与销毁的三种方法,观察者模式的应用,服务状态监控,以及配置类静态变量的使用。第篇中,我们提到一个简单的注解@LoadBalanced,似乎就能让RestTemplate具备负载均衡功能,但这个背后的技术细节是什么呢?
在前文的讲解中,我们提到了Ribbon的负载均衡实现思路,并且师傅悟纤提到Ribbon的实现方式与我们自定义的类似。为了验证这一点,悟纤将深入Ribbon的源码世界,探寻真相。
首先,让我们回顾一下在使用Ribbon开启负载均衡时的代码示例,通过服务名称而非IP地址进行请求。这种方法与我们之前讨论的扩展方法非常相似。
接着,我们看到Ribbon的核心自动配置类RibbonAutoConfiguration,它包含一个内部类RibbonClientHttpRequestFactoryConfiguration,这个类负责扩展RestTemplate的功能。虽然没有直接看到拦截器的注入,但后续的LoadBalancerAutoConfiguration类中,@LoadBalanced注解的使用和Spring扩展点的使用,都预示着拦截器的存在。
LoadBalancerAutoConfiguration类利用SmartInitializingSingleton扩展点,将自定义的拦截器LoadBalancerInterceptor添加到RestTemplate中。这个拦截器在请求处理过程中,根据负载均衡算法从多个服务器中选择合适的服务器进行请求。
至于@LoadBalanced注解,其关键作用是通过Qualifier限定,确保只有标注了该注解的RestTemplate被注入。简单来说,使用@Autowired和@LoadBalanced组合,Spring会自动识别并注入配置好的负载均衡的RestTemplate实例。
总结来说,Ribbon的负载均衡实现是通过自定义注解、拦截器和Spring扩展点的巧妙结合。当我们使用@LoadBalanced时,实际上是告诉Spring我们需要一个已经配置好负载均衡功能的RestTemplate。这就是Spring Cloud Ribbon的负载均衡原理,它将配置和逻辑分离,使得代码更加简洁且易于维护。
最后,问题留给你:@Autowired和@LoadBalanced如何协同工作,使得配置的RestTemplate自动注入?这背后的原理,需要你进一步研究Spring的依赖注入和扩展点机制来解答。」
SpringCloud(3):使用Ribbon进行负载均衡配置,以及遇坑指南
使用Ribbon进行负载均衡配置是Spring Cloud体系中的一种关键实践。由于Eureka中已经集成了Ribbon,因此无需额外引入依赖。启动多个服务提供方时,在服务消费方的启动类中启用@LoadBalanced注解来激活负载均衡机制。将@LoadBalanced注解添加到消费方的RestTemplate方法上,即可实现通过服务名调用提供方的服务。
在配置过程中,服务消费方通常使用DiscoveryClient来获取提供方的服务列表,并通过该列表指定具体的服务实例及其主机和端口。然而,开启负载均衡后,系统会自动选择合适的服务实例,无需人工指定,以提升服务调用的效率和可用性。
值得注意的是,一旦使用了@LoadBalanced注解,直接访问提供方的特定主机名和端口号会引发异常(如java.lang.IllegalStateException: No instances available for localhost)。同时,服务名中应避免使用下划线,否则可能会遇到请求URI格式错误(如Request URI does not contain a valid hostname: service_provider/user/4...)的问题。
在消费方控制器中,实现远程服务调用时,负载均衡效果通过LoadBalancerInterceptor和RibbonLoadBalancerClient类的源码展现。RibbonLoadBalancerClient通过默认的轮询策略分配服务实例,而其他策略如随机策略则可以在消费方配置文件中进行指定。重新运行测试用例后,负载均衡策略的切换效果明显。
深入RibbonLoadBalancerClient源码,可以观察到通过BaseLoadBalancer类的chooseServer方法调用rule接口以执行负载均衡策略,其中轮询策略(RoundRobinRule)是默认设置。除了轮询策略之外,随机策略等其他负载均衡策略也可通过配置文件进行选择,以适应不同场景的需求。在实践过程中,通过测试和调整配置,可以有效提升服务调用的负载均衡效果。