我的系统对它的工作有严格的“仅一次”的要求.它是一个事件驱动的系统,带有中间件,不能保证一次和一次消息传递(如果怀疑给定的消息是否是重新交付的,它将标记任何给定的消息为“已传递”).本质上,“仅一次”处理就归结为我们核心域对象的状态,即,这是一个相当标准的设置,…
>消息到达
>执行业务逻辑
>状态已更新
>生成输出并将其发送到下游系统
3必须最终达到数据库(帐簿和记录),4可以采用多种形式,但是所有形式都是到外部系统的某种消息传递.还有其他各种流程,但它们都归结为这种处理方式.所有消息将在核心域对象的单个实例上操作,因此该处理适合将该实例固定到单个jvm.
我的Q很笼统,可能太笼统了,但我还是会问.也就是说,在维持所需保证的前提下,可以采用哪些策略/模式来提高吞吐量?另外,会导致性能下降的主要陷阱是什么?
例如,一种思路是避免关键路径上的任何持久性,这归结为一个问题,即如何保持内存状态的一致性而不需要从数据库中刷新.
您可以假定可以通过某种分区策略进行横向扩展,但是该方面超出了q的范围.问号是关于如何在这样的系统中扩大单个节点的吞吐量.
请注意,这是大型企业环境中的java / oracle,因此利基硬件(例如exadata和朋友或某些高级网络工具包)很好.
解决方法:
在很大程度上,取决于您需要如何保证如何处理故障.使用平面日志文件和/或冗余服务器来保持持久性,您可以实现每秒超过一百万的消息传递速率.
您需要的主要模式是角色模式.为了提高吞吐量,您需要能够透明地批处理数据,这是设计的一部分.我个人喜欢使用直接ByteBuffer(大多数数据不在堆上),因为它们是处理大量数据的轻量级方式,可以轻松地将其复制和读取/写入NIO通道.我已经为无gc的输入/输出编写了自己的解析/日志库.
另一个有用的策略是预分配和回收对象.通过不创建垃圾(或仅创建每天可以收集一次的非常少量的垃圾),可以帮助消除GC的风险.
诀窍是在满足持久性保证之前,不释放处理结果. (最简单的方法是没有任何保证,并说最后几笔交易可能会丢失,将由人工处理)
会影响性能的主要因素是
> IO,您希望这是异步的.
>锁定过度
>创建很多对象将导致缓存效率低下(因为新对象会有效地滚动出有用的数据)回收的对象可能会保留在缓存中.
> GC可能会伤害最坏情况的延迟.如果您只关心吞吐量,那么这无关紧要.
>确保您预热了代码.默认情况下,您需要在短时间内执行10,000次方法调用(或具有一个循环多次的循环),以触发该方法进行编译.如果您的系统延迟低但吞吐量却不高,则可能无法编译大部分关键代码.
>确保您使用的是合适的硬件,并且具有Java的最新版本.较旧的机器和较旧的Java版本可能会慢很多.