今天,2022 年 01 月 13 日。

学完了尚硅谷的一个叫尚医通的项目,它是一套前后端分离的微服务架构的项目,用的技术栈非常全,是真实的解决业务问题的。(因为我发现北京有个统一的预约挂号平台,和它一模一样,可能是他们接的外包吧)现在我算是做完了,做一个小总结,把它放在简历上。

不过有点担忧,一是技术只是会用,不是特别的了解,面试的时候被多问一下可能就被打上“不了解它的原理”的标签。我也想啊,但学不来了,那些八股文太深,劝退劝退。我只能说我是一个合格的“黑盒使用者”,会用,能干活,这点我还是很有自信的!二是感觉缺少了一些设计上面的理解,我的工作只是CRUD的感觉。它的数据结构、实体类、层级都是早早就给定好了,我做的只是查一查,稍微有点难度的就是一些分页查询和联表查询。我认为系统设计和分析那块才是重点,这里能做好,后面的只是体力活。我现在...确实也只是会做体力活。我现在的实力,就是慢慢地调,能做好,但可能时间上会长一点,应该是手生手熟的问题吧。

我会按照我理解的各部分去分析分析,架构图如下:

image20220113230529416.png

业务流程:
image20220113233418650.png

网关(Spring Gateway)

网关在系统中作一个分流和认证的功能,对前端来说,能够统一地请求后台的服务地址,并且对于集群的服务,能够做到负载均衡的效果。同时,网关还能对登录认证作统一处理,一些需要登录才能继续的操作,则需要它带上对应的凭证才放行。在项目中,使用JWT作为状态凭证,当它正确时才能进行一些权限操作,比如实名认证、预约挂号等。

这部分,一开始使用的是nginx,这是一个代理服务器,以前有用过一下,只知道它很轻量级,常做反向代理。后面换成了spring gateway,直接运行一个网关服务,把跨域问题和认证问题都解决了,主要写写配置和过滤器。它还有一个强大的功能就是配置路由,在配置文件可以配置路由和断言。如下:

