Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client 调用 server 附带的 values 会被原样再发送回来,是否可控不发送 #45

Closed
fengqi opened this issue Nov 18, 2022 · 7 comments
Labels

Comments

@fengqi
Copy link

fengqi commented Nov 18, 2022

ctx.write的时候,会把收到的values原样回传,然而client.Call是拿不到最新的values的,因为接触不到完整的消息体,在on函数和middleware可以拿到,但是这些都是全局的

c/s场景下单向调用的场景,可以认为是浪费了,values越大浪费越多,如果是server端因为需要还额外通过middleware写入了一下信息自己用,那回传的数据就更多了

所以如果能让client可以方便的获取到values,这样可能部分场景能用到,另外就是可选关闭,我目前是通过middleware手动清空,但是感觉不够优雅

@lesismal
Copy link
Owner

感谢兄弟深度使用和支持,但是你的理解可能不太对,可以根据实际场景来优化使用方式。

ctx.write的时候,会把收到的values原样回传

这个不准确。ctx.Write只是把原有的message的value赋值给回包的message的values字段,但是否需要encode到回包给client发回去,由用户负责,如果需要,用户在中间件内实现,如果不需要,则只是一个字段赋值,没什么高额成本

message.values字段是为了业务方便,比如公共的验证、公共信息,在中间件里提取设置到values里,实际的handler里直接取就可以了,不需要每个handler内都去先解析一次。
但message.values字段,并不是要求用户必须使用的,你不需要,可以不使用。或者,出于性能考虑的,建议直接在Request的结构体携带公共字段,这样避免再使用中间件二次序列化。其他issue里的这些问题,也是类似的:
#43 (comment)

然而client.Call是拿不到最新的values的,因为接触不到完整的消息体,在on函数和middleware可以拿到,但是这些都是全局的

同样是不准确的。与我上面所说的一样,中间件、message.values是为了用户额外需求的方便而提供的、不是必须使用这种方式。如果你不用中间件、或者中间件不改变原始包体,那么你request被序列化到body的部分,handler就能从ctx都拿到完整消息体。

c/s场景下单向调用的场景,可以认为是浪费了,values越大浪费越多,如果是server端因为需要还额外通过middleware写入了一下信息自己用,那回传的数据就更多了

我给arpc留了比较自由的扩展方式,但是用户想要性能最佳,还是想要逻辑便利或者其他什么考量,得根据不同的侧重点,采取正确的使用方式才能获得最佳性价比。
我没有给arpc固定某一种序列化方案,比如固定使用pb或者json,但是你仍然可以在自己的用户协议层,设计成结构体自带公共字段,比如在有需要的路由上,你的pb struct都携带一个公共字段的结构体(或者干脆就是多个基础类型的公共字段),你就只需要ctx.Bind一下,也不需要使用中间件了,更不存在你这里所说的浪费了

其他的rpc框架,多数是一个方案固定了所有路由的序列化方案,通常你也只能通过这种方式携带公共字段,或者hack body也是类似arpc中间的方式。但在arpc里,你不同的路由甚至可以使用不同的序列化,甚至直接使用string、[]byte作为request/response。

所以如果能让client可以方便的获取到values,这样可能部分场景能用到,另外就是可选关闭,我目前是通过middleware手动清空,但是感觉不够优雅

如果用我前面说的在需要的路由里的pb proto里自带公共字段、不需要的不带公共字段,就没有你的这种困扰。
或者你如果一定要使用中间件,中间件根据不同的路由判断是否需要encode/decode values,也不是什么麻烦事。

另外一个issue中的tracing的问题,是因为三方自带的pb结构已经是那样子,用中间件实现的原因:
一是与用户proto解耦,如果不考虑解耦,你们自己的proto里都带上opentracing的pb字段,也可以实现,那样就不用中间件。
二是中间件性能虽然不是最佳,但看上去略优雅一些,而且多数时候,既然都用链路追踪了,集群规模已经比较大、可以横向扩展,业务系统承载力靠堆机器能搞定所以更偏重一些业务系统稳定性和可追溯性,所以单个调用的响应性能其实要求并不高,额外的这点开销也不算太大。
而且,那毕竟是个编解码中间件的例子,所以用了中间件。

@fengqi
Copy link
Author

fengqi commented Nov 18, 2022

values确实是我在中间件自己加上去的,issue发完我就在想这个回传与否好像已经是我自己的责任了

@lesismal
Copy link
Owner

如果只是想中间件里,不去做某些message的编解码,先看看中间件的例子,比如这里才是真正把values序列化并且添加到body的逻辑,如果不需要,你可以通过ctx.Set一个flag来判断是否需要编码到body,也可以根据msg.Method()来按照路由设置是否需要编码进去:
https://github.com/lesismal/arpc/blob/master/extension/middleware/coder/appender.go#L29

既然是中间件、是开放给用户自己扩展的,而且不是http header那种统一标准的协议,用户应该根据自己的需要来定制。

@fengqi
Copy link
Author

fengqi commented Nov 18, 2022

感谢耐心回复,我会继续用中间件传递额外信息,value暂定用flag控制

@lesismal
Copy link
Owner

感谢耐心回复,我会继续用中间件传递额外信息,value暂定用flag控制

好的。如果有需要特殊优化的,欢迎随时来讨论。

@github-actions
Copy link

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label Dec 19, 2022
@github-actions
Copy link

github-actions bot commented Jan 2, 2023

This issue was closed because it has been inactive for 14 days since being marked as stale.

@github-actions github-actions bot closed this as completed Jan 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants