fanliang11 / surging

Surging is a micro-service engine that provides a lightweight, high-performance, modular RPC request pipeline. support Event-based Asynchronous Pattern and reactive programming ,The service engine supports http, TCP, WS,Grpc, Thrift,Mqtt, UDP, and DNS protocols. It uses ZooKeeper and Consul as a registry, and integrates it. Hash, random, polling, Fair Polling as a load balancing algorithm, built-in service governance to ensure reliable RPC communication, the engine contains Diagnostic, link tracking for protocol and middleware calls, and integration SkyWalking Distributed APM
MIT License
3.24k stars 924 forks source link

RpcContext获取Payload问题 #288

Closed ggh5270 closed 5 years ago

ggh5270 commented 5 years ago

token通过 RpcContext.GetContext().SetAttachment("payload", payload)这方式传给接口,当网关部署多个节点时,使用 RpcContext.GetContext().GetAttachment("payload")获取回token,会出现token获取错乱的问题。请问楼主是否有这个问题?

fanliang11 commented 5 years ago

什么错乱问题,请描述清楚

ggh5270 commented 5 years ago

部署多个网关节点的情况下,A和B两个用户登陆,当B用户调用接口时,有可能会获取到了A的token。原因分析是:网关传token给接口,用的是固定的payload这个key,接口获取token也是用payload这个key,导致取了其它人的token,请问楼主是否有这个问题?

fanliang11 commented 5 years ago

明确告诉你不会,建议你去看看ThreadLocal

liuhll commented 5 years ago

关于获取运行时用户你可以参考的修改的ClrServiceEntryFactory和这里Session,会相对容易很多

ggh5270 commented 5 years ago

我们实际的项目中就出现这个问题了,两个用户操作的间隔很短时,就有可能出现,但这种机率非常低,我看了ThreadLocal,有可能是ThreadLocal中的值上次没清空,这个值就会保留下来继续被使用

fanliang11 commented 5 years ago

ThreadLocal 是线程级变量,而RpcContext 是ThreadLocal 的存储数据上下文,不同的请求是不同的线程,之间是线程隔离的,你说机率低出现问题,我觉得不可能

ggh5270 commented 5 years ago

ThreadLocal 的存储数据上下文,不同的请求是不同的线程,之间是线程隔离的 这种针单台服务器是对的,如果部署多台服务器,这种线程处理就会有问题了,不同服务器线程不一样,导致取的payload就有问题

liuhll commented 5 years ago

payload在不同服务之间的传递不是通过rpcParams传递的么?

liuhll commented 5 years ago

你可以像我这样处理,在接受到请求的时候:

 if (parameters.ContainsKey("payload"))
                     {
                         if (RpcContext.GetContext().GetAttachment("payload") == null)
                         {
                             var serializer = ServiceLocator.GetService<ISerializer<string>>();
                             var payloadString = serializer.Serialize(parameters["payload"], true);
                             RpcContext.GetContext().SetAttachment("payload", payloadString);
                         }
                     }