42

再谈服务流量控制(10.8)

 5 years ago
source link: http://blog.sina.com.cn/s/blog_493a84550102xxyb.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在SOA服务治理中流量控制,服务限流或断流都是经常谈到的内容,今天再谈下ESB服务总线里面的服务流量控制策略和控制方法逻辑。对于服务流量控制,其目的是确保ESB服务总线运行正常,而不会被某些业务系统的大并发,大数据量异常消费调用导致整个ESB服务总线宕机或内存溢出。

ESB服务总线的正常运行主要涉及到可用连接数,可用内存数两个关键指标。一个是要确保当前线程池有可用的连接能够用于新的服务消费和调用,其次就是要确保正常的JVM内存回收机制能够确保当前的JVM有可用的内存,而不是内存持续上升导致内存溢出。

我们常说对于ESB服务总线,对于大并发小数据量,耗时短的服务调用支撑是没有任何问题的,由于数据量小内存不会出问题,由于调用时间短可用连接使用也不会有问题。而经常出问题的都是其他一些扩展场景。

场景1:大并发量小数据量,耗时长

这是一个典型场景,比如查询服务接口,本身查询条件和查询返回的数据量都很小,但是源系统根据查询条件来得出查询结果相对耗时,这就是典型的并发大数据量小,但是耗时长的场景。在这种场景下,内存没有任何问题,但是由于耗时长,线程池中的连接会一直被占用无法释放,这就导致新的需求无法获取连接的问题,这个实话一般会导致由于服务获取可用连接的超时报错。但是这种场景下往往Server本身不会整个宕机或不可用。更多的是并发服务请求排队等待服务连接。

场景2:大数据量调用

大数据量的服务调用一般来说整个服务响应时间也会增加,即耗时也会增长。因此大数据量调用,不管是否是大并发都容易引起内存溢出问题。即只要是大数据量调用,服务响应耗时又长,即代表这个时候这个服务运行消息体一直在内存里面,JVM也无法进行内存回收。直接导致内存溢出,整个Server宕机掉。这也是常说的,大数据量调用往往才是最容易导致ESB服务总线出问题的地方。

流控策略1:对于大并发下的流控策略

对于服务大并发下的流控策略相对来说比较简单,一般不会说直接去断流完全禁止访问,而是分配受控的可用线程和连接数给服务请求。在这种情况下,如果出现大并发调用,就在入口处排队等待,而不是占用线程池中的其它可用连接。通过这种方式做限流处理,可以确保服务器资源和连接不被但个服务调用全部消耗完。

如果要通过程序来实现限流或断流,那么这个就需要设定一个时间间隔,我们可以动态的计算最近的一个时间间隔中的服务调用并发数,比如最近1分钟的服务调用并发数,如果并发数大于1万次就直接拒绝访问返回错误,如果并发数在1万次以内就访问通过。由于这种方式本身会导致服务调用异常,因此如果这种直接返回错误异常,往往会影响到业务,因此对于这种方式还是要慎重使用。或者在实现的时候一定要考虑清楚合理的业务并发量,并设置一个阈值,超过阈值的200%或300%才做拒绝处理。

ESB总线本身也提供出口流控,即大并发请求缓慢推给后端系统,这个和消息中间件本身的后端系统并发削峰是一个道理,一般只在后端需求存在明显的性能问题的时候才会去启用。

场景1:大数据量小的流控策略

大数据量服务消费调用对ESB服务总线的影响最大。这种调用本身分为两个场景,一个是对于导入类服务实际服务输入的数据量就很大,还有一类是对于查询类服务没有做分页处理,服务响应输出的数据量很大。对于两种场景往往都容易导致总线内存溢出或管道破裂。

对于导入类服务,需要进行入口流控,即收到服务请求后,计算数据量,如果数据量大于基准值,则直接返回错误和异常,提升报文量太大无法处理。但是这种情况下由于需要接收到所有报文才能够计算真正的报文量,因此服务调用耗时仍然会很长,比如30秒或更长,因此仍然会占有大量的连接。

对于查询类服务,即在获取到源端系统返回的消息后,计算数据量,如果数据量大于基准值,也是不进行传输处理,直接返回给客户端异常错误。对于这种情况同样需要接收完所有的数据后才知道数据量有多大,因此在整个过程中也会一直占用连接。

上面两种方式同样都会耗费JVM内存,但是好处就是获取到信息后执行流控处理后可以完成请求调用直接返回错误或异常,在返回异常后该连接可以关闭掉,并且JVM可以启动内存回收。而不是等待大数据请求传输过程完成才能够去回收内存。

另外我一直在考虑JVM有无一直内存回收机制,即如果观察到内存使用率达到某个临界值,比如超过80%,对于耗内存的线程直接进行强制进行内存回收而不需要等待线程运行完成。如果有这样的机制,那么就可以确保JVM内存不会异常,整个总线仅仅是个别大数据量调用服务报错,而不会影响到其它服务。

其次,大数据量调用一遍也会长耗时,为了减少长耗时的服务调用,对于服务调用的超时时间设置也需要慎重。在前面已经讲过有两个超时时间,一个是连接超时,即连接到源端系统超时,这个要尽量端,只要发现源端系统访问不了直接报错超时;还有一个就是数据接收超时,对于这个超时也不要设置太大的值,对于大数据量调用超过这个值,即使数据没有接收完,也报超时,超时后JVM就可以快速启动垃圾回收释放内存。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK