apache cxf_Apache CXF负载平衡和故障转移

apache cxf

不久前,我们已经面临了基于Apache CXF的负载平衡Web服务客户端的需求。 此外,当某些服务器关闭时,客户端应自动进行故障转移。 更糟糕的是,服务器目标地址列表要从外部服务获取并在运行时更新。

最终,我们最终获得了本地开发的负载平衡微库(ESB / UDDI / WS-Addressing似乎是一个有趣的选择,但在我们的情况下这是一个过大的选择)。 是否仅知道Apache CXF已经(几乎)已经支持所有这些功能?

不过,不要怪我们,仅提及此功能会指向非常糟糕的文档页面(如果您将404称为“差”)。 如果它不在正式文档中,我希望可以在Apache CXF Web服务开发书中找到它-不幸的是,那里也很不幸。 但是,嘿,您自己探索这些功能不是更有趣吗? 这是我们开始的客户端配置:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:clustering="http://cxf.apache.org/clustering"xmlns:util="http://www.springframework.org/schema/util"><jaxws:client id="testServiceClient"serviceClass="com.blogspot.nurkiewicz.cxfcluster.SimpleService"address="http://serverA/simple"></jaxws:client></beans>
端点接口在这里并不重要,足以知道将testServiceClient注入了其他服务,并且负载平衡和故障转移功能不应影响现有代码。 请注意,服务地址是固定的且经过硬编码的(当然可以将其外部化并在启动时读取)。
令人惊讶的是,仅启用故障转移是非常简单,直接和不言自明的(尽管是XML):
<jaxws:client id="testServiceClient"serviceClass="com.blogspot.nurkiewicz.cxfcluster.SimpleService"address="http://serverA/simple"><jaxws:features><clustering:failover><clustering:strategy><bean class="org.apache.cxf.clustering.RandomStrategy"><property name="alternateAddresses"><util:list><value>http://serverB/simple</value><value>http://serverC/simple</value><value>http://serverD/simple</value></util:list></property></bean></clustering:strategy></clustering:failover></jaxws:features></jaxws:client>
serverA地址用作主要端点,但是当它失败时, 将以随机顺序检查所有故障转移端点( serverB , serverC和serverD )。 为了发挥这种配置的作用,我建议您打开Apache CXF请求和响应日志记录 :
<cxf:bus><cxf:features><cxf:logging/></cxf:features>
</cxf:bus>
再次(!),官方文档中没有提到非常方便的配置参数prettyLogging ,该参数可以应用于日志记录功能,以便在记录之前正确格式化XML请求和响应( 换行和缩进)。 我不建议在生产设置中使用它,但是在开发和测试过程中,格式化SOAP消息是非常宝贵的:
<bean id="abstractLoggingInterceptor" abstract="true"><property name="prettyLogging" value="true"/>
</bean>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" parent="abstractLoggingInterceptor"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" parent="abstractLoggingInterceptor"/><cxf:bus><cxf:inInterceptors><ref bean="loggingInInterceptor"/></cxf:inInterceptors><cxf:outInterceptors><ref bean="loggingOutInterceptor"/></cxf:outInterceptors><cxf:outFaultInterceptors><ref bean="loggingOutInterceptor"/></cxf:outFaultInterceptors><cxf:inFaultInterceptors><ref bean="loggingInInterceptor"/></cxf:inFaultInterceptors>
</cxf:bus>
因此,如果主要端点不可用,我们的服务很好地故障转移到备份端点。 但是我们有四个等效的服务器,我们希望我们的客户以相同的概率(轮循,随机?)平等地对待它们。 这是负载均衡进入阶段的时候:
<jaxws:client id="testServiceClient" serviceClass="com.blogspot.nurkiewicz.cxfcluster.SimpleService"><jaxws:features><clustering:loadDistributor><clustering:strategy><bean class="org.apache.cxf.clustering.SequentialStrategy"><property name="alternateAddresses"><util:list><value>http://serverA/simple</value><value>http://serverB/simple</value><value>http://serverC/simple</value><value>http://serverD/simple</value></util:list></property></bean></clustering:strategy></clustering:loadDistributor></jaxws:features></jaxws:client>
请注意,客户端本身不再定义地址属性。 这表明, alternateAddresses列表仅在所有调用中使用,并且不存在主地址-实际上是这种情况。 SequentialStrategy将使用一个端点接另一个端点,以提供良好的循环实现(也提供RandomStrategy )。 同样,在此配置中,您将免费获得故障转移–如果任何端点发生故障,将从第一个端点开始的所有端点都将受到检查(显然,刚刚发生故障的端点除外)。
大! 现在,CXF客户端变得更加僵化和容错。 但是,在我们追求更高可用性并最大程度地减少停机时间的过程中,仅在应用程序启动时才加载备用节点(换句话说,添加新服务器需要所有客户端重新启动)实在太过局限了。 幸运的是,我们可以通过两个简单的步骤使负载均衡更加动态。
<jaxws:client id="testServiceClient" serviceClass="com.blogspot.nurkiewicz.cxfcluster.SimpleService"><jaxws:features><clustering:loadDistributor><clustering:strategy><bean class="org.apache.cxf.clustering.SequentialStrategy"><property name="alternateAddresses" ref="alternateAddresses"/></bean></clustering:strategy></clustering:loadDistributor></jaxws:features></jaxws:client><util:list id="alternateAddresses" list-class="java.util.concurrent.CopyOnWriteArrayList"><value>http://serverA/simple</value><value>http://serverB/simple</value><value>http://serverC/simple</value><value>http://serverD/simple</value>
</util:list>
没什么,提取嵌套的匿名bean。 但是可以访问此列表(请注意,我使用了java.util.concurrent.CopyOnWriteArrayList )使我们可以将其注入任何其他服务,从而可能改变其状态。 我怎么知道这行得通? 好吧,我花了几个下午来调试Apache CXF,以最终发现负载平衡算法:第一次调用时,CXF要求策略提供可能节点的列表。 然后它会将这个列表返回策略要求到(在这里小编WTF ......)挑选一个战略决定哪些地址,使用和删除列表中挑选地址(另一个小一个在这里...)当CXF发现列表是空的,故事重复本身。 因此,如果我们在运行时替换备用地址列表,则一轮新列表将返回到核心CXF基础结构。
因为我是JMX的拥护者,所以这是我们修改地址列表的方法(您可以使用任何喜欢的机制):
@Service
@ManagedResource
public class AlternateAddressesManager {@Resourceprivate List alternateAddresses;@ManagedOperationpublic void addAlternateAddress(String address) {alternateAddresses.add(address);}@ManagedOperationpublic boolean removeAlternateAddress(String address) {return alternateAddresses.remove(address);}@ManagedAttributepublic List getAlternateAddresses() {return Collections.unmodifiableList(alternateAddresses);}}
是的,这是SequentialStrategy使用的非常相同的alternateAddresses列表,因此,只需对其进行修改,就可以更改CXF寻址行为。 可以说,我们可以扩展CopyOnWriteArrayList,添加一些额外的启用JMX的方法(或者,探究Springs的灵活性,直接通过JMX公开List方法!),但这会降低可维护性,我认为这是较差的设计。
最后,我们可以按照下面的屏幕快照启动jconsole或JVisualVM,并享受我们的负载平衡基础架构:
快乐? 并不是的。 在研究CXF源代码时,我遇到了关于LoadDistributorFeature和FailoverTargetSelector类的可怕的JavaDoc注释,它们在负载平衡过程中起着重要的作用:
/ **
* […]
*请注意,此功能会即时更改导管,从而使
* 客户端不是线程安全的。
* /
重点放在粗体的文本上(好的,老实说,我不理解其余内容)。 如果您已经使用Spring一段时间,您就会知道testServiceClient bean是多个线程同时使用的共享单例(否,使其原型作用域无济于事;为什么?),这与默认的EJB无状态会话bean相反,被汇集。 幸运的是,Spring也为此提供了一个内置的解决方案。 但是在我最终提出正确的解决方案之前,出现了一些障碍。
首先,来自CXF名称空间的jaxws:client标记不允许定义bean范围,默认情况下为单例,而我们要合并客户端。 因此,我不得不使用org.apache.cxf.jaxws.JaxWsProxyFactoryBean恢复到良好的旧bean定义。 没问题,稍微冗长些,尽管如果您不希望使用自定义Spring名称空间,则可能一开始就使用它。 现在最好的部分是:我可以将具有原型范围的任何bean封装在特殊的代理中,Spring会自动创建一个对象池(基于commons-pool库),并根据需要创建尽可能多的bean实例,以使每个bean仅由一个使用。线。 配置如下:
<bean id="testServiceClientFactoryBean" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"><property name="serviceClass" value="com.blogspot.nurkiewicz.cxfcluster.SimpleService"/><property name="features"><util:list><bean class="org.apache.cxf.clustering.LoadDistributorFeature"><property name="strategy"><bean class="org.apache.cxf.clustering.SequentialStrategy"><property name="alternateAddresses" ref="alternateAddresses"/></bean></property></bean></util:list></property>
</bean><bean id="testServiceClientTarget" factory-bean="testServiceClientFactoryBean" factory-method="create" scope="prototype" lazy-init="true"/><bean id="testServiceClient" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="targetSource"><bean class="org.springframework.aop.target.CommonsPoolTargetSource"><property name="targetClass" value="com.blogspot.nurkiewicz.cxfcluster.SimpleService"/><property name="targetBeanName" value="testServiceClientTarget"/><property name="maxSize" value="10"/><property name="maxWait" value="5000"/></bean></property>
</bean>
您是否注意到maxSize和maxWait池属性? 他们真是太酷了 ! 您可以告诉Spring在池中创建的客户端不要超过10个,并且如果池为空(当前正在使用所有Bean),我们应该等待不超过5000毫秒(之后发生的事情是可配置的!)非常简单但功能强大的限制机制,比JMS或显式线程池简单得多,我们绝对免费! 例如,不想服务超过20个并发Web服务客户端? 使服务器端点访问服务Bean的大小限制为20。超过此限制的客户端将被拒绝,因为没有可用的服务Bean。
当然,在成人世界中,没有任何效果可以预期。 我很快发现JaxWsProxyFactoryBean.create不是线程安全的, 并报告了CXF-3558 。 作为解决方法,我必须通过将其 子类化 来同步 CommonsPoolTargetSource 使用的客户端工厂 :
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.PoolUtils;
import org.springframework.aop.target.CommonsPoolTargetSource;public class SynchCommonsPoolTargetSource extends CommonsPoolTargetSource {@Overrideprotected ObjectPool createObjectPool() {return PoolUtils.synchronizedPool(super.createObjectPool());}}
似乎需要同步工厂,所以我创建了SPR-8382-也许它将找到正式发行的方式。 顺便说一句,在撰写本文时,我还报告了IDEA-70365 – 报告了List类型bean的 虚假 “无法自动装配”错误
最后! 我们的负载平衡和故障转移就像一个魅力。 下一步将是暂时丢弃掉了几秒钟的节点,如果此后端点仍然掉线,则增加此时间。 但是Apache CXF在这一领域的API如此糟糕,以至于我不得不离开这个话题一段时间。 也许您可以帮忙?

参考: NoBlogDefFound博客上的 JCG合作伙伴 Tomasz 在Apache CXF中启用负载平衡和故障转移 。

相关文章 :
  • 具有Spring和Maven教程的JAX–WS
  • Spring 3 RESTful Web服务
  • Tomcat 7上具有RESTeasy JAX-RS的RESTful Web服务– Eclipse和Maven项目

翻译自: https://www.javacodegeeks.com/2011/06/apache-cxf-load-balancing-failover.html

apache cxf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/359675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU 1874 最直接的最短路径问题

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1874 Problem Description某省自从实行了很多年的畅通工程计划后&#xff0c;终于修建了很多路。不过路多了也不好&#xff0c;每次要从一个城镇到另一个城镇时&#xff0c;都有许多种道路方案可以选择&#xf…

晶体管

晶体管-沟道 场效应-电容性的控制沟道 势效应-直接控制沟道 平带电压 由于半导体和金属的功函数的不同&#xff0c;导致半导体表面层并不属于平带状态&#xff0c;为了恢复平带状态所加的电压为平带电压&#xff0c;Vfb 转载于:https://www.cnblogs.com/rice808/p/3874597.html…

领域驱动设计模式设计与实践_在域驱动设计中使用状态模式

领域驱动设计模式设计与实践域驱动设计&#xff08;DDD&#xff09;是一种开发软件的方法&#xff0c;其中&#xff0c;通过将实现与核心业务概念的不断发展的模型相联系&#xff0c;解决了问题的复杂性。 该术语是由Eric Evans创造的&#xff0c;并且有一个DDD专用站点可以促进…

