链路追踪-调用链跟踪-Jaeger

文章目录

    • 一、什么是链路跟踪
    • 二、OpenCensus
      • OpenCensus 主要特点
      • OpenTracing标准
      • 基本概念
        • Span
    • 三、典型服务端产品
      • 什么是OpenTracing?
      • opentracing 使用介绍
    • 四、Jaeger
      • Jaeger 包含的模块
      • Jaeger-client(客户端库)
    • 五、Jaeger服务容器化部署
      • 过程问题整理
    • 六、Jaeger客户端 java代码测试验证
    • 七、Jaeger客户端 go代码测试验证

一、什么是链路跟踪

在微服务为我们提供了模块分,低耦合的高效开发和DevOPS中,具体业务中当一个请求中,请求了多个服务单元,如果请求出现了错误或异常,很难去定位是哪个服务出了问题,这时就需要链路追踪。可能你会想在业务系统中请求中埋点,或写日志,但是这种都需要在业务代码中来写,而且耦合在代码中,不具备微服务的扩张性后后期的易维护行。

链路跟踪系统可以做很多事情,如下:

  • 故障快速定位
  • 各个调用环节的性能分析
  • 数据分析
  • 生成服务调用拓扑图
  • 调用请求量统计
  • 应用依赖分析

其中最主要的功能就是,可以帮助开发者快速分析和诊断分布式应用架构下的性能瓶颈,提高微服务时代下的开发诊断效率。

二、OpenCensus

官网 http://opencensus.io/
DevOps 漫谈:基于OpenCensus构建分布式跟踪系统
参考URL: https://www.jianshu.com/p/d6a2f124c766

由于各种分布式追踪系统层出不穷,且有着相似的API语法,但各种语言的开发人员依然很难将他们各自的系统和特定的分布式追踪系统进行整合。在这种情况下,OpenTracing规范出现了。

OpenCensus 是 Google 开源的一个用来收集和追踪应用程序指标中立厂商的第三方库。支持多个语言的lib库,但是不能展示。

**这个只是个数据收集的lib库,但是真正的数据展示要放到web系统当中。
其中 Zipkin, Prometheus, Jaeger 都可以展示这些数据。**其中 Prometheus Jaeger 是golang 写的。

OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。OpenTracing正在为全球的分布式追踪,提供统一的概念和数据标准。

OpenTracing 只是一种协议,是一种标准化。没有它,你的应用程序照样会玩的很好,只不过失去了和其他组件交流的能力。

每一次技术迭代都是对过去技术的抽象和升华。 OpenTracing 同样抽象出调用链必须的数据模型,只需要按照其标准,一个golang语言的程序和java语言的跨平台调用链就可以很容易的实现。

官网: http://opentracing.io/

OpenCensus 主要特点

  • 标准通信协议和一致的 API :用于处理 metric 和 trace
  • 多语言库,包括Java,C++,Go,.Net,Python,PHP,Node.js,Erlang 和 Ruby
  • 与 RPC 框架的集成,可以提供开箱即用的追踪和指标。
  • 集成的存储和分析工具
  • 完全开源,支持第三方集成和输出的插件化
  • 不需要额外的服务器或守护进程来支持 OpenCensus
  • In process debugging:一个可选的代理程序,用于在目标主机上显示请求和指标数据

OpenTracing标准

OpenTracing语义标准规范及实现
参考URL: https://blog.csdn.net/u013970991/article/details/77822060
分布式追踪系统 – Opentracing
参考URL: https://zhuanlan.zhihu.com/p/83654617
Tracing与Metrics的邂逅,提供更强大的APM能力
参考URL: https://www.jianshu.com/p/9824a9eee491

OpenTracing标准 描述的语言无关的数据模型,以及OpenTracing API的使用方法。在此数据模型中,包含了两个相关的概念 Span Tag 和 (结构化的) Log Field,尽管在标准中,已经明确了这些操作,但没有定义Span的tag和logging操作时,key的使用规范。

OpenTracing数据模型
OpenTracing中的Trace(调用链)通过归属于此调用链的Span来隐性的定义。
特别说明,一条Trace(调用链)可以被认为是一个由多个Span组成的有向无环图(DAG图), Span与Span的关系被命名为References。

