1.turbine是什么?它的作用是什么?

Turbine is a tool for aggregating streams of Server-Sent Event (SSE) JSON data into a single stream. The targeted use case is metrics streams from instances in an SOA being aggregated for dashboards.

For example, Netflix uses Hystrix which has a realtime dashboard that uses Turbine to aggregate data from 100s or 1000s of machines.

2.eureka启动turbine类StartEurekaTurbine

public static void main(String[] args) {
OptionParser optionParser = new OptionParser();
optionParser.accepts("port").withRequiredArg();
optionParser.accepts("app").withRequiredArg();
optionParser.accepts("urlTemplate").withRequiredArg(); OptionSet options = optionParser.parse(args);
int port = -1;
if (!options.has("port")) {
System.err.println("Argument -port required for SSE HTTP server to start on. Eg. -port 8888");
System.exit(-1);
} else {
try {
port = Integer.parseInt(String.valueOf(options.valueOf("port")));
} catch (NumberFormatException e) {
System.err.println("Value of port must be an integer but was: " + options.valueOf("port"));
}
} String app = null;
if (!options.has("app")) {
System.err.println("Argument -app required for Eureka instance discovery. Eg. -app api");
System.exit(-1);
} else {
app = String.valueOf(options.valueOf("app"));
} String template = null;
if (!options.has("urlTemplate")) {
System.err.println("Argument -urlTemplate required. Eg. http://" + EurekaStreamDiscovery.HOSTNAME + "/metrics.stream");
System.exit(-1);
} else {
template = String.valueOf(options.valueOf("urlTemplate"));
if (!template.contains(EurekaStreamDiscovery.HOSTNAME)) {
System.err.println("Argument -urlTemplate must contain " + EurekaStreamDiscovery.HOSTNAME + " marker. Eg. http://" + EurekaStreamDiscovery.HOSTNAME + "/metrics.stream");
System.exit(-1);
}
} logger.info("Turbine => Eureka App: " + app);
logger.info("Turbine => Eureka URL Template: " + template); try {
Turbine.startServerSentEventServer(port, EurekaStreamDiscovery.create(app, template));
} catch (Throwable e) {
e.printStackTrace();
}
}

执行类如下;

startServerSentEventServer(port, aggregateHttpSSE(discovery));

首先,聚合http

  /**
* Aggregate multiple HTTP Server-Sent Event streams into one stream with the values summed.
* <p>
* The returned data must be JSON data that contains the following keys:
* <p>
* instanceId => Unique instance representing each stream to be merged, such as the instanceId of the server the stream is from.
* type => The type of data such as HystrixCommand or HystrixThreadPool if aggregating Hystrix metrics.
* name => Name of a group of metrics to be aggregated, such as a HystrixCommand name if aggregating Hystrix metrics.
*
* @param uri
* @return
*/
public static Observable<GroupedObservable<TypeAndNameKey, Map<String, Object>>> aggregateHttpSSE(StreamDiscovery discovery) {
Observable<StreamAction> streamActions = discovery.getInstanceList().publish().refCount();
Observable<StreamAction> streamAdds = streamActions.filter(a -> a.getType() == ActionType.ADD);
Observable<StreamAction> streamRemoves = streamActions.filter(a -> a.getType() == ActionType.REMOVE); Observable<GroupedObservable<InstanceKey, Map<String, Object>>> streamPerInstance =
streamAdds.map(streamAction -> {
URI uri = streamAction.getUri(); Observable<Map<String, Object>> io = Observable.defer(() -> {
Observable<Map<String, Object>> flatMap = RxNetty.createHttpClient(uri.getHost(), uri.getPort(), PipelineConfigurators.<ByteBuf>sseClientConfigurator())
.submit(createRequest(uri))
.flatMap(response -> {
if (response.getStatus().code() != 200) {
return Observable.error(new RuntimeException("Failed to connect: " + response.getStatus()));
}
return response.getContent()
.doOnSubscribe(() -> logger.info("Turbine => Aggregate Stream from URI: " + uri.toASCIIString()))
.doOnUnsubscribe(() -> logger.info("Turbine => Unsubscribing Stream: " + uri))
.takeUntil(streamRemoves.filter(a -> a.getUri().equals(streamAction.getUri()))) // unsubscribe when we receive a remove event
.map(sse -> JsonUtility.jsonToMap(sse.getEventData()));
});
// eclipse is having issues with type inference so breaking up
return flatMap.retryWhen(attempts -> {
return attempts.flatMap(e -> {
return Observable.timer(1, TimeUnit.SECONDS)
.doOnEach(n -> logger.info("Turbine => Retrying connection to: " + uri));
});
}); }); return GroupedObservable.from(InstanceKey.create(uri.toASCIIString()), io);
}); return StreamAggregator.aggregateGroupedStreams(streamPerInstance);
}

