酒店项目总结

1、项目简介

背景

该项目是依托微信小程序和App客户端提供线上预定酒店和旅游产品的互联网产品。

解决用户痛点

1、提高了用户搜索酒店和预定酒店的效率。

2、售后保障了用户合法权益。

3、基于数据分析给予用户更多场景下的组合。

目的

1、提高技术视野,从不知道到知道。

2、体验真实项目流程,感受真实的项目开发流程和开发场景。

3、工程化实践,微服务项目最佳工程化搭建。

4、强身健体,身体是革命的本钱,再忙再累也要锻炼身体。

项目开发流程

项目架构图

流程:

  • 用户发起请求后,请求首先到达域名服务器DNS(Domain Name System)进行请求解析,其中包括WAF(Web Application Firewall)、内容分发网络CDN(Content Distribution Network)和防火墙等。
  • DNS解析后,首先到达Nginx集群,Nginx通过反向代理算法(轮询(默认)、权重、ip_hash、最少连接)将请求转发到网关(SpringCloud Gateway)。网关通过Sentinel+Shard进行授权认证,通过Apollo进行动态路由,通过令牌桶算法进行限流,再通过断言(Predicate)和过滤器(Filter)经过负载均衡(Ribbon)加熔断降级(Sentinel)路由到具体的微服务。期间,还可以使用Redis用作缓存。
  • 请求到达认证中心微服务,通过OAuth2和Spring Security进行授权,颁发令牌,然后去往指定的微服务。微服务与微服务之间通过OpenFeign来相互调用。
  • 在请求到达网关时,配置中心和注册中心使用Nacos,使用Apollo配置动态路由,使用Spring Boot Admin来监控微服务的健康状态,同时可以使用日志微服务来记录日志。
  • Beats负责收集日志数据发送给Logstash,然后Logstash将数据发送给Kafka进行解耦、异步处理和流量削峰,最后将日志信息发送到ElasticSearch,维护人员通过Kibana进行查看。
  • 持久化存储用主从复制的MySQL,缓存使用Redis,消息队列使用RabbitMQ和Mirror,全文检索使用分布式搜索ElasticSearch,对象存储使用OSB,任务管理使用XXL-JOB。
  • 监控中心使用Skywalking UI,使用链路追踪Zipkin,监控报警Prometheus、Grafance和Alertmanager,将报警信息发送到短信、微信或者邮箱中。
  • 项目中还用了分布式,有分布式主键、分布式锁和分布式事务等,实现的技术有CAP和BASE。其中,CAP包括一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),三者不可能同时满足,最多只能满足其二。BASE是基于CAP理论演化而来的,包括基本可用(Basically Available)、软状态(Soft State)、最终一致性(Eventual Consistency)。CAP的核心就是强一致性,而BASE理论的核心是最终一致性。

项目结构

2、设计数据库

下面是我总结的几点注意事项:

  • 表名和字段名采用下划线(_)连接,要见名知意。
  • 最好不要用缩写。
  • 所有字段最好设置默认值,然后非空。
  • 选择合适的字段类型,长度不要过多或过少。
  • 如果不是必要,字段名前缀最好不要和表名重复。
  • 必须要根据阿里开发手册来设计数据库。
  • 字段名不要使用is_前缀,否则使用代码生成器会出问题。
  • 表名和字段名统一使用小写。不要一个字段大写,一个字段小写。
  • 每一个字段都写好注释。

上图是我自己第一次设计数据库时的一个表,有一些字段没有设置非空和默认值,然后用了is_前缀,还有一些字段是数据库里的特殊字段,没有处理,还有字段类型没有选择好,比如价格,应该使用int类型。

上图是我们队综合了其他人的表第一次设计数据库时的一个表,很多字段没有设置非空和默认值,然后用了is_前缀,还有一些字段是数据库里的特殊字段,没有处理,还有字段类型没有选择好,比如价格,应该使用int类型。还有备用字段是多余的。

上图是经过师哥开会之后,历经多次的一个改版,其中的问题还有字段名是数据库的特殊字段,字段类型还是选择的不对。

上图是经过师哥开会之后,我们队内历经多次的一个最终版本,其中的主要问题还有字段名是数据库的特殊字段。