Span,可以被翻译为跨度,可以被理解为一次方法调用, 一个程序块的调用, 或者一次RPC/数据库访问.只要是一个具有完整时间周期的程序访问,都可以被认为是一个span.

每个Span包含以下的状态:

  • An operation name,操作名称
  • A start timestamp,起始时间
  • A finish timestamp,结束时间
  • Span Tag,一组键值对构成的Span标签集合。键值对中,键必须为string,值可以是字符串,布尔,或者数字类型。
  • Span Log,一组span的日志集合。
    每次log操作包含一个键值对,以及一个时间戳。
    键值对中,键必须为string,值可以是任意类型。
    但是需要注意,不是所有的支持OpenTracing的Tracer,都需要支持所有的值类型。
  • SpanContext,Span上下文对象 (下面会详细说明)
  • References(Span间关系),相关的零个或者多个Span(Span间通过SpanContext建立这种关系)

OpenTracing API

  • Tracer
    Tracer接口用来创建Span,以及处理如何处理Inject(serialize) 和 Extract (deserialize),用于跨进程边界传递。它具有如下官方能力:
    创建一个新Span
    必填参数
    operation name, 操作名, 一个具有可读性的字符串,代表这个span所做的工作(例如:RPC方法名,方法名,或者一个大型计算中的某个阶段或子任务)。操作名应该是一个抽象、通用,明确、具有统计意义的名称。因此,“get_user” 作为操作名,比 "get_user/314159"更好。
    例如,假设一个获取账户信息的span会有如下可能的名称:

    操作名 指导意见
    get 太抽象
    get_account/792 太明确
    get_account 正确的操作名,关于account_id=792的信息应该使用Tag操作

  • Span
    当Span结束后(span.finish()),除了通过Span获取SpanContext外,下列其他所有方法都不允许被调用。
    不需要任何参数。

返回值,Span构建时传入的SpanContext。这个返回值在Span结束后(span.finish()),依然可以使用。

基本概念

Span

Span表示Jaeger中的逻辑工作单元,具有操作名称,操作的开始时间和持续时间。跨度可以嵌套并排序以建立因果关系模型。

在广义上,一个trace代表了一个事务或者流程在(分布式)系统中的执行过程。在OpenTracing标准中,trace是多个span组成的一个有向无环图(DAG),每一个span代表trace中被命名并计时的连续性的执行片段。

跟踪是通过系统的数据/执行路径,可以看作跨度的有向无环图。
在这里插入图片描述每个 Span 包含以下对象:

  • Operation name:操作名称 (也可以称作 Span name)。
  • Start timestamp:起始时间。
  • Finish timestamp:结束时间。
  • Span tag:一组键值对构成的 Span 标签集合。键值对中,键必须为 String,值可以是字符串、布尔或者数字类型。
  • Span log:一组 Span 的日志集合。每次 Log 操作包含一个键值对和一个时间戳。键值对中,键必须为 String,值可以是任意类型。
  • SpanContext: pan 上下文对象。每个 SpanContext 包含以下状态:
    • 要实现任何一个 OpenTracing,都需要依赖一个独特的 Span 去跨进程边界传输当前调用链的状态(例如:Trace 和 Span 的 ID)。
    • Baggage Items 是 Trace 的随行数据,是一个键值对集合,存在于 Trace 中,也需要跨进程边界传输。
  • References(Span 间关系):相关的零个或者多个 Span(Span 间通过 SpanContext 建立这种关系)。

Span 共有属性:

  • TraceId
  • SpanId
  • Start Time
  • End Time
  • Status

Span 可选属性:

  • Parent SpanId
  • Remote Parent
  • Attributes
  • Annotations
  • Message Events
  • Links

三、典型服务端产品

支持 OpenTracing 的开源产品可以在这里找到 : http://opentracing.io/documentation/pages/supported-tracers.html

典型的如 SpringCloud 集成的 Zipkin 。Jaeger 是 Uber 开发的一款调用链服务端产品,开发语言为 golang ,能够兼容接收 OpenTracing 格式的数据。根据其 发展历史 ,可以说是 Zipkin 的升级版。另外,其基于 udp (也可以 http )的传输协议,更加定位了其高效、迅速的特点。

因此,后面我们重点介绍 jaeger。

什么是OpenTracing?

OpenTracing语义标准规范及实现
参考URL: https://blog.csdn.net/u013970991/article/details/77822060
Go微服务全链路跟踪详解
参考URL: https://studygolang.com/articles/23528?fr=sidebar

现在有许多开源的分布式跟踪库可供选择,其中最受欢迎的库可能是Zipkin²和Jaeger³。 选择哪个是一个令人头疼的问题,因为你现在可以选择最受欢迎的一个,但是如果以后有一个更好的出现呢?OpenTracing⁴可以帮你解决这个问题。它建立了一套跟踪库的通用接口,这样你的程序只需要调用这些接口而不被具体的跟踪库绑定,将来可以切换到不同的跟踪库而无需更改代码。Zipkin和Jaeger都支持OpenTracing。

OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。OpenTracing正在为全球的分布式追踪,提供统一的概念和数据标准。

关于OpenTracing的一个Java版本的实现请参考如下代码:
https://github.com/opentracing/opentracing-java

opentracing 使用介绍

opentracing 使用介绍
参考URL: https://www.colabug.com/2017/1031/1788712/

四、Jaeger

Jaeger-分布式调用链跟踪系统理论与实战
参考URL: https://blog.csdn.net/zuiyijiangnan/article/details/103836060
对接Jaeger
参考URL: https://help.aliyun.com/document_detail/68035.html

Jaeger 是 Uber 开发的一款调用链服务端产品,开发语言为 golang ,能够兼容接收 OpenTracing 格式的数据。根据其 发展历史 ,可以说是 Zipkin 的升级版。另外,其基于 udp (也可以 http )的传输协议,更加定位了其高效、迅速的特点

Jaeger 开源社区
作为一个开源项目,一个由数百个贡献者组成的社区不断改进完善着 Jaeger。Jaeger 基于与供应商无关的 OpenTracing API 和工具。

共享出行公司 Uber 在 2015 年开发了开源项目 Jaeger。2017 年,Jaeger 纳入云原生计算基金会(CNCF)的孵化项目,2019 年,Jaeger 正式毕业。

Jaeger 包含的模块

Jaeger有5个模块元素,如下所列出,接下来我们来分别解释这五个模块的作用:

  • Jaeger-client
    (OpenTracing API 各语言的实现,用于在应用中塞入信息采集点)

jaeger-client直接采集服务站点的链路数据,统一发送到Kafka消息队列,Kafka消费端go-server直接对数据进行消费,存储Cassandra。

  • Agent
    负责发送的进程,对 spans 进行处理并发送给 collector,监听 spans 的 UDP 发送。设计这层是为了作为基础组件部署到主机上,从 client 中抽象出了 collector 的发现和路由

  • Collector
    接收agent 批量发来的数据,将数据落地到我们选择的存储里面,Collector 本身是无状态的。我们可以运行多个collector.

  • Data Store
    追踪信息的存储Cassandra

  • jaeger-query
    从存储中检索追踪信息并通过 UI 展示。

  • jaeger-ui
    UI 展示层,基于 React。 顾名思义,数据我们既然存储落地了,这就是个查询展示的页面。

一套完整的Jager追踪系统包括Jaeger-client、Jaeger-agent、Jaeger-collector、Database和Jaeger-query UI等基本组件,如下图架构图所示,**Jaeger客户端支持多种语言,jaeger-agent与客户端进行数据交互,并把数据push到Jaeger-collector组件,Jaeger-collector将数据持久化到数据库,Jaeger-query是一个web服务,用于展示跟踪链路。**以下为Jaeger容器化部署的基本流程: 分为测试环境和正式环境两种方式。
在这里插入图片描述

Jaeger-client(客户端库)

client是客户端lib,便于不同语言的项目来介入到Jaeger中,当我们的应用程序装载上之后,client会负责收集并发送数据到Agent。当前Jaeger的SDK支持有如下:

–官方
1.Go
2.Java
3.Node
4.Python
5.C++
–非官方
1.PHP
3.Others

