puniverse / quasar

Fibers, Channels and Actors for the JVM
http://docs.paralleluniverse.co/quasar/
Other
4.56k stars 575 forks source link

fiber parking or parked has no chance to to call `park` #221

Open smallnest opened 8 years ago

smallnest commented 8 years ago

I write a program that queries memcached and sends a lot of http requests to CDN servers. I use comsat http client to send http requests. When I test its performance, AssertionError was thrown (quasar is 0.7.6, comsat-httpclient-0.7.0.jar):

Exception in Fiber "fiber-10002608" java.lang.AssertionError: Unexpected task state (fiber parking or parked has no chance to to call `park`): -2
    at co.paralleluniverse.concurrent.forkjoin.ParkableForkJoinTask.park(ParkableForkJoinTask.java:223)
    at co.paralleluniverse.fibers.FiberForkJoinScheduler$FiberForkJoinTask.park(FiberForkJoinScheduler.java:288)
    at co.paralleluniverse.fibers.Fiber.park1(Fiber.java:707)
    at co.paralleluniverse.fibers.Fiber.park(Fiber.java:620)
    at co.paralleluniverse.fibers.Fiber.park(Fiber.java:624)
    at co.paralleluniverse.fibers.FiberAsync.run(FiberAsync.java:121)
    at co.paralleluniverse.fibers.httpclient.AsyncHttpReq.run(AsyncHttpReq.java:26)
    at co.paralleluniverse.fibers.httpclient.FiberHttpClient.doExecute(FiberHttpClient.java:96)
    at co.paralleluniverse.fibers.httpclient.FiberHttpClient.execute(FiberHttpClient.java:161)
    at co.paralleluniverse.fibers.httpclient.FiberHttpClient.execute(FiberHttpClient.java:190)
    at com.abc.common.util.HttpUtil.getLocationByHttpHEAD(HttpUtil.java:549)
    at com.abc.mgt.ContentRouterProxy.callCCRForClientEdgeCache(ContentRouterProxy.java:388)
    at co.paralleluniverse.strands.SuspendableUtils$VoidSuspendableCallable.run(SuspendableUtils.java:44)
    at co.paralleluniverse.strands.SuspendableUtils$VoidSuspendableCallable.run(SuspendableUtils.java:32)
    at co.paralleluniverse.fibers.Fiber.run(Fiber.java:1072)

My question is why this exception was thrown and how to fix it? I can't find any document to avoid it.

pron commented 8 years ago

Can you share your code?

smallnest commented 8 years ago

It is a complex system that I try to replace threads with fibers and it has too many dependencies. I can exact the major biz logic as this:

            new Fiber<Void>(new SuspendableRunnable() {
                public void run() throws SuspendExecution, InterruptedException {
                    try {
                        c1.m1();
                    } catch (Exception ex) {

                    }
                }
            }).start();

            Class c1:

            @Suspendable
            pubic void m1() {
                //do something
                c2.m2()
                //do something
            }

            Class c2:
            @Suspendable
            pubic void m2() {
                //do something
                c3.m3()
                //do something
            }

            Class c3:
            @Suspendable
            pubic void m3() {
                //do something
                c4.m4()
                //do something
            }

            Class c4:
            @Suspendable
            pubic void m4() {
                //do something
                c5.m5()
                //do something
            }

            Class c5:
            @Suspendable
            pubic void m5() {
                //do something
                contentRouterProxy.m6()
                //do something
            }

            Class contentRouterProxy:
            @Suspendable
            pubic void m6() {
                //do something
                HttpUtil.getLocationByHttpHEAD()
                //do something
            }

            class HttpUtil:

            @Suspendable
            public static void getLocationByHttpHEAD(......)
                String location = ......

                for(int i = 0; i < maxRedirectLoopStatic; i++){
                    HttpUriRequest httpRequest = new HttpHead(location);
                    httpRequest.setHeader("Connection", "keep-alive");
                    CloseableHttpResponse response = client.execute(httpRequest);
                    //EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
                    response.close();

                    if (response.getStatusLine().getStatusCode() /100 = 3) {
                        location = getLocation(response)
                        continue
                    }

                    return

                }
                .....
            }

            public static RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(1000)
            .setConnectTimeout(1000)
            .setConnectionRequestTimeout(1000)
            .setRedirectsEnabled(false)
            .build();

            public static CloseableHttpClient client = FiberHttpClientBuilder.
            create(Runtime.getRuntime().availableProcessors()). // use 2 io threads
            setDefaultRequestConfig(requestConfig).
            disableConnectionState().
            setMaxConnPerRoute(20000).
            setMaxConnTotal(20000).build();

Basically a fiber runs nested methods and the last method uses comsat-httpclient to do redirection manually.

There are a lot of requests at that moment.

smallnest commented 8 years ago

Is one fiber parked more than once? At the first the fiber state is changed from RUNNABLE to PARKING, At that moment the fiber is parked again.

pron commented 8 years ago

Is one fiber parked more than once?

It appears that way from the exception, but I have a hard time seeing how this could happen. If you don't mind sharing your code, you can upload it here or send it to me personally (ron [at] ourdomain)