3、API设计

下面是我总结的几点注意事项:

  • 可以遵循Restful风格,也可以不遵循,但最好统一。
  • GET和DELETE请求的参数需要在Query里写,POST和PUT的请求要以JSON的格式。
  • 请求路径不能以驼峰的方式,要以-分隔。
  • 实体类的属性名和数据库里的字段名保持一致且下划线转驼峰。
  • 响应结果必须要有code和message,data没有数据时可为空。
  • 类上的映射路径和方法上的映射路径不要重复。
  • 涉及到金额字段,数据库采用分为单位存储,返回数据时,必须转为以元为单位。
  • 不能返回多余的属性。
  • 日期类型统一用Date。

以下是我负责的其中一个API,经过队内多次的改版之后的一个最终版本。

4、接口设计

数据库设计好,API也设计好,接下来就可以进行接口设计了。

  • 接口要继承mybatis-plus的接口,使用mybatis-plus内置的方法。
  • DAO层需要继承mybatis-plus的BaseMapper接口。

  • 业务接口层,需要继承mybatis-plus的IService接口。

  • 业务实现类层,需要继承ServiceImpl接口

5、编码阶段

注意事项:

  • 控制层接收参数时必须做非空校验,如果是实体类,则校验必须的字段。

  • 控制层不做任何逻辑处理,只有调用业务层的方法,获取数据,然后返回结果。

  • 业务层返回数据,而不是返回结果。

  • 对数据库的操作使用mybatis-plus,并且service层只能注入service,不能直接操作别的DAO。

  • 使用mybatis-plus,不能将字段名硬编码到代码中,要使用lambda表达式,也叫做方法引用。

  • 代码中不要有魔法值,将常量放到枚举中。

  • 不要使用==null这些判断,统一使用hutool工具包。

  • 只涉及单个数据库的,必须加事务,如果不止一个库,则不能加事务。

  • 配置相关,不要放在业务层,需要单独配置。

  • 不要使用try-catch,如果需要,统一抛出异常。会使用全局异常进行捕捉。

  • 不要使用if-else,在if中如果没有数据,直接抛出异常或返回。

  • 日志打印,只打印关键地方,节约资源。

  • 方法上写注释,增加可阅读性。

  • 字符串拼接,不要直接使用+,使用StringBuilder或StringBuffer,但要注意它们的区别。

  • 如果分支特别多的情况下,使用switch,使的代码更加简洁,但,别忘了break。

  • 每一个模块只负责自己的活,如果需要别的类,则将对应的代码写在别的类中,通过注入service来调用。

  • 上传图片等操作不要写在一个方法里,最好可以写一个工具类。

  • 大小写问题,如DAO、DTO、VO和BO必须大写。

  • 如果要自己写xml,必须保证走索引,目前阶段,也推荐每次只对单表操作,多查询几次没关系。因为单表走索引容易保证,多表连查走索引不好保证。其次,如果要系统拆分,多表连查很难拆出来。

6、总结

