看了最近文章的反馈,似乎波澜不惊的样子,应该是看官觉得都是小菜,那我就直上硬菜,人狠话不多,开始!
准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7.13/Mysql8.0.11/Lombok0.26/Erlang21.2/postman7.5.0

难度:新手--战士--老兵--大师

目标:1,模拟商城系统,订单服务RPC调用库存服务,同时物流服务 RPC调用订单服务(订单服务双重身份) 2.订单服务通过MQ消息机制与物流服务通信

步骤

1.整体架构分析:

三服务:订单business,库存stock,物流logistics,business服务两个核心方法,一是未付订单处理,二是支付订单处理。stock服务一个核心方法,更新库存。logistics服务一个存快递单核心方法。四模块:common是公共模块,business

2.数据库设计,具体见sql脚本,5个table,其中delivery是快递,item是商品,order_detail是订单商品明细,

来个代表,order表字段设计,id做PK,BIGINT自增,order_id做订单号,为啥这么设计?id仅是PK,自增,有利于mysql的索引查询效率,mysql是按PK有序存储,pk简单有序,非常利于索引树查找,order_id具有业务含义,变化,值复杂,兼职做PK效率不高,反例就是直接使用自增id做订单号,等需要DB迁移时,就呵呵了,试想迁入的DB也有自增id字段。。。

3.mbg生成, RabbitMQ,Cors,统一异常,统一响应,均见往期文章,

4.改造下之前的MQ组件,com.biao.mall.common.service.MsgConsumer,将其中的URL变量去掉,放到sendPost参数中,注意这里是个json字符串,这样的妙处就是MsgConsumer完全作为一个独立的收消息组件了,只要有MQ消息,就处理,并根据json字符串的URL,发往目标URL,“高内聚,低耦合”,完美!反例就是将MQ消息接收放到各服务端。

5.写了两个BO(BusinessObject),业务对象,用于抽象对应真实的业务场景,只有与具体实际业务相关的属性。好处就是减少信息暴露风险,瘦身传输对象,还有如VO,DTO等,如下为OrderBO:

6. 写com.biao.mall.common.service.DubboOrderService,

两个方法,因是update,都加了事务注解,自动使用spring的事务管理,

7.写DubboOrderService实现,

com.biao.mall.business.impl.DubboOrderServiceImpl

只看重点:保存未付款订单方法,

前端传来一个orderBO,生成订单流程:使用雪花算法取得order_id,(见下节文章),然后就是写入数据库一个订单。常见的就是一个订单里多个商品,所以for循环处理,生成多个orderDetail,保存进DB。mbp的CRUD很方便,拿来就用,这里的 stockService即是RPC调用对象,不是spring的bean注入模式。

库存处理要注意,先看看剩余量,搞出库存负数就要和boss说拜拜了!

减库存模式:下单即减,下单加锁。下单即减,就直接减掉库存了,订单取消再返回来,简单粗暴。下单加锁,下单即锁住部分库存,不能用,但库存的数量包括锁住的,订单取消,只是取消锁住的部分。适用场景不同,下单即减在库存充足使用,下单加锁在秒杀,库存有限使用。我采用使用锁模式。12306就是典型的锁模式。

8.那既然调用到了stock服务,就来写service:

com.biao.mall.common.service.DubboStockService

updateStockRPC是DubboOrderServiceImpl中调用的,还有个updateStock,开发过程中废弃了,因不能RPC使用,因为参数QueryWrapper不支持RPC传递,MBP的缺陷?!

9.写stock服务的实现

com.biao.mall.stock.impl.DubboStockServiceImpl

注意点:updateById和update都是dao方法,但前者每次只更新一个,后者,呵呵,qw为null的话,全表update,务必保证qw非空!

10.再回来写com.biao.mall.business.impl.DubboOrderServiceImpl

订单付款处理:增加了快递服务的MQ逻辑,直接写入URL,并封装进消息。

for循环展开,里面一个细节:不需要if判断了?留给看官吧,

11. 写快递服务:com.biao.mall.common.service.DubboDeliveryService

12,写快递logistics服务com.biao.mall.logistic.impl.DubboDeliveryServiceImpl

的实现:RPC调用方式,

13.最后各模块的展开的全家福:

13.主体流程应该是:

14. 让马儿欢快地跑起来!启动:zk-->business-->stock-->logistics,可以看到服务已经成功注册到zk:

