2014-11-22 74 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註釋和附加線程池