5

के आधार पर हाइस्ट्रिक्स फ़ॉलबैक के साथ वितरित लेनदेन को कार्यान्वित करने के लिए कैसे करें मैं अपनी माइक्रो सेवा प्रणाली, टिकट बिक्री प्लेटफॉर्म को लागू करने के लिए वसंत बादल का उपयोग कर रहा हूं। परिदृश्य है, एक ज़ुउल प्रॉक्सी, एक यूरेका रजिस्ट्री, और 3 सेवा है: उपयोगकर्ता सेवा, ऑर्डर सेवा और टिकट सेवा। सेवाओं एक दूसरे के साथ संवाद करने के लिए feign घोषणात्मक REST क्लाइंट का उपयोग करें।स्प्रिंग क्लाउड आर्किटेक्ट

अब टिकट खरीदने के लिए एक समारोह है, मुख्य प्रक्रिया के रूप में नीचे है:
1. आदेश सेवा बनाने के लिए आदेश
2. आदेश सेवा स्थिति लंबित साथ आदेश इकाई बनाने अनुरोध स्वीकार करते हैं।
3. उपयोगकर्ता वेतन संसाधित करने के लिए ऑर्डर सेवा कॉल उपयोगकर्ता सेवा।
4. उपयोगकर्ता टिकट अपडेट करने के लिए ऑर्डर सेवा कॉल टिकट सेवा।
5. आदेश सेवा आदेश इकाई को अंतिम रूप में अपडेट करें।

और मैं लेनदेन को लागू करने के लिए Hystrix Fallback का उपयोग करना चाहता हूं। उदाहरण के लिए, यदि भुगतान प्रक्रिया समाप्त हो गई है, लेकिन टिकट की गतिविधि के दौरान कुछ त्रुटि हुई। उपयोगकर्ता भुगतान, और ऑर्डर स्थिति कैसे रीसेट करें। चूंकि उपयोगकर्ता भुगतान अन्य सेवा में है।

निम्नलिखित मेरा वर्तमान समाधान है, मुझे यकीन नहीं है कि यह उचित है या नहीं। या ऐसा करने के लिए कोई और बेहतर तरीका है।

सबसे पहले, OrderResource:

@RestController 
@RequestMapping("/api/order") 
public class OrderResource { 

    @HystrixCommand(fallbackMethod = "createFallback") 
    @PostMapping(value = "/") 
    public Order create(@RequestBody Order order) { 
    return orderService.create(order); 
    } 

    private Order createFallback(Order order) { 
    return orderService.createFallback(order); 
    } 
} 

फिर OrderService:

@Service 
public class OrderService { 

    @Transactional 
    public Order create(Order order) { 
     order.setStatus("PENDING"); 
     order = orderRepository.save(order); 

     UserPayDTO payDTO = new UserPayDTO(); 
     userCompositeService.payForOrder(payDTO); 

     order.setStatus("PAID"); 
     order = orderRepository.save(order); 

     ticketCompositeService.moveTickets(ticketIds, currentUserId); 

     order.setStatus("FINISHED"); 
     order = orderRepository.save(order); 
     return order; 
    } 

    @Transactional 
    public Order createFallback(Order order) { 
     // order is the object processed in create(), there is Transaction in create(), so saving order will be rollback, 
     // but the order instance still exist. 
     if (order.getId() == null) { // order not saved even. 
      return null; 
     } 
     UserPayDTO payDTO = new UserPayDTO(); 
     try { 
      if (order.getStatus() == "FINISHED") { // order finished, must be paid and ticket moved 
       userCompositeService.payForOrderFallback(payDTO); 
       ticketCompositeService.moveTicketsFallback(getTicketIdList(order.getTicketIds()), currentUserId); 
      } else if (order.getStatus() == "PAID") { // is paid, but not sure whether has error during ticket movement. 
       userCompositeService.payForOrderFallback(payDTO); 
       ticketCompositeService.moveTicketsFallback(getTicketIdList(order.getTicketIds()), currentUserId); 
      } else if (order.getStatus() == "PENDING") { // maybe have error during payment. 
       userCompositeService.payForOrderFallback(payDTO); 
      } 
     } catch (Exception e) { 
      LOG.error(e.getMessage(), e); 
     } 

     order.setStatus("FAILED"); 
     orderRepository.save(order); // order saving is rollbacked during create(), I save it here to trace the failed orders. 
     return order; 
    } 
} 

