MSAez를 사용한 event stroming결과 아래와 같이 설계
MSAez로 구현한 Aggregate단위로 Entity를 선언 후, 구현 진행.
package shop;
import javax.persistence.*;
import org.springframework.beans.BeanUtils;
import shop.external.Payment;
import java.util.List;
@Entity
@Table(name="Order_table")
public class Order {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Long productId;
private Long qty;
private String orderStatus;
private Long orderId;
@PostPersist
public void onPostPersist()
{
Ordered ordered = new Ordered();
BeanUtils.copyProperties(this, ordered);
ordered.setOrderStatus("Order");
ordered.setOrderId(this.getOrderId());
ordered.publishAfterCommit();
shop.external.Payment payment = new shop.external.Payment();
System.out.println("결제 이벤트 발생");
payment.setId(this.getOrderId());
payment.setStatus("Paid");
OrderApplication.applicationContext.getBean(shop.external.PaymentService.class)
.pay(payment);
}
@PreUpdate
public void onPrePersist(){
OrderCanceled orderCanceled = new OrderCanceled();
BeanUtils.copyProperties(this, orderCanceled);
if(orderCanceled.getOrderStatus().equals("Cancel"))
{
orderCanceled.setOrderStatus(this.getOrderStatus());
orderCanceled.publishAfterCommit();
}
else
{
PaymentRequested paymentRequested = new PaymentRequested();
BeanUtils.copyProperties(this, paymentRequested);
paymentRequested.publishAfterCommit();
//orderCanceled.publishAfterCommit();
//Following code causes dependency to external APIs
// it is NOT A GOOD PRACTICE. instead, Event-Policy mapping is recommended.
//shop.external.Cancellation cancellation = new shop.external.Cancellation();
// mappings goes here
//OrderApplication.applicationContext.getBean(shop.external.CancellationService.class)
// .cancel(cancellation);
}
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
public Long getQty() {
return qty;
}
public void setQty(Long qty) {
this.qty = qty;
}
public void setOrderStatus(String orderStatus){this.orderStatus = orderStatus;}
public String getOrderStatus(){return orderStatus;}
public Long getOrderId(){return orderId;}
public void setOrderId(Long orderId){this.orderId = orderId;}
}
REST API에서의 테스트를 통하여 구현내용이 정상적으로 동작함을 확인.
Order 내에 아래와 같은 FeignClient 선언
package shop.external;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.Date;
@FeignClient(name="pay", url="${api.url.pay}")
//@FeignClient(name="pay", url="http://pay:8080")
public interface PaymentService {
@RequestMapping(method= RequestMethod.GET, path="/payments")
public void pay(@RequestBody Payment payment);
}
@PoosePersist에서 이벤트 처리 수행
@PostPersist
public void onPostPersist()
{
Ordered ordered = new Ordered();
BeanUtils.copyProperties(this, ordered);
ordered.setOrderStatus("Order");
ordered.setOrderId(this.getOrderId());
ordered.publishAfterCommit();
shop.external.Payment payment = new shop.external.Payment();
System.out.println("결제 이벤트 발생");
payment.setId(this.getOrderId());
payment.setStatus("Paid");
OrderApplication.applicationContext.getBean(shop.external.PaymentService.class)
.pay(payment);
}
Pay서비스와 Order 서비스가 둘 다 돌아가고 있을 때에는 Order서비스에 아래와 같이 수행 하여도 이상 없음.
Pay 서비스를 내린 후, Order 서비스만 돌아가고 있는 상태에서는 Order 서비스에 아래와 같이 수행시 이상 발생.
Payment.java내에서 아래와 같이 서비스 Publish 구현
@PostUpdate
public void onPostUpdate()
{
Paid paid = new Paid();
BeanUtils.copyProperties(this, paid);
paid.publishAfterCommit();
}
Delivery 서비스 내 Policy Handler에서 아래와 같이 Sub 구현
@StreamListener(KafkaProcessor.INPUT)
public void wheneverPaid_Ship(@Payload Paid paid){
if(paid.isMe()){
System.out.println("##### listener Ship : " + paid.toJson());
Delivery delivery = new Delivery();
delivery.setDeliveryStatus("ordered");
System.out.println("Delivery start");
deliveryRepository.save(delivery);
}
}
Pay 서비스와 Delivery 서비스가 둘 다 동시에 돌아가고 있을때 Pay 서비스 실행시 이상 없음.
Pay 서비스는 실행한 채, Delivery 서비스를 내린 후, Pay 서비스를 실행하여도 이상 없이 동작 가능.
Gateway 서비스 실행 상태에서 8088과 8084로 각각 서비스 실행하여도 동일하게 Pay 서비스 실행됨 확인.
viewer를 별도로 구현하여 아래와 같이 view 실행 결과 확인 가능
다른 서비스와 달리 Order 서비스는 h2db 가 아닌 hsqldb 를 사용
deployment.yml파일 내용 가운데 http -> tcpSocket변경, 8080 -> 8081로 변경 후, 서비스 확인 수행
kubectl describe deploy order 명령어로 확인시 아래와 같은 결과 확인.
아무런 제약 주지 않은채 readness만 적용할 경우, availability 100% 확인.
delivery 서비스의 readness를 주석처리 한 후, availability 확인.
Configmap 생성 후, 아래와 같이 적용 수행