Symptom
Code processing process:
Public class ensuretrademsgaction implements runnable {private ordermessage message; Public void run () {id = message. GETID (); Model = orderservice. getorder (ID); // call model remotely. setmemberid (message. getmemberid (); Model. setname (message. getname (); Save (model); // Save the database }}
Two messages:
{id:1,memberId:"a",name:"a"}{id:2,memberId;"b",name:"bb"}
Finally, the two data entries in the database are:
id memberId name1 b bb2 b bb
Reasoning
We can see that part of the first message is overwritten by the second message.
The analysis code concludes that the process looks like this:
1. received the first message.
2. Retrieve the ID and execute a remote call (the second message is received at this time, which overwrites the message variable)
3. Get the memberid and name in the message (Note: The memberid and name are already the values of the second message)
4. Save to database
View the action construction method for Cause Analysis
In this way, the constructed action is a Singleton, and the message is a member variable, so it is not thread-safe.
<Bean id = "ensuretrademsgaction" class = "com. Alibaba. China. Levit. biz. daemon. Rialto. Action. ensuretrademsgaction"/> Note: no scope = "prototype"
The following two threads are used in the message receiving and processing process:
1. When receiving a message, the corresponding number of sessions will be generated according to the number of configured instances to receive the message, and then the multi-thread calls the dowork of asyncworker to process the message.
{code}public interface AsyncWorker { boolean doWork(Serializable message);}{code}
2. When Rialto processes messages through pipeline, it will be processed through the thread pool (the thread pool size is specified by the poolsize in the configuration)
{code}<pipeline name="bailProccess" poolSize="2" watermark="100" exception="logging">{code}{code}public void submitTask(Runnable task) {ExecutorService service = pool;if (service != null) {service.execute(task);}}{code}
Note: executes the given command at some time in the future. the command may execute in a new thread, In a pooled thread, or in the calling thread, at the discretion of the executor implementation.
So
The problem occurs because the message variable is overwritten by the next thread during multi-thread processing, resulting in data inconsistency.
Solution
1. Add scope = "prototype" to get different instances for each getbean, so there is a thread security problem. Disadvantage: You must construct an instance every time...
2. Miscellaneous