消費端調優:
一、connections
這個參數可以在服務提供端發布服務的時候配置,也可以在消費端引用服務的時候配置,但是這個值是只對消費端生效的,所以一般是服務提供端不建議配置,如果配置,請斟酌一下,詳情請查看《對connections參數的設置 》。 不管是在消費端或者服務提供端,如果對某個服務配置了connections參數,並且該參數大於1,那麼就會導致消費端在創建該服務的遠程 socketclient的時候(如果是dubbo協議的話)將會給該服務初始化一個私有的socketclient。所以一般不建議對這個值進行調整。
服務端優化調整:
相對余消費端,服務端調優的參數相對多一些,但是配置的時候也需要謹慎。
一、executes
這個參數是可以精確到方法級別的參數,就是可以指定調用遠程接口某個方法的是該參數的值。具體是怎麼配置的可以到官方文檔裡面去看看那,這裡只是描述這個參數實際意義以及使用的時候應該注意點。
要說這個參數,就要所介紹ExecuteLimitFilter,他是這個參數使用者,看到Filter大家就應該懂了,就是在每個方法請求前後加上業務邏輯。下面貼出裡面的代碼:
@Activate(group = Constants.PROVIDER, value = Constants.EXECUTES_KEY) public class ExecuteLimitFilter implements Filter { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); String methodName = invocation.getMethodName(); int max = url.getMethodParameter(methodName, Constants.EXECUTES_KEY, 0); if (max > 0) { RpcStatus count = RpcStatus.getStatus(url, invocation.getMethodName()); if (count.getActive() >= max) { throw new RpcException("Failed to invoke method " + invocation.getMethodName() + " in provider " + url + ", cause: The service using threads greater than <dubbo:service executes=\"" + max + "\" /> limited."); } } long begin = System.currentTimeMillis(); boolean isException = false; RpcStatus.beginCount(url, methodName); try { Result result = invoker.invoke(invocation); return result; } catch (Throwable t) { isException = true; if(t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new RpcException("unexpected exception when ExecuteLimitFilter", t); } } finally { RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, isException); } } }上面這段代碼主要是看兩個地方,分別是第7行和第10 行,第7行是獲取配置的executes的值,是一個int類型的,描述數量,然後第10行是獲取當前請求方法當前的狀態,裡面既有一個active屬性 (該屬性是AtomacInteger類型的,大家應該懂了為什麼用這個類型),表示當前請求的方法處於執行狀態的線程數量,如果這個值大於或者等於配置 的值那麼直接拋出異常,那麼消費端就會收到一個RPC的異常導致調用服務失敗,這是這個參數最終導致的效果。
@Activate(group = Constants.CONSUMER, value = Constants.ACTIVES_KEY) public class ActiveLimitFilter implements Filter { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); String methodName = invocation.getMethodName(); int max = invoker.getUrl().getMethodParameter(methodName, Constants.ACTIVES_KEY, 0); RpcStatus count = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName()); if (max > 0) { long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.TIMEOUT_KEY, 0); long start = System.currentTimeMillis(); long remain = timeout; int active = count.getActive(); if (active >= max) { synchronized (count) { while ((active = count.getActive()) >= max) { try { count.wait(remain); } catch (InterruptedException e) { } long elapsed = System.currentTimeMillis() - start; remain = timeout - elapsed; if (remain <= 0) { throw new RpcException("Waiting concurrent invoke timeout in client-side for service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName() + ", elapsed: " + elapsed + ", timeout: " + timeout + ". concurrent invokes: " + active + ". max concurrent invoke limit: " + max); } } } } } try { long begin = System.currentTimeMillis(); RpcStatus.beginCount(url, methodName); try { Result result = invoker.invoke(invocation); RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, true); return result; } catch (RuntimeException t) { RpcStatus.endCount(url, methodName, System.currentTimeMillis() - begin, false); throw t; } } finally { if(max>0){ synchronized (count) { count.notify(); } } } } }上面代碼大致上和executes一樣,唯一不同的就是多了一個等待時間,當當前執行該方法的線程超出了最大限制,那麼可以等待一個timeout時間,如果時間過了還是超出了最大限制,那麼就拋出異常。這個相對余executes來說溫柔那麼點。這就是那點不同!
@Override public void connected(Channel ch) throws RemotingException { Collection<Channel> channels = getChannels(); if (accepts > 0 && channels.size() > accepts) { logger.error("Close channel " + ch + ", cause: The server " + ch.getLocalAddress() + " connections greater than max config " + accepts); ch.close(); return; } super.connected(ch); }這個方法是每個消費端向服務提供端創建一個socket連接的時候都會觸發,上面可以清晰看到如果連接當前服務端的消費端數量超出了配置的值,那麼將會關閉當前消費端連接的請求。這個只是對socket連接的數量限制,而不是像上面兩個參數對調用線程的配置。