通过这一个多月真实项目的开发,代码写的不是很多,但是花费的精力却比写代码花费的精力更多。这一次的项目开发,实实在在的从0到1,从一个什么都不知道的小白,经过师哥的指导,慢慢的了解了整个项目开发的流程,先是梳理项目的流程,再到整理项目,然后进行数据库设计、API设计、接口设计再到编码,看似这简简单单的六步,比单单敲代码难多了,下面我对这次项目的开发总结一下。

  • 第一个就是代码规范,在一个多月以来,其实技术没学到什么,学到更多的是规范和设计,因为技术,在 网上随便找一个视频就能学,但是规范和设计这些是在视频里学不到的。还有就是工具的使用,比如git,这个工具我以前是学过就没用过,导致在项目中用的时候很生疏,但是,通过这次的项目,我对git熟悉了很多,能够使用git最基本的功能了。
  • 在流程梳理过程中,在下面好几个设计阶段中,流程梳理是至关重要的,只有彻底的了解了这一个东西,才知道怎么实现,实现的步骤和如何优化,如何做到最好。也让我知道了一件事,做什么事都不能急,俗话说,心急吃不了热豆腐,只有在真正的了解了一件事之后,才可能动手去实现它,而不是一开始就直接开干。
  • 在设计数据库阶段,原本我听说在公司里项目开发前,数据库都是架构师设计好的,开发者直接用就行了。但这次自己去设计的时候,发现设计数据库比单纯的敲代码难太多了。在用户方面,需要考虑用户需要看什么信息,需要展示什么信息,什么信息是能改的,什么信息又不能改;在技术方面,设计表要遵循数据库的范式,要考虑到表中的每一个具体的字段是用来干嘛的,并且还得有适当得冗余。考虑关系时,有时还需要加中间表,中间表又得需要什么字段,又要给字段设置合适得字段类型,设置得不合理也会影响效率和空间。表设计完之后还需要加索引,需要想要什么信息,怎么查,给哪些字段加索引。还有一种情况就是索引会失效的情况,这些都需要考虑的。我个人觉得,数据库的设计应该是项目开发流程中最难、最复杂的一个流程,如果前期设计的不合理,后期在开发中,还需要修改。这次我们团队经过好几次的讨论,才最终把最终版本定下来,并且,在后期开发时,还修改过字段。
  • 在API设计阶段,其实一开始,师哥让我们每一个人都自己设计一个API出来的时候,其他人不知道,反正我是懵逼的,API我会用,但根本不会设计。和数据库设计类似,但比数据库设计简单,需要考虑界面需要展示哪些信息,然后用什么方式请求,请求参数需要什么,需不需要包装,响应信息需要什么,请求路径是什么。在这一模块我也学会了使用ApiPost这个工具,国产的,全中文,这个工具不仅可以发送请求,还可以进行API设计,挺好用的。
  • 在接口设计中,也是需要考虑用户需要哪些信息,根据API设计来填充参数,返回对应数据,提前写好方法。如果是搜索等接口的话,条件太多,一般前端都是会以JSON格式请求的,这时就需要一个DTO、VO等来封装条件。
  • 在编码阶段中,因为我是直接用代码生成器直接生成的,所以基础的类都不需要自己去创建,但是,好像团队里其他的小伙伴有遇到一些问题,就是如何使用mybatis-plus里的内置方法,所以,DAO和service接口都需要继承mybatis-plus提供的接口,这个问题我以前也不知道,因为是自动生成的,就没留意过,但是通过一些小伙伴的反馈,下次我就能注意了。在业务层调用DAO层的方法时,不要使用baseMapper来调用,直接用this调用,增加可阅读性。在编码阶段中,我印象最深的还是代码规范,这个问题,师哥也讲了好久,并且在代码里,也不要有硬编码的代码出现,如果有,可以替换成方法引用。还有事务的问题,只涉及到一个库,比如只有MySQL这一个,就可以用事务,如果在一个方法里,不仅有MySQL,还有Redis相关的操作,这时就不能加事务,而且,还要考虑在哪些情况下事务会失效的问题。并且,通过这个编码阶段,我还熟悉了stream流的相关操作。还有一些注意事项,就是在上面有提到过的,这里就不再阐述了。

最后,通过这次这个项目,先不谈技术,就光看这些设计(数据库设计、API设计等),就对我的经验有了质的飞跃,让我明白了这些设计原则,需要考虑哪些东西,还有师哥每一次开会都会传授我们很多宝贵的经验,这些在视频里都是学不到的知识,师哥有句话让我印象深刻

工作之后,大家都是同一个起点,不要把自己搞得有多牛逼,如果你有80分,请不要想着把它提高到90分、100分,而是想着怎么把那些没有80分的人提高到80分,然后在一起进步,不要过于看中自己的能力。

接下来要学习的地方还有很多,像以前学过的很多技术点都忘了,都需要巩固加强。因为现在也要找工作,所以需要疯狂的背八股文和刷算法题,还有计算机网络和操作系统,这两门课也很重要。我们需要时刻保持一颗童心般的好奇,在技术面前要永远有上进心,这样技术才能不断的提高,同时,也需要保持团队之间的协作,团队之间互帮互助,这样才能走的更高更远。

最后的最后,再次感谢师哥这一个多月以来的指导。