序文
私たちの日常の事業開発プロセスでは、それは多かれ少なかれ同時機能を使用されます。だから、同時使用機能の間に、それは確かに次のような問題に遭遇します
同時スレッドプールは、どのくらいの最後に設定されていますか?
通常は少し古いプログラマは、このような声明を聞いたことがあり(NはCPUの数を表します)
CPU集約型アプリケーションは、スレッドサイズはN + 1に設定されています
IO負荷の高いアプリケーション、スレッドプールのサイズは2Nに設定されています
最後にこの引数が正しくありませんか?
実際には、これは本当から遠いです。なぜ?
まず、我々はこの文が真であると仮定して、フリップサイドを持っているし、我々は、単一のサーバーに展開されているどのように多くのサービスを気にしません。スレッドプールのサイズは、サーバのみについて監査することができますので、このステートメントが正しくありませんので。これは、特にどのようにそれのサイズを設定する必要がありますか?
このアプリケーションは、2つのハイブリッドであり、中にCPU集中型のタスク、だけでなく、IO集約型であると仮定すると、私たちはそれを設定する方法を変更?それはそれをスローすることを決定するだけでは難しいことではありませんか?
だから、最後に、私たちはどのようにそれのスレッドプールのサイズを設定するには?あなたはそれを上陸させた案内するいくつかの具体的な実践はありますか?のは、より深く見てみましょう。
リトルの法則(リトル・ルール)
システム要求の到着率の積と要求の平均数は、それぞれ別々の要求に要する時間に等しいです。
サーバ単核球と仮定すると、対応するサービス要求量(QPS)ことを確認する必要があります10は、要求は、実際に、すなわち1秒、サーバ10は、要求を処理するたびに、ハンドル、10件のスレッドが必要
同様に、我々は、スレッドプールのサイズを決定するために、法律・リトル(リトルの法則)を使用することができます。私達はちょうど要求到着率と処理するための平均時間を計算する必要があります。その後、リトル(リトルの法則)へのルールの値は、平均的なシステム要求から計算することができます。次の式を用いて推定
* スレッドプールのサイズ=((IO時間+スレッドCPU時間をスレッド)/タイムCPUスレッド)CPU番号**
練習
式では、我々は3つの特定の値を理解する必要があります
かかる要求時間(IO時間+スレッドCPU時間をスレッド)
この要求時間(スレッドのCPU時間)
CPUの数
要求時間がかかります
Webサービス・コンテナ、フィルターによって消費取得時間の前後にリクエストを傍受することができます
public class MoniterFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(MoniterFilter.class); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long start = System.currentTimeMillis(); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String uri = httpRequest.getRequestURI(); String params = getQueryString(httpRequest); try { chain.doFilter(httpRequest, httpResponse); } finally { long cost = System.currentTimeMillis() - start; logger.info("access url [{}{}], cost time [{}] ms )", uri, params, cost); } private String getQueryString(HttpServletRequest req) { StringBuilder buffer = new StringBuilder("?"); Enumeration<String> emParams = req.getParameterNames(); try { while (emParams.hasMoreElements()) { String sParam = emParams.nextElement(); String sValues = req.getParameter(sParam); buffer.append(sParam).append("=").append(sValues).append("&"); } return buffer.substring(0, buffer.length() - 1); } catch (Exception e) { logger.error("get post arguments error", buffer.toString()); } return ""; } }
CPU 计算时间
CPU 计算时间 = 请求总耗时 - CPU IO time
假设该请求有一个查询 DB 的操作,只要知道这个查询 DB 的耗时(CPU IO time),计算的时间不就出来了嘛,我们看一下怎么才能简洁,明了的记录 DB 查询的耗时。
通过(JDK 动态代理/ CGLIB)的方式添加 AOP 切面,来获取线程 IO 耗时。代码如下,请参考:
public class DaoInterceptor implements MethodInterceptor { private static final Logger logger = LoggerFactory.getLogger(DaoInterceptor.class); @Override public Object invoke(MethodInvocation invocation) throws Throwable { StopWatch watch = new StopWatch(); watch.start(); Object result = null; Throwable t = null; try { result = invocation.proceed(); } catch (Throwable e) { t = e == null ? null : e.getCause(); throw e; } finally { watch.stop(); logger.info("({}ms)", watch.getTotalTimeMillis()); } return result; } }
CPUの数
論理CPUの数は、スレッドプールのサイズが与えられたときCPUの参照番号
猫の/ proc / cpuinfoの| grepの "プロセッサ" | トイレ-l
概要
適切な設定スレッドプールのサイズは実際には容易ではありませんが、上記の式と特定のコードによって、我々はすぐに設定どのくらい地面このスレッドプールを計算することができます。
しかし、最終的には終わりが、我々はまだ圧力試験、圧力テストテストテストによって微調整するためにのみ、その後、我々は大きさの最終的な構成が正確であることを保証することができます必要があります。
I種類の公共のホ[プログラマ]の懸念へようこそドキュメントが内側になり、記事の冒頭は、内側に更新されますマークします。
遂に
サポートのおかげで、ヨーヨーの記事を覚えて賞賛のポイントのように、みんなと共有へようこそ!