然后启动聚合

public static void startServerSentEventServer(int port, Observable<GroupedObservable<TypeAndNameKey, Map<String, Object>>> streams) {
logger.info("Turbine => Starting server on " + port); // multicast so multiple concurrent subscribers get the same stream
Observable<Map<String, Object>> publishedStreams = streams
.doOnUnsubscribe(() -> logger.info("Turbine => Unsubscribing aggregation."))
.doOnSubscribe(() -> logger.info("Turbine => Starting aggregation"))
.flatMap(o -> o).publish().refCount(); RxNetty.createHttpServer(port, (request, response) -> {
logger.info("Turbine => SSE Request Received");
response.getHeaders().setHeader("Content-Type", "text/event-stream");
return publishedStreams
.doOnUnsubscribe(() -> logger.info("Turbine => Unsubscribing RxNetty server connection"))
.flatMap(data -> {
return response.writeAndFlush(new ServerSentEvent(null, null, JsonUtility.mapToJson(data)));
});
}, PipelineConfigurators.<ByteBuf>sseServerConfigurator()).startAndWait();
}

3.单独启动turbine的过程和上面类似StartTurbine

 public static void main(String[] args) {
OptionParser optionParser = new OptionParser();
optionParser.accepts("port").withRequiredArg();
optionParser.accepts("streams").withRequiredArg(); OptionSet options = optionParser.parse(args);
int port = -1;
if (!options.has("port")) {
System.err.println("Argument -port required for SSE HTTP server to start on.");
System.exit(-1);
} else {
try {
port = Integer.parseInt(String.valueOf(options.valueOf("port")));
} catch (NumberFormatException e) {
System.err.println("Value of port must be an integer but was: " + options.valueOf("port"));
}
} URI[] streams = null;
if (!options.hasArgument("streams")) {
System.err.println("Argument -streams required with URIs to connect to. Eg. -streams \"http://host1/metrics.stream http://host2/metrics.stream\"");
System.exit(-1);
} else {
String streamsArg = String.valueOf(options.valueOf("streams"));
String[] ss = streamsArg.split(" ");
streams = new URI[ss.length];
for (int i = 0; i < ss.length; i++) {
try {
streams[i] = new URI(ss[i]);
} catch (URISyntaxException e) {
System.err.println("ERROR: Could not parse stream into URI: " + ss[i]);
System.exit(-1);
}
}
} if (streams == null || streams.length == 0) {
System.err.println("There must be at least 1 valid stream URI.");
System.exit(-1);
} try {
Turbine.startServerSentEventServer(port, Turbine.aggregateHttpSSE(streams));
} catch (Throwable e) {
e.printStackTrace();
}
}

netflix turbine概述的更多相关文章

  1. netflix ribbon概述

    LB方案分类 目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略 ...

  2. netflix feign概述

    1.什么是feign?feign的作用是什么? Feign is a java to http client binder inspired by Retrofit, JAXRS-2.0, and W ...

  3. 第二十六章 hystrix-dashboard + turbine

    一.使用turbine的意义 引入多个hystrix stream: 1.使用hystrix-dashboard的可以添加多个stream的功能 图中添加的两个stream会在真正monitor的时候 ...

  4. 附7 turbine

    一.作用 聚集同一个微服务的相同的commandKey.Threadpool.commandGroupKey数据进行聚合 二.配置 1.集群(cluster)(turbine聚集数据的粒度) turb ...

  5. Building microservices with Spring Cloud and Netflix OSS, part 2

    In Part 1 we used core components in Spring Cloud and Netflix OSS, i.e. Eureka, Ribbon and Zuul, to ...

  6. 基于Spring Cloud和Netflix OSS构建微服务,Part 2

    在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...

  7. spring cloud熔断监控Hystrix Dashboard和Turbine

    参考: http://blog.csdn.net/ityouknow/article/details/72625646 完整pom <?xml version="1.0" e ...

  8. SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)

    1.概念:Hystrix 熔断机制 2.具体内容 所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢? 当现在服务的 ...

  9. Spring Cloud 入门教程(八): 断路器指标数据监控Hystrix Dashboard 和 Turbine

    1. Hystrix Dashboard (断路器:hystrix 仪表盘)  Hystrix一个很重要的功能是,可以通过HystrixCommand收集相关数据指标. Hystrix Dashboa ...

随机推荐

  1. JVM内存管理简单剖析

    Java是一个跨平台语言,屏蔽操作系统的差异,无需关心复杂内存管理,做到编写一次到处运行.其强大的能力源于Java Virtual Machine (虚拟机)默默的付出.代码运行在虚拟机之上,虚拟机运 ...

  2. 关于Subversion主从备份方式的调整(全量、增量脚本)更新

    本文引用于http://blog.chinaunix.net/uid-25266990-id-3369172.html 之前对Subversion服务器作了迁移,关于SVN的架构也走了调整,有单一的服 ...

  3. 【CS round 34】Minimize Max Diff

    [题目链接]:https://csacademy.com/contest/round-34/task/minimize-max-diff/ [题意] 给你n个数字; 数组按顺序不下降; 让你删掉k个数 ...

  4. android将String转化为MD5的方法+一些String经常使用的方法

    public class StringUtils { public static String MD5Encode(String origin) { String resultString = nul ...

  5. 主程的晋升攻略(4):TCP、消息分包和协议设计

    在<主程的晋升攻略(3):IP.DNS和CDN>中,一次网络请求经过DNS解析知道了目的IP,如今就要发出网络包,这里我们说一说TCP的相关话题. TCP是一种流式协议 讲网络编程的教科书 ...

  6. Solr DataImportHandler 配置

    DIH主要用于从数据库抓取数据并创建索引.另外还能够从HTTP(RSS.ATOM)拉数据. 相关概念: Datasource:数据源,包含获取数据必需的信息:数据位置(url).数据库driver.登 ...

  7. cocos2d-x中的二段构造模式

    学习cocos2d-x的过程中,会发现很多对象都通过一个静态函数create来创建.比方以下的一个样例 #define CREATE_FUNC (__TYPE__) \ static __TYPE__ ...

  8. vim 插件之NERD tree

    NERD tree 这个插件可以用来快速浏览目录结构,打开文件 地址 http://www.vim.org/scripts/script.php?script_id=1658 https://gith ...

  9. 关于fetch

    前言: fetch是用来取代传统的XMLHttpRequest的. 它的优点很多,包括链式调用的语法.返回promise等. 什么是fetch? fetch api是基于promise的设计,它是为了 ...

  10. 索引-mysql索引创建、查看、删除及使用示例

    mysql索引创建.查看.删除及使用示例 1.创建索引: ALTER TABLE用来创建普通索引.UNIQUE索引或PRIMARY KEY索引. ALTER TABLE table_name ADD ...