项目背景:
依托微信小程序和App 客户端提供线上预定酒店和旅游产品的互联网产品。
- 解决用户痛点1:提高了用户搜索酒店和预定酒店的效率
- 解决用户痛点2:售后功能保障了用户的合法权益
- 解决用户痛点3:基于数据分析提供给用户多需求场景的组合产品
开发流程:
项目架构图:
项目最终实现的流程:
1、前端的请求进行DNS解析。
2、再通过nginx集群(作用:反向代理与虚拟主机)反向代理到Webflux网关中,通过网关微服务进行指定的Predicate(断言)和Filter(过滤器)来匹配对应的controller层的请求地址,其中Sentinel+Shard进行认证授权,中间还可以整合Redis来实现令牌限流(请求限制)。
3、nacos在整个项目架构中起到注册中心以及配置中心的作用,不需要自己在独立创建一个eureka注册中心微服务已经配置中心微服务。并且在nacos中,可以将配置重复的代码放置在通用的配置中。并且可以在controller层通过@RequestScope注解来实现配置文件自动刷新。
4、请求通过Gateway,通过Ribbon、Sentinel来实现负载均衡(将任务(请求)分摊到多个操作单元进行执行)以及熔断降级(为了保证服务的可用性)的策略。
5、通过SpringSecurity框架与OAuth2认证中心整合JWT进行公钥私钥的颁发授权与相应验签认证功能(授权服务器通过私钥加密形成令牌,对外用资源服务器提供公钥,利用公钥来验证令牌的合法性)。
6、SpringBoot在业务集群中通过openFeign来进行业务集群间业务的调用,在业务中,使用到一些工具:Mysql--->主从复制进行数据的持久化操作,RabbitMQ---->实现消息队列,用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用,ElasticSearch----->进行全文检索,阿里云OSS云存储服务----->进行对象存储、企业数据管理等
7、在业务集中还需要实现对应的分布式事务、分布式锁。需要遵循CAP定理----->
Base定理:
BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写。
BASE定理来源:是CAP中一致性和可用性的权衡结果,它来自大规模互联网分布式系统的总结,是基于CAP定理逐步演化而来的。
BASE定理的核心思想:即使无法做到强一致性,但是每个应用可以根据自身的业务特定,采用合适的方式来达到最终一致性。
8、日志收集通过Beats、ELK、和Kafka整和完成,具体过程是这样的:Beats用于日志数据采集使用,Logstash收集日志,发送给Kafka进行解耦、异步处理和流量削峰,然后通过Elasticsearch集群存储日志数据,索引日志数据,再通过Kibana视图形式展现日志信息,更加人性化地在客户端进行检索以及相关操作。
9、监控中心由Skywalking来实现:
SkyWalking 逻辑上分为四部分: 探针, 平台后端, 存储和用户界面。
- 探针 基于不同的来源可能是不一样的, 但作用都是收集数据, 将数据格式化为 SkyWalking 适用的格式.
- 平台后端, 支持数据聚合, 数据分析以及驱动数据流从探针到用户界面的流程。分析包括 Skywalking 原生追踪和性能指标以及第三方来源,包括 Istio 及 Envoy telemetry , Zipkin 追踪格式化等。
- 存储 通过开放的插件化的接口存放 SkyWalking 数据. 你可以选择一个既有的存储系统, 如 ElasticSearch, H2 或 MySQL 集群(Sharding-Sphere 管理),也可以选择自己实现一个存储系统. 当然, 我们非常欢迎你贡献新的存储系统实现。
- UI 一个基于接口高度定制化的Web系统,用户可以可视化查看和管理 SkyWalking 数据。
运维报警系统由Prometheus实现,Skywalking与Prometheus结合Grafana最终和Alertmanager通过短信、微信或者邮件的形式给模块负责人发送警告通知。
10、由开发人员将代码上传到github,通过docker容器进行部署,在通过k8s进行资源的编排等,使用Jenkins Pipeline进行代码构建、代码测试、部署等,最后由运维人员进行运维
工程架构:
项目中的收获:
一、数据库方面:
1、数据库必备的4大字段:
1.1、id:主键,BIGINT类型,对应java中的Long
1.2、deleted:删除,TINYINT,所有的删除都必须是逻辑删除,除非业务需求是物理删除
1.3、update_time:更新时间,要求有默认值,CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
1.4、create_time:创建时间,要求又默认值,CURRENT_TIMESTAMP
2、数据库中的字段,都应该需要设置默认值,主外键字段除外
3、一对多或者多对多表的设计,使用中间表来进行连接。
4、字段名需要见名知意
下面是我们组最终设计的数据库:
二、接口的设计
我负责的是房型的添加和删除、里面还包括图片、房型、房型与床型中间表、房型与餐食中间表的添加与删除。
接口的请求方式一律使用post请求。
下面仅列举房型的添加和删除:
房型的删除:
三、代码的开发:
以图片的上传为示例:
controller层:
service层:
总结:
1、逻辑部分放在service层来实现,controller层的代码最大层度的简洁,controller层只写请求成功的返回值,请求失败的返回值在service层实现。
2、在写业务逻辑时,要if(){},来代替if(){}else{}、循环里面尽量不要在嵌套循环等来增强代码的可读性。
3、使用自定义异常,当业务逻辑执行失败时,直接抛异常。
4、使用hutool依赖来进行代码的开发,使得代码更加优雅,比如:判断对象为空---->使用ObjectUtil.isEmpty()里面传入对象,来判断。集合的判断---->CollectionUtil.isEmpty(),传入集合来判断、
5、在进行查询业务时,应该使用单表查询,不要使用两表联查以及多表联查,因为单表查询好走索引,多表联查不好走索引。
6、在进行controller层编写的时候,方法名应与参数地址尽量一致
7、参数名采用驼峰命名
8、金额数据:后端使用整数存,但是到了前端部分要转化为小数(类型为Number)
9、数据库中存在的字段的参数,命名要保持一致
10、如果参数中用多个 id 参数,必须区分命名,且要与数据库一致
11、传参的实例值尽量真实一点,参数描述简练准确
12、响应数据示例的格式必须的实际的格式,响应数据的类型和描述和请求参数的要求一致
13、路径请求格式(业务/模块/方法) 方法名里面要加能表示动作的词
14、DAO层的代码直接继承BaseMapper<实体类>,service继承IService<实体类>,serviceImpl继承ServiceImpl<DAO类,实体类>实现对应的service