- should not block while processing a message
- prefer immutable message
- batch and piggy(捎带)
- avoid polling, try callback notify
- cache,但是要注意数据同步更新问题
- 顺序
- 事务(事务管理器要求事务处理必须在同一个线程内)
生产者生成过快或者消费者消费过慢都会导致队列堵塞。反之,则会导致资源浪费。
解决方案。生产者和消费者之间除了消息通道,还应该有控制通道。类似于TCP的拥塞控制。 另外,在现实场景中,生产者的生成速度往往是不可控制的,取决于业务需求。这就对消费者的处理能力提出了要求。
要防止消息丢失,要求队列无限大。而内存对了是不可能做到,所以只能持久化到磁盘。但是要求处理速度够快,所以应该尽量把消息缓存到内存中。不过需要解决好内存和磁盘之间的同步问题。
事实上,持久化消息队列(Persistent Message Queue)的需求很常见。一个原因就是上面提到的,消息队列满了,需要转存到磁盘上。第二个原因就是消息处理或者发送失败了,是简单的丢弃呢?还是先放到磁盘中稍后再试(当然,最好有个retryCount计数,避免垃圾消息)。
引入持久化消息队列,最主要的问题就是如何缓冲区队列与磁盘队列之间的同步问题。在消息处理完成后,一定要记得把磁盘中的消息给删除掉,否则会导致消息重复处理,同时会导致queue堆积。
网络IO往往是性能的主要消耗点,所以能够减少就尽量减少。比如CSS合并和分片。facade模式和DTO也是这方面的考虑。一个常见的实现就是生产者先将消息写到本地,等缓冲区满了或者打到一定的条件时,再一次批量发送给消费者。所以批量往往跟异步相关联。对于实时性要求不是很高的业务场景,这是一个不错的优化点。比如facebook的主动推送,就是把5s内的消息合并再推送给客户端。
尽量去中心化,尽量使每个服务对等,尽量让你的服务无状态,这样你的服务就很容易线性拓展。
尽量让每一个操作都是幂等的。
为了避免资源的创建和销毁成本,往往对资源进行cache,就是常见的pool,比如线程池,连接池。而且是prefork,系统启动的时候就分配好。