单体应用拆分为微服务遭遇水土不服,服务间资源调用不畅,如何修改架构?

2023-11-01 18:02:38 +08:00
 chinaguaiu

如题,公司团队此前比较缺乏微服务开发的经验,开发前期也只是简单按照模块划分的思路设计了微服务,思路简述为:在业务上呈现内聚的资源将被整合为一个服务,服务的业务逻辑实现是需要频繁访问这部分资源的;而如果仍然需要额外的资源(这个资源划分到了其它服务),通过服务间通信解决(使用 Restful 请求或者中间件);一些服务间通用的资源通过 jar 包依赖的形式引入。

一段时间的开发之后产生了一些阻碍,主要发生在服务间资源调用中,如下:

  1. Restful 接口方式调用服务间资源十分缓慢和繁琐。服务对外暴露的 Restful API 全部是直接面向外部调用设计的,每一次调用都需要走完完整的参数处理以及鉴权验证逻辑。服务间之间互相调用依然是使用这种 API ,每一次调用都基本等同于外部调用,需要重新走一次参数处理和鉴权验证的逻辑,运行效率很差,也导致方法实现中充斥大量冗余参数和冗余返回结果(对于服务间调用来说) 。
  2. 某些功能的实现需要频繁进行服务间资源调用。这个意思不是服务调用链路太长,而是诸如服务 A 的某一业务逻辑需要同一时间需要重复访问服务 B 五到六次,或者说服务 A 的某一业务逻辑需要同时访问服务 B 、C 、D 、E 、F 等。又由于 1 的问题,效率极差。

如何针对性解决两个问题?重新设计一类面向内部服务调用的 Restful 接口?还是服务间调用引入 MQ 中间件?

想请教一下 V 友们有没有相关的解决思路,由于公司团队包括我自己也没有太多开发微服务的经验,还望大家可以详细讲讲。

3957 次点击
所在节点    程序员
40 条回复
tool2d
2023-11-01 21:01:47 +08:00
rest 短链接对于维护复杂状态还是挺麻烦的,最好就是改成长链接的 rpc 来维护。
wyx119911
2023-11-01 21:08:29 +08:00
1. 微服务之间调用鉴权改为验证加密票据,票据由对外网关统一验证用户信息后办法,后续判断票据有效跳过没必要的验证逻辑。
2. 首先问题可能是不熟悉微服务的架构模式,导致调用不合理。另外有些调用确实很多无法避免的情况,可以用并发请求来解决(例如多协程),这里要注意瞬时请求量,保护被调服务不被冲垮。
lsk569937453
2023-11-01 21:12:57 +08:00
并发不到 200 的业务还搞这么复杂吗???确定不是过度设计?
xiangyuecn
2023-11-01 21:21:53 +08:00
话说天下大势,分久必合,合久必分。
iyaozhen
2023-11-01 21:22:46 +08:00
@ZZ74 不是拆出那么多的,是大家都新建一个服务,慢慢的就多了
chinaguaiu
2023-11-01 21:31:46 +08:00
@lanlanye 2 首先肯定是设计问题,然后又由于 1 加剧了状况,需要写大量的冗余代码拼装请求去进行服务调用,响应时间还很长
chinaguaiu
2023-11-01 21:42:34 +08:00
@ZZ74 #19 “内部调用何必呢。” 是的内部调用没有必要鉴权,现在问题是暴露出的所有接口都是面向外部调用设计的,例如说 api 方法签名里包含请求参数 appid 、userid 、sign 、time 等,就没考虑内部调用的场景,导致现在内部调用都是先拼接参数字段再发起请求,和维持一个外部用户 agent 没有区别。所以现在是想绕过这些已经定义的 Restful api 去进行内部请求,但是没有思路。
chinaguaiu
2023-11-01 21:44:38 +08:00
@lsk569937453 项目要求,不得不上,当时选取微服务架构的原因就不是技术因素
chinaguaiu
2023-11-01 21:49:40 +08:00
@wyx119911 1. 思路不错,感谢; 2. 可以考虑。并发指的是同步并发还是异步并发?这种内部业务逻辑要求即时处理数据的场景不能使用异步吧。
tangAtang
2023-11-01 22:12:05 +08:00
@chinaguaiu 应该说的是同步并发,比如需要拿 A+B+C 数据,数据之间没依赖就并发拿。但是感觉这也治标不治本
wmper
2023-11-01 22:18:18 +08:00
这样才不会失业啊,啥搞才有搞头。
Chad0000
2023-11-02 02:24:50 +08:00
@Sean46
嗯,就是这个。我都把方案搞出来了,开始写代码了,才看到这个框架。当然我也用不到因为我是 C#
xuanbg
2023-11-02 07:49:04 +08:00
1 、内部 Restful API 调用不可能慢,慢一定是别的原因造成,必须要把这个原因找出来
2 、内部访问不需要鉴权,所以,鉴权放到网关上去实现。具体可以参考我的开源项目,点我头像自己找
3 、服务 A 的某一业务逻辑需要同时访问服务 B 、C 、D 、E 、F 等,这种情况一定是设计问题,需要重新设计才能解决
yinmin
2023-11-02 08:33:42 +08:00
跨服务器的 1 次请求至少 1 毫秒。微服务不是函数,别在循环里几百/几千次去调用,一定是慢的。

