【SkyWalking】分布式服务追踪与调用链系统

1、基本介绍

SkyWalking是一个开源的观测平台,官网:Apache SkyWalking

可监控:分布式追踪调用链 、jvm内存变化、监控报警、查看服务器基本配置信息。

2、SkyWalking架构原理

在整个skywalking的系统中,有三个角色:
1.skywalking agent 和业务系统(jar)关联在一起,负责收集各种监控数据;
2.skywalking oapservice负责处理监控数据,比如接受skywalking agent的监控数据,并存储在数据库中(例如elasticsearch、mysql中等);接受skywalking webapp的前端请求,从数据库查询数据,并返回数据给前端。,Skywalking oapservice通常以集群的形式存在;
3.skywalking webapp 前端界面,用于展示数据。

2.1、skywalking 底层原理流程

1.springboot项目启动的时候 是不需要引入任何的jar包,

2.启动springboot项目时被skywalking skywalking-agent.jar 代理拦截

        -- agent代理拦截是jdk提供的一种技术;可以使启动jar包时不需要引入任何依赖,agent就可以对java程序做业务增强,类似AOP技术,但是比AOP级别更高,agent属于监控整个java进程。

3.将rpc请求数据 发送给我们的skywalking oapservice接口项目,

4.连接到我们的skywalking webapp项目展示数据,

5.数据最终是可以持久化存放在 db或者es中。

        -- SkyWalking 默认是将数据存入在内存中,如果重启SkyWalking 数据则都会丢失。

3、skywalking 环境安装

1. 下载apache-skywalking-apm-6.5.0.tar安装包,下载链接:百度网盘 skywalking.tar  

1.1. 下载数据库链接:百度网盘 mysql-connector-java-8.0.16.jar  后续做数据持久化会用到。

