简体   繁体   English

如何缓存Apache CXF为特定Java对象生成的编组SOAP XML以提高性能?

[英]How can I cache the marshalled SOAP XML generated by Apache CXF for a particular Java Object to improve performance?

In my application, we have a webservice method called getFoo() which returns a Foo object. 在我的应用程序中,我们有一个名为getFoo()的webservice方法,它返回一个Foo对象。 The getFoo() method is called several hundred times a second . getFoo()方法每秒调用几百次 The Foo object is Marshalled from our Java object to the SOAP XML response using Apache CXF. Foo对象使用Apache CXF从我们的Java对象编组到SOAP XML响应。

From profiling our application, we determined that the marshalling of this object (java object -> soap encoded xml) is the single greatest consumer of CPU cycles. 通过分析我们的应用程序,我们确定该对象的编组(java对象 - > soap编码的xml)是CPU周期的最大消费者。 and since our Foo object isn't changing very often, remarshalling this object each time is unnecessary. 由于我们的Foo对象不经常更改,因此每次都不需要重新编组此对象。

I figured this is a common optimization and wondered how others have addressed it. 我认为这是一个常见的优化,并想知道其他人如何解决它。 I briefly looked at the CXF docs and there is a Marshall interceptor which I could probably make use of. 我简要地看了一下CXF文档,还有一个我可以使用的Marshall拦截器。 I could create a Map which could map Foo objects to the XML encoded version. 我可以创建一个可以将Foo对象映射到XML编码版本的Map。 But, then a few other issues come up like how do you remove objects from this Map once they are no longer needed etc. It'd be nice if there was built in support for somehow detecting changes to the object and re-marshalling... Nothing impossible, but didn't want to reinvent the wheel. 但是,还有一些其他的问题出现了,如果不再需要它们如何从这个地图中删除对象等等。如果内置支持以某种方式检测对象的更改并重新编组,那就太好了。没有什么不可能,但不想重新发明轮子。

EDIT (6/16/09) : Have made some progress by making a custom BareOutInterceptor and modifying the Interceptor chain to call the custom one. 编辑(6/16/09) :通过制作自定义BareOutInterceptor并修改拦截器链以调用自定义链来取得一些进展。 The custom adds some additional logic to only call the "writeParts(....)" method which performs the marshalling only the once for a given java object. 自定义添加了一些额外的逻辑,只调用“writeParts(....)”方法,该方法仅对给定的java对象执行一次编组操作。 Will post solution once finished. 完成后会发布解决方案。 Also, I renamed the question. 另外,我重新命名了这个问题。

Ok, not exactly the answer you are looking for, but anyway: The reason that REST is used in Webservices with high traffic (eg Google), is that REST is designed to be cacheable - whereas SOAP is just NOT designed to be cachable. 好吧,不完全是你正在寻找的答案,但无论如何:REST用于具有高流量的Web服务(例如谷歌)的原因是REST被设计为可缓存的 - 而SOAP只是不设计为可缓存的。

SOAP is basically based on (per HTTP definition) non-cacheable POST requests, and REST uses GET - which is easy to cache. SOAP基本上是基于(每个HTTP定义)不可缓存的POST请求,而REST使用GET - 这很容易缓存。

You would have to inspect the SOAP (POST) request before it goes to the actual Webservice - ie using a proxy. 您必须在进入实际Web服务之前检查SOAP(POST)请求 - 即使用代理。 "Standard" proxies are usually unaware of SOAP syntax. “标准”代理通常不了解SOAP语法。

IBM's WebSphere Application Server though can do that IBM的WebSphere Application Server虽然可以做到这一点

Regards, Olaf 此致,奥拉夫

There is no strict requirement in SOAP that you need to use a framework like CXF to handle the server or client SOAP endpoints. SOAP中没有严格要求您需要使用像CXF这样的框架来处理服务器或客户端SOAP端点。 We just ran into client thread deadlocks when using an Axis 1.4-based SOAP client to talk to an Axis 1.1-based server, and fixed them by ditching Axis and making the requests in hand-written code. 当使用基于Axis 1.4的SOAP客户端与基于Axis 1.1的服务器通信时,我们遇到了客户端线程死锁,并通过抛弃Axis并在手写代码中发出请求来修复它们。 We had to lie to the Axis server by telling it we still had an Axis client, but felt no remorse! 我们不得不撒谎到Axis服务器,告诉它我们还有一个Axis客户端,但感到没有悔意! ;-) ;-)

Similarly, you should be able to bypass CXF and generate SOAP responses in your own handwritten java code. 同样,您应该能够绕过CXF并在您自己的手写Java代码中生成SOAP响应。 Then you can use a Map to cache your marshalled (unparsed, serialized) XML strings and eliminate this hotspot. 然后,您可以使用Map缓存已编组(未解析,序列化)的XML字符串并消除此热点。

Strongly agree with Olaf on REST: if you fully leverage HTTP, then all this caching happens for free in all the intermediate caches between your server and your clients. 非常赞同Olaf关于REST:如果你充分利用HTTP,那么所有这些缓存都会在服务器和客户端之间的所有中间缓存中免费发生。 That's certainly something to consider for new services. 对于新服务来说,这当然是值得考虑的事情。

Update: CXF has the notion of customizable interceptor chains . 更新:CXF具有可定制拦截器链的概念。 One type of outbound interceptor is for the MARSHAL phase, so it sounds like you could add this cache there without having to ditch CXF. 一种类型的出站拦截器用于MARSHAL阶段,所以听起来你可以在那里添加这个缓存,而不必抛弃CXF。 Perhaps a CXF expert can verify that for us? 也许CXF专家可以为我们验证这一点?

The Foo object is Marshalled from our Java object to the SOAP XML response using Apache CXF. Foo对象使用Apache CXF从我们的Java对象编组到SOAP XML响应。
.. the single greatest consumer of CPU cycles. .. CPU周期的最大消费者。 and since our Foo object isn't changing very often, remarshalling this object each time is unnecessary. 由于我们的Foo对象不经常更改,因此每次都不需要重新编组此对象。

Does the client application need to know of changes in Foo instantly or as soon as possible? 客户端应用程序是否需要立即或尽快知道Foo中的更改?

Why not cache it on the consumer/client side? 为什么不将它缓存在消费者/客户端? A design where you are calling the same web service method hundreds of times per second probably isn't the best. 您每秒数百次调用相同Web服务方法的设计可能不是最好的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM