您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Dubbo并發(fā)調(diào)優(yōu)的參數(shù)分別是什么,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
消費(fèi)端調(diào)優(yōu):
一、connections
這個(gè)參數(shù)可以在服務(wù)提供端發(fā)布服務(wù)的時(shí)候配置,也可以在消費(fèi)端引用服務(wù)的時(shí)候配置,但是這個(gè)值是只對(duì)消費(fèi)端生效的,所以一般是服務(wù)提供端不建議配置,如果配置,請(qǐng)斟酌一下。不管是在消費(fèi)端或者服務(wù)提供端,如果對(duì)某個(gè)服務(wù)配置了connections參數(shù),并且該參數(shù)大于1,那么就會(huì)導(dǎo)致消費(fèi)端在創(chuàng)建該服務(wù)的遠(yuǎn)程socketclient的時(shí)候(如果是dubbo協(xié)議的話(huà))將會(huì)給該服務(wù)初始化一個(gè)私有的socketclient。所以一般不建議對(duì)這個(gè)值進(jìn)行調(diào)整。
服務(wù)端優(yōu)化調(diào)整:
相對(duì)余消費(fèi)端,服務(wù)端調(diào)優(yōu)的參數(shù)相對(duì)多一些,但是配置的時(shí)候也需要謹(jǐn)慎。
一、executes
這個(gè)參數(shù)是可以精確到方法級(jí)別的參數(shù),就是可以指定調(diào)用遠(yuǎn)程接口某個(gè)方法的是該參數(shù)的值。具體是怎么配置的可以到官方文檔里面去看看那,這里只是描述這個(gè)參數(shù)實(shí)際意義以及使用的時(shí)候應(yīng)該注意點(diǎn)。
要說(shuō)這個(gè)參數(shù),就要所介紹ExecuteLimitFilter,他是這個(gè)參數(shù)使用者,看到Filter大家就應(yīng)該懂了,就是在每個(gè)方法請(qǐng)求前后加上業(yè)務(wù)邏輯。下面貼出里面的代碼:
@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);
}
}
}
上面這段代碼主要是看兩個(gè)地方,分別是第7行和第10行,第7行是獲取配置的executes的值,是一個(gè)int類(lèi)型的,描述數(shù)量,然后第10行是獲取當(dāng)前請(qǐng)求方法當(dāng)前的狀態(tài),里面既有一個(gè)active屬性(該屬性是AtomacInteger類(lèi)型的,大家應(yīng)該懂了為什么用這個(gè)類(lèi)型),表示當(dāng)前請(qǐng)求的方法處于執(zhí)行狀態(tài)的線程數(shù)量,如果這個(gè)值大于或者等于配置的值那么直接拋出異常,那么消費(fèi)端就會(huì)收到一個(gè)RPC的異常導(dǎo)致調(diào)用服務(wù)失敗,這是這個(gè)參數(shù)最終導(dǎo)致的效果。
二、actives
這個(gè)參數(shù)基本上和excetes一樣,但是有一點(diǎn)不同,在說(shuō)這不同之前,還是看看另一個(gè)Filter,看名字你們應(yīng)該就知道它是做什么的了—— ActiveLimitFilter,下面同樣貼出代碼:
@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一樣,唯一不同的就是多了一個(gè)等待時(shí)間,當(dāng)當(dāng)前執(zhí)行該方法的線程超出了最大限制,那么可以等待一個(gè)timeout時(shí)間,如果時(shí)間過(guò)了還是超出了最大限制,那么就拋出異常。這個(gè)相對(duì)余executes來(lái)說(shuō)溫柔那么點(diǎn)。這就是那點(diǎn)不同!
三、accepts
在看代碼之前先看看這個(gè)參數(shù)的意思,這個(gè)參數(shù)是告知服務(wù)提供端能接收多少個(gè)消費(fèi)端連接該服務(wù)提供方。下面接著上代碼,這個(gè)參數(shù)的體現(xiàn)是在類(lèi)AbstractServer中。代碼如下:
要說(shuō)這個(gè)參數(shù),就要所介紹ExecuteLimitFilter,他是這個(gè)參數(shù)使用者,看到Filter大家就應(yīng)該懂了,就是在每個(gè)方法請(qǐng)求前后加上業(yè)務(wù)邏輯。下面貼出里面的代碼:
@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);
}
這個(gè)方法是每個(gè)消費(fèi)端向服務(wù)提供端創(chuàng)建一個(gè)socket連接的時(shí)候都會(huì)觸發(fā),上面可以清晰看到如果連接當(dāng)前服務(wù)端的消費(fèi)端數(shù)量超出了配置的值,那么將會(huì)關(guān)閉當(dāng)前消費(fèi)端連接的請(qǐng)求。這個(gè)只是對(duì)socket連接的數(shù)量限制,而不是像上面兩個(gè)參數(shù)對(duì)調(diào)用線程的配置。
以上歸納出的幾個(gè)參數(shù)建議服務(wù)端生效的在服務(wù)端配置,消費(fèi)端生效的在消費(fèi)端配置,不然會(huì)導(dǎo)致一些不可控的現(xiàn)象出現(xiàn)。這也叫改哪里的東西就應(yīng)該在哪里,而不能亂放。
上述就是小編為大家分享的Dubbo并發(fā)調(diào)優(yōu)的參數(shù)分別是什么了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。