2. 进入到bin目录(Windows直接双击启动startup.bat / Linix则执行startup.sh

    注:启动startup.bat = 同时启动oapService.bat 和 webappService.bat

3. 查看webapp管理界面 http://127.0.0.1:8080

4、skywalking-agent监控springboot.jar包

1. 创建一个springboot项目,并打成jar包

2. 启动springboot.jar包时指定agent目录下的skywalking-agent.jar,注意skywalking-agent.jar要写绝对路径

启动jar包命令: java -javaagent:skywalking-agent.jar -jar springboot.jar

 启动jar包命令,同时设置服务名称为server-member: 

java -javaagent:skywalking-agent.jar 

-Dskywalking.agent.service_name=server-member  -jar springboot.jar

4、测试访问几次接口,然后去SkyWalking控制台 http://127.0.0.1:8080/ 查看效果。

4.1、如何在IDEA中使用skywalking

IDEA启动配置:

-javaagent:D:\java\dev-tool\skywalking\apache-skywalking-apm-6.5.0\apache-skywalking-apm-bin\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=server-member
-Dskywalking.collector.backend_service=127.0.0.1:11800

IDEA启动服务后,调用接口,然后进入WEB页面查看效果:

5、SkyWalking获取全局追踪id

        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-trace</artifactId>
            <version>6.5.0</version>
        </dependency>

获取 TraceContext.traceId();


    @RequestMapping("/member")
    public String orderToMember(@RequestParam("id") Integer id) {
        // 获取request对象
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        getHeders(request);
        // 获取traceId
        String traceId = TraceContext.traceId();
        log.info(">>traceId:{}<<", traceId);
        Integer j = 1 / id;
        return "我是会员服务:" + traceId + "," + j;
    }

    public static void getHeders(HttpServletRequest request) {
        //2.获得所有头的名称
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {//判断是否还有下一个元素
            String nextElement = headerNames.nextElement();//获取headerNames集合中的请求头
            String header2 = request.getHeader(nextElement);//通过请求头得到请求内容
            log.info("请求头=========={}" + nextElement + "VALUE:" + header2);
            //System.out.println(nextElement+":"+header2);
        }
    }

6、SkyWalking告警功能

SkyWalking 告警功能是在6.x版本新增的,其核心由一组规则驱动,这些规则定义在SkyWalking目录的config/alarm-settings.yml文件中。

SkyWalking告警后会调用开发者自己定义的接口,

注:自定义的接口地址配置到alarm-settings.yml的webhooks下,当SkyWalking产生告警后会调用webhooks下的URL地址传入告警信息;

alarm-settings.yml文件预先定义了一些常用的告警规则。如下:

1.过去3分钟内服务平均响应时间超过1秒

2.服务成功率在过去2分钟内低于80%

3.服务90%响应时间在过去3分钟内低于1000毫秒

4.服务实例在过去2分钟内的平均响应时间超过1秒

5.端点平均响应时间过去2分钟超过1秒

6.1、自定义告警接口接收数据格式

[{
    "scopeId": 1,
    "scope": "SERVICE",
    "name": "serviceA",
    "id0": 12,
    "id1": 0,
    "ruleName": "service_resp_time_rule",
    "alarmMessage": "alarmMessage xxxx",
    "startTime": 1560524171000
}, {
    "scopeId": 1,
    "scope": "SERVICE",
    "name": "serviceB",
    "id0": 23,
    "id1": 0,
    "ruleName": "service_resp_time_rule",
    "alarmMessage": "alarmMessage yyy",
    "startTime": 1560524171000
}]

scopeId、scope:所有可用的 Scope 详见

org.apache.skywalking.oap.server.core.source.DefaultScopeDefine

name:目标 Scope 的实体名称

id0:Scope 实体的 ID

id1:保留字段,目前暂未使用

ruleName:告警规则名称

alarmMessage:告警消息内容

startTime:告警时间,格式为时间戳

6.2、 编写告警接口

6.2.1、封装报警参数的对象

/**
 * 封装报警参数的对象
 */

public class AlarmMessageDto {
    private int scopeId;
    private String name;
    private int id0;
    private int id1;
    private String alarmMessage;
    private long startTime;

    public int getScopeId() {
        return scopeId;
    }

    public String getName() {
        return name;
    }

    public int getId0() {
        return id0;
    }

    public int getId1() {
        return id1;
    }

    public String getAlarmMessage() {
        return alarmMessage;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setScopeId(int scopeId) {
        this.scopeId = scopeId;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId0(int id0) {
        this.id0 = id0;
    }

    public void setId1(int id1) {
        this.id1 = id1;
    }

    public void setAlarmMessage(String alarmMessage) {
        this.alarmMessage = alarmMessage;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
}

6.2.2、提供报警接口

import com.mayikt.entity.AlarmMessageDto;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 报警接口
 */
@RestController
public class PoliceService {

    private List<List<AlarmMessageDto>> listAlarmMessage = new ArrayList<>();

    /**
     * 接收告警信息
     *
     * @param alarmMessageList
     */
    @RequestMapping(value = "/police", method = RequestMethod.POST)
    public void alarm(@RequestBody List<AlarmMessageDto> alarmMessageList) {
        listAlarmMessage.add(alarmMessageList);
    }

    /**
     * 打印告警信息
     *
     * @return
     */
    @RequestMapping("/getListAlarmMessageDto")
    public List<List<AlarmMessageDto>> getListAlarmMessageDto() {
        return listAlarmMessage;
    }

}

7、SkyWalking数据持久化

SkyWalking 默认是将数据存入在内存中,如果重启SkyWalking 数据则都会丢失。

我们可以选择将数据持久化存放在mysql、es中等。

1、打开SkyWalking目录config/application.yml,在里边配置Mysql的连接信息;

storage:
  selector: ${SW_STORAGE:mysql} #默认使用的H2数据库存储,将h2改为mysql
  mysql: #修改mysql连接 IP端口号,数据库
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest?serverTimezone=UTC&characterEncoding=utf-8"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root@1234}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}

2、在oap-libs/目录中放入 mysql-connector-java-8.0.16.jar 

百度网盘 点击下载

3、重启SkyWalking,会自动在配置的Mysql库中创建依赖的表结构。

 

猜你喜欢

转载自blog.csdn.net/qq_36881887/article/details/127633041