html 英文文字纵向排列,CSS几种简单方法实现文字竖向排版

1.一个句子的竖向排列如图&#xff1a;1.2. test.one {width: 20px;margin: 0 auto;line-height: 24px;font-size: 20px;}.two {width: 15px;margin: 0 auto;line-height: 24px;font-size: 20px;word-wrap: break-word;/*英文的时候需要加上这句&#xff0c;自动换行*/}我是竖列…

jstree 节点拖拽保存数据库

需要jstree具有拖拽功能需要在加载jstree时添加dnd插件&#xff0c;具体看代码&#xff1a; $(**).jstree({//plugins-各种jstree的插件引入&#xff0c;展示树的多样性 plugins : [ "dnd", "types", "wholerow" ], core : {"check_callbac…

html js utf8编码转换,js 编码转换 gb2312 和 utf8 互转的2种方法

方法一:function gb2utf8(data){var glbEncode [];gb2utf8_data data;execScript("gb2utf8_data MidB(gb2utf8_data, 1)", "VBScript");var tescape(gb2utf8_data).replace(/%u/g,"").replace(/(.{2})(.{2})/g,"%$2%$1").replace(/…

向其他进程注入代码的三种方法

如何向其他线程的地址空间中注入代码并在这个线程的上下文中执行之&#xff1f; 目录&#xff1a;●导言●Windows 钩子&#xff08;Hooks&#xff09;●CreateRemoteThread 和LoadLibrary 技术○进程间通讯●CreateRemoteThread 和 WriteProcessmemory 技术○如何使用该技术子…

自动添加html结束标志,HTML:包含或排除可选的结束标记?

MYYA我在这里添加一些链接来帮助您了解HTML的历史&#xff0c;以便您了解各种矛盾。这不是你的问题的答案&#xff0c;但在阅读这些各种摘要后你会知道更多。我们是怎么来到这里的&#xff1f; - 潜入HTML5网络历史HTML简史HTML的历史 - HTML WG WikiDive Into HTML5的一些摘录…

JAR清单类路径不仅适用于Java Application Launcher

自从我开始学习Java以来​​&#xff0c;我几乎已经知道&#xff0c; 清单文件中的Class-Path标头字段为可执行JAR &#xff08;具有由另一个称为Main-Class清单指定应用程序起点的 JAR&#xff09;指定相对运行时类路径。 一个同事最近碰到一个让我感到惊讶&#xff0c;因为它…

[原创]ActionScript3游戏中的图像编程(连载五)

总目录&#xff1a;http://www.cnblogs.com/iloveas/p/3879125.html 1.1.2 Flash中的ARGB模式与不透明度的关系 ARGB是Flash&#xff0c;svg等矢量处理软件特有的一种色彩模式&#xff0c;事实上我觉得它有点扯淡&#xff0c;A&#xff08;alpha&#xff09;不应该作为一个通道…

通过url,获取html内容,并解析,如何使用 JavaScript 解析 URL

在 Web 开发中&#xff0c;有许多情况需要解析 URL&#xff0c;这篇主要学习如何使用 URL 对象实现这一点。开始创建一个以下内容的 HTML 文件&#xff0c;并在浏览器中打开。JavaScript URL parsing// 激动人心的代码即将写在这里如果你想尝试本文中的任何内容&#xff0c;可以…

define 汉字 error C2001: newline in constant

这个问题真的很让我头大&#xff0c;搜了很多办法都不行&#xff0c;问题是我之前也遇到过&#xff0c;但是编码转为utf-8 unsignature就行了&#xff0c;这次把编码从gb转为utf-8 unsignature 却不行。于是想看看cocos2d-x库文件的编码格式&#xff0c;发现用的是utf-8&#x…

solaris安装java_Solaris是出色的Java开发平台的原因

solaris安装java几天前&#xff0c;我发布了“ OpenSolaris的死亡&#xff1a;为Java开发人员选择操作系统 ”&#xff0c;其中我说Solaris是Java开发人员的绝佳平台。 这篇文章的重点只是想知道自OpenSolaris淘汰以来我将使用哪个Solaris版本。 正如Neil的评论使我意识到的那样…

正确使用计算机说课稿,《计算机结构原理初步》说课稿

在教师招聘考试的过程中&#xff0c;高中信息说课稿的难度就在于如何处理理论与实践的关系&#xff0c;希望这篇《计算机结构原理初步》说课稿能给予你帮助。各位考官大家好!我是号考生&#xff0c;今天我说课的题目是《计算机结构原理初步》。现代教学理论认为&#xff0c;在教…

stringstream实例

stringstream的具体作用稍后来总结&#xff0c;这里分享一个实例&#xff0c;从txt文档中读取数据&#xff0c;并对进行处理。 #include <iostream> #include <sstream> //stringstream的头文件 #include <fstream> #include <vector> #include <s…

计算机2013知识,2013年全国计算机一级考试B基本知识点五

基础5单元格操作对已建立的工作表&#xff0c;根据需要可以编辑修改其中的数据首先要移动单元格指针到目的地或选定编辑对象&#xff0c;然后才能进行增、删、改操作。1.单元格指针的移动要编辑某单元格&#xff0c;必须把单元格指针移动到该单元格&#xff0c;使之成为当前单元…

两种解决IE6不支持固定定位的方法

有两种让IE6支持position:fixed1.用CSS执行表达式 *{margin:0;padding:0;} * html,* html body{ background-image:url(about:blank);background-attachment:fixed; } * html .fixed{position:absolute;bottom:auto;top:expression(eval(document.documentElement.scrollTopdoc…

smartgwt_高级SmartGWT教程,第1部分

smartgwt贾斯汀&#xff08;Justin&#xff09;&#xff0c;帕特&#xff08;Pat&#xff09;和我已经开始着手进行一个需要管理和管理用户界面的副项目。 在与SmartGWT和GWT共同工作了一段时间之后&#xff0c;我们决定使用SmartGWT创建接口。 我们非常喜欢视觉组件&#xff0…

计算机英语女人英语怎么说,英语时差:计算机和女人

00:0000:00微信扫码登陆&#xff0c;畅听全站所有音频&#xff01;(20秒后自动关闭)X关注后&#xff0c;点此关闭https://online2.tingclass.net/lesson/shi0529/10000/10183/67.mp3https://image.tingclass.net/statics/js/2012When you hear the term, "computer geek,&…

Python 生成账号密码算法

有个需求&#xff0c;需要伪造跟用户行为非常类似的账号密码&#xff0c;而且需要一个阀值控制伪造的数量。 在这需求上&#xff0c;还有一个就是需要控制生成的比率、跳出率不能过高或者太低。 对此就随手用python写了一个&#xff0c;bug不知道有木有&#xff0c;没有测&…