大促之前全链路压测监控篇

skywalking服务监控

skywalking简介

Skywalking 是一个APM系统,即应用性能监控系统,为微服务架构和云原生架构系统设计。它通过探针自动收集所需的指标,并进行分布式追踪。通过这些调用链路以及指标,Skywalking APM会感知应用间关系和服务间关系,并进行相应的指标统计。目前支持链路追踪和监控应用组件如下,基本涵盖主流框架和容器,如国产PRC Dubbo和motan等,国际化的spring boot,spring cloud都支持了
SkyWalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器
(Docker、K8S、Mesos)架构而设计
SkyWalking是观察性分析平台和应用性能管理系统。提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案
SkyWalking组件

  • Skywalking Agent: 采集 tracing (调用链数据)和 metric (指标)信息并上报,上报通过HTTP或者gRPC方式发送数据到Skywalking Collector
  • Skywalking Collector : 链路数据收集器,对agent传过来的 tracing 和 metric 数据进行整合分析通过 Analysis Core 模块处理并落入相关的数据存储中,同时会通过 Query Core 模块进行二次统计和监控告警
  • Storage: Skywalking的存储,支持以 ElasticSearch 、 Mysql 、 TiDB 、 H2等作为存储介质进行数据存储
  • UI: Web可视化平台,用来展示落地的数据,目前官方采纳了RocketBot作为SkyWalking的主UI

配置SkyWalking

下载SkyWalking
下载SkyWalking的压缩包,解压后将压缩包里面的agent文件夹放进本地磁盘,探针包含整个目录,请不要改变目录结构。
Agent配置
通过了解配置,可以对一个组件功能有一个大致的了解,解压开skywalking的压缩包,在
agent/config文件夹中可以看到agent的配置文件,从skywalking支持环境变量配置加载,在启动的时候优先读取环境变量中的相关配置。
在这里插入图片描述
skywalking agent使用javaagent无侵入式的配合collector实现对分布式系统的追踪和相关数据的上下文传递。
配置探针
配置SpringBoot启动参数,需要填写如下的运行参数,代码放在后面,需要的自己粘贴。

-javaagent:D:/apache-skywalking-apm-bin/agent/skywalking-agent.jar 
-Dskywalking.agent.service_name=storage-server

在这里插入图片描述

  • javaagent:复制的agent目录下探针的jar包路径
  • skywalking.agent.service_name:需要在skywalking显示的服务名称
  • skywalking.collector.backend_service:skywalking服务端地址默认是11800

Arthas服务诊断

在这里插入图片描述

Arthas是什么

Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。
Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

Arthas能做什么

当你遇到以下类似问题而束手无策时, Arthas 可以帮助你解决:

在这里插入图片描述
Arthas 采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

安装使用

快速安装
下载 arthas-boot.jar ,然后用 java -jar 的方式启动

curl -O https://arthas.aliyun.com/arthas-boot.jar 
java -jar arthas-boot.jar

在这里插入图片描述
启动arthas
在命令行下面执行(使用和目标进程一致的用户启动,否则可能attach失败):

java -jar arthas-boot.jar
  • 执行该程序的用户需要和目标进程具有相同的权限。比如以 admin 用户来执行: sudo su admin && java -jar arthas-boot.jar 或 sudo -u admin -EH java -jar arthas-boot.jar 。
  • 如果attach不上目标进程,可以查看 ~/logs/arthas/ 目录下的日志。
  • 如果下载速度比较慢,可以使用aliyun的镜像: java -jar arthas-boot.jar --repo-mirror
    aliyun --use-http
  • java -jar arthas-boot.jar -h 打印更多参数信息。

选择java进程
在打印的java进程中选择一个需要 attach 的进程,我们在这里选择 4 这个order-service的java进程
在这里插入图片描述
命令列表
在这里插入图片描述

线程命令

dashboard指令

当前系统的实时数据面板,按 ctrl+c 退出。
当运行在服务时,会显示当前服务的实时信息,如HTTP请求的qps, rt, 错误数, 线程池信息等等。
参数说明
在这里插入图片描述
使用
在Arthas中输入 dashboard 命令会得到如下界面

dashboard

在这里插入图片描述
线程参数解释

  • ID: Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应。
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的cpu使用率。比如采样间隔1000ms,某个线程的增量cpu时间为100ms,则cpu使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量CPU时间,数据格式为 秒
  • TIME: 线程运行总CPU时间,数据格式为 分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是daemon线程
thread相关指令

查看当前线程信息,查看线程的堆栈
参数说明
在这里插入图片描述
cpu使用率如何统计
这里的cpu使用率与linux 命令 top -H -p 的线程 %CPU 类似,一段采样间隔时间内,当前JVM里各个线程的增量cpu时间与采样间隔时间的比例。

工作原理

  • 首先第一次采样,获取所有线程的CPU时间(调用的是java.lang.management.ThreadMXBean#getThreadCpuTime()及 sun.management.HotspotThreadMBean.getInternalThreadCpuTimes() 接口)
  • 然后睡眠等待一个间隔时间(默认为200ms,可以通过 -i 指定间隔时间)
  • 再次第二次采样,获取所有线程的CPU时间,对比两次采样数据,计算出每个线程的增量CPU时间 线程CPU使用率 = 线程增量CPU时间 /采样间隔时间 * 100%

注意: 这个统计也会产生一定的开销(JDK这个接口本身开销比较大),因此会看到 as 的线程占用一定的百分比,为了降低统计自身的开销带来的影响,可以把采样间隔拉长一些,比如5000毫秒

JVM内部线程
Java 8之后支持获取JVM内部线程CPU时间,这些线程只有名称和CPU时间,没有ID及状态等信息(显示ID为-1)。 通过内部线程可以观测到JVM活动,如GC、JIT编译等占用CPU情况,方便了解JVM整体运行状况。

  • 当JVM 堆(heap)/元数据(metaspace)空间不足或OOM时,可以看到GC线程的CPU占用率明显高于其他的线程。
  • 当执行 trace/watch/tt/redefine 等命令后,可以看到 JIT 线程活动变得更频繁。因为JVM热更 新class字节码时清除了此class相关的 JIT 编译结果,需要重新编译。

JVM内部线程包括下面几种:

  • JIT编译线程: 如 C1 CompilerThread0 , C2 CompilerThread0
  • GC线程: 如 GC Thread0 , G1 Young RemSet Sampling
  • 其它内部线程: 如 VM Periodic Task Thread , VM Thread , Service Thread
显示线程列表

输入thread 列出来线程列表,默认按照CPU增量时间降序排列,只显示第一页数据。

thread

在这里插入图片描述
显示所有线程
显示所有匹配线程信息,有时需要获取全部JVM的线程数据进行分析。

thread -all

在这里插入图片描述
打印线程堆栈
通过 thread id 命令, 显示指定线程的运行堆栈,我们看下 139 这个线程的堆栈信息

thread 139

这样可以打印出来线程139的堆栈以及调用关系
在这里插入图片描述
排查死锁
找出当前阻塞其他线程的线程
有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了 thread -b , 一键找出那个罪魁祸首。

thread -b

发现当前没有发现阻塞其他线程的线程

虚拟机命令

jvm相关指令

查看当前JVM信息
查看JVM信息
jvm 命令可以打印出当前微服务jvm相关的参数

jvm

在这里插入图片描述
Thread相关
在这里插入图片描述
参数解释

  • COUNT: JVM当前活跃的线程数
  • DAEMON-COUNT: JVM当前活跃的守护线程数
  • PEAK-COUNT: 从JVM启动开始曾经活着的最大线程数
  • STARTED-COUNT: 从JVM启动开始总共启动过的线程次数
  • DEADLOCK-COUNT: JVM当前死锁的线程数
JVM选项指令

查看,更新VM诊断相关的参数

查看相关选项
通过该命令可以看到当前jvm的一些参数选项

vmoption

在这里插入图片描述
查看指定选项
这里我们查看是否打开了 PrintGCDetails

vmoption PrintGCDetails

在这里插入图片描述
更新选项
我们可以使用arthas对jvm的选项进行更新,这里我们开启 PrintGCDetails

vmoption PrintGCDetails true

在这里插入图片描述

类相关命令

搜索相关类
查看JVM已加载的类信息,SC是“Search-Class” 的简写,这个命令能搜索出所有已经加载到 JVM中的 Class 信息
参数说明
在这里插入图片描述
class-pattern支持全限定名,如com.黑马.test.AAA,也支持com/黑马/test/AAA这样的格式,这样,我们从异常堆栈里面把类名拷贝过来的时候,不需要在手动把 / 替换为 . 。
sc 默认开启了子类匹配功能,也就是说所有当前类的子类也会被搜索出来,想要精确的匹配,请打开 options disable-sub-class true 开关
模糊搜索
该命令可以搜索 com.heima.fulllink 下面的包以及子包的类

sc com.heima.fulllink.*

在这里插入图片描述
打印类的详细信息
可以使用 -d 参数打印 类的详细信息

sc -d com.heima.fulllink.module.po.OrderPO

在这里插入图片描述
打印出类的Field信息
该命令可以打印类中字段信息,可以看到各种字段的介绍

sc -d -f com.heima.fulllink.module.po.OrderPO

在这里插入图片描述
搜索相关方法
sm是“Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
sm 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
参数说明
在这里插入图片描述
查看类的方法
查看 com.heima.fullink.service.impl.AsyncOrderServiceImpl 类的相关方法

sm com.heima.fullink.service.impl.AsyncOrderServiceImpl

可以看到该方法有两个方法actualPlaceOrder以及processOrder在这里插入图片描述
查看方法信息
通过 -d 可以看到方法的详细信息

sm -d com.heima.fullink.service.impl.AsyncOrderServiceImpl

我们发现通过-d参数可以看到方法的详细信息
在这里插入图片描述
查看具体方法信息
我们可以在类名后面加入方法名称就可以查看具体的方法详情

sm -d com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder

在这里插入图片描述
反编译
jad 命令将 JVM 中实际运行的 class 的 byte code 反编译成 java 代码,便于你理解业务逻辑;

  • 在 Arthas Console 上,反编译出来的源码是带语法高亮的,阅读更方便
  • 当然,反编译出来的 java 代码可能会存在语法错误,但不影响你进行阅读理解

参数说明
在这里插入图片描述
反编译类
可以将jvm内存中的类进行反编译

jad com.heima.fullink.service.impl.AsyncOrderServiceImpl

反编译后信息比较全面,有类加载等信息
在这里插入图片描述
只显示源代码
默认情况下,反编译结果里会带有 ClassLoader 信息,通过 --source-only 选项,可以只打印源代码。

jad --source-only com.heima.fullink.service.impl.AsyncOrderServiceImpl

我们发现通过 --source-only 后就没有了类加载等信息
在这里插入图片描述
反编译指定的方法
有时候我们可以反编译类中的指定方法

jad --source-only com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder

这样只会反编译对应的方法的代码
在这里插入图片描述
不显示行号
有时候我们不需要打印行号,可以使用 --lineNumber 参数来设置是否显示行号,默认值为true,显示指定为false则不打印行号

jad --source-only com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder --lineNumber false

通过这种方式我们可以不显示具体行号
在这里插入图片描述

监控相关命令

方法执行监控

monitor 命令是一个非实时返回命令,对匹配 class-pattern / method-pattern / condition-express 的类、方法的调用进行监控。
实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止。
服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何Arthas命令不会引起原有业务逻辑的改变。

监控的维度说明

在这里插入图片描述
参数说明
方法拥有一个命名参数 [c:] ,意思是统计周期(cycle of output),拥有一个整型的参数值在这里插入图片描述

打印方法调用
monitor -c 20 com.heima.fullink.service.impl.AsyncOrderServiceImpl 
actualPlaceOrder

这样每隔20秒打印一次 actualPlaceOrder 方法的调用信息
在这里插入图片描述
查看方法参数
watch 让你能方便的观察到指定方法的调用情况。能观察到的范围为: 返回值 、 抛出异常 、 入 参 ,通过编写 OGNL 表达式进行对应变量的查看。
参数说明
watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象
在这里插入图片描述
观察表达式
这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写 " {params,returnObj}" ,只要是一个合法的 ognl 表达式,都能被正常支持。
使用说明

  • watch 命令定义了4个观察事件点,即 -b 方法调用前, -e 方法异常后, -s 方法返回后, -f 方法结束后
  • 4个观察事件点 -b 、 -e 、 -s 默认关闭, -f 默认打开,当指定观察点被打开后,在相应事件点会 对观察表达式进行求值并输出
  • 这里要注意 方法入参 和 方法出参 的区别,有可能在中间被修改导致前后不一致,除了 -b 事件点 params代表方法入参外,其余事件都代表方法出参
  • 当使用 -b 时,由于观察事件点是在方法调用前,此时返回值或异常均不存在

方法调用前
通过该命令我们可以查看到方法调用前的 actualPlaceOrder 方法第一个参数的入参信息

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " 
{params[0],returnObj}" -b 

在这里插入图片描述
我们看到入参是对象,但是看不到对象的具体数据,我们可以使用 -x 表示遍历深度,可以调整来打印具体的参数和结果内容,默认值是1

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " {params[0],returnObj}" -x 2 -b

我们将遍历的深度设置为两层,这样我们就可以看到对象里面的属性在这里插入图片描述
方法调用后
通过该命令我们可以查看到方法调用后的 actualPlaceOrder 方法第一个参数的入参信息和返回值

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " {params[0],returnObj}" -x 2

在这里插入图片描述
我们发现在方法返回调用后监控参数获取到了方法的返回结果
方法调用前后
有时候我们需要查看方法执行前后的结果信息,我们可以使用如下的形式查看

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " {params[0],returnObj}" -x 2 -b -s -n 2

这样我们可以查看方法的执行前后的参数信息
在这里插入图片描述

  • 参数里 -n 2 ,表示只执行两次
  • 这里输出结果中,第一次输出的是方法调用前的观察表达式的结果,第二次输出的是方法返回后的 表达式的结果
  • 结果的输出顺序和事件发生的先后顺序一致,和命令中 -s -b 的顺序无关

条件表达式
查看参数还支持查看满足特定条件后才会打印参数

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " {params[0],returnObj}" "params[0].amount>100" -x 2

只有满足 amount 参数大于100的数据才会打印参数信息
在这里插入图片描述
查看耗时慢的参数
有时候我们需要查看因为那些参数导致服务速度慢,可以使用如下的形式

watch com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder " {params[0],returnObj}" "#cost>50" -x 2

这样只有方法调用耗时大于50ms的方法才会打印参数信息
在这里插入图片描述

链路追踪

方法内部调用路径,并输出方法路径上的每个节点上耗时
trace 命令能主动搜索 class-pattern / method-pattern 对应的方法调用路径,渲染和统计整
个调用链路上的所有性能开销和追踪调用链路。

参数说明
在这里插入图片描述
跟踪方法
能够跟踪方法的调用链信息,并且可以打印方法调用耗时

trace com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder

在这里插入图片描述
限制次数
如果方法调用的次数很多,那么可以用 -n 参数指定捕捉结果的次数。比如下面的例子里,捕捉到一次调用就退出命令。

trace com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder -n 1

在这里插入图片描述
根据耗时过滤
有时候我们只要查看耗时时间长的调用的方法,我们可以使用如下方式

trace com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder '#cost > 80' -n 1

只会展示耗时大于80ms的调用路径,有助于在排查问题的时候,只关注异常情况
在这里插入图片描述

调用路径

输出当前方法被调用的调用路径
很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。
参数说明
在这里插入图片描述
查看方法调用

stack com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder

这样就可以看到 actualPlaceOrder 是从什么地方调用过来的
在这里插入图片描述
根据条件过滤
有时候我们只需要看特定条件的的调用路径,可以使用如下形式

stack com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder "params[0].amount>100" -n 1

我们只需要打印金额大于100的调用链,并且只需要打印一次
在这里插入图片描述
根据耗时过滤
有时候我们只需要过滤耗时长的调用路径,可以使用如下的形式

stack com.heima.fullink.service.impl.AsyncOrderServiceImpl actualPlaceOrder '#cost > 80' -n 1

只打印耗时大于80ms的方法调用路径
在这里插入图片描述

生成火焰图

profiler 命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。
参数说明
在这里插入图片描述
启动profile
默认情况下,生成的是cpu的火焰图,即event为 cpu 。可以用 --event 参数来指定

profiler start

在这里插入图片描述
进行服务压测
在这里插入图片描述
查看profiler状态
可以查看当前profiler在采样哪种 event 和采样时间。

profiler status

在这里插入图片描述
停止profiler

profiler stop

停止后会自动生成svg格式的文件
在这里插入图片描述
默认情况下,生成的结果保存到应用的 工作目录 下的 arthas-output 目录。可以通过 --file 参数来指定输出结果路径。比如:

profiler stop --file /tmp/output.svg

在这里插入图片描述
生成html格式结果
默认情况下,结果文件是 svg 格式,如果想生成 html 格式,可以用 --format 参数指定:

profiler stop --format html

在这里插入图片描述
或者在 --file 参数里用文件名指名格式。比如 --file /tmp/result.html

查看结果
通过浏览器查看arthas-output下面的profiler结果,默认情况下,arthas使用3658端口,但是一般不允许外部IP访问,我们可以下载到本地查看
在这里插入图片描述

生产环境部署服务

环境服务列表

需要在虚拟机或者linux服务器启动运行环境
在这里插入图片描述
应用服务列表
应用服务可以单独部署或者在idea中启动
在这里插入图片描述
docker-compose 编排环境
我们的docker-compose只对环境进行了搭建,具体微服务在本地运行或者在容器运行都可以。

version: '2'
services:
    mysql:
        image: mysql:5.7
        hostname: mysql
        container_name: mysql
        ports:
            - "3306:3306"
        environment:
            MYSQL_ROOT_PASSWORD: 123456
        volumes:
            - "/opt/full-link-pressure/etc/mysql:/etc/mysql/conf.d"
            - "/opt/full-link-pressure/data/mysql:/var/lib/mysql"
    rabbitMQ:
        image: rabbitmq:management
        hostname: rabbitMQ
        container_name: rabbitMQ
        ports:
            - "5672:5672"
            - "15672:15672"
    redis:
        image: redis
        hostname: redis
        container_name: redis
        ports:
            - "6379:6379"
        volumes:
            - "/opt/full-link-pressure/etc/redis/redis.conf:/etc/redis/redis.conf"
            - "/opt/full-link-pressure/data/redis:/data"
        command:
           redis-server /etc/redis/redis.conf
    nacos:
        image: nacos/nacos-server
        hostname: nacos
        container_name: nacos
        depends_on:
            - mysql
        ports:
           - "8848:8848"
        environment:
            MODE: standalone
            MYSQL_SERVICE_HOST: mysql
            MYSQL_SERVICE_PORT: 3306
            MYSQL_SERVICE_DB_NAME: nacos_config
            MYSQL_SERVICE_USER: root
            MYSQL_SERVICE_PASSWORD: 123456
    skywalking:
        image: apache/skywalking-oap-server:8.5.0-es7
        hostname: skywalking
        container_name: skywalking
        ports:
           - "1234:1234"
           - "11800:11800"
           - "12800:12800"
    skywalkingui:
        image: apache/skywalking-ui
        hostname: skywalkingui
        container_name: skywalkingui
        depends_on:
            - skywalking
        environment:
            SW_OAP_ADDRESS: http://skywalking:12800
        ports:
           - "8080:8080"

初始化数据

  1. 初始化用户数据以及产品数据
    nacous-config
CREATE SCHEMA nacos_config;
USE nacos_config;

CREATE USER 'nacos_user'@'%' IDENTIFIED BY 'pwd4nacos';
GRANT ALL privileges ON `nacos_config`.* TO `nacos_user`@'%';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info   */
/******************************************/
CREATE TABLE `config_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) DEFAULT NULL,
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  `c_desc` varchar(256) DEFAULT NULL,
  `c_use` varchar(64) DEFAULT NULL,
  `effect` varchar(64) DEFAULT NULL,
  `type` varchar(64) DEFAULT NULL,
  `c_schema` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info 存放配置文件内容';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_aggr   */
/******************************************/
CREATE TABLE `config_info_aggr` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(255) NOT NULL COMMENT 'group_id',
  `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
  `content` longtext NOT NULL COMMENT '内容',
  `gmt_modified` datetime NOT NULL COMMENT '修改时间',
  `app_name` varchar(128) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_beta   */
/******************************************/
CREATE TABLE `config_info_beta` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_info_tag   */
/******************************************/
CREATE TABLE `config_info_tag` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL COMMENT 'content',
  `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  `src_user` text COMMENT 'source user',
  `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = config_tags_relation   */
/******************************************/
CREATE TABLE `config_tags_relation` (
  `id` bigint(20) NOT NULL COMMENT 'id',
  `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
  `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
  `data_id` varchar(255) NOT NULL COMMENT 'data_id',
  `group_id` varchar(128) NOT NULL COMMENT 'group_id',
  `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
  `nid` bigint(20) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`nid`),
  UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = group_capacity   */
/******************************************/
CREATE TABLE `group_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';

/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = his_config_info   */
/******************************************/
CREATE TABLE `his_config_info` (
  `id` bigint(64) unsigned NOT NULL,
  `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `data_id` varchar(255) NOT NULL,
  `group_id` varchar(128) NOT NULL,
  `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
  `content` longtext NOT NULL,
  `md5` varchar(32) DEFAULT NULL,
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00',
  `src_user` text,
  `src_ip` varchar(20) DEFAULT NULL,
  `op_type` char(10) DEFAULT NULL,
  `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
  PRIMARY KEY (`nid`),
  KEY `idx_gmt_create` (`gmt_create`),
  KEY `idx_gmt_modified` (`gmt_modified`),
  KEY `idx_did` (`data_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';


/******************************************/
/*   数据库全名 = nacos_config   */
/*   表名称 = tenant_capacity   */
/******************************************/
CREATE TABLE `tenant_capacity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
  `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
  `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
  `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
  `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
  `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
  `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
  `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';


CREATE TABLE `tenant_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `kp` varchar(128) NOT NULL COMMENT 'kp',
  `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
  `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
  `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
  `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
  `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
  KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info 命名空间';

CREATE TABLE users (
	username varchar(50) NOT NULL PRIMARY KEY,
	password varchar(500) NOT NULL,
	enabled boolean NOT NULL
);

CREATE TABLE roles (
	username varchar(50) NOT NULL,
	role varchar(50) NOT NULL
);

INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
  1. 将feign,hystrix,ribbon等统一配置配置到nacos
# 配置超时时间
feign:
  hystrix:
    enabled: true  #开启熔断
  httpclient:
    enabled: true
hystrix:
  threadpool:
    default:
      coreSize: 50
      maxQueueSize: 1500
      queueSizeRejectionThreshold: 1000
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 60000
ribbon:
  ConnectTimeout: 10000
  ReadTimeout: 50000

准备工作

安装Agent
将部署在本地的agent复制到 centos 主机中
在这里插入图片描述
打包微服务
将微服务打包并上传到centos中
在这里插入图片描述
打包后并上传到centos中去
在这里插入图片描述
配置启动脚本
编写启动脚本
在启动脚本中加入对于jvm内存的限制以及对 skywalking 的配置

vi start.sh
#!/bin/bash

# 启动account-service
nohup java -jar account-service-1.0-SNAPSHOT.jar -Xms128m -Xmx128m -javaagent:/opt/full-link-pressure/agent/skywalking-agent.jar -Dskywalking.agent.service_name=Account-server > logs/account-service.out 2>&1 &

# 启动storage-service
nohup java -jar storage-service-1.0-SNAPSHOT.jar -Xms128m -Xmx128m -javaagent:/opt/full-link-pressure/agent/skywalking-agent.jar -Dskywalking.agent.service_name=storage-service > logs/storage-service.out 2>&1 &

# 启动order-service
nohup java -jar   order-service-1.0-SNAPSHOT.jar -Xms128m -Xmx128m -javaagent:/opt/full-link-pressure/agent/skywalking-agent.jar -Dskywalking.agent.service_name=order-service >   logs/order-service.out 2>&1 &

# 启动notice-service
nohup java -jar  notice-service-1.0-SNAPSHOT.jar -Xms128m -Xmx128m -javaagent:/opt/full-link-pressure/agent/skywalking-agent.jar -Dskywalking.agent.service_name=notice-service >  logs/notice-service.out 2>&1 &

# 启动gateway-server
nohup java -jar  gateway-server-1.0-SNAPSHOT.jar -Xms128m -Xmx128m -javaagent:/opt/full-link-pressure/agent/skywalking-agent.jar -Dskywalking.agent.service_name=gateway-server >  logs/gateway-server.out 2>&1 &

在这里插入图片描述

创建一个log目录

mkdir logs
chmod 755 start.sh

完整结构如下
在这里插入图片描述
配置数据库访问权限
需要配置数据库的外网访问权限

GRANT ALL PRIVILEGES ON fulllink.* TO 'root'@'%' IDENTIFIED BY '123456'; 
GRANT ALL PRIVILEGES ON `fulllink-shadow`.* TO 'root'@'%' IDENTIFIED BY 
'123456'; 
FLUSH PRIVILEGES; 

启动微服务

执行启动脚本

# 启动微服务集群 
./start.sh 
# 查看java进程 
ps -ef|grep java

在这里插入图片描述
nacos查看注册列表
访问 http://192.168.10.30:8848/nacos 进入nacos注册列表
在这里插入图片描述
我们发现服务都已经注册了

测试接口
使用postman测试服务接口是否正常,我们访问发现是可以正常访问的
在这里插入图片描述
查看skyworking

压测调优

jmeter配置
配置好压测数据,并且配置压测线程数1000 进行10轮压测
在这里插入图片描述

第一轮压测

链路分析优化
我们找到一个调用时长1S左右的链路,分析发现在存储服务调用时,耗时较长,但是数据库调用耗时并不长,基本说明是存储服务的连接池耗尽导致调用过长
在这里插入图片描述
数据库连接池优化
调整存储服务的连接池,由原来的最大10 改为100

initialSize: 10 
minIdle: 20 
maxActive: 100

查看JVM内存
我们发现jvm中的老年代并没有太大的变化,说明我们的JVM不需要怎么优化
在这里插入图片描述
并且我们发现我们的eden区每隔一段时间就会垃圾回收一次,并且很少有晋升到老年代的情况
在这里插入图片描述

第二轮压测

结果已经由原来的服务内部的耗时 变为了fegin的耗时,这种情况下可以考虑使用fegin的连接池优化或者新增节点
在这里插入图片描述
观察消费节点
发现消费速度很慢,产生了大量消息堆积
在这里插入图片描述
发现平均响应时间在200ms左右
在这里插入图片描述
检查断点链路 /storage/order/actualPlaceOrder
发现是事务提交慢造成的,这个时候就需要优化mysql服务器了
在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