client是支持OpenTracing标准的,如上文提到,Zipkin也是支持OpenTracing标准的,这也就意味着,我们的应用程序在嵌入Jaeger-client的地方,可以随时替换成Zipkin,对业务是完全透明的。

五、Jaeger服务容器化部署

官方文档: https://www.jaegertracing.io/docs/1.18/getting-started/
参考URL: https://www.cnblogs.com/battlescars/p/jaeger_deployment.html

推荐官方文档,已经比较详细!

  1. 下载jaeger docker 镜像。
docker pull jaegertracing/all-in-one
  1. 运行docker镜像
docker run -d --name jaeger \-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \-p 5775:5775/udp \-p 6831:6831/udp \-p 6832:6832/udp \-p 5778:5778 \-p 16686:16686 \-p 14268:14268 \-p 14250:14250 \-p 9411:9411 \jaegertracing/all-in-one:latest

网上demo,应该是只需要把 6831、16686端口暴露出来,未测试

docker run -d --name jaeger \-p 6831:6831/udp \-p 16686:16686 \jaegertracing/all-in-one:1.17

现在可以访问localhost:16686来查看jaeger的UI界面。

过程问题整理

  1. docker run运行 jaeger 报错:WARNING: IPv4 forwarding is disabled. Networking will not work.

解决办法:

vi /etc/sysctl.conf
或者

vi /usr/lib/sysctl.d/00-system.conf
添加如下代码:
net.ipv4.ip_forward=1

重启network服务

systemctl restart network
查看是否修改成功

sysctl net.ipv4.ip_forward
如果返回为“net.ipv4.ip_forward = 1”则表示成功了

解决办法:

在宿主机上面执行:

net.ipv4.ip_forward=1 >> /usr/lib/sysctl.d/00-system.conf
重启network和docker服务

systemctl restart network && systemctl restart docker
成功解决!!

六、Jaeger客户端 java代码测试验证

集成 opencensus
https://opencensus.io/guides/exporters/supported-exporters/java/jaeger/

关于OpenTracing的一个Java版本的实现请参考如下代码:https://github.com/opentracing/opentracing-java

Tracing中依赖的几个重要类

Endpoint - IP,端口和应用服务名等信息
Sampler - 采样器,根据traceId来判断是否一条trace需要被采样,即上报到zipkin
TraceContext - 包含TraceId,SpanId,是否采样等数据
CurrentTraceContext - 是一个辅助类,可以用于获得当前线程的TraceContext
Propagation - 是一个可以向数据携带的对象carrier上注入(inject)和提取(extract)数据的接口
Propagation.Factory - Propagation的工厂类

七、Jaeger客户端 go代码测试验证

官网: https://opencensus.io/guides/grpc/go/
golang实现简单的jaeger-demo
参考URL: https://www.pianshen.com/article/6298261661/
代码示例可参考一位go大佬的一个示例:https://github.com/xinliangnote/go-gin-api

调私有方法setupJaegerTracing,设置 tracing

	jaeger := setupJaegerTracing("lotus")

私有方法setupJaegerTracing 设置了 jaeger agent地址。

整体思路为:
jaeger.NewExporter 方法创建一个 NewExporter ,然后调opencensus的 trace.RegisterExporter 注册这个输出器,这样就把 jaeger和trace关联起来了。 然后就可以调用 trace.StartSpan 开始一个Span。

demo代码如下:

