架構模式是軟體架構中在給定環境下常遇到問題的通用的、可重用的解決方案。類似於軟體設計模式但覆蓋範圍更廣,致力於軟體工程中不同問題,如計算機硬體效能限制、高可用性、業務風險極小化。一些架構模式在軟體框架被實現。- 維基百科
分層架構Pipeline架構事件驅動架構分層架構分層架構模式
分層架構模式工作中用的比較多,常見的有MVC等,透過分層將職責劃分到某一層上,層次清晰,架構明瞭。
我們以MVC來舉例說明:controller -> service -> dao
@RestController@RequestMapping("/order")public class OrderController { @Autowired private OrderService orderService; /** * 新增訂單 * @param order * @return */ @PostMapping("/add") public Response addOrder(Order order) { orderService.add(order); return Response.success(); }}
public interface OrderService { /** * 新增訂單 * @param order * @return */ boolean add(Order order);}
public interface OrderRepository { int save(Order order);}
按照依賴方向,上層依次依賴下層,每一層處理不同到邏輯。
Pipeline架構Pipeline架構模式
Pipeline架構也稱為管道或流水線架構,處理流程成線性,各個環節有相應到元件處理,從前到後順序執行。
概念說明:
source: 資料來源,通常使用流資料為源,比如:KafkaSource;
channel:通道或管道,用於處理或轉換資料,比如:JsonChannel;
Component: 元件,用於執行邏輯的最小單元,source,channel,sink都是一個Component;
Pipeline: 管道或流水線,一個Pipeline由上面的元件組成,不同的業務可以組裝成不同的Pipeline;
程式碼實現:數字資料來源 -> 累加 -> 轉成字串 -> 落地
/** * 元件 */public interface Component<T> { /** * 元件名稱 * @return */ String getName(); /** * 獲取下游元件 * @return */ Collection<Component> getDownStrems(); /** * 元件執行 */ void execute(T o);}
public abstract class AbstractComponent<T, R> implements Component<T>{ @Override public void execute(T o) { // 當前元件執行 R r = doExecute(o); System.out.println(getName() + " receive " + o + " return " + r); // 獲取下游元件,並執行 Collection<Component> downStreams = getDownStrems(); if (!CollectionUtils.isEmpty(downStreams)) { downStreams.forEach(c -> c.execute(r)); } } protected abstract R doExecute(T o);}
/** * 資料來源 */public abstract class Source<T, R> extends AbstractComponent<T, R>{}
/** * 管道/通道 * @param <T> */public abstract class Channel<T, R> extends AbstractComponent<T, R> {}
/** * 資料落地 * @param <T> */public abstract class Sink<T, R> extends AbstractComponent<T, R> {}
public class IntegerSource extends Source<Integer, Integer>{ @Override protected Integer doExecute(Integer o) { return o; } @Override public String getName() { return "Integer-Source"; } @Override public Collection<Component> getDownStrems() { return Collections.singletonList(new IncrChannel()); }}
public class IncrChannel extends Channel<Integer, Integer> { @Override protected Integer doExecute(Integer o) { return o + 1; } @Override public String getName() { return "Incr-Channel"; } @Override public Collection<Component> getDownStrems() { return Collections.singletonList(new StringChannel()); }}
public class StringChannel extends Channel<Integer, String> { @Override protected String doExecute(Integer o) { return "str" + o; } @Override public String getName() { return "String-Channel"; } @Override public Collection<Component> getDownStrems() { return Collections.singletonList(new StringSink()); }}
public class StringSink extends Sink<String, Void>{ @Override protected Void doExecute(String o) { return null; } @Override public String getName() { return "String-Sink"; } @Override public Collection<Component> getDownStrems() { return null; }}
/** * 流水線 */public class Pipeline { /** * 資料來源 */ private Source source; public Pipeline(Source source) { this.source = source; } /** * 啟動 */ public void start() { source.execute(1); }}
測試:
public class PipelineTest { @Test public void test() { Pipeline pipeline = new Pipeline(new IntegerSource()); pipeline.start(); }}
執行結果:
Integer-Source receive 1 return 1
Incr-Channel receive 1 return 2
String-Channel receive 2 return str2
String-Sink receive str2 return null
事件驅動架構事件驅動模式
事件驅動是以某個具體事件為觸發條件,從而貫穿這個處理流程。通常事件驅動屬於釋出訂閱模式或觀察者模式, 用於非同步處理,解耦業務邏輯。具體實現有程序內的和分散式的方式,比如:EventBus, MQ等等。
程式碼舉例:
public class OrderEventListener implements Listener<OrderEvent> { @Override public void onEvent(OrderEvent event) { System.out.println("receive event: " + event); }}
public class EventBus { private final static List<Listener> listeners = new ArrayList<>(); /** * 註冊監聽器 * @param listener */ public static void registerListener(Listener listener) { listeners.add(listener); } /** * 釋出事件 * @param event */ public void publishEvent(Event event) { // 收到並處理事件 listeners.forEach(l -> { l.onEvent(event); }); }}
測試:
@Componentpublic class OrderEventListener { @Async @EventListener(OrderEvent.class) public void onEvent(OrderEvent event) { System.out.println("receive event: " + event); }}
public class EventTest { @Autowired private ApplicationContext context; @Test public void publishEvent() { OrderEvent event = new OrderEvent("order_1", OrderState.PENDING_PAYMENT); context.publishEvent(event); }}
總結
以上透過程式碼例項簡單說明了工作中常用到的架構模式,但是模式不是固定的,工作中需結合實際情況按需使用即可。