تسلط بر الگوی حماسه در Spring Boot: ساده تر کردن تراکنش های میکروسرویس پیچیده

Summarize this content to 400 words in Persian Lang
بیایید در مورد استفاده از الگوی Saga در Spring Boot برای مدیریت تراکنشهای پیچیده در میکروسرویسها صحبت کنیم. این رویکرد زمانی بسیار مفید است که با سیستم های توزیع شده سروکار دارید و نیاز دارید همه چیز را هماهنگ نگه دارید.
اول از همه، حماسه چیست؟ این اساسا راهی برای مدیریت یک سری معاملات محلی است که با هم کار می کنند تا یک فرآیند تجاری بزرگتر را تکمیل کنند. هر مرحله در حماسه کار خود را انجام می دهد و اگر مشکلی پیش بیاید، ما برنامه ای برای خنثی کردن یا رفع آن داریم.
دو نوع اصلی حماسه وجود دارد: رقص و ارکستراسیون. با طراحی رقص، هر سرویس می داند که در مرحله بعد چه کاری انجام دهد و مرحله بعدی را آغاز می کند. از طرف دیگر، ارکستراسیون یک هماهنگ کننده مرکزی دارد که به هر سرویس می گوید چه کاری انجام دهد.
بیایید با یک حماسه مبتنی بر رقص در Spring Boot شروع کنیم. در اینجا یک مثال ساده آورده شده است:
@Service
public class OrderService {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void createOrder(Order order) {
// Save order
saveOrder(order);
// Publish event
kafkaTemplate.send(“order-created”, order.getId());
}
@KafkaListener(topics = “payment-processed”)
public void handlePaymentProcessed(String orderId) {
// Update order status
updateOrderStatus(orderId, “PAID”);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این تنظیمات، هر سرویس زمانی که بخش خود را از تراکنش کامل میکند، رویدادها را منتشر میکند. سایر سرویس ها به این رویدادها گوش می دهند و بر اساس آن واکنش نشان می دهند.
حال، بیایید به یک حماسه مبتنی بر ارکستراسیون نگاه کنیم. ما از Spring State Machine برای مدیریت وضعیت حماسه استفاده خواهیم کرد:
@Configuration
@EnableStateMachine
public class OrderSagaStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {
@Override
public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderState.CREATED)
.state(OrderState.PAYMENT_PENDING)
.state(OrderState.STOCK_CHECKING)
.state(OrderState.COMPLETED)
.state(OrderState.FAILED);
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderState.CREATED).target(OrderState.PAYMENT_PENDING)
.event(OrderEvent.INITIATE_PAYMENT)
.and()
.withExternal()
.source(OrderState.PAYMENT_PENDING).target(OrderState.STOCK_CHECKING)
.event(OrderEvent.PAYMENT_COMPLETED)
.and()
.withExternal()
.source(OrderState.STOCK_CHECKING).target(OrderState.COMPLETED)
.event(OrderEvent.STOCK_CONFIRMED)
.and()
.withExternal()
.source(OrderState.STOCK_CHECKING).target(OrderState.FAILED)
.event(OrderEvent.STOCK_UNAVAILABLE);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این ماشین حالت جریان حماسه ما را تعریف می کند. هر حالت نشان دهنده مرحله ای از فرآیند است و رویدادها باعث انتقال بین حالت ها می شوند.
یکی از پیچیدهترین بخشهای اجرای حماسه، رسیدگی به شکستها و جبران اقدامات است. اگر در نیمه راه مشکلی پیش بیاید، باید اقداماتی را که قبلا برداشته ایم خنثی کنیم یا جبران کنیم. در اینجا نحوه برخورد با شکست در حماسه سفارش ما آمده است:
@Service
public class OrderSagaOrchestrator {
@Autowired
private StateMachine<OrderState, OrderEvent> stateMachine;
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
public void processOrder(Order order) {
stateMachine.start();
try {
stateMachine.sendEvent(OrderEvent.INITIATE_PAYMENT);
paymentService.processPayment(order);
stateMachine.sendEvent(OrderEvent.PAYMENT_COMPLETED);
boolean stockAvailable = inventoryService.checkStock(order);
if (stockAvailable) {
stateMachine.sendEvent(OrderEvent.STOCK_CONFIRMED);
} else {
stateMachine.sendEvent(OrderEvent.STOCK_UNAVAILABLE);
compensate(order);
}
} catch (Exception e) {
compensate(order);
}
}
private void compensate(Order order) {
if (stateMachine.getState().getId() == OrderState.STOCK_CHECKING) {
paymentService.refundPayment(order);
}
// Add more compensation logic as needed
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در این مثال، اگر متوجه شویم که سهام پس از پردازش پرداخت در دسترس نیست، یک اقدام جبرانی برای بازپرداخت وجه پرداختی را آغاز می کنیم.
عدم توانایی یکی دیگر از مفاهیم مهم هنگام کار با حماسه است. ما باید اطمینان حاصل کنیم که حتی اگر مرحله ای تکرار شود (به دلیل تلاش های مجدد یا مشکلات شبکه)، مشکلی ایجاد نمی کند. در اینجا نحوه اجرای یک سرویس پرداخت ناتوان به شرح زیر است:
@Service
public class IdempotentPaymentService {
@Autowired
private PaymentRepository paymentRepository;
@Transactional
public void processPayment(String orderId, BigDecimal amount) {
String idempotencyKey = generateIdempotencyKey(orderId);
if (paymentRepository.findByIdempotencyKey(idempotencyKey).isPresent()) {
// Payment already processed, do nothing
return;
}
// Process the payment
Payment payment = new Payment(orderId, amount, idempotencyKey);
paymentRepository.save(payment);
}
private String generateIdempotencyKey(String orderId) {
return orderId + “-payment”;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این سرویس بررسی میکند که آیا پرداختی با همان کلید عدم توانایی قبلاً پردازش شده است یا خیر. اگر چنین است، دوباره پرداخت را پردازش نمی کند.
وقتی نوبت به آزمایش حماسه می رسد، می تواند بسیار پیچیده شود. ما باید نه تنها مسیر شاد، بلکه سناریوهای مختلف شکست و اقدامات جبرانی را نیز آزمایش کنیم. در اینجا یک تست ساده با استفاده از JUnit و Mockito آورده شده است:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderSagaOrchestratorTest {
@Autowired
private OrderSagaOrchestrator orchestrator;
@MockBean
private PaymentService paymentService;
@MockBean
private InventoryService inventoryService;
@Test
public void testSuccessfulOrderProcessing() {
Order order = new Order(“123”, BigDecimal.valueOf(100));
when(paymentService.processPayment(order)).thenReturn(true);
when(inventoryService.checkStock(order)).thenReturn(true);
orchestrator.processOrder(order);
verify(paymentService).processPayment(order);
verify(inventoryService).checkStock(order);
// Add more verifications as needed
}
@Test
public void testCompensationWhenStockUnavailable() {
Order order = new Order(“123”, BigDecimal.valueOf(100));
when(paymentService.processPayment(order)).thenReturn(true);
when(inventoryService.checkStock(order)).thenReturn(false);
orchestrator.processOrder(order);
verify(paymentService).processPayment(order);
verify(inventoryService).checkStock(order);
verify(paymentService).refundPayment(order);
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این آزمایشها هم مورد موفقیتآمیز و هم موردی را که در آن غرامت نیاز است بررسی میکند.
نظارت بر حماسه ها در تولید برای حفظ یک سیستم سالم بسیار مهم است. ما میتوانیم از Spring Boot Actuator همراه با ابزارهایی مانند Prometheus و Grafana برای ردیابی معیارهایی مانند زمان اتمام حماسه، نرخ شکست و اقدامات جبرانی استفاده کنیم.
در اینجا نحوه افزودن معیارهای سفارشی به ارکستراتور حماسه آمده است:
@Service
public class OrderSagaOrchestrator {
private final Counter sagaCompletions;
private final Counter sagaFailures;
private final Timer sagaDuration;
public OrderSagaOrchestrator(MeterRegistry registry) {
this.sagaCompletions = registry.counter(“order_saga_completions”);
this.sagaFailures = registry.counter(“order_saga_failures”);
this.sagaDuration = registry.timer(“order_saga_duration”);
}
public void processOrder(Order order) {
Timer.Sample sample = Timer.start();
try {
// Saga logic here
sagaCompletions.increment();
} catch (Exception e) {
sagaFailures.increment();
throw e;
} finally {
sample.stop(sagaDuration);
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
این معیارها به ما بینش ارزشمندی در مورد نحوه عملکرد حماسه های ما در تولید می دهد.
اجرای حماسه در Spring Boot پیاده روی در پارک نیست، اما ابزاری قدرتمند برای مدیریت تراکنش های پیچیده و توزیع شده است. با طراحی دقیق حماسههای خود، پیادهسازی منطق مدیریت خطا و جبران صحیح، و راهاندازی نظارت قوی، میتوانیم سیستمهای انعطافپذیر و مقیاسپذیری بسازیم که میتوانند حتی پیچیدهترین فرآیندهای تجاری را مدیریت کنند.
به یاد داشته باشید، کلید اجرای موفق حماسه، فکر کردن در مورد تمام سناریوهای شکست احتمالی و نحوه مدیریت آنها است. این فقط در مورد مسیر خوشبختی نیست، بلکه در مورد مدیریت برازنده همه چیزهایی است که ممکن است در یک سیستم توزیع شده اشتباه پیش بروند.
همانطور که با حماسه ها کار می کنید، احتمالاً با چالش هایی مانند برخورد با تراکنش های طولانی مدت، رسیدگی به وقفه های زمانی و مدیریت بازیابی حماسه پس از خرابی سیستم مواجه خواهید شد. همه اینها زمینه هایی هستند که شما باید استراتژی هایی را برای نیازهای سیستم خود ایجاد کنید.
حماسه ها موضوع بزرگی هستند و همیشه چیزهای بیشتری برای یادگیری وجود دارد. همانطور که آنها را در برنامه های Spring Boot خود پیاده سازی می کنید، الگوهای جدید و بهترین شیوه ها را کشف خواهید کرد. به آزمایش، آزمایش و اصلاح رویکرد خود ادامه دهید. با گذشت زمان و تجربه، میتوانید با استفاده از الگوی حماسی در Spring Boot، سیستمهای توزیعشده فوقالعاده قوی و مقیاسپذیر بسازید.
مخلوقات ما
حتماً خلاقیت های ما را بررسی کنید:
مرکز سرمایه گذار | زندگی هوشمند | دوره ها و پژواک ها | اسرار گیج کننده | هندوتوا | Elite Dev | مدارس JS
ما در حالت متوسط هستیم
بینش کوآلای فنی | دوران و پژواک جهان | سرمایه گذار مرکزی متوسط | رازهای گیج کننده رسانه | رسانه علم و عصر | هندوتوای مدرن
بیایید در مورد استفاده از الگوی Saga در Spring Boot برای مدیریت تراکنشهای پیچیده در میکروسرویسها صحبت کنیم. این رویکرد زمانی بسیار مفید است که با سیستم های توزیع شده سروکار دارید و نیاز دارید همه چیز را هماهنگ نگه دارید.
اول از همه، حماسه چیست؟ این اساسا راهی برای مدیریت یک سری معاملات محلی است که با هم کار می کنند تا یک فرآیند تجاری بزرگتر را تکمیل کنند. هر مرحله در حماسه کار خود را انجام می دهد و اگر مشکلی پیش بیاید، ما برنامه ای برای خنثی کردن یا رفع آن داریم.
دو نوع اصلی حماسه وجود دارد: رقص و ارکستراسیون. با طراحی رقص، هر سرویس می داند که در مرحله بعد چه کاری انجام دهد و مرحله بعدی را آغاز می کند. از طرف دیگر، ارکستراسیون یک هماهنگ کننده مرکزی دارد که به هر سرویس می گوید چه کاری انجام دهد.
بیایید با یک حماسه مبتنی بر رقص در Spring Boot شروع کنیم. در اینجا یک مثال ساده آورده شده است:
@Service
public class OrderService {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
public void createOrder(Order order) {
// Save order
saveOrder(order);
// Publish event
kafkaTemplate.send("order-created", order.getId());
}
@KafkaListener(topics = "payment-processed")
public void handlePaymentProcessed(String orderId) {
// Update order status
updateOrderStatus(orderId, "PAID");
}
}
در این تنظیمات، هر سرویس زمانی که بخش خود را از تراکنش کامل میکند، رویدادها را منتشر میکند. سایر سرویس ها به این رویدادها گوش می دهند و بر اساس آن واکنش نشان می دهند.
حال، بیایید به یک حماسه مبتنی بر ارکستراسیون نگاه کنیم. ما از Spring State Machine برای مدیریت وضعیت حماسه استفاده خواهیم کرد:
@Configuration
@EnableStateMachine
public class OrderSagaStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {
@Override
public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderState.CREATED)
.state(OrderState.PAYMENT_PENDING)
.state(OrderState.STOCK_CHECKING)
.state(OrderState.COMPLETED)
.state(OrderState.FAILED);
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderState.CREATED).target(OrderState.PAYMENT_PENDING)
.event(OrderEvent.INITIATE_PAYMENT)
.and()
.withExternal()
.source(OrderState.PAYMENT_PENDING).target(OrderState.STOCK_CHECKING)
.event(OrderEvent.PAYMENT_COMPLETED)
.and()
.withExternal()
.source(OrderState.STOCK_CHECKING).target(OrderState.COMPLETED)
.event(OrderEvent.STOCK_CONFIRMED)
.and()
.withExternal()
.source(OrderState.STOCK_CHECKING).target(OrderState.FAILED)
.event(OrderEvent.STOCK_UNAVAILABLE);
}
}
این ماشین حالت جریان حماسه ما را تعریف می کند. هر حالت نشان دهنده مرحله ای از فرآیند است و رویدادها باعث انتقال بین حالت ها می شوند.
یکی از پیچیدهترین بخشهای اجرای حماسه، رسیدگی به شکستها و جبران اقدامات است. اگر در نیمه راه مشکلی پیش بیاید، باید اقداماتی را که قبلا برداشته ایم خنثی کنیم یا جبران کنیم. در اینجا نحوه برخورد با شکست در حماسه سفارش ما آمده است:
@Service
public class OrderSagaOrchestrator {
@Autowired
private StateMachine<OrderState, OrderEvent> stateMachine;
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
public void processOrder(Order order) {
stateMachine.start();
try {
stateMachine.sendEvent(OrderEvent.INITIATE_PAYMENT);
paymentService.processPayment(order);
stateMachine.sendEvent(OrderEvent.PAYMENT_COMPLETED);
boolean stockAvailable = inventoryService.checkStock(order);
if (stockAvailable) {
stateMachine.sendEvent(OrderEvent.STOCK_CONFIRMED);
} else {
stateMachine.sendEvent(OrderEvent.STOCK_UNAVAILABLE);
compensate(order);
}
} catch (Exception e) {
compensate(order);
}
}
private void compensate(Order order) {
if (stateMachine.getState().getId() == OrderState.STOCK_CHECKING) {
paymentService.refundPayment(order);
}
// Add more compensation logic as needed
}
}
در این مثال، اگر متوجه شویم که سهام پس از پردازش پرداخت در دسترس نیست، یک اقدام جبرانی برای بازپرداخت وجه پرداختی را آغاز می کنیم.
عدم توانایی یکی دیگر از مفاهیم مهم هنگام کار با حماسه است. ما باید اطمینان حاصل کنیم که حتی اگر مرحله ای تکرار شود (به دلیل تلاش های مجدد یا مشکلات شبکه)، مشکلی ایجاد نمی کند. در اینجا نحوه اجرای یک سرویس پرداخت ناتوان به شرح زیر است:
@Service
public class IdempotentPaymentService {
@Autowired
private PaymentRepository paymentRepository;
@Transactional
public void processPayment(String orderId, BigDecimal amount) {
String idempotencyKey = generateIdempotencyKey(orderId);
if (paymentRepository.findByIdempotencyKey(idempotencyKey).isPresent()) {
// Payment already processed, do nothing
return;
}
// Process the payment
Payment payment = new Payment(orderId, amount, idempotencyKey);
paymentRepository.save(payment);
}
private String generateIdempotencyKey(String orderId) {
return orderId + "-payment";
}
}
این سرویس بررسی میکند که آیا پرداختی با همان کلید عدم توانایی قبلاً پردازش شده است یا خیر. اگر چنین است، دوباره پرداخت را پردازش نمی کند.
وقتی نوبت به آزمایش حماسه می رسد، می تواند بسیار پیچیده شود. ما باید نه تنها مسیر شاد، بلکه سناریوهای مختلف شکست و اقدامات جبرانی را نیز آزمایش کنیم. در اینجا یک تست ساده با استفاده از JUnit و Mockito آورده شده است:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderSagaOrchestratorTest {
@Autowired
private OrderSagaOrchestrator orchestrator;
@MockBean
private PaymentService paymentService;
@MockBean
private InventoryService inventoryService;
@Test
public void testSuccessfulOrderProcessing() {
Order order = new Order("123", BigDecimal.valueOf(100));
when(paymentService.processPayment(order)).thenReturn(true);
when(inventoryService.checkStock(order)).thenReturn(true);
orchestrator.processOrder(order);
verify(paymentService).processPayment(order);
verify(inventoryService).checkStock(order);
// Add more verifications as needed
}
@Test
public void testCompensationWhenStockUnavailable() {
Order order = new Order("123", BigDecimal.valueOf(100));
when(paymentService.processPayment(order)).thenReturn(true);
when(inventoryService.checkStock(order)).thenReturn(false);
orchestrator.processOrder(order);
verify(paymentService).processPayment(order);
verify(inventoryService).checkStock(order);
verify(paymentService).refundPayment(order);
}
}
این آزمایشها هم مورد موفقیتآمیز و هم موردی را که در آن غرامت نیاز است بررسی میکند.
نظارت بر حماسه ها در تولید برای حفظ یک سیستم سالم بسیار مهم است. ما میتوانیم از Spring Boot Actuator همراه با ابزارهایی مانند Prometheus و Grafana برای ردیابی معیارهایی مانند زمان اتمام حماسه، نرخ شکست و اقدامات جبرانی استفاده کنیم.
در اینجا نحوه افزودن معیارهای سفارشی به ارکستراتور حماسه آمده است:
@Service
public class OrderSagaOrchestrator {
private final Counter sagaCompletions;
private final Counter sagaFailures;
private final Timer sagaDuration;
public OrderSagaOrchestrator(MeterRegistry registry) {
this.sagaCompletions = registry.counter("order_saga_completions");
this.sagaFailures = registry.counter("order_saga_failures");
this.sagaDuration = registry.timer("order_saga_duration");
}
public void processOrder(Order order) {
Timer.Sample sample = Timer.start();
try {
// Saga logic here
sagaCompletions.increment();
} catch (Exception e) {
sagaFailures.increment();
throw e;
} finally {
sample.stop(sagaDuration);
}
}
}
این معیارها به ما بینش ارزشمندی در مورد نحوه عملکرد حماسه های ما در تولید می دهد.
اجرای حماسه در Spring Boot پیاده روی در پارک نیست، اما ابزاری قدرتمند برای مدیریت تراکنش های پیچیده و توزیع شده است. با طراحی دقیق حماسههای خود، پیادهسازی منطق مدیریت خطا و جبران صحیح، و راهاندازی نظارت قوی، میتوانیم سیستمهای انعطافپذیر و مقیاسپذیری بسازیم که میتوانند حتی پیچیدهترین فرآیندهای تجاری را مدیریت کنند.
به یاد داشته باشید، کلید اجرای موفق حماسه، فکر کردن در مورد تمام سناریوهای شکست احتمالی و نحوه مدیریت آنها است. این فقط در مورد مسیر خوشبختی نیست، بلکه در مورد مدیریت برازنده همه چیزهایی است که ممکن است در یک سیستم توزیع شده اشتباه پیش بروند.
همانطور که با حماسه ها کار می کنید، احتمالاً با چالش هایی مانند برخورد با تراکنش های طولانی مدت، رسیدگی به وقفه های زمانی و مدیریت بازیابی حماسه پس از خرابی سیستم مواجه خواهید شد. همه اینها زمینه هایی هستند که شما باید استراتژی هایی را برای نیازهای سیستم خود ایجاد کنید.
حماسه ها موضوع بزرگی هستند و همیشه چیزهای بیشتری برای یادگیری وجود دارد. همانطور که آنها را در برنامه های Spring Boot خود پیاده سازی می کنید، الگوهای جدید و بهترین شیوه ها را کشف خواهید کرد. به آزمایش، آزمایش و اصلاح رویکرد خود ادامه دهید. با گذشت زمان و تجربه، میتوانید با استفاده از الگوی حماسی در Spring Boot، سیستمهای توزیعشده فوقالعاده قوی و مقیاسپذیر بسازید.
مخلوقات ما
حتماً خلاقیت های ما را بررسی کنید:
مرکز سرمایه گذار | زندگی هوشمند | دوره ها و پژواک ها | اسرار گیج کننده | هندوتوا | Elite Dev | مدارس JS
ما در حالت متوسط هستیم
بینش کوآلای فنی | دوران و پژواک جهان | سرمایه گذار مرکزی متوسط | رازهای گیج کننده رسانه | رسانه علم و عصر | هندوتوای مدرن