package mainimport ("context""fmt""github.com/urfave/cli/v2""go.opencensus.io/trace""os""time""contrib.go.opencensus.io/exporter/jaeger"logging "github.com/ipfs/go-log/v2"
)var log = logging.Logger("tracing")func main() {logging.SetLogLevel("*", "info")app := &cli.App{Name: "greet",Usage: "say a greeting",Action: func(c *cli.Context) error {fmt.Println("Greetings")//todo some thingreturn nil},}jaeger := setupJaegerTracing("lotus")defer func() {if jaeger != nil {jaeger.Flush()}}()ctx, span := trace.StartSpan(context.Background(), "/cli")defer span.End()fmt.Println("Hello world!")duration := time.Duration(10) * time.Secondtime.Sleep(duration)fmt.Println("Hello world!2")app.Setup()app.Metadata["traceContext"] = ctxif err := app.Run(os.Args); err != nil {span.SetStatus(trace.Status{Code:    trace.StatusCodeFailedPrecondition,Message: err.Error(),})os.Exit(1)}}func setupJaegerTracing(serviceName string) *jaeger.Exporter {//if _, ok := os.LookupEnv("LOTUS_JAEGER"); !ok {//	return nil//}//agentEndpointURI := os.Getenv("LOTUS_JAEGER")agentEndpointURI := "127.0.0.1:6831"je, err := jaeger.NewExporter(jaeger.Options{AgentEndpoint: agentEndpointURI,ServiceName:   serviceName,})if err != nil {log.Errorw("Failed to create the Jaeger exporter", "error", err)return nil}trace.RegisterExporter(je)trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample(),})return je
}

登录 127.0.0.1:16686 查看结果,可以看到 我们在 StartSpan指定的 操作名 cli,我们

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/649379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

csdn黑色背景用法

在edge浏览器下,下载油猴脚本管理器 脚本下载 edge扩展 效果图如下:::

[ACM学习] 进制转换

进制的本质 本质是每一位的数位上的数字乘上这一位的权重 将任意进制转换为十进制 原来还很疑惑为什么从高位开始,原来从高位开始的,可以被滚动地乘很多遍。 将十进制转换为任意进制

适合深夜发朋友圈的心灵鸡汤(整理70句)

1、很多时候,我们赢得了口舌,却失去了感情。 2、失恋到极致的时候,我真的会用后退来保护自己。 3、全身心地去爱,你可能会受到伤害,但这是完整人生的唯一方式。 4、自由不是想干什么就干什么,而是不想干…

Linux中LVM实验

LVM实验: 1、分区 -L是大小的意思-n名称的意思 从vg0(卷组)分出来 2、格式化LV逻辑卷 LVM扩容 如果icdir空间不够了, 扩展空间lvextend -L 5G /dev/vg0/lv1 /dev/vg0/lv1(pp,vg,lv) 刷新文件系统xfs_growfs /lvdir VG扩容 …

php:规范小数位数,例:10.00展示为10,10.98展示为10.98

代码 <?php$value 10.98; // 原始的双精度类型值if ($value floor($value)) {$formattedValue number_format($value, 0); // 10.00 转换为 10echo $formattedValue;} else {$formattedValue number_format($value, 2); // 10.98 保持为 10.98echo $formattedValue;} …

Sublime Text 3配置 Java 开发环境

《开发工具系列》 《开发语言-Java》 Sublime Text 3配置 Java 开发环境 一、引言二、主要内容1. 初识 Sublime Text 32. 初识 Java3. 接入 Java3.1 JDK 下载3.2 安装和使用 java3.3 环境变量配置 4. 配置 Java 开发环境5. 编写 Java 代码6. 编译和运行 Java 代码7. 乱码问题 三…

服务器无法访问外网怎么办

目前是互联网时代&#xff0c;网络已经成为人们日常生活中不可或缺的一部分。我们通过网络获取信息、进行沟通、甚至进行工作&#xff0c;因此&#xff0c;保持网络的稳定和通畅是非常重要的。然而&#xff0c;有时候我们可能会遇到一些网络无法访问外网的问题&#xff0c;这给…

作者推荐 | 【深入浅出MySQL】「底层原理」探秘缓冲池的核心奥秘,揭示终极洞察

探秘缓冲池的核心奥秘&#xff0c;揭示终极洞察 缓存池BufferPool机制MySQL缓冲池缓冲池缓冲池的问题 缓冲池的原理数据预读程序的局部性原则&#xff08;集中读写原理&#xff09;时间局部性空间局部性 innodb的数据页查询InnoDB的数据页InnoDB缓冲池缓存数据页InnoDB缓存数据…

[DIOR | DIOR-R]旋转目标检测数据集——基于YOLOv8obb,map50已达81.8%

DIOR是一个用于光学遥感图像目标检测的大规模基准数据集。涵盖20个对象类。这20个对象类是飞机、机场、棒球场、篮球场、桥梁、烟囱、水坝、高速公路服务区、高速公路收费站、港口、高尔夫球场、地面田径场、天桥、船舶、体育场、储罐、网球场、火车站、车辆和风磨。 1. DIOR简…

常见の算法链表问题

时间复杂度 1.链表逆序 package class04;import java.util.ArrayList; import java.util.List;public class Code01_ReverseList {public static class Node {public int value;public Node next;public Node(int data) {value data;}}public static class DoubleNode {publi…

Java 字符串 05 练习-遍历字符串和统计字符个数

代码&#xff1a; import java.util.Scanner; public class practice{public static void main(String[] args) {//键盘录入一个字符串&#xff0c;并进行遍历&#xff1b;Scanner input new Scanner(System.in);System.out.println("输入一个字符串&#xff1a;")…

webassembly003 whisper.cpp的main项目-1

参数设置 /home/pdd/le/whisper.cpp-1.5.0/cmake-build-debug/bin/main options:-h, --help [default] show this help message and exit-t N, --threads N [4 ] number of threads to use during computation-p N, --processors …

Android App开发-简单控件(2)——视图基础

2.2 视图基础 本节介绍视图的几种基本概念及其用法&#xff0c;包括如何设置视图的宽度和高度&#xff0c;如何设置视图的外部间距和内部间距&#xff0c;如何设置视图的外部对齐方式和内部对齐方式等等。 2.2.1 设置视图的宽高 手机屏幕是块长方形区域&#xff0c;较短的那…

【星海随笔】unix 启动问题记录.

启动Ubuntu操作系统时&#xff0c;直接进入GRUB状态。 调试时候&#xff0c;曾显示 no bootable device no known filesystem detected 注意&#xff1a; 目前 GRUB 分成 GRUB legacy 和 GRUB 2。版本号是 0.9x 以及之前的版本都称为 GRUB Legacy &#xff0c;从 1.x 开始的就称…

NODE笔记 2 使用node操作飞书多维表格

前面简单介绍了node与简单的应用&#xff0c;本文通过结合飞书官方文档 使用node对飞书多维表格进行简单的操作&#xff08;获取token 查询多维表格recordid&#xff0c;删除多行数据&#xff0c;新增数据&#xff09; 文章目录 前言 前两篇文章对node做了简单的介绍&#xff…

eNSP学习——配置通过STelnet登陆系统

目录 背景 实验内容 实验目的 实验步骤 实验拓扑 详细配置过程 基础配置 配置SSH server 配置SSH client 配置SFTP server 与client 背景 由于Telnet缺少安全的认证方式&#xff0c;而且传输过程采用的是TCP进行明文传输。单纯的提供Telnet服务容易招致主机IP地址欺骗、路…

数据分析 - 图形化解释(后续添加)

图形化解释 作为数据分析师来说一个好的图形&#xff0c;就是自己的数据表达能力 简单文本 只有一两项数据需要分享的时候&#xff0c;简单的文本是最佳的沟通方法 下图的对比可以看出来文字的表达效果会好很多 散点图 散点图在展示两件事的关系时很有用&#xff0c;观察是否存…

【搞懂设计模式】命令模式:从遥控器到编程的妙用!

我们都熟悉电视遥控器&#xff0c;它有许多按钮&#xff0c;每个按钮都有确定的功能。你按下电源键电视就会打开&#xff0c;再按下一次电视就会关闭。编程世界里也有这种模式&#xff0c;这就是我们说的命令模式。 命令模式是一种设计模式&#xff0c;它把一个请求或操作封装…

以梦为码,CodeArts Snap 缩短我与算法的距离

背景 最近一直在体验华为云的 CodeArts Snap&#xff0c;逐渐掌握了使用方法&#xff0c;代码自动生成的准确程度大大提高了。 自从上次跟着 CodeArts Snap 学习用 Python 编程&#xff0c;逐渐喜欢上了 Python。 我还给 CodeArts Snap 起了一个花名&#xff1a; 最佳智能学…

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密处理流程

计算机技术的发展与应用为企业的生产生活提供了坚实基础&#xff0c;但同时也为网络安全威胁制造了有利条件。近期&#xff0c;网络上的勒索病毒非常嚣张&#xff0c;给企业的计算机服务器带来严重威胁。近日&#xff0c;云天数据恢复中心接到山东某制造公司的求助&#xff0c;…