कुछ महत्वपूर्ण बिंदुओं यहां हैं:

  1. OrderResource.create(order) विधि में @HystrixCommand का उपयोग करना, fallback समारोह के साथ।
  2. यदि सृजन में कुछ त्रुटि है, उदाहरण OrderResource.create(order) में उपयोग किया गया उदाहरण फ़ॉलबैक फ़ंक्शन में फिर से उपयोग किया जाएगा। हालांकि इस order की दृढ़ता रोल-बैक होगी। लेकिन इस उदाहरण में डेटा अभी भी चलने की जांच के लिए इस्तेमाल किया जा सकता है।
  3. इसलिए मैं एक स्थिति का उपयोग करता हूं: 'पेंडिंग', 'भुगतान', 'अंतिम', यह जांचने के लिए कि कुछ सेवा कॉल की गई है या नहीं।
  4. ticketCompositeService और userCompositeService एक feign ग्राहक है। फेगबैक क्लाइंट विधि payForOrder() के लिए, फ़ॉलबैक के लिए payForOrderFallback() कोई अन्य विधि है।
  5. मुझे यह सुनिश्चित करने की ज़रूरत है कि फ़ॉलबैक विधियों को कई बार कहा जा सकता है।
  6. ticketCompositeService और userCompositeService कॉल के लिए try/catch जोड़ें, यह सुनिश्चित करने के लिए कि आदेश 'FAILED' स्थिति के साथ वैसे भी बचाएगा।

ऐसा लगता है कि यह समाधान अधिकांश समय पर काम कर सकता है। इसके अलावा, फ़ॉलबैक फ़ंक्शन में, यदि userCompositeService.payForOrderFallback(payDTO); में कुछ त्रुटि है, तो निम्न समग्र सेवा कॉल नहीं कहा जाएगा।

और, एक और समस्या यह है कि, मुझे लगता है कि यह बहुत जटिल है।

तो, इस परिदृश्य के लिए, मैं दूरस्थ लेनदेन को सही ढंग से और प्रभावी ढंग से कैसे कार्यान्वित करना चाहिए। कोई सुझाव या सलाह मदद मिलेगी। धन्यवाद।

+0

आपको इवेंट सोर्सिंग + सीक्यूआरएस तकनीक [लिंक] (https://stackoverflow.com/questions/44114755/how-to-do-2-phase-commit-between-two-micro-servicesspring-boot) – sathees

उत्तर

1

हाइस्ट्रिक्स फॉलबैक के भीतर मुआवजे तर्क लिखना खतरनाक नहीं है क्योंकि इसमें कोई दृढ़ता शामिल नहीं है।

यह दृष्टिकोण किसी भी लचीलापन की पेशकश नहीं करता है। डेटाबेस से एसीआईडी ​​गारंटी यहां शामिल बाहरी पार्टियों की वजह से पर्याप्त नहीं है, और हाइस्ट्रिक्स फ़ॉलबैक आपको किसी भी चीज़ से सुरक्षित नहीं रखेगा जो आपके कोड का हिस्सा नहीं है।

उदाहरण के लिए, यदि आपका समाधान भुगतान पूरा होने के बाद आउटेज (कहते हैं, बिजली आउटेज या एक साधारण kill -9) अनुभव करता है, तो आप आदेश और मुआवजे तर्क दोनों खो देंगे, जिसका अर्थ है कि ऑर्डर का भुगतान किया जाएगा, लेकिन डेटाबेस में मौजूद नहीं है ।

एक अधिक लचीला दृष्टिकोण घटना-संचालित डिलीवरी के लिए किसी भी लोकप्रिय संदेश दलाल और तर्क को संसाधित करने में कुछ समर्पण शामिल करेगा ताकि यह सुनिश्चित किया जा सके कि घटनाओं की गुणवत्ता एक बार सुनिश्चित हो जाती है जब घटनाओं के बाद घटनाओं को फिर से प्राप्त किया जाता है।

+0

आज़माएं धन्यवाद, मैं इसके बारे में भी बहुत कुछ जांचता हूं, कई परीक्षण कोड लिखता हूं, मेरा अंतिम समाधान कुछ एमक्यू और घटना संचालित प्रक्रिया का भी उपयोग करना है। धन्यवाद। – Mavlarn

संबंधित मुद्दे