mq的概念(一种互联网项目开发方式)

Wesley13
• 阅读 299

前言

现在一个互联网时代,也是一个大数据时代。随着互联网的高速发展,对产品的要求越来越高。尽管现在IT技术也已经很成熟,但是还有很多刚开始接触互联网项目的团队却不知道如何下手。前两天我见了一名创业者,与他公司的技术负责人了解了一下他们的项目架构,觉得很有问题,但是他们已经开发了半年之久要想从根本解决问题已经不太容易了。关于mq思想,就是想讲给那些即将要做互联网项目或刚开始做的项目团队。

个人履历

我12年底开始参加工作,刚开始是做手机端开发,后来转入java后端开发。偶然的一次机会我参与一个互联网项目开发,当时我只是一个普通研发,跟随同事一块研究探讨如何研发互联网项目。但是项目大概做了3个月就停掉了,由于商务原因没有继续研发下去。也就是在那时候我决定开始研究到底什么是大数据,什么叫做高并发。在14年底我辞掉了工作与朋友一块开始了创业之路,我们公司主要是做手机app项目。那也正是O2O流行的时候,在那段时间我们接触了很多创业者,他们都有一个互联网的产品,他们找到我们让我们帮他们实现功能。也是在这段经历中让我学会如何开发互联网项目。

mq思想的由来

在去年阿里云的技术分享会上,他们邀请各个互联网公司的技术大佬分享他们的技术框架,小咖秀的技术总监讲过一句话:“互联网的项目一定要做到可以拆分”。mq本意是指消息中间件,被用于服务之间的消息数据通讯。但是在这里它不仅仅是指消息通讯又有了一层另外的含义。

如何拆分项目

大学上课的是时候,老师就在讲做项目要划分项目模块,后来参加工作的时候我们也都划分了模块,但是划分完以后觉得也没有什么特别清晰的感觉,只是觉的多了几个package而已。如何拆分项目始终不是很清晰,在慢慢锻炼的过程中我发现了如何划分项目模块的方式,就是直接通过db来划分项目模块。

从数据库设计就开始拆分模块

假设我们要做一个商城项目,商城有订单/商品/用户三个模块。那么我会直接在设计数据库的时候就将他们拆分成三个模块。表名会叫做:t_o_order/t_p_product/t_u_user。然后在设计他们模块下其他表时会通过模块的前缀名做区分。并且做到不让业务在实现功能的时候需要跨模块做数据库操作。若存在的话可能的原因有两种:1设计的模块不合理。2可以通过模块数据冗余的方式避免模块调用。设计完以后,可以达到的效果就是,完全可以让各个模块存放在不同的数据库下。

mq的概念(一种互联网项目开发方式)

如何拆分项目

当我们把数据库模块划分好了以后,项目模块划分就简单了。只需要配合着db来划分模块就行了,也就是将t_u_划分为一个模块,t_o_一个模块,t_p_一个模块。然后配套的dao service都放在一个模块下。 效果如下: mq的概念(一种互联网项目开发方式)

模块之前如何通讯

同一个项目,肯定无法避免项目内部模块之间的相互调用,比如下单接口,该接口必定会关联到用户以及商品模块。那么我们如何处理呢。若直接在订单模块调用商品或者用户模块,那么有会导致项目模块高度耦合无法分离了。 如下: 所以我们添加mq模块: 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的实现:

@Service
public class MQUserServiceImpl implements MQUserService {

    @Autowired
    private UserService userService;

    @Override
    public User checkUserMoney(int userId) throws ServiceException {
        return userService.checkUserMoney(userId);
    }
}




@Service
public 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的概念(一种互联网项目开发方式)

关于mq-demo代码:该代码仅仅作为一个框架理解的demo,该demo没有实际功能。

原帖地址:https://github.com/1991wangliang/mq\_demo

qq交流群:554855843

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Karen110 Karen110
2年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
Android蓝牙连接汽车OBD设备
//设备连接public class BluetoothConnect implements Runnable {    private static final UUID CONNECT_UUID  UUID.fromString("0000110100001000800000805F9B34FB");
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这