用户一次 click 操作,调用 1 次 a 服务,每次 a 服务调用 10 次 b 服务,每次 b 服务调用 10 次 c 服务,每次 c 服务运行了 10 条 sql 数据库服务,就是妥妥的耗时>1 秒。
yinmin
2023-11-02 08:54:21 +08:00
如果运行太慢,项目无法交付,短平快的方式是:
1. 去掉用户权鉴改 token 直接校验
2. 将调用密度高的微服务安装在一台机器里,内部使用 unix socket 替代 tcp 。然后依样画葫芦安装出多台机器跑负载均衡。

用以上 2 条之后,速度可能会有十倍,甚至百倍的提升。
fkdog
2023-11-02 09:41:04 +08:00
乱拆的结果就是这样的。
如果现在连这种 controller 层的问题都能难倒你们,后边各种事物、同步延迟、一致性岂不是能把你们搞炸锅?
你们业务量多大要拆出服务来啊
dahuahua
2023-11-02 09:42:48 +08:00
在第一层校验通过后,往请求头里写个 verify-pass 的标志,内部服务先判断是否有这个标志,再来决定是否进行二次校验,将来单独交付内部服务的时候,也不会缺失这部分校验能力。
cp19890714
2023-11-02 10:01:08 +08:00
* 服务对外暴露的 Restful API 全部是直接面向外部调用设计的.
内部接口与外部接口需要分开.

* 需要重新走一次参数处理和鉴权验证的逻辑
鉴权应该在 gateway. 既然现在已经在每个服务中都有鉴权了, 那可以为内部 API 添加一个统一前缀, 来跳过鉴权.
参数处理本来就是必要的, 省不掉.

* 重复访问服务 B 五到六次
如果是同一个功能, 应该考虑 多个接口合并到一个接口
远程调用是 IO, 不能循环调用, 应该改为批量.
对于数据变化不大的, 使用本地缓存.

* 或者说服务 A 的某一业务逻辑需要同时访问服务 B 、C 、D 、E 、F 等。又由于 1 的问题,效率极差。
大部分情况下, 一个功能不会同时调用 BCEDF 这么多的服务接口. 可以考虑下是否是服务拆得太细.
jackwv
2023-11-02 10:41:44 +08:00
最上层做一个 API 聚合,下面的 RPC 服务 循环依赖就循环依赖,简单快捷。
wwwz
2023-11-02 10:53:08 +08:00
好家伙,自创微服务是吧
上 Spring Cloud Alibaba 全家桶

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/987593

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX