Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的开源项目, 2017年12月SkyWalking成为Apache国内首个个人孵化项目, 2019年4月17日SkyWalking从Apache基金会的孵化器毕业成为顶级项目, 目前SkyWalking支持Java、 .Net、 Node.js、 go、 python等探针, 数据存储支持MySQL、 ElasticSearch等, SkyWalking与Pinpoint相同, 对业务代码无侵入, 不过探针采集数据粒度相较于Pinpoint来说略粗, 但性能表现优秀, 目前SkyWalking增长势头强劲, 社区活跃, 中文文档齐全, 没有语言障碍, 支持多语言探针, 这些都是 SkyWalking的优势所在, 还有就是SkyWalking支持很多框架, 包括很多国产框架, 例如, Dubbo、 gRPC、 SOFARPC 等等, 同时也有很多开发者正在不断向社区提供更多插件以支持更多组件无缝接入SkyWalking。
官网地址:https://skywalking.apache.org/
这个是官网的架构设计图:
SkyWalking有两中版本,ES版本和非ES版。如果我们决定采用ElasticSearch作为存储,那么就下载es版本。 SkyWalking 支持 ES、MySQL 等等作为存储器,实现链路等信息的读写。
一般情况下,我们推荐使用 ES 存储器。
下面我们来安装一下。
es 安装这个之前有说明,可以自行去看文章安装。
skywalking安装可以参考官网,下载源码包,在linux或者windows环境安装。
解压后如下:
- agent目录将来要拷贝到各服务所在机器上用作探针
- bin目录是服务启动脚本
- config目录是配置文件
- oap-libs目录是oap服务运行所需的jar包
- webapp目录是web服务运行所需的jar包
接下来,要选择存储了,支持的存储有:
- H2
- ElasticSearch 6, 7
- MySQL
- TiDB
- InfluxDB
作为监控系统,首先排除H2和MySQL,这里推荐InfluxDB,它本身就是时序数据库,非常适合这种场景
这里要注意,最新的安装包jdk1.8以上才可以。我这里是11:
接下来,我们选择es作为存储数据源,在 config/application.yml ,设置storage中的es地址即可,如果是集群,就写集群的地址
2.2. 安装Agent
https://github.com/apache/skywalking/blob/v8.2.0/docs/en/setup/service-agent/java-agent/README.md
将agent目录拷贝至各服务所在的机器上
这里,我将它拷贝至某个服务目录下:
SkyWalking插件都是即插即用的,可以把optional-plugins中的插件放到plugins中
修改 agent/config/agent.config 配置文件,也可以通过命令行参数指定
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800} ip改为自己服务的地址即可。
这个包的位置可以随便放,可以在你的启动参数里面加上,也可以使用jar的方式指定路径:
-javaagent:D:\work\gitwork\mavendemo\skywalking-agent\skywalking-agent.jar -Dskywalking.agent.service_name=skywalking-jsbc-service -Dskywalking.collector.backend_service=127.0.0.1:11800
接着修改监控web端口地址:
当然也可以不用修改,使用默认的地址和端口。
启动skywalking服务:
现在打开
我现在比如向数据库中插数据,
模拟100次插入:
通过postman请求:
打开监控可以看到下面的链路日志和执行时间:
’
服务执行响应时间,成功率等等指标,可以去官网上看文档
服务拓扑结构
链路log和执行时间,这样可以看出链路消耗时间和性能
除来这个我们可以Grafana 来监控性能,比如redis,mysql之类的性能。
Grafana安装也很简单,下载源码包,解压后直接启动即可:
然后启动:
账号密码admin/admin
添加redis数据源
如果是集群的,填写集群地址即可,保存后,我们可以自定义redis性能,也可以使用官方的模版导入json文件模版即可:
Redis Dashboard | Grafana Labs
下面我们写个程序读写redis,下面是pom文件:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<!-- redis分布式锁 -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<!-- redis 连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
@Test
public void shouldUse3DbConcurrent(){
final String key3="dm:3:cr:string:key";
final String key0="dm:0:cr:string:key";
List<String> keys=Arrays.asList(key0, key3);
stringRedisManager.deleteKeyBatch(keys);
string3RedisManager.deleteKeyBatch(keys);
stringRedisManager.set(key0, "0");
string3RedisManager.set(key3, "0");
int threadCount=500;
int addTotal=50000;
RedisAddManager addManager0=new RedisAddManager(stringRedisManager, key0, threadCount, addTotal);
RedisAddManager addManager3=new RedisAddManager(string3RedisManager, key3, threadCount, addTotal);
addManager0.startThreads();
addManager3.startThreads();
addManager0.countDown();
addManager3.countDown();
//等待线程执行完毕
addManager0.joins();
addManager3.joins();
int expectedTotal=threadCount*addTotal;
String expectedTotalStr=String.valueOf(expectedTotal);
String result0=stringRedisManager.get(key0);
Assert.assertEquals(expectedTotalStr, result0);
String result0_=stringRedisManager.get(key3);
Assert.assertNull(result0_);
String result3=string3RedisManager.get(key3);
Assert.assertEquals(expectedTotalStr, result3);
String result3_=string3RedisManager.get(key0);
Assert.assertNull(result3_);
}
private class RedisAddManager{
private CountDownLatch countDownLatch=new CountDownLatch(1);
private RedisManager<String,String> stringRedisManager;
private String key;
private int threadCount;
private int addTotal;
private List<Thread> threads=new ArrayList<>();
public RedisAddManager(RedisManager<String, String> stringRedisManager, String key, int threadCount, int addTotal) {
this.stringRedisManager = stringRedisManager;
this.key = key;
this.threadCount=threadCount;
this.addTotal = addTotal;
}
启动执行后,可以看到仪表盘redis的读写性能: