ROCKETMQ source of information on the implementation of distributed things are not fully open source, I am based on 3.4.6 analysis. One of the classes is transactionmqproducer. Source code Analysis Transactionmqproducer is the core base class for sending distributed thing messages, where Sendmessageintransaction is the primary sending method. The core steps of the approach are 3 steps.
1.1. Producer sends a prepared message to the broker.
1.2. Call Localtransactionexecutor to execute local business logic and commit things.
1.3. After the local thing is committed, send the thing confirmation message. Analyze Sendmessageintransaction Source code
Public Transactionsendresult sendmessageintransaction (final Message msg,final Localtransactionexecuter TranExecuter,
Final Object Arg) throws Mqclientexception {//1. Tranexecutor, you need to apply your own development implementation if (NULL = = Tranexecuter) {
throw new Mqclientexception ("Tranexecutor is null", NULL); }//2.
Check messages for various properties and reload Validators.checkmessage (MSG, this.defaultmqproducer);
Sendresult sendresult = null;
3.1 Set Send Message property type, thing Prep message Messageaccessor.putproperty (MSG, messageconst.property_transaction_prepared, "true"); 3.2 Set the GROUP messageaccessor.putproperty (msg, Messageconst.property_producer_group, THIS.D) that the message belongs to
Efaultmqproducer.getproducergroup ());
try {//4. Send a preliminary message Sendresult = This.send (msg);
} catch (Exception e) {throw new Mqclientexception ("Send Message Exception", e); }//5. Initialize local thing reload--unknow unknown state localtransactionstate LocaltranSactionstate = Localtransactionstate.unknow;
Throwable localexception = null; 6. Determine the status of the Send prestaged message switch (Sendresult.getsendstatus ()) {case SEND_OK: {try {if (Sendresult
. Gettransactionid ()! = null) {Msg.putuserproperty ("__transactionid__", Sendresult.gettransactionid ()); }//7.
Executes the local thing logic, the user implements the business logic part localtransactionstate = Tranexecuter.executelocaltransactionbranch (msg, ARG);
if (null = = localtransactionstate) {localtransactionstate = Localtransactionstate.unknow; }//8. Determine the local thing state if (localtransactionstate! = localtransactionstate.commit_message) {log.in
Fo ("Executelocaltransactionbranch return {}", localtransactionstate);
Log.info (Msg.tostring ());
}}catch (Throwable e) {log.info ("Executelocaltransactionbranch exception", e);
Log.info (Msg.tostring ()); Localexception= e;
}} break; Case Flush_disk_timeout:case Flush_slave_timeout:case slave_not_available:localtransactions
Tate = Localtransactionstate.rollback_message;
Break
Default:break;
}//9 Send a thing confirmation message based on the local state of things.
try {this.endtransaction (Sendresult, Localtransactionstate, localexception);
} catch (Exception e) {log.warn ("Local transaction execute" + localtransactionstate
+ ", but end broker transaction failed", E); }//1.
Build returns the result of sending things transactionsendresult Transactionsendresult = new Transactionsendresult ();
Transactionsendresult.setsendstatus (Sendresult.getsendstatus ());
Transactionsendresult.setmessagequeue (Sendresult.getmessagequeue ());
Transactionsendresult.setmsgid (Sendresult.getmsgid ());
Transactionsendresult.setqueueoffset (Sendresult.getqueueoffset ()); TranSactionsendresult.settransactionid (Sendresult.gettransactionid ());
Transactionsendresult.setlocaltransactionstate (localtransactionstate);
return transactionsendresult; }
Analyze
endtransactionSource
private void Endtransaction (//Final Sendresult Sendresult,//FINAL localtransactionstate Localt Ransactionstate,//Final throwable localexception) throws RemotingException, Mqbrokerexception,interruptedexc Eption, Unknownhostexception {//message ID final MessageId id = Messagedecoder.decodemessageid (Sendresult.getm
SgId ());
Thing ID String TransactionID = Sendresult.gettransactionid (); Get brokeraddr final String brokeraddr = This.mQClientFactory.findBrokerAddressInPublish (sendresult.getmessageque
UE (). Getbrokername ());
Building a Confirmation object request header information Endtransactionrequestheader Requestheader = new Endtransactionrequestheader ();
Set the thing Request ID Requestheader.settransactionid (TransactionID);
Sets the offset of the message offset Requestheader.setcommitlogoffset (Id.getoffset ()); Determine the local thing State switch (localtransactionstate) {case Commit_message:/** set Success Message type **/RequestheadEr.setcommitorrollback (Messagesysflag.transactioncommittype);
Break Case Rollback_message:/** set rollback message type **/requestheader.setcommitorrollback (messagesysflag.transactionrollbacktype
);
Break
Case UNKNOW:requestHeader.setCommitOrRollback (Messagesysflag.transactionnottype);
Break
Default:break;
} requestheader.setproducergroup (This.defaultMQProducer.getProducerGroup ());
Requestheader.settranstatetableoffset (Sendresult.getqueueoffset ());
Requestheader.setmsgid (Sendresult.getmsgid ()); String Remark = localexception! = null?
("Executelocaltransactionbranch Exception:" + localexception. ToString ()): null;
/** sends a thing acknowledgment message **/This.mQClientFactory.getMQClientAPIImpl (). Endtransactiononeway (Brokeraddr, Requestheader, remark,
This.defaultMQProducer.getSendMsgTimeout ());
}