#设置路由id
spring.cloud.gateway.routes[0].id=service-hosp
#设置路由的uri
spring.cloud.gateway.routes[0].uri=lb://service-hosp
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[0].predicates= Path=/*/hosp/**

诚然,这都是一些小把戏,我现在也只是会用用,改一改加一加。在实习的公司里面我似乎都没有见到过这个,似乎是专门的运维在做,当然,这我也得懂一点点,自己搞个小项目也能用上。

服务发现(Nacos)

nacos和eureka一样,都是用作服务发现,我理解它是一个对微服务进行一个统一的管理,各个服务之间都是有联系的,nacos能够感知各服务当前的状态(存活或死亡?)。同时,它的服务名机制也能与远程调用相配合,远程调用只需填写服务名,而不是服务器主机地址,当它发生改变时,不影响我的调用。

了解得比较浅薄,只知道开一下,然后填个地址即可,这似乎也是运维搞的活【x】。

数据存储部分

这里使用了三种数据库,一种消息队列,非常全面。

  • Redis:主要做验证码的有效时间和支付二维码的有效时间的存储。
  • MySQL:主要的数据都在这里存了,数据字典、医院、部门、排班、医院设置、用户、订单、记录等等。
  • MongoDB:这是一个我没使用过的文档型数据库,主要存储医院设置相关的信息,如医院、部门、排班信息。使用的场景是医院端把数据发到预约挂号平台后台,然后后台接收并保存到MongoDB中,之后要查询的时候只要带上适当的条件就行(关于MongoDB的查询也是一个新东西)。不过我发现它会自己消失,可能有个默认的存活期之类的东西?之后有需要的话再重新系统地学习学习吧...
  • RabbitMQ:一种消息队列,使用起来似乎比kafka难一些2333333333因为它的监听器比较繁杂,也可能是没有系统地学习。这个使用是一些订单预约数的异步操作。

云服务部分

这次体验了一下腾讯云短信服务、阿里云OSS、微信登录和微信支付这几个第三方的服务,感觉文档非常齐全,跟着例子直接改改就能上手了,非常好用!想吐槽一下阿里云的短信服务的审核,有点严格了,我申请一直不通过,就改用腾讯云的SMS。当时还想着,我和视频里面的操作不一样,会不会不太好,结果这个担忧是多余的,我跟着文档改一改相关数据,一下就测通了。

因此,我感受到这种开发越来越傻瓜式,只要有一点开发经验都能用上,当然,也可能是我没有遇到一些难的业务场景或者做的不是“最佳实践”,给我一种很简单的错觉。

主要的Service

用户服务

主要是手机号登录、微信扫码登录和后台用户信息展示等接口。

手机号登录使用了上述腾讯云的短信服务,输入手机号并且成功获取验证码后,会把验证码存到Redis中,并设置一个过期时间。当用户输入验证码时,会与Redis中的进行比对,正确的话,即把用户信息存到数据库中,并使用JWT生成token,标记用户登录状态。

微信登录也是类似的做法,不过得按照它的流程进行(如下图)。我主要做后台的开发,前端部分不太理会,我把参数拼接好给前端,然后前端按照微信的规则写好即可。后面待用户扫码后,微信会请求我的回调地址,我根据微信的文档获取用户信息,再进行业务操作。这部分有文档,按步就班地做倒是没啥难度的。
image20220114134744390.png

后面用户信息接口就是CRUD了,没啥可说的。

数据字典服务

这部分是存储一些固定的数据,比如国家省市县信息、医院等级等等。首先它支持excel导入和导出,用到了文件上传下载以及EasyExcel的使用,然后还有一些层级的查找,比如根据值查询下级节点,根据值获取数据字典名称等。在数据库中,它利用了parent_id这个外键进行层级的划分,而我在实习的时候,正巧也遇到这种父子级的数据关系的处理,所以这部分写起来还是挺容易的。

远程调用服务

使用Feign Client实现,其实就是写几个接口,然后调用其它服务的接口,但是它又不用写具体的实现,因为具体的实现在调用那里。这样做有什么好处呢?它可以与nacos进行配合,使用服务名进行调用,避免了域名修改而造成的修改。好像还有一些效率上的比对 ???待填坑,不过这确实挺好用的,只是我的机子太卡,总会Read Timeout。

医院服务

医院部分可以分为医院管理、设置管理、部门管理和排班管理。主要用在预约挂号的前台、后台,以及各医院的管理平台上。它的难点在于各种查询,比如mongo的聚合查询......这块说难不难,说易也不易,主要困惑的点在于我不太熟悉它的数据间的关系,也就是它的表结构、数据构成、存储以及前端所需要的字段,做得挺迷糊的,但是做的那些东西我大都用过,比如MP,真的是方便。

下单服务

最重要的部分,也就是预约挂号!它分为几个阶段,首先是保存订单,即挑选好就诊人,确定好要挂号的医院、选号、选医生,先保存。然后调用医院端的平台,医院端记录好之后,会返回一个状态,根据状态再进行决策。如果调用成功,就再保存一些其它信息,比如预约标志、预约序号、取号时间等等(这些数据是在各医院端的,从返回数据中取)。同时,这里也使用到了RabbitMQ进行异步的处理,比如号源数量、短信通知(终于知道为什么有时候看着有号却抢不到,其实已经没号了,只不过更新不及时)。

经过上面的步骤,下单算是完成了一半,因为你还没有给钱【x】。给钱这块我原本想直接点了个确定就修改状态得了,但是视频里面把微信的号给贡献出来了,也就跟着做做吧。主要是体验为主,这个要300一年呢,而且流程也非常固定,都是填好一些确定的参数,然后调用就行了。

统计服务和定时服务

这两块没有做,不过也是一些CRUD的活。统计服务是指计算一下今天预约了多少用户,挂出去了多少单这些,也就是查一查数据库。定时任务是定时发短信给用户,提醒已挂号的用户及时就诊,这个可以用cron表达式,加一个注解配置一下就行了。

医院端

这个就是各医院操作的平台,比如上传医院信息、部门信息、排班表等等数据,发送到预约挂号平台的后台,后台再把数据存储。此后,用户访问平台的前端页面就能看到新的数据。在下单服务中,有一些信息(如剩余号数、支付情况等等)需要医院端进行确认,确认之后才回返回。?不过里我要先打个问号,为什么不把所有的东西都放在挂号平台上,比如支付了就直接改库,剩余号数也直接改,而不用通知他们。。。

小结

大致就是这些内容,待我整理一下,然后到时再想想面试官会怎么提问,有、方,到时又是“不理解底层”就GG了。