赞
踩
频繁的调用provider接太浪费了, 就有了将多个请求合并为一个请求的方式。
首先在provider中提供一个请求合并的接口:
@RestController public class UserController { /**【既可以处理多个,也可以处理单个请求】 *单个请求的话,List中只有一项数据 *假设 consumer 传过来的多个id格式是 1,2,3,4....*/ @GetMapping("/user/{ids}") public List<User> getUserByIds(@PathVariable String ids){ System.out.println(ids); String[] split = ids.split(","); List<User> user = new ArrayList<>(); for(String s : split){ User user1 = new User(); user1.setId(Integer.parseInt(s)); user.add(user1); } return user; } }
然后在Hystrix中定义UserService:
@Service
public class UserService {
@Autowired
RestTemplate restTemplate;
public List<User> getUsersByIds(List<Integer> ids){
User[] users = restTemplate.getForObject("http://provider/user/{1}", User[].class, StringUtils.join(ids, ","));
return Arrays.asList(users);
}
}
接下来定义 UserBatchCommand ,相当于我们之前的 HelloCommand:
public class UserBatchCommand extends HystrixCommand<List<User>> { private List<Integer> ids; private UserService userService; public UserBatchCommand(List<Integer> ids, UserService userService) { super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("batchCmd")).andCommandKey(HystrixCommandKey.Factory.asKey("batchKey"))); this.ids = ids; this.userService = userService; } @Override protected List<User> run() throws Exception { return userService.getUsersByIds(ids); } }
public class UserCollapseCommand extends HystrixCollapser<List<User>, User, Integer> { private UserService userService; private Integer id; public UserCollapseCommand(UserService userService, Integer id) { super(HystrixCollapser.Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("UserCollapseCommand")).andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(200))); this.userService = userService; this.id = id; } /** * 请求参数 * * @return */ @Override public Integer getRequestArgument() { return id; } /** * 请求合并的方法 * * @param collection * @return */ @Override protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Integer>> collection) { List<Integer> ids = new ArrayList<>(collection.size()); for (CollapsedRequest<User, Integer> userIntegerCollapsedRequest : collection) { ids.add(userIntegerCollapsedRequest.getArgument()); } return new UserBatchCommand(ids, userService); } /** * 请求结果分发 * * @param users * @param collection */ @Override protected void mapResponseToRequests(List<User> users, Collection<CollapsedRequest<User, Integer>> collection) { int count = 0; for (CollapsedRequest<User, Integer> request : collection) { request.setResponse(users.get(count++)); } } }
然后测试调用:
@GetMapping("/hello5") public void hello5() throws ExecutionException,InterruptedException{ HystrixRequestContext ctx = HystrixRequestContext.initializeContext(); UserCollapseCommand cmd1 = new UserCollapseCommand(userService, 99); UserCollapseCommand cmd2 = new UserCollapseCommand(userService, 98); UserCollapseCommand cmd3 = new UserCollapseCommand(userService, 97); Future<User> q1 = cmd1.queue(); Future<User> q2 = cmd2.queue(); Future<User> q3 = cmd3.queue(); User u1 = q1.get(); User u2 = q2.get(); User u3 = q3.get(); System.out.println(u1); System.out.println(u2); System.out.println(u3); Thread.sleep(2000);//睡2秒就变成两次请求, UserCollapseCommand cmd4 = new UserCollapseCommand(userService, 96); Future<User> q4 = cmd4.queue(); User u4 = q4.get(); System.out.println(u4); ctx.close(); }
@Service public class UserService { @Autowired RestTemplate restTemplate; /** * 注解方式实现请求合并 * @param id * @return HystrixCollapse *【重要:@HystrixCollapser 注解指定批处理方法】 */ @HystrixCollapser(batchMethod = "getUsersByIds",collapserProperties = {@HystrixProperty(name = "timerDelayInMilliseconds",value = "200")}) public Future<User> getUserById(Integer id) { return null; } @HystrixCommand public List<User> getUsersByIds(List<Integer> ids){ User[] users = restTemplate.getForObject("http://provider/user/{1}", User[].class, StringUtils.join(ids, ",")); return Arrays.asList(users); } }
测试方法:
/** * 注解方式实现请求合并 测试方法 * @throws ExecutionException * @throws InterruptedException */ @GetMapping("/hello6") public void hello6() throws ExecutionException, InterruptedException { HystrixRequestContext ctx = HystrixRequestContext.initializeContext(); Future<User> q1 = userService.getUserById(99); Future<User> q2 = userService.getUserById(98); Future<User> q3 = userService.getUserById(97); User u1 = q1.get(); User u2 = q2.get(); User u3 = q3.get(); System.out.println(u1); System.out.println(u2); System.out.println(u3); Thread.sleep(2000); Future<User> q4 = userService.getUserById(96); User u4 = q4.get(); System.out.println(u4); ctx.close(); }
小结 :@HystrixCollapser(batchMethod = “getUserByIds”,collapserProperties = {@HystrixProperty(name = “timerDelayInMilliseconds”,value = “200”)})
@HystrixCommand
代码地址:https://github.com/astronger/springcloud-simple-samples
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。