专栏首页奔跑的人生[Spring cloud 一步步实现广告系统] 19. 监控Hystrix Dashboard

[Spring cloud 一步步实现广告系统] 19. 监控Hystrix Dashboard

在之前的18次文章中,我们实现了广告系统的广告投放广告检索业务功能,中间使用到了 服务发现Eureka服务调用Feign,网关路由Zuul以及错误熔断HystrixSpring Cloud组件。 简单调用关系:

但是系统往往都会报错,我们之前定义了一些容错类和方法,但是只是在控制台可以看到错误信息,我们想要统计一些数据,怎么才能更直观的看到我们的服务调用情况呢,接下来,和大家讨论一个新的熔断监控组件Hystrix Dashboard,顾名思义,从名字上我们就能看出来,它是监控的图形化界面。

Hystrix 在服务中的使用

结合openfeign使用

在我们实际的项目当中,使用的最多的就是结合FeignClient#fallbackHystrix一起来实现熔断,我们看一下我们在mscx-ad-feign-sdk中的实现。

@FeignClient(value = "mscx-ad-sponsor", fallback = SponsorClientHystrix.class)
public interface ISponsorFeignClient {
    @RequestMapping(value = "/ad-sponsor/plan/get", method = RequestMethod.POST)
    CommonResponse<List<AdPlanVO>> getAdPlansUseFeign(@RequestBody AdPlanGetRequestVO requestVO);

    @RequestMapping(value = "/ad-sponsor/user/get", method = RequestMethod.GET)
    /**
     * Feign 埋坑之 如果是Get请求,必须在所有参数前添加{@link RequestParam},不能使用{@link Param}
     * 会被自动转发为POST请求。
     */
    CommonResponse getUsers(@RequestParam(value = "username") String username);
}

在上述代码中,我们自定义了一个feignclient,并且给了这个client一个fallback的实现类:

@Component
public class SponsorClientHystrix implements ISponsorFeignClient {
    @Override
    public CommonResponse<List<AdPlanVO>> getAdPlansUseFeign(AdPlanGetRequestVO requestVO) {
        return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get plan error.");
    }

    @Override
    public CommonResponse getUsers(String username) {
        return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get user error.");
    }
}

这个fallback类实现了我们自定义的ISponsorFeignClient,那是因为fallback的方法必须和原始执行类的方法签名保持一致,这样在执行失败的时候,可以通过反射映射到响应的降级方法/容错方法。 在mscx-ad-search服务中,我们通过注入ISponsorFeignClient来调用我们的mscz-ad-sponsor服务。

@RestController
@Slf4j
@RequestMapping(path = "/search-feign")
public class SearchFeignController {

    /**
     * 注入我们自定义的FeignClient
     */
    private final ISponsorFeignClient sponsorFeignClient;
    @Autowired
    public SearchFeignController(ISponsorFeignClient sponsorFeignClient) {
        this.sponsorFeignClient = sponsorFeignClient;
    }

    @GetMapping(path = "/user/get")
    public CommonResponse getUsers(@Param(value = "username") String username) {
        log.info("ad-search::getUsersFeign -> {}", JSON.toJSONString(username));
        CommonResponse commonResponse = sponsorFeignClient.getUsers(username);
        return commonResponse;
    }
}
使用HystrixCommand

其实Hystrix本身提供了一种直接在方法中应用的方式,就是使用@ com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand,我们看一下这个类的源码:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {
    ...

        /**
     * Specifies a method to process fallback logic.
     * A fallback method should be defined in the same class where is HystrixCommand.
     * Also a fallback method should have same signature to a method which was invoked as hystrix command.
     * for example:
     * <code>
     *      @HystrixCommand(fallbackMethod = "getByIdFallback")
     *      public String getById(String id) {...}
     *
     *      private String getByIdFallback(String id) {...}
     * </code>
     * Also a fallback method can be annotated with {@link HystrixCommand}
     * <p/>
     * default => see {@link com.netflix.hystrix.contrib.javanica.command.GenericCommand#getFallback()}
     *
     * @return method name
     */
    String fallbackMethod() default "";

    ...
}

我们主要关注2个点:

  1. @Target({ElementType.METHOD})表明当前的注解只能应用在方法上面。
  2. 可直接定义fallbackMethod来保证容错。这个方法有一个缺陷,就是必须和执行方法在同一个类文件中,这就会造成我们的方法在实现的时候,显得特别的冗余和不够优雅。

以我们的mscx-ad-search中的广告查询为例:

