1. 整合sentinel流控
当需要对一个接口进行流量监控时可以使用springboot整合sentinel
(1)在common模块中导入依赖 spring-cloud-starter-alibaba-sentinel;
(2)下载sentinel控制台并启动;
(3)配置 sentinel 控制台地址信息
spring.cloud.sentinel.transport.dashboard=localhost:8333
spring.cloud.sentinel.transport.port=8719
(4)在控制台调整参数(默认所有的流控规则保存在内存中,重启失效)
对获取当前秒杀活动添加流量控制,当请求超过时,会被阻塞
(5)添加统计审计信息,对每一个微服务都导入 spring-boot-starter-actuator,并暴露所有端点 management.endpoints.web.exposure.include=*
(6)添加配置类,自定义 sentinel 流控返回的数据
@Configuration
public class GulimallSeckillSentinelConfig {
public GulimallSeckillSentinelConfig() {
WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().write(JSON.toJSONString(error));
}
});
}
}
2. sentinel熔断降级
(1)服务调用方的熔断保护:feign.sentinel.enable=true
(2)远程服务发生异常时,触发我们的熔断回调方法
在商品服务详情中会进行远程调用秒杀服务,当秒杀服务异常时,会触发fallback方法
@Override
public SkuItemVo item(Long skuId) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = new SkuItemVo();
//1、sku基本信息的获取 pms_sku_info
CompletableFuture<SkuInfoEntity> infoFutrue = CompletableFuture.supplyAsync(() -> {
SkuInfoEntity info = getById(skuId);
skuItemVo.setInfo(info);
return info;
}, executor);
//3、获取spu的销售属性组合
CompletableFuture<Void> saleAttrFuture = infoFutrue.thenAcceptAsync((res)->{
List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(saleAttrVos);
},executor);
//4、获取spu的介绍 pms_spu_info_desc
CompletableFuture<Void> descFuture = infoFutrue.thenAcceptAsync((res)->{
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesc(spuInfoDescEntity);
},executor);
//5、获取spu的规格参数信息
CompletableFuture<Void> baseAttrFuture = infoFutrue.thenAcceptAsync((res)->{
List<SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(attrGroupVos);
},executor);
//2、sku的图片信息 pms_sku_images
CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
List<SkuImagesEntity> images = skuImagesService.getImagesBySkuId(skuId);
skuItemVo.setImages(images);
}, executor);
CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {
//3、远程调用查询当前sku是否参与秒杀优惠活动
R skuSeckilInfo = seckillFeignService.getSkuSeckilInfo(skuId);
if (skuSeckilInfo.getCode() == 0) {
//查询成功
SeckillSkuVo seckilInfoData = skuSeckilInfo.getData("data", new TypeReference<SeckillSkuVo>() {
});
skuItemVo.setSeckillSkuVo(seckilInfoData);
if (seckilInfoData != null) {
long currentTime = System.currentTimeMillis();
if (currentTime > seckilInfoData.getEndTime()) {
skuItemVo.setSeckillSkuVo(null);
}
}
}
}, executor);
//等待所有任务都完成
CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture,seckillFuture).get();
return skuItemVo;
}
@FeignClient(value = "gulimall-seckill",fallback = SeckillFeignServiceImpl.class)
public interface SeckillFeignService {
/**
* 根据skuId查询商品是否参加秒杀活动
* @param skuId
* @return
*/
@GetMapping(value = "/sku/seckill/{skuId}")
R getSkuSeckilInfo(@PathVariable("skuId") Long skuId);
}
@Slf4j
@Component
public class SeckillFeignServiceImpl implements SeckillFeignService {
@Override
public R getSkuSeckilInfo(Long skuId) {
log.info("熔断方法调用......");
return R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(),BizCodeEnume.TO_MANY_REQUEST.getMsg());
}
}
也可以在控制台中对远程服务指定降级规则
3. 整合zipkin
(1)docker 安装 zipkin 服务器
docker run -d -p 9411:9411 openzipkin/zipkin
(2)导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
zipkin 依赖也同时包含了 sleuth,可以省略 sleuth 的引用
(3)添加zipkin相关配置
#服务追踪
spring.zipkin.base-url=http://zipkin安装地址:9411/
#关闭服务发现
spring.zipkin.discovery-client-enabled=false
spring.zipkin.sender.type=web
#配置采样器
spring.sleuth.sampler.probability=1
服务调用链追踪信息统计
Zipkin 默认是将监控数据存储在内存的,如果 Zipkin 挂掉或重启的话,那么监控数据就会丢失。所以如果想要搭建生产可用的 Zipkin,就需要实现监控数据的持久化。而想要实现数据持久化,自然就是得将数据存储至数据库,通常选用Elasticsearch。