0 概述
在实际工作中,时常会遇到一个接口服务会调用很多其他的服务(10几个甚至更多,这些服务之间大多都不是相互依赖的),如果采用串行化调用,那么这个接口的服务rt(response time)就会很高,20*50ms=1000ms(假设该接口服务需要调用20个服务,平均每个服务rt为50ms)。本文主要给出Future结合Rxjava 实现异步化调用。(需要调用的服务方支持异步化调用)。
1 异步化调用
用户信息的异步查询,需要你调用服务支持异步调用~
@Component
public class UserServiceManager {
@Autowired
private UserService userService;
/**
* 根据userId异步查询用户信息
*
* @param userIds
* @return 用户Id和User映射
*/
public Single<Map<Long, User>> asynGetUserInfoMap(final Set<Long> userIds) {
if (userIds == null || userIds.isEmpty()) {
return null;
}
//todo
Future<List<User>> resultFuture = null;//需要服务支持异步化调用
//通过Rxjava 发射出去
return Single.from(new AsyncResponseFuture<List<User>, Map<Long, User>>(resultFuture) {
@Override
public Map<Long, User> process(List<User> response) {
Map<Long, User> retMap = new HashMap<>();
if (response == null ) {
return retMap;
}
for (User u : response) {
retMap.put(u.getUserId(), u);
}
return retMap;
}
}, 2000, TimeUnit.MILLISECONDS);
}
}
public abstract class AsyncResponseFuture<P,R> implements Future<R> {
private Future<P> future;
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
public AsyncResponseFuture(Future<P> future) {
this.future = future;
}
@Override
public boolean isDone() {
return future.isDone();
}
@Override
public R get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
P response=future.get(timeout,unit);
return process(response);
}
//处理相应的业务逻辑
public abstract R process(P response);
}
2 获取数据工具实现类
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Single;
import rx.functions.Action1;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
/**
* 异步工具类
*/
public class AsyncUtils {
private static final Logger logger = LoggerFactory.getLogger(AsyncUtils.class);
private static final String TIME_OUT_DESC = "timeout subscribe fail msg[%s]";
private static final String SUBSCRIBE_FAIL_DESC = "subscribe fail msg[%s]";
//获取单个对象 mgs 用于日志标识
public static <T> T getObject(Single<T> source, final String msg) {
final InnerReturn<T> innerValue = new InnerReturn<>();
if (source == null) {
return null;
}
source.subscribe(new Action1<T>() {
@Override
public void call(T t) {
innerValue.setValue(t);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable e) {
if (e != null && e instanceof TimeoutException) {
logger.error(String.format(TIME_OUT_DESC, msg));
} else {
logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
}
}
});
return innerValue.getValue();
}
//获取list 对象 mgs 用于日志标识
public static <T> List<T> getList(Single<List<T>> source, final String msg) {
final List<T> results = Lists.newArrayList();
if (source != null) {
source.subscribe(new Action1<List<T>>() {
@Override
public void call(List<T> t) {
if (t != null) {
results.addAll(t);
}
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable e) {
if (e instanceof TimeoutException) {
logger.error(String.format(TIME_OUT_DESC, msg));
} else {
logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
}
}
});
}
return results;
}
//获取Map 对象 mgs 用于日志标识
public static <K, V> Map<K, V> getMap(Single<Map<K, V>> source, final String msg) {
final Map<K, V> results = Maps.newConcurrentMap();
if (source != null) {
source.subscribe(new Action1<Map<K, V>>() {
@Override
public void call(Map<K, V> t) {
if (t != null) {
results.putAll(t);
}
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable e) {
if (e instanceof TimeoutException) {
logger.error(String.format(TIME_OUT_DESC, msg));
} else {
logger.error(String.format(SUBSCRIBE_FAIL_DESC, msg), e);
}
}
});
}
return results;
}
public static <K, V> Map<K, V> getBatchMap(List<Single<Map<K, V>>> sources, final String msg) {
final Map<K, V> results = Maps.newHashMap();
if (sources != null && !sources.isEmpty()) {
for (Single<Map<K, V>> source : sources) {
Map<K, V> result = getMap(source, msg);
if (result != null) {
results.putAll(result);
}
}
}
return results;
}
private static class InnerReturn<T> {
private T value;
public InnerReturn() {
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public static void main(String[] args) {
if(null instanceof AsyncUtils)
{
System.out.print(false);
}
}
}
3 测试使用
@Service
public class TestService {
@Autowired
private UserServiceManager userService;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public void test() {
Set<Long> set=new HashSet<>();
set.add(12314L);
set.add(142114L);
//调用时候不会阻塞
Single<Map<Long, User>> singleUserMap1 = userService.asynGetUserInfoMap(set);
System.out.print("异步调用");
Single<Map<Long, User>> singleUserMap2 = userService.asynGetUserInfoMap(set);
//获取数据时候会阻塞
Map<Long,User> userMap1=AsyncUtils.getMap(singleUserMap1,"singleUserMap");
Single<Map<Long, User>> userMap2 = userService.asynGetUserInfoMap(set);
} }