@Service
@Slf4j
public class SearchImpl implements ISearch {

    /**
     * 查询广告容错方法
     *
     * @param e 第二个参数可以不指定,如果需要跟踪错误,就指定上
     * @return 返回一个空map 对象
     */
    public SearchResponse fetchAdsFallback(SearchRequest request, Throwable e) {

        System.out.println("查询广告失败,进入容错降级 : %s" + e.getMessage());
        return new SearchResponse().builder().adSlotRelationAds(Collections.emptyMap()).build();
    }

    @HystrixCommand(fallbackMethod = "fetchAdsFallback")
    @Override
    public SearchResponse fetchAds(SearchRequest request) {
        ...
    }
}

在我们请求出错的时候,会转到我们的fallback方法,这个实现是通过在应用启动的时候,我们开始了@EnableCircuitBreaker注解,这个注解会通过AOP拦截所有的HystrixCommand方法,将HystrixCommand整合到springboot的容器中,并且将注解标注的方法放入hystrix的线程中,一旦失败,通过反射调用fallback方法来实现。

创建dashboard project

上述代码我们看了Hystrix实现熔断的2种方式,接下来我们来实现请求监控的图形化界面,创建mscx-ad-dashboard,Let's code. 依然遵从我们springboot项目的三部曲:

  1. 加依赖 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.2.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> <version>1.2.7.RELEASE</version> </dependency> <!--eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies>
  2. 加注解 /** * AdDashboardApplication for Hystrix Dashboard 启动类 * * @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a> * @since 2019/8/15 */ @SpringBootApplication @EnableDiscoveryClient @EnableHystrixDashboard public class AdDashboardApplication { public static void main(String[] args) { SpringApplication.run(AdDashboardApplication.class, args); } }
  3. 改配置 server: port: 1234 spring: application: name: mscx-ad-dashboard eureka: client: service-url: defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ management: endpoints: web: exposure: include: "*"`

直接启动,可以看到如下页面:

添加要监控的服务地址:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [Spring cloud 一步步实现广告系统] 2. 配置&Eureka服务

    mscx-ad-sponsor就是我们的广告投放系统。如上结构,我们需要首先创建一个Parent Project mscx-ad

    Isaac Zhang
  • [Spring cloud 一步步实现广告系统] 6. Service实现&Zuul配置&Test

    这里我们使用Spring DATA JPA来实现数据库操作,当然大家也可以使用Mybatis,都是一样的,我们依然以用户表操作为例:

    Isaac Zhang
  • [Spring cloud 一步步实现广告系统] 11. 使用Feign实现微服务调用

    上一节我们使用了Ribbon(基于Http/Tcp)进行微服务的调用,Ribbon的调用比较简单,通过Ribbon组件对请求的服务进行拦截,通过Eureka S...

    Isaac Zhang
  • Android编程实现ListView中item部分区域添加点击事件功能

    本文实例讲述了Android编程实现ListView中item部分区域添加点击事件功能。分享给大家供大家参考,具体如下:

    砸漏
  • 2015谷歌I/O大会综述:Android M、Android Studio、云端测试工具

    2015谷歌I/O大会如期在美国旧金山举行,和以往一样,谷歌带来了一系列的产品更新和为开发者提供了更多的开发工具,下面我们以一个简要的形式,为你展现本次开发者大...

    CSDN技术头条
  • SpringBoot Session管理工具类

    RequestHolder是获取每次请求的HttpServletRequest对象的工具类。

    多凡
  • MapStruct 爬坑指南

    第一步当然是引入pom依赖,目前1.3版本还是beta所以选择引入1.2版本,使用IDEA的小伙伴推荐去插件商店搜索MapStruct,下载插件可以获得更好的体...

    tanoak
  • 5.FFMPEG-Qt移植ffmpeg、ffmpeg结构体介绍

    https://blog.csdn.net/leixiaohua1020/article/details/11693997

    张诺谦
  • 开发者:微软OS第三方开发者优势有待释放

    本文同时发表于2009年10月19日的《通信产业报》    手机,这一人们日常生活中扮演日趋重要角色的设备,从一个打电话、发短信的联络工具,发展到集通讯、商务、...

    ShiJiong
  • python中的深拷贝与浅拷贝

    赋值的时候,是直接引用,b与a其实都指向同一个对象,所以当a改变时,b也随机改变; 浅拷贝的时候,a与c独立,但是子对象指向同一对象,a变化时,c列表的子列表...

    生信编程日常

扫码关注云+社区

领取腾讯云代金券