curator icon indicating copy to clipboard operation
curator copied to clipboard

a concurrent issue found in TreeCache.class,explanation along with co…

Open leyoliu1987 opened this issue 7 years ago • 9 comments

here sleep a shot time to ensure  invoking method "publishEvent"  after all other eventType case,

because I found more event such as NODE_ADD received again after I have received INITIALLIZED eventType when I restart my Application in my own Linsener which implements the interface TreeCacheListener,so,I believe a concurrent issue occurs, I guess attitional code execution delayed the invoke method "publishEvent" in CASE GET_DATA.

leyoliu1987 avatar Dec 14 '17 08:12 leyoliu1987

hi leyoliu,

Thank you for contribution.

There are many tests about order of events on startup. For example: TestTreeCache.testStartup()

Are you able to write a test to show the failure you see?

Thank you, Scott

dragonsinth avatar Dec 14 '17 17:12 dragonsinth

Hi Mr Scott, Thank you for reply me! I test my appliation many times again, below is my simple code and running result and zookeeper Node structure.

zk node structure: TOPIC LISTENERIPS:192.168.58.22 SENDCHANNEL SMS:true WECHAT:false WEBSOCKET:dragnet SERVERNAME:test TOPICNAME:dragnet

public class TopicTreeListener implements TreeCacheListener {

@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
	ChildData data = event.getData();
	Type type = event.getType();
	System.out.println("type="+type);
    }

}

below is my running result:

type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=INITIALIZED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED

image

leyoliu1987 avatar Dec 16 '17 15:12 leyoliu1987

Hi Mr Scott, I'm waiting your reply

leyoliu1987 avatar Dec 19 '17 05:12 leyoliu1987

Hi Mr Scott, Thank you for reply me! I test my appliation many times again, below is my simple code and running result and zookeeper Node structure.

zk node structure: TOPIC LISTENERIPS:192.168.58.22 SENDCHANNEL SMS:true WECHAT:false WEBSOCKET:dragnet SERVERNAME:test TOPICNAME:dragnet

public class TopicTreeListener implements TreeCacheListener {

@Override public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception { ChildData data = event.getData(); Type type = event.getType(); System.out.println("type="+type); } }

below is my running result:

type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED type=INITIALIZED type=NODE_ADDED type=NODE_ADDED type=NODE_ADDED

https://user-images.githubusercontent.com/32660478/34071705-4276f034-e2b5-11e7-966c-d69d153211ed.png

leyoliu1987 avatar Dec 19 '17 05:12 leyoliu1987

Hi @leyoliu1987 I tried but I cannot reproduce your problem.

I added a new example, https://github.com/apache/curator/blob/master/curator-examples/src/main/java/cache/TreeCacheExample.java

When I run TreeCacheExample, I do not your problem. I see INITIALIZED happen at the very end after all NODE_ADDED events.

dragonsinth avatar Dec 20 '17 23:12 dragonsinth

Hi Mr Scott, I absolutely aggree you are right when you use "cache.getListenable().addListener(T listener)",can you try more time by using "cache.getListenable().addListener(T listener, Executor executor)" like below:

public class TreeCacheExample { public static void main(String[] args) throws Exception { CuratorFramework client = CreateClientExamples.createSimple("127.0.0.1:2181"); client.getUnhandledErrorListenable().addListener((message, e) -> { System.err.println("error=" + message); e.printStackTrace(); }); client.getConnectionStateListenable().addListener((c, newState) -> { System.out.println("state=" + newState); }); client.start();

    TreeCache cache = TreeCache.newBuilder(client, "/").setCacheData(false).build();
     **ExecutorService pool = Executors.newFixedThreadPool(10);**
    cache.getListenable().addListener((c, event) -> {
        if ( event.getData() != null )
        {
            System.out.println("type=" + event.getType() + " path=" + event.getData().getPath());
        }
        else
        {
            System.out.println("type=" + event.getType());
        }
    },**pool** );
    cache.start();

    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    in.readLine();
}

}

leyoliu1987 avatar Dec 22 '17 08:12 leyoliu1987

if use " ExecutorService pool = Executors..newCachedThreadPool()" as ThreadPool is no problem. I don't know why .

leyoliu1987 avatar Dec 22 '17 08:12 leyoliu1987

Hi @leyoliu1987,

I think the executor is your problem. If you use Executors.newFixedThreadPool(10) you are creating 10 different threads to handle events on. When numerous events fire at close to the same time, you will handle all of those events concurrently. That makes you will observe them simultaneously / concurrently / out of order / in a racy way. So this is not a TreeCache problem. If you use a single-threaded executor you should see everything in sequential order.

Thanks! Scott

dragonsinth avatar Dec 22 '17 16:12 dragonsinth

I encountered the same problem,although no add new node!

abxworld avatar Dec 19 '19 12:12 abxworld

Closed as inactive. Also TreeCache is deprecated in favor of CuratorCache.

tisonkun avatar Sep 25 '22 14:09 tisonkun