我觉得题主需要明确一下自己的需求是什么,一个服务调用,该等的时间是不得不等的。而且题目描述中,并没有说明这个服务A的使用场景:是再作为一个服务进行暴露呢,还是它本身就是一个服务消费方,负责消费服务B和服务C。
我理解一下你的意思,尝试归纳一下问题:
问题
你需要新写一个服务A,这个服务A依赖于高时延的服务B和C,
在B,C有结果后才能计算出结果并作为服务A的结果返回
服务A现在有两个可能的场景:服务A是C端的服务,也就是说,是一个调用方,比如在手机端进行两个服务的调用,并处理两个服务的结果,得到新的结果来填充某个字段。使用回调或者异步的方式进行。例如Android里有着各种回调供以调用,并要求延时任务不阻塞主线程;JS等也有异步操作,去处理这种情形。如果使用新的线程去做或者使用线程池反而引入了复杂度。
服务A是Server端的服务,需要封装B,C两个服务。
分析
这个情况我觉得大概率是题主遇到的问题。那么我们对服务A的设计目标就是,尽可能得提高服务A的服务能力,提高服务A的QPS。我们简化一下这个问题,问题等价于:
我们要构建一个服务,这个服务需要访问一个(我们简化成一个)耗时任务,这种情况下,应该怎么设计这个服务,并尽可能的提高并发量。
这里还存在一个问题,就是这个耗时任务究竟是什么任务。有两种情况:访问数据库这样的BIO任务
可以异步的任务。
对于情况一,没有别的什么办法,由于JDBC的限制,我们不得不去维护一个数据库连接池,进行BIO的操作
那么我们现在的问题就是,对于可以异步的耗时任务,我们如何构建一个服务,对它进行封装与其他的业务处理,并尽可能得提高我们写的服务的并发量。
答案很明显,为了提高我们的服务的并发量,我们应该尝试去使用IO多路复用技术,提高连接数;对于耗时任务使用异步任务进行处理。
对于Java生态来说,Netty是一个成熟而稳定的选择。那么问题就在于Netty是怎么做的呢?题主应该是一个新手,所以我推荐这个教程,给题主参考。sanshengshui/netty-learning-examplegithub.com
那解决了IO多路复用的问题,我们如何解决异步的请求问题呢。
答案是,还是算了吧。比起使用异步来省点线程的消耗,使用Java来写异步代码带来的风险和心智负担costs more。同样,我们使用线程池的方式,在Netty中对耗时任务进行处理。
具体写法是
static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
...
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
// Tell the pipeline to run MyBusinessLogicHandler's event handler methods // in a different thread than an I/O thread so that the I/O thread is not blocked by // a time-consuming task. // If your business logic is fully asynchronous or finished very quickly, you don't // need to specify a group. pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
// 这里的MyBusinessLogicHandler就是一个耗时逻辑
有一个例子可以参考这里。
其他
还有一个问题就是,如果真的是像访问DB那样对耗时逻辑,除了使用连接池将DB连接异步化github.com
总结业务还是要分析清楚,明白自己到底需要做什么
可以将Netty当作一个TCP连接管理器,解决C端发起的连接问题,提高连接利用效率
Netty中最好不要使用耗时任务
如果要使用,可以将其异步化或者使用线程池handle
话说回来。对于题主的问题,这篇回答其实没有正面回复。答案还是当然可以。比如你可以用异步的HttpClient发起请求
所以,浪费吗,,,没办法。。。it costs
参考