2014-11-22 44 views
2

我们有一项将某些数据写入文件的服务。每个请求新文件。例如:Java Spring异步性能

GET http://service.somecompany.com/save/{data} 

此请求将创建新文件/var/files/{random-name}.txt

服务使用@Async构建,以避免客户端在文件写入时等待。请参阅代码示例:

@Controller 
public class SomeController { 

    @Autowired 
    private SomeService someService; 

    @RequestMapping(value = "/save/{data}", method = RequestMethod.GET) 
    public @ResponseBody 
    String add(@PathVariable("data") String data) { 
     someService.saveData(data); 
     return "Ok!"; 
    } 
} 

SomeService实现:

@Service 
public class SomeServiceImpl implements SomeService { 

    @Async 
    public Future<Boolean> saveData(String data) { 
     // file saving with BufferedWriter ... 
     return new AsyncResult<Boolean>(successful); 
    } 
} 

目前每个请求将创建新的线程。但是,如果我将发送100 000个数据保存请求 - 它们将创建最大可用线程数。这将会写入数据太慢。 也许更好,以限制线程数:

<task:annotation-driven executor="taskExecutor" /> 
<bean id="taskExecutor" 
    class="org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean"> 
    <property name="corePoolSize" value="100" /> 
    <property name="maxPoolSize" value="250" /> 
    <property name="keepAliveSeconds" value="60" /> 
</bean> 

但如果限制 - 选择哪种尺寸?或者,也许这是真的不同地提高性能?你怎么看?

回答

0

按顺序完成磁盘IO的速度更快(特别是在非SSD驱动器上,我认为SSD的情况也是如此)。如果你的任务没有做任何事情,除了写入磁盘(没有计算从多线程中受益),我只会使用一个线程。

+0

感谢您的回答。 (这是kaqqao答案下的评论副本)。使用线程的动机不在进行一些计算。动机是避免客户等待。这很关键。预计的负载也是每秒100-200个请求。数据大小平均为1 KB。 SSD几乎不会..因此,线程数量之外的任何东西都不会保留.. – 2014-11-22 17:46:32

+1

无论您的池是否有1个线程或200个,用户都不会等待,因为您正在调用异步方法。作业将被放入队列中,等待一个线程执行它。写入200个文件所花费的时间可能会比一个线程少100个,因为您不会有更多的上下文切换,并且写入将是顺序的而不是并发的。我不明白你最后两句话。 – 2014-11-22 17:56:22

+0

对不起,我的英语不好。并感谢您的帮助。我将尝试用一个线程进行投票。 – 2014-11-22 18:36:19

0

让我们现实一点。 真的会有100000个同时请求吗?即使您每天看到10 000次访问,也不太可能同时有30次以上访问,更不用说确切的网址。另外,除非你有一些可笑的SSD阵列,否则你的限制因素将是磁盘I/O,而不是线程池。因此,总而言之,根据访问者数量,文件大小和磁盘性能,该池应该可能相当小,也许10个线程,除非您真的有一些恶劣的硬件和很多并发请求的可能性很高。编辑: 我完全同意J Nizet。如果你有一个单独的磁盘,并且线程除了写入(没有业务逻辑)什么都不做,那么一个线程是有意义的,因为这个线程一次只能写一个东西。

+0

感谢您的回答。 使用线程的动机不在进行一些计算。动机是避免客户等待。这很关键。预计的负载也是每秒100-200个请求。数据大小平均为1 KB。 SSD几乎不会..因此,线程数量以外的任何东西都不会保留.. – 2014-11-22 17:34:22

0

我看到2个解决方案:

  1. 写入延迟1线与预存使用异步文件IO像AsynchronousFileChannel持久化数据
  2. (看Java 7的文件功能或Google相关UTIL库),所以你止跌不需要@Async注释和附加线程池