mq的概念(一種互連網項目開發方式) 前言
現在一個互連網時代,也是一個大資料時代。隨著互連網的高速發展,對產品的要求越來越高。儘管現在IT技術也已經很成熟,但是還有很多剛開始接觸互連網項目的團隊卻不知道如何下手。前兩天我見了一名創業者,與他公司的技術負責人瞭解了一下他們的項目架構,覺得很有問題,但是他們已經開發了半年之久要想從根本解決問題已經不太容易了。關於mq思想,就是想講給那些即將要做互連網項目或剛開始做的項目團隊。 個人履曆
我12年底開始參加工作,剛開始是做手機端開發,後來轉入java後端開發。偶然的一次機會我參與一個互連網項目開發,當時我只是一個普通研發,跟隨同事一塊研究探討如何研發互連網項目。但是項目大概做了3個月就停掉了,由於商務原因沒有繼續研發下去。也就是在那時候我決定開始研究到底什麼是大資料,什麼叫做高並發。在14年底我辭掉了工作與朋友一塊開始了創業之路,我們公司主要是做手機app項目。那也正是O2O流行的時候,在那段時間我們接觸了很多創業者,他們都有一個互連網的產品,他們找到我們讓我們幫他們實現功能。也是在這段經曆中讓我學會如何開發互連網項目。 mq思想的由來
在去年阿里雲的技術分享會上,他們邀請各個互連網公司的技術大佬分享他們的技術架構,小咖秀的技術總監講過一句話:“互連網的項目一定要做到可以拆分”。mq本意是指訊息中介軟體,被用於服務之間的訊息資料通訊。但是在這裡它不僅僅是指訊息通訊又有了一層另外的含義。 如何拆分項目
大學上課的是時候,老師就在講做項目要劃分項目模組,後來參加工作的時候我們也都劃分了模組,但是劃分完以後覺得也沒有什麼特別清晰的感覺,只是覺的多了幾個package而已。如何拆分項目始終不是很清晰,在慢慢鍛煉的過程中我發現了如何劃分項目模組的方式,就是直接通過db來劃分項目模組。 從資料庫設計就開始拆分模組
假設我們要做一個商城項目,商城有訂單/商品/使用者三個模組。那麼我會直接在設計資料庫的時候就將他們拆分成三個模組。表名會叫做:t_o_order/t_p_product/t_u_user。然後在設計他們模組下其他表時會通過模組的首碼名做區分。並且做到不讓業務在實現功能的時候需要跨模組做資料庫操作。若存在的話可能的原因有兩種:1設計的模組不合理。2可以通過模組資料冗餘的方式避免模組調用。設計完以後,可以達到的效果就是,完全可以讓各個模組存放在不同的資料庫下。
如何拆分項目
當我們把資料庫模組劃分好了以後,項目模組劃分就簡單了。只需要配合著db來劃分模組就行了,也就是將t_u_劃分為一個模組,t_o_一個模組,t_p_一個模組。然後配套的dao service都放在一個模組下。 效果如下: 模組之前如何通訊
同一個項目,肯定無法避免項目內部模組之間的相互調用,比如下單介面,該介面必定會關聯到使用者以及商品模組。那麼我們如何處理呢。若直接在訂單模組調用商品或者使用者模組,那麼有會導致項目模組高度耦合無法分離了。 如下: 所以我們添加mq模組: 模組之間的相互依賴變成了對mq模組的依賴。這樣模組不會相互依賴了,但是卻都依賴mq。但是mq模組的原則是這樣的:1 mq模組不參與任何業務處理,只做模組之間的協調調用。2 mq模組下會有各個模組的業務調度類,每個業務類下暴漏出的方法,都是需要被其他模組調用的。
我們來看一段代碼,學習一下mq如何工作的。這是一個下單的業務方法。方法裡需要訪問使用者和商品模組,但是該業務下盡通過mq模組訪問,而不直接存取模組。
@Autowired private MQUserService mqUserService; @Autowired private MQProductService mqProductService; @Autowired private OrderDao orderDao; @Override public Map<String, Object> createOrder(String json) throws ServiceException { int productId = JsonUtils.getInt(json,"productId",0); int userId = JsonUtils.getInt(json,"userId",0); //todo 檢查商品庫存 Product product = mqProductService.checkProductCount(productId); //todo 檢查使用者金額 User user = mqUserService.checkUserMoney(userId); //todo 組裝訂單資料 Order order = null; //todo 建立訂單 orderDao.createOrder(order); Map<String, Object> res = new HashMap<>(); res.put("order",order); res.put("product",product); res.put("user",user); return res; }
再來看一下mq模組的MQUserService和MQProductService的實現:
@Servicepublic class MQUserServiceImpl implements MQUserService { @Autowired private UserService userService; @Override public User checkUserMoney(int userId) throws ServiceException { return userService.checkUserMoney(userId); }}
@Servicepublic class MQProductServiceImpl implements MQProductService { @Autowired private ProductService productService; @Override public Product checkProductCount(int productId) throws ServiceException { return productService.checkProductCount(productId); }}
mq模組下的業務實現僅僅起到了調用的功能,沒有具體的商務邏輯。 這樣設計mq模組有什麼意義
. 通過mq的概念我們輕鬆的降低模組之間的耦合. . 簡化了模組之間協作開發的難度。
若a模組需要協調b模組的功能的時候,a模組只需要在b模組mq下的模組Service下添加一個自己需要業務介面就行了,然後通知b模組實現該介面即可。 . 當需要做拆分項目的時候,只需要將mq模組替換成RPC即可。
這樣的項目前期可以是在一個項目下,而且很好的解決了項目模組劃分和配合的問題,再就是在項目的後期需要做拆分的時候。只需要調整一下mq模組即可,此時的mq模組才是真正的訊息調度模組。 從單機系統演變成為叢集系統
只要我們在設計之初就考慮到了如何拆分項目,那麼當項目達到單機瓶頸的時候,做拆分就簡單了,這個時候只需要讓mq模組的注入方式調用其他模組改成RPC調用即可。然後再添加對分散式交易的支援這樣一個分布式叢集系統就搭建好了。關於RPC遠程調用可以使用阿里的dubbo架構,關於分散式交易可以採用我封裝的transaction架構.
分布式系統的架構圖:
關於mq-demo代碼:該代碼僅僅作為一個架構理解的demo,該demo沒有實際功能。
原文地址:https://github.com/1991wangliang/mq_demo