Hi Khan,
Thanks for pointing out this issue. I guess we could change logic to:
if (max > 0 && !RpcStatus.beginCount(url, methodName, max)) {
...
} else {
RpcStatus.beginCount(url, methodName);
}
And we should do the same logic in ExecuteLimitFilter. Let me know your
opinion on this.
Thanks,
-Ian.
On Wed, Dec 19, 2018 at 7:42 PM Imteyaz Khan <[email protected]> wrote:
> Hi All,
> I was trying to write UT for ActiveLimitFilter for RuntimeException
> scenarion and below is my UT for the same
>
> ActiveLimitFilterTest.java
>
> @Test()
> public void testInvokeRuntimeExceptionWithActiveCountMatch() {
> URL url =
> URL.valueOf("test://test:11/test?accesslog=true&group=dubbo&version=1.1&actives=0");
> Invoker<ActiveLimitFilterTest> invoker = new
> RuntimeExceptionInvoker(url);
> Invocation invocation = new MockInvocation();
> RpcStatus count = RpcStatus.getStatus(invoker.getUrl(),
> invocation.getMethodName());
> int beforeExceptionActiveCount = count.getActive();
> try {
> activeLimitFilter.invoke(invoker, invocation);
> } catch (RuntimeException ex) {
> int afterExceptionActiveCount = count.getActive();
> assertEquals("After exception active count should be same"
> , beforeExceptionActiveCount, afterExceptionActiveCount);
> }
> }
>
>
> Where I am expecting RpcStatus active count before call and after invoke
> should be same, irrespective of exceptional handling by ActiveLimitFilter
> (e.g. in this case it should be 0). UT showing me that after encountering
> exception it is not same, on my further investigation I found that
>
>
> - If there is no *actives (ACTIVE_KEY) *is set or if its value is less
> then *1* then it is always returning -1 (in UT active count), which
> means there is more number of call can be possible then it is
> allowed(this
> is my interpretation , correct me if this is wrong). e.g. if within a
> minute 10 call are allowed and if we encounter 5 *RuntimeException *then
> in total we could landed up allowing 15 invoke. I am suspecting this is
> because *max *being *0* we don't increment active count of RpcStatus
> and then decrease it in finally block where we have not even have
> increase
> the count, because *max* is before the count increment
>
> if (max > 0 && !RpcStatus.beginCount(url, methodName, max))
>
> As a reference I am copying the current master branch code of
> ActiveLimitFilter.java. Would request to correct my understanding if it is
> wrong, and if you feel my observation is correct then I would can raise a
> PR for fixing this issue.
> *Note: UT is in my local I have not checked in into any branch.
>
> if (max > 0 && !RpcStatus.beginCount(url, methodName, max)) {
> long timeout =
> invoker.getUrl().getMethodParameter(invocation.getMethodName(),
> Constants.TIMEOUT_KEY, 0);
> long start = System.currentTimeMillis();
> long remain = timeout;
> synchronized (count) {
> while (!RpcStatus.beginCount(url, methodName, max)) {
> try {
> count.wait(remain);
> } catch (InterruptedException e) {
> // ignore
> }
> 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: " + count.getActive()
> + ". max concurrent invoke limit: " + max);
> }
> }
> }
> }
>
> boolean isSuccess = true;
> long begin = System.currentTimeMillis();
> try {
> return invoker.invoke(invocation);
> } catch (RuntimeException t) {
> isSuccess = false;
> throw t;
> } finally {
> RpcStatus.endCount(url, methodName,
> System.currentTimeMillis() - begin, isSuccess);
> if (max > 0) {
> synchronized (count) {
> count.notifyAll();
> }
> }
> }
>