基于springcloud异步线程池、⾼并发请求feign的解决⽅
案ScenTaskTestApplication.java
st;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author scen
* @version 2018年9⽉27⽇上午11:51:04
*/
@EnableFeignClients
@SpringBootApplication
public class ScenTaskTestApplication {
public static void main(String[] args) {
SpringApplication.run(ScenTaskTestApplication.class, args);
}
}
application.properties
spring.application.name=scen-task-test
server.port=9009
abled=true
#熔断器失败的个数==进⼊熔断器的请求达到1000时服务降级(之后的请求直接进⼊熔断器)
hystrixmand.questVolumeThreshold=1000
#回退最⼤线程数
hystrixmand.default.fallback.isolation.semaphore.maxConcurrentRequests=50
#核⼼线程池数量
hystrix.Size=130
#请求处理的超时时间
ution.isolation.thread.timeoutInMilliseconds=100000
ribbon.ReadTimeout=120000
#请求连接的超时时间
ribbon.ConnectTimeout=130000
eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${server.port}}
eureka.instance.preferIpAddress=true
eureka.client.service-url.defaultZone=127.0.0.1:9000/eureka
st.user.service=debug
springframework.boot=debug
logging.level.custom=info
AsyncConfig.java
st;
import t.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.urrent.ThreadPoolTaskExecutor;
import urrent.Executor;
/**
* springboot异步线程池配置
* @author Scen
* @date 2018/11/7 18:28
*/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
/
/定义线程池
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//核⼼线程数
taskExecutor.setCorePoolSize(20);
//线程池最⼤线程数
taskExecutor.setMaxPoolSize(100);
//线程队列最⼤线程数
taskExecutor.setQueueCapacity(10);
//初始化
taskExecutor.initialize();
return taskExecutor;
}
}
DoTaskClass.java
st;
st.pojo.User;
st.pojo.UserEducation;
st.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.List;
/
**
* 任务类定义异步⼯作任务
* @author Scen
* @date 2018/11/7 18:40
*/
springcloud和springboot@Component
public class DoTaskClass {
/**
* ⼀个feign的客户端
*/
private final UserService userService;
@Autowired
public DoTaskClass(UserService userService) {
this.userService = userService;
}
/**
* 核⼼任务
*
* @param uid
*/
@Async
public void dotask(String uid) {
/
**
* 模拟复杂⼯作业务(109个线程同时通过feign请求微服务提供者)
*/
{
List<UserEducation> userEducationByUid = userService.findUserEducationByUid(uid); List<String> blackList = BlackList();
String userSkilled = UserSkilled(uid);
String userFollow = UserFollow(uid);
User userById = UserById(uid);
List<String> followList = FollowList(uid);
int userActivityScore = UserActivityScore(uid);
}
// 打印线程名称分辨是否为多线程操作
System.out.println(Thread.currentThread().getName() + "===任务" + uid + "执⾏完成==="); }
}
TestController.java
st;
st.pojo.User;
st.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/
**
* 测试案例
* @author Scen
* @date 2018/11/7 18:10
*/
@RestController
public class TestController {
/**
* 此处仅⽤此feign客户端请求微服务获取核⼼⼯作所需参数
*/
private final UserService userService;
/
**
* 核⼼⼯作异步算法
*/
private final DoTaskClass doTaskClass;
@Autowired
public TestController(DoTaskClass doTaskClass, UserService userService) {
this.doTaskClass = doTaskClass;
this.userService = userService;
}
/**
* ⼿动触发⼯作
* @throws InterruptedException
*/
@RequestMapping("/test")
public void task() throws InterruptedException {
/*
取到1000个要执⾏任务的必备参数
*/
List<User> userList = userService.findAllLite(1, 1000);
for (int i = 0; i < userList.size(); i++) {
try {
// 异步线程开始⼯作
doTaskClass.(i).getId());
} catch (Exception e) {
/*
若并发线程数达到MaxPoolSize+QueueCapacity=110(参考AsyncConfig配置)会进⼊catch代码块
i--休眠3秒后重试(尝试进⼊线程队列:当且仅当109个线程有⼀个或多个线程完成异步任务时重试成功)
*/
i--;
Thread.sleep(3000*3);
}
System.out.println(i);
}
}
}
相关线程池、超时时间等数量和⼤⼩按实际业务配置
补充:SpringCloud关于@FeignClient和Hystrix集成对http线程池监控问题
@FeignClient可以作为Http代理访问其他微服务节点,可以⽤apache的httpclient替换@FeignClient原⽣的URLConnection请求⽅式,以达到让http请求⾛Http线程池的⽬的。
⽽@FeignClient和hystrix集成之后,在hystrix dashboard上可以监控到 @FeignClient 中接⼝调⽤情况和 @FeignClient 中httpclient中线程池使⽤状况。
下⾯是demo的⽰例:
1、@FeignClient的接⼝代码如下:
@FeignClient(value="service-A", fallback=ServiceClientHystrix.class)
public interface ServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/add/{id}")
String add(@PathVariable("id") Integer id);
}
2、ServiceClientHystrix.java
@Component
public class ServiceClientHystrix implements ServiceClient{
@Override
public String add(Integer id) {
return "add value from ServiceClientHystrix";
}
}
3、关于@FeignClient和hystrix
集成后,Http线程池配置如下:
hystrix.threadpool.服务实例ID.参数
例如设置httpclient的线程池最⼤线程数量
hystrix.Size=20//默认是hystrix.Size = 10
hystrix.threadpool.service-A.maximumSize=20//默认是hystrix.threadpool.default.maximumSize = 10
启动服务后⽤测试⽤例连续调⽤接⼝测试,⽤hystrix dashboard
监控得到下图监控效果:
去掉hystrix.threadpool.服务实例ID.参数配置后,再次⽤测试⽤例调⽤接⼝得到监控如下图:
PoolSize的⼤⼩取决于hystrix.threadpool.服务实例ID.coreSize⼤⼩设置
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论