应用场景
对于单服务来说,比如一个普通的商城的服务,有一个接口返回商品的信息,针对不同的国家/地区可能有不同的搜索结果,需要根据入参识别所属国家,并将这个国家信息传递到下游接口使用,我们首先会想到用Java中提供的threadlocal类来存储线程私有的变量,在入口处识别国家信息放入threadlocal,在后续的使用中直接从threadlocal中获取即可。(本质上是通过线程持有的threadlocalMap来区分不同的线程);
此外,对于公司级别的链路追踪系统一般通过提供jar包的方式,使用方可以通过jar包中的方法来向上下文中放置数据,在应用内部和应用中进行传递。
上述两个场景都面临同一个问题:如果处理过程中,使用了线程池/或者新建了子线程,threadlocal就不好用了。因为新建的子线程的threadlocalMap中并没有存储对应的值,当我们把一些参数存储在threadlocal中时,应用内部使用线程池执行任务或者重新创建线程的时候,新的线程就无法访问到原有线程持有的threadlocal数据,threadlocal变量中存储的内容会丢失,(也就是上下文信息需要从创建任务的时刻传递到run这个线程的时刻)。
解决思路
线程之间的通信方式主要有两大类,一种是通过消息的方式通信,另一种是共享数据来通信。
上面两种方法,无非是在创建新的线程/线程池进行调度的时候,想办法把threadlocal变量传递过去,既然是在服务内部,共享数据的方式更为合理。