下载地址Downloads | Apache SkyWalking
SkyWalking APM 9.2.0
Java Agent 8.12.0
linux搭建skywalking
0.安装jdk,配置环境变量
1.安装es,elasticsearch.service,修改内存限制LimitMEMLOCK=infinity # 增加配置
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.2-x86_64.rpm
2.使用es存储,服务启动默认4g内存
vim /etc/elasticsearch/jvm.options
-Xms1g
-Xmx1g
3.重新加载启动脚本并启动并加入开机自启
systemctl daemon-reload && systemctl start elasticsearch && systemctl enable elasticsearch
systemctl status elasticsearch查看运行状态
systemctl stop elasticsearch停止es
4.skywalking默认采用h2存储
5.curl 127.0.0.1:9200查看cluster.name
cluster.name: cghes与SW_NAMESPACE对应,启动oapService.sh成功后占用 11800,12800端口(netstat -lntp查看)
1. 链路追踪框架对比
项目 | Cat | Zipkin | SkyWalking |
---|---|---|---|
调用链可视化 | 有 | 有 | 有 |
聚合报表 | 非常丰富 | 少 | 较丰富 |
服务依赖图 | 简单 | 简单 | 好 |
埋点方式 | 侵入式 | 侵入式 | 非侵入,字节码增强 |
VM监控指标 | 好 | 无 | 有 |
支持语言 | java/.net | 丰富 | java/.net/Nodejs/php/go |
存储机制 | mysql(报表),本地文件/HDFS(调用链) | 内存,es,mysql等 | H2,es |
社区支持 | 主要国内 | 国外主流 | Apache支持 |
使用案例 | 美团,携程,陆金所 | 京东,阿里定制后不开源 | 华为,小米,当当,微众银行 |
APM | 是 | 否 | 是 |
是否支持webflux | 否 | 是 | 是 |
2.微服务接入SkyWalking,每一个微服务启动加入agent,针对不同的服务开启探针配置agent.conf收集数据的颗粒度
# skywalking-agent.jar的磁盘路径
-javaagent:所在路径 jar
# 在skywalking上显示的服务名
-DSW_AGENT_NAME=dev-third
3.探针配置agent.conf
agent/config/agent.config
中支持的属性列表
属性名 | 描述 | 默认值 |
---|---|---|
agent.namespace |
命名空间,用于隔离跨进程传播的header。如果进行了配置,header将为HeaderName:Namespace . |
未设置 |
collector.backend_service | 接收skywalking trace数据的后端地址 | 127.0.0.1:11800 |
plugin.mysql.trace_sql_parameters | 如果设置为 true, SQL 查询 (典型的是 java.sql.PreparedStatement ) 的参数也会被采集. |
false |
plugin.tomcat.collect_http_params |
这个配置项控制Tomcat插件是否应该收集请求的参数. 同样,在概要追踪中隐式激活. | false |
plugin.springmvc.collect_http_params | 这个配置项控制SpringMVC插件是否应该收集请求的参数, 当您的Spring应用程序基于Tomcat时, 只需要设置 plugin.tomcat.collect_http_params 或 plugin.springmvc.collect_http_params 之一. 同样,在概要追踪中隐式激活. | false |
plugin.http.http_params_length_threshold | 当启用 COLLECT_HTTP_PARAMS 时,要保留多少字符并将其发送到OAP后端,请使用负值来保留和发送完整的参数. 添加这个配置项是为了提高性能. |
1024 |
plugin.jedis.trace_redis_parameters | 如果设置为 true,redis参数将被采集 | false |
plugin.mongodb.trace_param | 如果为true,记录所有访问MongoDB的参数信息。默认为false,表示仅记录操作名,不记录参数信息。 | false |
plugin.postgresql.trace_sql_parameters | 如果设置为true,将收集sql的参数(通常是 java.sql.PreparedStatement ). |
false |
plugin.elasticsearch.trace_dsl | 如果为true,记录所有访问ElasticSearch的DSL信息。默认为false | false |
plugin.springmvc.use_qualified_name_as_endpoint_name | 如果为true,endpoint的name为方法的全限定名,而不是请求的URL。默认为false。 | false |
plugin.solrj.trace_statement | 如果为 true, 追踪 Solr 查询请求中的所有查询参数(包括 deleteByIds 和 deleteByQuery) 默认为 false. | false |
plugin.feign.collect_request_body | 如果为 true, fegin调用请求体将打印 | false |
4.追踪Gateway
Spring Cloud Gateway 是基于 WebFlux 实现,必须搭配上apm-spring-cloud-gateway-2.1.x-plugin 和 apm-spring-webflux-x.x-plugin 两个插件
将agent/optional-plugins下的两个插件 复制到 agent/plugins目录下
5.请求参数上报
pom.xml依赖
org.apache.skywalking
apm-toolkit-trace
common工程下新建请求参数filter类extend HttpFilter,微服务工程启动类加扫包
import com.alibaba.nacos.shaded.com.google.common.collect.ImmutableSet;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Set;
import java.util.stream.Collectors;
/**
* skywalking 请求参数封装,通过ActiveSpan,输出到skywalking,如需打印,启动类加入扫包 com.***.***.common.skywalking
*/
@Slf4j
@Component
public class SkyWalkingReqParamFilter extends HttpFilter {
private static final ImmutableSet IGNORED_HEADERS;
static {
Set ignoredHeaders = ImmutableSet.of(
"Content-Type",
"User-Agent",
"Accept",
"Cache-Control",
"Postman-Token",
"Host",
"Accept-Encoding",
"Connection",
"Content-Length")
.stream()
.map(String::toUpperCase)
.collect(Collectors.toSet());
IGNORED_HEADERS = ImmutableSet.copyOf(ignoredHeaders);
}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
try {
filterChain.doFilter(requestWrapper, responseWrapper);
} finally {
try {
//构造请求的方法&URL&参数
StringBuilder sb = new StringBuilder("curl")
.append(" -X ").append(request.getMethod())
.append(" ").append(request.getRequestURL().toString());
if (StringUtils.hasLength(request.getQueryString())) {
sb.append("?").append(request.getQueryString());
}
//构造header
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
if (!IGNORED_HEADERS.contains(headerName.toUpperCase())) {
sb.append(" -H '").append(headerName).append(": ").append(request.getHeader(headerName)).append("'");
}
}
//获取body
String body = new String(requestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
if (StringUtils.hasLength(body)) {
sb.append(" -d '").append(body).append("'");
}
//输出到input
ActiveSpan.tag("input", sb.toString());
//获取返回值body
String responseBody = new String(responseWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
//输出到output
ActiveSpan.tag("output", responseBody);
} catch (Exception e) {
log.warn("fail to build http log", e);
} finally {
responseWrapper.copyBodyToResponse();
}
}
}
}
6.skywalking整合logback
pom依赖
org.apache.skywalking
apm-toolkit-logback-1.x
logback-spring.xml,区分环境
${pattern}
true
info
${log.home}/default.log
${log.home}/%d{yyyy-MM-dd}/default-%i.log.gz
7
5GB
128 MB
${pattern}
true
error
ACCEPT
DENY
${log.home}/error.log
${log.home}/error.log.%d{yyyy-MM-dd}
7
${pattern}
-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint}%clr(${LOG_LEVEL_PATTERN:-%5p})
%clr(${PID:- }){magenta} [%tid] %clr(---){faint}%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan}
%clr(:){faint}%m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n