15.postman给个测试,模拟前端:第一条流程

16.订单数据库:

其他数据库就不一一细看了,

17.第二条流程测试:可以看到响应的是一个我们封装的对象。

18.项目源码地址:其中的day08

https://github.com/xiexiaobiao/dubbo-project.git

项目复盘记:

1.这个demo做出来,花了5个晚上,完全是从New-->Project开始的,一句话:纸上得来终觉浅,绝知此事要躬行!

2.dubbo的微服务架构,其实最核心就是这些,实际生产中就是服务更多,通信方式更多,并常有集群和负载均衡,其他一些中间件等。

3.Lombok不兼容典型表现,虽然实体类加了@Data,

4.既然是老兵级别,我想说些细节:a.字符串判空用StringUtil.isEmpty(); b.对象比较用Object.equals(), c.时间属性全部更新为localDateTime,代替Date,为了线程安全,d.对MQ做了抽象集中, e.实体属性用Integer f.表字段设计细节,

5.一个偶然发现,druid和mbg的版本要搭配好,否则出现,druid无法解析Date-->LocalDateTime

>>>>attempting to get column 'gmt_create' from result set.  Cause: java.sql.SQLFeatureNotSupportedException

亲测:mbg3.1.2+druid1.1.18报错。mbg3.1.2+druid1.1.19正常!

5.如果前端传入就是非ISO格式,不带T的日期,我就是硬杠这个问题!经诊断,原因就是fastjson不能解析这个格式。解决:添加能解析的日期格式:com.biao.mall.common.util.MyDateFormat,并注入:com.biao.mall.common.conf.WebConfig

6.对DB中自增长的字段,务必要在entity上加上@TableId(type = IdType.AUTO),这个mbp也不会给自动加上,要手动设置。

测试:去掉后,insert前打印实体:DubboOrderEntity{ id=null, gmtCreate=2019-08-16T00:00,gmtModified=null,orderId='360059542158184448', >>>>>>>>> java.lang.IllegalArgumentException: argument type mismatch>>>>可见 id =null,导致无法insert,

添加后:  ==>  Preparing: INSERT INTO dubbo_order ( gmt_create, order_id, detail_id, order_desc, user_id ) VALUES ( ?, ?, ?, ?, ? ),可见,insert语句忽略了id字段,这正是想要的效果!

6.双重@service注解:有点意思! 测试完全ok。听说dubbo的@service不能和@Transactional 同时存在,有待验证!

7.模块间不能循环依赖,如 A-->B,B-->A,会提示出错:Circular dependency between the following tasks:

解决方法:将B中的部分转移到A,或到公共模块,避免循环。

8.遇到错误 >>>  qos-server can not bind localhost:22222,

知识点:Qos=Quality of Service,qos是Dubbo的在线运维命令,可以对服务进行动态的配置、控制及查询,原因:provider已经使用了默认的qos端口导致consumer启动时使用默认的出错,配置为不同的端口即可。

9.遇到错误>>>com.alibaba.dubbo.rpc.RpcException: Unsupported client type: curator, supported client type is grizzly mina netty netty3 netty4

可能的问题:org.apache.curator 依赖未加入模块依赖

10.遇到错误提示:

问题分析:这里提示键值重复,我在DB中将该字段设置为UQ,目的是防止重复,这里却产生了问题,因为mybatis的单表默认方法:dubboStockDao.update(stockEntity,qw)生成的SQL是除了PK外,直接set其他所有字段,导致无法更新。解决:1.dao中自己写update方法,除去UQ字段  2,更好的:DB中的字段,都不要使用UQ,应该在应用层处理,这是个原则,DB只存数据,尽量少逻辑

11.其实上面这个项目有个重大的bug,各位看官可以思考下,且看我下回分解。

12.码字N小时,上头了.

往期文章推荐:

Dubbo学习系列之六(微服务架构实战)的更多相关文章

  1. springcloud与docker微服务架构实战--笔记

    看了<微服务那些事>之后,Spring boot和Spring Cloud的关系理清楚了,Spring cloud各个模块的作用也了解了. 但是,Spring cloud 与Docker的 ...

  2. 庐山真面目之六微服务架构Consul集群、Ocelot网关集群和Nginx版本实现

    庐山真面目之六微服务架构Consul集群.Ocelot网关集群和Nginx版本实现 一.简介      在上一篇文章<庐山真面目之五微服务架构Consul集群.Ocelot网关和Nginx版本实 ...

  3. 《Spring Cloud与Docker微服务架构实战》配套代码

    不才写了本使用Spring Cloud玩转微服务架构的书,书名是<Spring Cloud与Docker微服务架构实战> - 周立,已于2017-01-12交稿.不少朋友想先看看源码,现将 ...

  4. Dubbo和Spring Cloud微服务架构比较

    Dubbo 出生于阿里系,是阿里巴巴服务化治理的核心框架,并被广泛应用于中国各互联网公司:只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,设计的目的还是服务于自身的业务为主. 微服 ...

  5. Dubbo 和 Spring Cloud微服务架构 比较及相关差异

    你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构. 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务, ...

  6. Spring Cloud与Docker微服务架构实战 PDF版 内含目录

    Spring Cloud与Docker微服务架构实战  目录 1 微服务架构概述 1 1.1 单体应用架构存在的问题1 1.2 如何解决单体应用架构存在的问题3 1.3 什么是微服务3 1.4 微服务 ...

  7. Dubbo和Spring Cloud微服务架构'

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

  8. dubbo和dubboX与微服务架构(dubbo一)

    一.传统三层架构模式的缺陷 三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:界面层(User Interface layer)web.业务逻辑层(Bu ...

  9. 你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构

    微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业 ...

随机推荐

  1. Mac配置Gradle环境

    下载Gradle 下载地址:https://gradle.org/install 下载最新版本:gradle-3.3 (当前最新版2017年2月8日) 配置Gradle环境 我的本机Gradle存放路 ...

  2. js递归优化

    递归优化 递归在我们平时撸码中会经常用到,不过可能很多人不知道递归的弊端,就是会导致调用栈越来越深.如果没有节制的使用递归可能会导致调用栈溢出. 那什么是递归呢? 递归调用是一种特殊的嵌套调用,是某个 ...

  3. #华为云·寻找黑马程序员#微服务-你真的懂 Yaml 吗?

    在Java 的世界里,配置的事情都交给了 Properties,要追溯起来这个模块还是从古老的JDK1.0 就开始了的. "天哪,这可是20年前的东西了,我居然还在用 Properties. ...

  4. 如何运用DDD - 领域服务

    目录 如何运用DDD - 领域服务 概述 什么是领域服务 从实际场景下手 更贴近现实 领域服务VS应用服务 扩展上面的需求 最常见的认证授权是领域服务吗 使用领域服务 不要过多的使用领域服务 不要将过 ...

  5. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: REFERENCES command denied to user 'nali'@'localhost' for table 'dbs'

    按照教程 Install hive on Mac with Homebrew,在 mac 上安装 Hive 时, 最后执行 hive 命令后,出现错误: Exception in thread &qu ...

  6. shell 数组作为函数形参

    问题描述: 把字符串tarFile和数组slaves_hostIP传入函数processArray中并输出结果. #!/bin/bash function processArray() { tarFi ...

  7. Python爬虫根据关键词爬取知网论文摘要并保存到数据库中【入门必学】

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:崩坏的芝麻 由于实验室需要一些语料做研究,语料要求是知网上的论文摘要 ...

  8. html小工具——文章注释编辑器

    在网上阅读文章时,读者时常会想针对某段文字写一些自己的感想,可惜大部分阅读网站并不提供这样的功能,读者往往只能将文本复制到本地或在线的编辑器中编辑注释,之后如果想在其他地方回顾这些注释也必须先本地安装 ...

  9. Python3 常用模块1

    目录 os模块 对文件夹操作 对文件进行操作 sys模块 json 和pickle模块 logging模块 日志等级 longging模块的四大组件 自定义配置 os模块 通过os模块我们可以与操作系 ...

  10. Sample Preparation by Easy Extraction and Digestion (SPEED) - A Universal, Rapid, and Detergent-free Protocol for Proteomics based on Acid Extraction(一种使用强酸的蛋白质提取方法SPEED,普适,快速,无需去垢剂)-解读人:李思奇

    期刊名:Mol Cell Proteomics 发表时间:(2019年12月) IF:4.828 单位:德国Robert Koch 研究所 物种:多种 技术:新蛋白提取和酶解方法 一. 概述: 本文设 ...