各位大佬,最近项目拆分中,使用了 OpenFeign 调用。服务间调用的接口单独写个 api 模块(feign 接口),然后给其他服务进行引用,也就是服务提供方提供。 1.参考其他的有的是在 api 接口把 VO,,DTO,数据库实体都放在这里,但是我们现在这些都在 service 模块中; 2.api 模块 feign 接口的入参和返回,定义为什么呢,service 具体的实现的入参和返回也是引用 api 模块 feign 接口的入参和返回,还是定义自己的,OpenFeign 是可以不一样的,但是具体实现是什么呢; 3.现在 controller 的作用就是调用 service 直接返回,但是现在有人想在 controller 做参数校验+service 调用返回原始数据,不返回 xxxVO ,而是在 controller 包装成 VO 返回,可以根据多种要求返回,编写不同的 VO 对象返回,以前都是直接在 service 校验参数和封装。 4.Feign 接口返回的现在不使用统一对象封装,定义了一个 Decoder,这样就直接返回结果,还是使用统一结果封装 本人学习中,感觉没人的说的或者开源项目中都不一样,不知道具体的比较好的实现是什么
1
florentino 219 天前
本质就是通过 http 调用,至于你说的 VO,DTO 那些东西,可以放在 api 里面让其他服务依赖,也可以不放,调用方自己实现,反正最后都是会被序列化和反序列化的
另外可以不使用 OpenFeign, 实现一个纯 resttemplate 去调用服务,这样你就能理解的更深了 |
2
123zouwen 219 天前
1. 服务间调用的接口单独写个 api 模块(feign 接口),然后给其他服务进行引用,也就是服务提供方提供
|
3
SilenceLL 219 天前
1. 对内的 Feign 接口单独定义
2. DTO VO 这些抽离,按需引用 3. feign client 单独抽离,按需引用 |
4
123zouwen 219 天前
1. 服务间调用的接口单独写个 api 模块(feign 接口),然后给其他服务进行引用,也就是服务提供方提供
不是一定要求这个. 如果多个服务是不同语言的, 这样做没什么意义. 你就把它当成一个普通的对外提供服务的接口就行了,做好幂等处理. 2. 既然是都是对外提供的接口了, 入参和出参 你提供接口文档就行了, 别的服务想定义什么实体都行. 3. 服务拆分的时候,要明确拆分是否有必要? 我见过很多为了拆分而拆分的, 明明可以是在一起的,拆完后又要上分布式事务中间件,意义何在? 我觉得这是把单体思维代入到了微服务中. 分布式事务中间件个人觉得没有任何必要, 但很多 java 总希望能跟写单体服务一样直接 rpc 调用还能处理好事务. 都做服务拆分了,这些服务完全都可以用不同语言写,做好幂等. openFeign 也就是服务间的 http 调用 |
5
RedBeanIce 219 天前
我们在项目中抛弃了 feign 。。
但是写 go 的时候,又用了 grpc+protobuf ,,,不知道是好还是坏。 |
6
sighforever 219 天前
既然 api 已经会共享出去被其他项目引用,那比较好的设计就是这一层是独立的。
所有在接入层的数据实体也定义在提供的包里面。 对内只有 controller 层使用 api 层里面的数据,service 层不使用 api 层的数据实体,而是自己再定义一套,由 controller 层负责转换。 对于第三方,也可以直接调用 api 暴露出来的实体和你的服务交互了。 |
7
tom 219 天前 1
1 楼 @florentino 说的“本质就是通过 http 调用,至于你说的 VO,DTO 那些东西,可以放在 api 里面让其他服务依赖,也可以不放,调用方自己实现,反正最后都是会被序列化和反序列化的”
以及 4 楼 @123zouwen 说的“我觉得这是把单体思维代入到了微服务中. 分布式事务中间件个人觉得没有任何必要, 但很多 java 总希望能跟写单体服务一样直接 rpc 调用还能处理好事务.” 都非常对,是非常正确的微服务理念。基本上你从网上看到的绝大部分理论,都是指导你灵活使用,因为脱离了实际使用场景,并不会存在一个最佳实践。 而你困惑的地方在于,你没描述出来你们完整的工程场景,上面他们所说的都不足以解答你的疑惑,feign 用起来总是感觉有点不伦不类,对不对 我猜你是做 toB 的行业软件,业务逻辑复杂,功能点多,架构师又采用微服务形式,然后甚至一个功能模块一个微服务,从功能划分上倒是合理,但是呢,各模块之间的交付是很频繁及复杂的,互相调用的情况非常多, 硬套上微服务, 很难复用代码 & 控制事务, 如果各自解析 feign 的返回,还容易造成混乱(各种业务逻辑频繁变动、数据模型满天飞, 有些对象能有 200 多个属性)。 我是非常不建议也不喜欢大部分 toB 业务使用微服务开发的,不合适。 当然你们已经这么做了,我的建议是,各自模块的 DTO 、VO 、等 POJO ,自行维护。需要被其他模块调用的,复制一份 POJO 到 api 模块中,写好文档,做好代码同步即可。这样调用方不用关心如何解析,调用结果会自动转换为 POJO 对象,省心省事,又贴合单体应用的使用习惯。 有条件的话,还是从微服务的巨坑里爬出来吧。 |
8
chawuchiren 219 天前
@RedBeanIce 我感觉只要 grpc 不是用的 json ,都很好
|
9
MarioLuo 219 天前
服务拆分后各个服务之间通过 http 接口调用,那么第一个问题考虑的是要不要提供客户端?
第一种: 服务分为多个 maven 模块, 例如: user-api, user-provider, 优点代码复用, 缺点就是版本兼容,适合大量接口调用. 第二种: 调用方写代码调用,优点是按需写、灵活,缺点就是代码重复,适合少量接口调用. 第三种: 单独写一个 sdk 项目,优点是复用,缺点单独维护,也可根据 openapi 文档自动生成. 回到你的问题,如果使用第一种方式: 1. API 包种每个接口返回 VO/DTO, 不要直接返回数据库实体类,实体放在实现模块中,实体转换用 mapstract 即可。 2. Feign 中每个接口建议入参和返回都包装一个实体: UserAddReq, UserAddResp 以后便于扩展而不影响调用方,部分原子接口可不用包装比如根据 id 获取用户信息: Result<UserDTO> getUserById(@PathVariable("id") Long id); 3.因为我们是 bff 模式,原子服务的 service 层尽量返回实体,控制层包装转化为 DTO/VO; 4.目前我们是返回的 Result<?>, 然后 Result 里有个 tryThrow()方法,由调用方控制,灵活性更大,也可以用 Decoder 方式; 另外一个小地方命名冲突: 一般会在 bff 服务中请求响应都叫 XXxReqVO, XxxRespVO, 而在原子服务叫: XxxReq, XxxResp 。 我们实际中采用第一种和第二种混合: bff 服务调底层服务用第一种,相对独立或外部的服务调用使用第二种。 |
10
listkun 219 天前
feign 的本意是让你调用别人的时候,可以定义发送和接收的对象类,
分发出去的接口是 http 的,给出 http 文档即可,至于调用方用什么语言不重要 |
11
nitouge OP 多谢各位大佬的回复,受益匪浅. 项目的确是 tob,之前是微服务,模块比较少,一个主要的微服务,其他一些辅助的服务,现在是要做产品化,把那一个主要的服务拆分出单独的服务,这样可以单独收费,其他的可以按需要引入服务。目前给的时间多,我想考虑好再做
|
12
smartychaos 218 天前
有几种选择, 第一种是在 api 包( client api )里定义所需实体 VO, 服务端 web 包引用并实现这些 api 接口,实体可以直接引用。当然服务使用者也可以用,大家都便利。
|
13
flmn 213 天前
所以,干嘛不用 grpc 呢
|