天天看点

微服务架构的高并发问题

作者:马士兵教育

通过注册中心已经实现了微服务的服务注册和服务发现,并且通过Ribbon实现了负载均衡,已经借助Feign可以优雅的进行微服务调用。那么我们编写的微服务的性能怎么样呢,是否存在问题呢?

性能工具Jmetter

微服务架构的高并发问题

Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器,等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。

安装Jmetter

Jmetter安装十分简单,使用资料中的 apache-jmeter-2.13.zip 完整压缩包,解压找到安装目录下bin/jmeter.bat 已管理员身份启动即可

微服务架构的高并发问题

配置Jmetter

(1)创建新的测试计划

微服务架构的高并发问题

(2)测试计划下创建发起请求的线程组

微服务架构的高并发问题
  • 可以配置请求的线程数
  • 以及每个请求发送的请求次数

(3)创建http请求模板

微服务架构的高并发问题

(4)配置测试的接口信息

微服务架构的高并发问题

系统负载过高存在的问题

问题分析

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪。

在SpringBoot程序中,默认使用内置tomcat作为web服务器。单tomcat支持最大的并发请求是有限的,如果某一接口阻塞,待执行的任务积压越来越多,那么势必会影响其他接口的调用。

线程池的形式实现服务隔离

(1)配置坐标

为了方便实现线以线程池的形式完成资源隔离,需要引入如下依赖

<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.12</version>
</dependency>           

(2)配置线程池

配置HystrixCommand接口的实现类,再实现类中可以对线程池进行配置

public class OrderCommand extends HystrixCommand<String> {
private RestTemplate restTemplate;
private Long id;
public OrderCommand(RestTemplate restTemplate, Long id) {
super(setter());
this.restTemplate = restTemplate;
this.id = id;
}
private static Setter setter() {
// 服务分组
HystrixCommandGroupKey groupKey =
HystrixCommandGroupKey.Factory.asKey("order_product");
// 服务标识
HystrixCommandKey commandKey =
HystrixCommandKey.Factory.asKey("product");
// 线程池名称
HystrixThreadPoolKey threadPoolKey =
HystrixThreadPoolKey.Factory.asKey("order_product_pool");
/**
* 线程池配置
* withCoreSize : 线程池大小为10
* withKeepAliveTimeMinutes: 线程存活时间15秒
* withQueueSizeRejectionThreshold :队列等待的阈值为100,超过100执行拒绝
策略
*/
HystrixThreadPoolProperties.Setter threadPoolProperties =
HystrixThreadPoolProperties.Setter().withCoreSize(50)
.withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100);
// 命令属性配置Hystrix 开启超时
HystrixCommandProperties.Setter commandProperties =
HystrixCommandProperties.Setter()
// 采用线程池方式实现服务隔离
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrat
egy.THREAD)
// 禁止
.withExecutionTimeoutEnabled(false);
return
HystrixCommand.Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThread
PoolKey(threadPoolKey)
.andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefau
lts(commandProperties);
}
@Override
protected String run() throws Exception {
return restTemplate.getForObject("http://shop-service
product/product/"+id, String.class);
}
@Override
protected String getFallback(){
return "熔断降级";
}
}           

(3)配置调用

修改 OrderController ,使用自定义的OrderCommand完成调用

@Autowired
private RestTemplate restTemplate;
@GetMapping("/buy/{id}")
public String order(@PathVariable Long id) throws ExecutionException,
InterruptedException, TimeoutException {
return new OrderCommand(restTemplate,id).execute();
}           

继续阅读