You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

rpc_remoting_client.go 13 kB

4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. package rpc_client
  2. import (
  3. "math/rand"
  4. "strings"
  5. "sync"
  6. "time"
  7. )
  8. import (
  9. getty "github.com/apache/dubbo-getty"
  10. "github.com/pkg/errors"
  11. "go.uber.org/atomic"
  12. )
  13. import (
  14. getty2 "github.com/transaction-wg/seata-golang/pkg/base/getty"
  15. "github.com/transaction-wg/seata-golang/pkg/base/protocal"
  16. "github.com/transaction-wg/seata-golang/pkg/base/protocal/codec"
  17. "github.com/transaction-wg/seata-golang/pkg/client/config"
  18. "github.com/transaction-wg/seata-golang/pkg/util/log"
  19. "github.com/transaction-wg/seata-golang/pkg/util/runtime"
  20. )
  21. const (
  22. RPC_REQUEST_TIMEOUT = 30 * time.Second
  23. )
  24. var rpcRemoteClient *RpcRemoteClient
  25. func InitRpcRemoteClient() *RpcRemoteClient {
  26. rpcRemoteClient = &RpcRemoteClient{
  27. conf: config.GetClientConfig(),
  28. idGenerator: &atomic.Uint32{},
  29. futures: &sync.Map{},
  30. mergeMsgMap: &sync.Map{},
  31. rpcMessageChannel: make(chan protocal.RpcMessage, 100),
  32. BranchRollbackRequestChannel: make(chan RpcRMMessage),
  33. BranchCommitRequestChannel: make(chan RpcRMMessage),
  34. GettySessionOnOpenChannel: make(chan string),
  35. }
  36. if rpcRemoteClient.conf.EnableClientBatchSendRequest {
  37. go rpcRemoteClient.processMergedMessage()
  38. }
  39. return rpcRemoteClient
  40. }
  41. func GetRpcRemoteClient() *RpcRemoteClient {
  42. return rpcRemoteClient
  43. }
  44. type RpcRemoteClient struct {
  45. conf *config.ClientConfig
  46. idGenerator *atomic.Uint32
  47. futures *sync.Map
  48. mergeMsgMap *sync.Map
  49. rpcMessageChannel chan protocal.RpcMessage
  50. BranchCommitRequestChannel chan RpcRMMessage
  51. BranchRollbackRequestChannel chan RpcRMMessage
  52. GettySessionOnOpenChannel chan string
  53. }
  54. // OnOpen ...
  55. func (client *RpcRemoteClient) OnOpen(session getty.Session) error {
  56. go func() {
  57. request := protocal.RegisterTMRequest{AbstractIdentifyRequest: protocal.AbstractIdentifyRequest{
  58. Version: client.conf.SeataVersion,
  59. ApplicationID: client.conf.ApplicationID,
  60. TransactionServiceGroup: client.conf.TransactionServiceGroup,
  61. }}
  62. _, err := client.sendAsyncRequestWithResponse(session, request, RPC_REQUEST_TIMEOUT)
  63. if err == nil {
  64. clientSessionManager.RegisterGettySession(session)
  65. client.GettySessionOnOpenChannel <- session.RemoteAddr()
  66. }
  67. }()
  68. return nil
  69. }
  70. // OnError ...
  71. func (client *RpcRemoteClient) OnError(session getty.Session, err error) {
  72. clientSessionManager.ReleaseGettySession(session)
  73. }
  74. // OnClose ...
  75. func (client *RpcRemoteClient) OnClose(session getty.Session) {
  76. clientSessionManager.ReleaseGettySession(session)
  77. }
  78. // OnMessage ...
  79. func (client *RpcRemoteClient) OnMessage(session getty.Session, pkg interface{}) {
  80. log.Info("received message:{%v}", pkg)
  81. rpcMessage, ok := pkg.(protocal.RpcMessage)
  82. if ok {
  83. heartBeat, isHeartBeat := rpcMessage.Body.(protocal.HeartBeatMessage)
  84. if isHeartBeat && heartBeat == protocal.HeartBeatMessagePong {
  85. log.Debugf("received PONG from %s", session.RemoteAddr())
  86. return
  87. }
  88. }
  89. if rpcMessage.MessageType == protocal.MSGTypeRequest ||
  90. rpcMessage.MessageType == protocal.MSGTypeRequestOneway {
  91. log.Debugf("msgID:%s, body:%v", rpcMessage.ID, rpcMessage.Body)
  92. client.onMessage(rpcMessage, session.RemoteAddr())
  93. } else {
  94. mergedResult, isMergedResult := rpcMessage.Body.(protocal.MergeResultMessage)
  95. if isMergedResult {
  96. mm, loaded := client.mergeMsgMap.Load(rpcMessage.ID)
  97. if loaded {
  98. mergedMessage := mm.(protocal.MergedWarpMessage)
  99. log.Infof("rpcMessageID: %d,rpcMessage :%v,result :%v", rpcMessage.ID, mergedMessage, mergedResult)
  100. for i := 0; i < len(mergedMessage.Msgs); i++ {
  101. msgID := mergedMessage.MsgIDs[i]
  102. resp, loaded := client.futures.Load(msgID)
  103. if loaded {
  104. response := resp.(*getty2.MessageFuture)
  105. response.Response = mergedResult.Msgs[i]
  106. response.Done <- true
  107. client.futures.Delete(msgID)
  108. }
  109. }
  110. client.mergeMsgMap.Delete(rpcMessage.ID)
  111. }
  112. } else {
  113. resp, loaded := client.futures.Load(rpcMessage.ID)
  114. if loaded {
  115. response := resp.(*getty2.MessageFuture)
  116. response.Response = rpcMessage.Body
  117. response.Done <- true
  118. client.futures.Delete(rpcMessage.ID)
  119. }
  120. }
  121. }
  122. }
  123. // OnCron ...
  124. func (client *RpcRemoteClient) OnCron(session getty.Session) {
  125. client.defaultSendRequest(session, protocal.HeartBeatMessagePing)
  126. }
  127. func (client *RpcRemoteClient) onMessage(rpcMessage protocal.RpcMessage, serverAddress string) {
  128. msg := rpcMessage.Body.(protocal.MessageTypeAware)
  129. log.Infof("onMessage: %v", msg)
  130. switch msg.GetTypeCode() {
  131. case protocal.TypeBranchCommit:
  132. client.BranchCommitRequestChannel <- RpcRMMessage{
  133. RpcMessage: rpcMessage,
  134. ServerAddress: serverAddress,
  135. }
  136. case protocal.TypeBranchRollback:
  137. client.BranchRollbackRequestChannel <- RpcRMMessage{
  138. RpcMessage: rpcMessage,
  139. ServerAddress: serverAddress,
  140. }
  141. case protocal.TypeRmDeleteUndolog:
  142. break
  143. default:
  144. break
  145. }
  146. }
  147. //*************************************
  148. // ClientMessageSender
  149. //*************************************
  150. func (client *RpcRemoteClient) SendMsgWithResponse(msg interface{}) (interface{}, error) {
  151. if client.conf.EnableClientBatchSendRequest {
  152. return client.sendAsyncRequest2(msg, RPC_REQUEST_TIMEOUT)
  153. }
  154. return client.SendMsgWithResponseAndTimeout(msg, RPC_REQUEST_TIMEOUT)
  155. }
  156. func (client *RpcRemoteClient) SendMsgWithResponseAndTimeout(msg interface{}, timeout time.Duration) (interface{}, error) {
  157. ss := clientSessionManager.AcquireGettySession()
  158. return client.sendAsyncRequestWithResponse(ss, msg, timeout)
  159. }
  160. func (client *RpcRemoteClient) SendResponse(request protocal.RpcMessage, serverAddress string, msg interface{}) {
  161. client.defaultSendResponse(request, clientSessionManager.AcquireGettySessionByServerAddress(serverAddress), msg)
  162. }
  163. func (client *RpcRemoteClient) sendAsyncRequestWithResponse(session getty.Session, msg interface{}, timeout time.Duration) (interface{}, error) {
  164. if timeout <= time.Duration(0) {
  165. return nil, errors.New("timeout should more than 0ms")
  166. }
  167. return client.sendAsyncRequest(session, msg, timeout)
  168. }
  169. func (client *RpcRemoteClient) sendAsyncRequestWithoutResponse(session getty.Session, msg interface{}) error {
  170. _, err := client.sendAsyncRequest(session, msg, time.Duration(0))
  171. return err
  172. }
  173. func (client *RpcRemoteClient) sendAsyncRequest(session getty.Session, msg interface{}, timeout time.Duration) (interface{}, error) {
  174. var err error
  175. if session == nil || session.IsClosed() {
  176. log.Warn("sendAsyncRequestWithResponse nothing, caused by null channel.")
  177. }
  178. rpcMessage := protocal.RpcMessage{
  179. ID: int32(client.idGenerator.Inc()),
  180. MessageType: protocal.MSGTypeRequestOneway,
  181. Codec: codec.SEATA,
  182. Compressor: 0,
  183. Body: msg,
  184. }
  185. resp := getty2.NewMessageFuture(rpcMessage)
  186. client.futures.Store(rpcMessage.ID, resp)
  187. //config timeout
  188. _, _, err = session.WritePkg(rpcMessage, time.Duration(0))
  189. if err != nil {
  190. client.futures.Delete(rpcMessage.ID)
  191. }
  192. log.Infof("send message : %v,session:%s", rpcMessage, session.Stat())
  193. if timeout > time.Duration(0) {
  194. select {
  195. case <-getty.GetTimeWheel().After(timeout):
  196. client.futures.Delete(rpcMessage.ID)
  197. return nil, errors.Errorf("wait response timeout,ip:%s,request:%v", session.RemoteAddr(), rpcMessage)
  198. case <-resp.Done:
  199. err = resp.Err
  200. }
  201. return resp.Response, err
  202. }
  203. return nil, err
  204. }
  205. func (client *RpcRemoteClient) sendAsyncRequest2(msg interface{}, timeout time.Duration) (interface{}, error) {
  206. var err error
  207. rpcMessage := protocal.RpcMessage{
  208. ID: int32(client.idGenerator.Inc()),
  209. MessageType: protocal.MSGTypeRequest,
  210. Codec: codec.SEATA,
  211. Compressor: 0,
  212. Body: msg,
  213. }
  214. resp := getty2.NewMessageFuture(rpcMessage)
  215. client.futures.Store(rpcMessage.ID, resp)
  216. client.rpcMessageChannel <- rpcMessage
  217. log.Infof("send message : %v", rpcMessage)
  218. if timeout > time.Duration(0) {
  219. select {
  220. case <-getty.GetTimeWheel().After(timeout):
  221. client.futures.Delete(rpcMessage.ID)
  222. return nil, errors.Errorf("wait response timeout, request:%v", rpcMessage)
  223. case <-resp.Done:
  224. err = resp.Err
  225. }
  226. return resp.Response, err
  227. }
  228. return nil, err
  229. }
  230. func (client *RpcRemoteClient) sendAsync(session getty.Session, msg interface{}) error {
  231. var err error
  232. if session == nil || session.IsClosed() {
  233. log.Warn("sendAsyncRequestWithResponse nothing, caused by null channel.")
  234. }
  235. rpcMessage := protocal.RpcMessage{
  236. ID: int32(client.idGenerator.Inc()),
  237. MessageType: protocal.MSGTypeRequestOneway,
  238. Codec: codec.SEATA,
  239. Compressor: 0,
  240. Body: msg,
  241. }
  242. log.Infof("store message,id %d: %v", rpcMessage.ID, msg)
  243. client.mergeMsgMap.Store(rpcMessage.ID, msg)
  244. //config timeout
  245. pkgLen, sendLen, err := session.WritePkg(rpcMessage, time.Duration(0))
  246. if err != nil || (pkgLen != 0 && pkgLen != sendLen) {
  247. log.Warnf("start to close the session because %d of %d bytes data is sent success. err:%+v", sendLen, pkgLen, err)
  248. runtime.GoWithRecover(func() {
  249. session.Close()
  250. }, nil)
  251. return errors.Wrap(err, "pkg not send completely!")
  252. }
  253. return nil
  254. }
  255. func (client *RpcRemoteClient) defaultSendRequest(session getty.Session, msg interface{}) {
  256. rpcMessage := protocal.RpcMessage{
  257. ID: int32(client.idGenerator.Inc()),
  258. Codec: codec.SEATA,
  259. Compressor: 0,
  260. Body: msg,
  261. }
  262. _, ok := msg.(protocal.HeartBeatMessage)
  263. if ok {
  264. rpcMessage.MessageType = protocal.MSGTypeHeartbeatRequest
  265. } else {
  266. rpcMessage.MessageType = protocal.MSGTypeRequest
  267. }
  268. pkgLen, sendLen, err := session.WritePkg(rpcMessage, client.conf.GettyConfig.GettySessionParam.TCPWriteTimeout)
  269. if err != nil || (pkgLen != 0 && pkgLen != sendLen) {
  270. log.Warnf("start to close the session because %d of %d bytes data is sent success. err:%+v", sendLen, pkgLen, err)
  271. runtime.GoWithRecover(func() {
  272. session.Close()
  273. }, nil)
  274. }
  275. }
  276. func (client *RpcRemoteClient) defaultSendResponse(request protocal.RpcMessage, session getty.Session, msg interface{}) {
  277. resp := protocal.RpcMessage{
  278. ID: request.ID,
  279. Codec: request.Codec,
  280. Compressor: request.Compressor,
  281. Body: msg,
  282. }
  283. _, ok := msg.(protocal.HeartBeatMessage)
  284. if ok {
  285. resp.MessageType = protocal.MSGTypeHeartbeatResponse
  286. } else {
  287. resp.MessageType = protocal.MSGTypeResponse
  288. }
  289. pkgLen, sendLen, err := session.WritePkg(resp, time.Duration(0))
  290. if err != nil || (pkgLen != 0 && pkgLen != sendLen) {
  291. log.Warnf("start to close the session because %d of %d bytes data is sent success. err:%+v", sendLen, pkgLen, err)
  292. runtime.GoWithRecover(func() {
  293. session.Close()
  294. }, nil)
  295. }
  296. }
  297. func (client *RpcRemoteClient) RegisterResource(serverAddress string, request protocal.RegisterRMRequest) {
  298. session := clientSessionManager.AcquireGettySessionByServerAddress(serverAddress)
  299. if session != nil {
  300. err := client.sendAsyncRequestWithoutResponse(session, request)
  301. if err != nil {
  302. log.Errorf("register resource failed, session:{},resourceID:{}", session, request.ResourceIDs)
  303. }
  304. }
  305. }
  306. func loadBalance(transactionServiceGroup string) string {
  307. addressList := getAddressList(transactionServiceGroup)
  308. if len(addressList) == 1 {
  309. return addressList[0]
  310. }
  311. return addressList[rand.Intn(len(addressList))]
  312. }
  313. func getAddressList(transactionServiceGroup string) []string {
  314. addressList := strings.Split(transactionServiceGroup, ",")
  315. return addressList
  316. }
  317. func (client *RpcRemoteClient) processMergedMessage() {
  318. ticker := time.NewTicker(5 * time.Millisecond)
  319. mergedMessage := protocal.MergedWarpMessage{
  320. Msgs: make([]protocal.MessageTypeAware, 0),
  321. MsgIDs: make([]int32, 0),
  322. }
  323. for {
  324. select {
  325. case rpcMessage := <-client.rpcMessageChannel:
  326. message := rpcMessage.Body.(protocal.MessageTypeAware)
  327. mergedMessage.Msgs = append(mergedMessage.Msgs, message)
  328. mergedMessage.MsgIDs = append(mergedMessage.MsgIDs, rpcMessage.ID)
  329. if len(mergedMessage.Msgs) == 20 {
  330. client.sendMergedMessage(mergedMessage)
  331. mergedMessage = protocal.MergedWarpMessage{
  332. Msgs: make([]protocal.MessageTypeAware, 0),
  333. MsgIDs: make([]int32, 0),
  334. }
  335. }
  336. case <-ticker.C:
  337. if len(mergedMessage.Msgs) > 0 {
  338. client.sendMergedMessage(mergedMessage)
  339. mergedMessage = protocal.MergedWarpMessage{
  340. Msgs: make([]protocal.MessageTypeAware, 0),
  341. MsgIDs: make([]int32, 0),
  342. }
  343. }
  344. }
  345. }
  346. }
  347. func (client *RpcRemoteClient) sendMergedMessage(mergedMessage protocal.MergedWarpMessage) {
  348. ss := clientSessionManager.AcquireGettySession()
  349. err := client.sendAsync(ss, mergedMessage)
  350. if err != nil {
  351. for _, id := range mergedMessage.MsgIDs {
  352. resp, loaded := client.futures.Load(id)
  353. if loaded {
  354. response := resp.(*getty2.MessageFuture)
  355. response.Done <- true
  356. client.futures.Delete(id)
  357. }
  358. }
  359. }
  360. }