解决方案:分布式调用链没那么难搞,好用的开源工具实践在这
优采云 发布时间: 2022-11-29 12:37解决方案:分布式调用链没那么难搞,好用的开源工具实践在这
在微服务架构中,一个请求往往会涉及到多个模块、多个中间件,需要多台机器相互协作才能完成。在这一系列的调用请求中,有的是串行的,有的是并行的,那么如何确定这个请求后面调用了哪些应用程序、哪些模块、哪些节点以及调用顺序呢?如何定位各个模块的性能问题?本文将为您揭晓答案。
本文将从以下几个方面进行阐述:
分布式溯源系统原理与作用
如何衡量一个接口的性能,一般我们至少会关注以下三个指标:
单体架构
早期,公司刚起步的时候,可能会采用如下单体架构。对于单体结构,我们应该如何计算以上三个指标呢?
最容易想到的显然是使用AOP
使用AOP打印调用具体业务逻辑前后的时间来计算整体调用时间,使用AOP捕获异常,知道是哪里的调用导致了异常。
微服务架构
在单体架构中,由于所有的服务和组件都在一台机器上,所以这些监控指标相对容易实现。但是随着业务的快速发展,单体架构必然会向微服务架构发展,具体如下:
如图:一个稍微复杂的微服务架构
如果用户反映某个页面很慢,我们知道这个页面的请求调用链是A -----> C -----> B -----> D,如何定位哪个可能是模块在这个时候出现了问题。每个服务Service A、B、C、D都有几台机器。您如何知道请求在哪台特定机器上调用服务?
可以明显看出,由于无法准确定位每个请求的准确路径,微服务架构下存在以下痛点:
分布式调用链就是为解决上述问题而诞生的,其主要作用如下:
通过分布式跟踪系统,可以很好地定位后续请求的各个具体请求链接,从而轻松实现请求链接跟踪,轻松实现各模块的性能瓶颈定位和分析。
分布式调用链标准——OpenTracing
了解了分布式调用链的作用,下面我们来看看分布式调用链的实现和原理是如何实现的。首先,为了解决不同分布式跟踪系统API不兼容的问题,OpenTracing规范诞生了。OpenTracing 是一个轻量级的规范化层,位于应用程序/库和跟踪或日志分析器之间。
通过这种方式,OpenTracing 使开发人员能够通过提供独立于平台和供应商的 API 轻松添加跟踪系统的实现。
说到这里,你有没有想过在 Java 中有类似的实现?还记得JDBC吗,通过提供一套标准的接口供各个厂商实现,程序员可以针对接口进行编程,而不用关心具体的实现。这里的接口其实就是一个标准,所以制定一套标准非常重要,可以实现组件的可插拔性。
接下来我们看一下OpenTracing的数据模型。主要有以下三种类型:
理解这三个概念非常重要。为了让大家更好的理解这三个概念,我特地画了一张图:
如图所示,一个完整的订单请求就是一个Trace。显然,对于这个请求,必须有一个全局标识来标识这个请求。每次调用调用一个Span,每次调用都必须携带全局TraceId,这样全局TraceId才能与每次调用相关联。这个TraceId是通过SpanContext传递过来的。既然要传输,就必须按照协议来调用。如图所示,如果把transport protocol比作汽车,SpanContext比作货物,Span比作公路,应该更容易理解。
了解了这三个概念之后,我再来看看分布式追踪系统是如何在统一图中采集
微服务调用链的:
我们可以看到底层有一个Collector一直在默默的采集
数据,那么每次调用Collector都会采集
什么信息:
有了这些信息,采集
器为每次调用采集
的信息如下:
根据这些图表信息,显然可以画出调用链的可视化视图如下:
这样就实现了一个完整的分布式跟踪系统。
上面的实现看起来很简单,但是有几个问题需要我们仔细思考:
下面我就来看看SkyWalking是如何解决以上四个问题的。
SkyWalking的原理和架构设计
如何自动采集
跨度数据
" />
SkyWalking采用插件+javaagent的形式实现span数据的自动采集,可以对代码无侵入。插件意味着可插拔和良好的扩展性(稍后我们将介绍如何定义自己的插件。)。
如何跨进程传递上下文
我们知道数据一般分为header和body,就像http有header和body一样,RocketMQ也有MessageHeader,Message Body,body一般收录
业务数据,所以body不宜传context,应该传入表头,如图:
dubbo中的attachment相当于header,所以我们把context放在attachment中,这样就解决了context传递的问题。
提示:这里的上下文传递过程都是dubbo插件处理的,业务是不知道的。下面将分析这个插件是如何实现的。
traceId如何保证全局唯一性?
为了确保全局唯一性,我们可以使用分布式或本地生成的 ID。如果我们使用分布式,我们需要一个数字*敏*感*词*。每个请求必须首先请求数字*敏*感*词*。会有网络调用开销,所以SkyWalking最终采用了本地生成ID的方式,并且采用了著名的snowflow算法,性能较高。
图解:雪花算法生成的id
但是,雪花算法有一个众所周知的问题:时间回调,可能会导致重复生成id。那么SkyWalking是如何解决时间回调问题的呢?
每产生一个id,就会记录这个id产生的时间(lastTimestamp)。如果发现当前时间小于上次生成id的时间(lastTimestamp),说明发生了时间回调,此时会生成一个随机数作为traceId。
这里可能有些同学想认真点。他们可能认为生成的随机数也将与生成的全局 id 相同。最好再加一层验证。
这里想谈谈系统设计中方案的选择。首先,如果对生成的随机数进行唯一性校验,无疑会多出一层调用,会有一定的性能损失,但实际上时间回调的概率很小。(发生后,由于机器时间的紊乱,业务会受到很大的影响,所以机器时间的调整一定要谨慎),而且生成的随机数重合的概率也很小。综合考虑,确实没有必要再增加一个Layer全局唯一性校验。对于技术方案的选择,一定要避免过度设计,太多就是太多。
这么多请求,全部采集
会不会影响性能?
如果每一个请求都采集
起来,毫无疑问数据量会非常大,但是反过来想想,是不是真的有必要把每一个请求都采集
起来。其实大可不必。我们可以设置采样频率,只采样部分数据,SkyWalking默认设置为3秒采样3次,其余请求不采样,如图:
这样的采样频率其实已经足够我们分析元器件的性能了。以每 3 秒 3 个样本的频率采样数据有什么问题?理想情况下,每次服务调用都是在同一个时间点(如下图),所以每次都在同一个时间点采样真的没问题。
但是在生产中,基本上不可能每个服务调用都在同一个时间点被调用,因为期间存在网络调用延迟,实际调用情况很可能如下图所示:
在这种情况下,有些调用会在服务A上被采样,而不会在服务B和C上被采样,无法分析调用链的性能。那么SkyWalking是如何解决的呢?
是这样解决的:如果上游带了Context(说明上游已经采样),下游会强制采集数据。这使链接保持完整。
SkyWalking的基础设施
SkyWalking 的基础是以下架构。可以说几乎所有的分布式调用都是由以下几个部分组成的:
首先当然是节点数据的定期采样。数据采样后定期上报,存储在ES、MySQL等持久层。有了数据,自然要根据数据做可视化分析。
SkyWalking 的表现如何?
接下来想必大家比较关心的是SkyWalking的性能表现,那么我们就来看看官方的评测数据吧:
图中蓝色代表未使用SkyWalking时的表现,橙色代表使用SkyWalking时的表现。以上是TPS为5000时测得的数据,可以看出无论是CPU、内存,还是响应时间,使用SkyWalking带带来的性能损失几乎可以忽略不计。
接下来看一下SkyWalking与业界另一知名分布式追踪工具Zipkin、Pinpoint的对比(采样率为1秒,线程数为500,总请求数时进行对比)是 5000)。可见Zipkin(117ms)和PinPoint(201ms)在临界响应时间上远不如SkyWalking(22ms)!
从性能损失来看,SkyWalking 胜出!
让我们看另一个指标:代码的侵入性如何?ZipKin需要埋在应用中,代码侵入性大。SkyWalking使用javaagent+插件修改字节码。没有侵入代码。除了代码的性能和侵入性,SkyWaking 表现出色,还有以下优势:
我司在分布式调用链上的实践
SkyWalking在我司的应用架构
从上面可以看出SkyWalking有很多优点,那么它的组件我们都用上了吗?事实上,并非如此。我们来看看它在我们公司的应用架构:
从图中可以看出,我们只使用了SkyWalking代理进行采样,而放弃了“数据上报与分析”、“数据存储”、“数据可视化”等其他三个组件。
" />
那为什么不直接采用SkyWalking完整的解决方案呢,因为我们的Marvin监控生态在接入SkyWalking之前就已经比较完整了。如果换成SkyWalking,就完全没有必要了。两者都能满足我们的需求。其次,系统更换成本高。第三,如果重新连接到用户,学习成本非常高。
这也给了我们一个启示:任何产品抓住机会都是非常重要的,后续产品的更换成本会非常高。抢占先机,就是抢占用户心智。国外还是做不了Whatsapp一样的,因为机会没了。
另一方面,对于架构,没有最好的,只有最合适的。架构设计的本质是结合当前业务场景进行折衷的平衡。
我们公司对SkyWalking做了哪些改造和实践?
我公司主要做了以下改造和实践:
1)预发布环境因调试需要强制采样
从上面的分析可以看出,Collector是在后台定时采样的。这不好吗?为什么我们需要实施强制采样?或者排查定位问题,有时线上出现问题,我们希望在预发布上复现,希望看到这个请求完整的调用链,所以需要在预发布上进行强制采样。所以我们修改了Skywalking的dubbo插件来实现强制采样。
我们在request cookie上放一个类似force_flag = true的key-value对,表示我们要强制采样。网关收到这个cookie后,会在dubbo附件中带上键值对force_flag = true,然后skywalking的dubbo插件就可以根据这个来判断是否是强制采样。如果有这个值,就是强制采样。如果没有这个值,则进行正常定时采样。
2)实现更细粒度的采样?
Ha 称为更细粒度的采样。我们先来看一下skywalking默认的采样方式,即uniform sampling。
我们知道这个方法默认是在3秒前采样3次,其他的请求都被丢弃。在这种情况下,有一个问题。假设3秒内本机有多次dubbo、mysql、redis调用,但是如果前3次都是dubbo调用的话,其他像mysql、redis等调用无法采样,所以我们修改了skywalking实现分组抽样,如下:
也就是说3秒内采样redis、dubbo、mysql等3次就可以避免这个问题。
3)如何在日志中嵌入traceId?
在输出日志中嵌入traceId,方便我们排查问题,所以打印traceId是非常有必要的,如何在日志中嵌入traceId呢?我们使用log4j,这里我们需要了解一下log4j的插件机制,log4j允许我们自定义插件输出日志的格式,首先我们需要定义日志的格式,在自定义日志格式,作为账号字符,如下:
然后我们实现一个log4j插件,如下:
首先,log4j插件需要定义一个类,该类继承LogEventPatternConverter类,并用标准Plugin声明自己为Plugin,通过@ConverterKeys注解指定需要替换的占位符,然后在format方法中替换失去。这样日志中就会出现我们想要的TraceId,如下:
4)我司开发了哪些skywalking插件?
SkyWalking 实现了很多插件,但是没有提供memcached 和druid 的插件,所以我们按照其规范开发了这两个插件:
插件是如何实现的,可以看到主要由三部分组成:
可能大家看了还是不太明白,下面就用dubbo plugin来简单说明一下。我们知道,在dubbo服务中,每次请求都会收到来自netty的消息,提交给业务线程池处理,真正调用到业务方法时结束。中间经过十几个Filter处理。
而MonitorFilter可以拦截所有客户端请求或者服务端处理请求,所以我们可以增强MonitorFilter,在调用invoke方法之前,将全局traceId注入到它的Invocation attachment中,从而保证请求到达真正业务之前全局traceId已经存在逻辑。
那么显然我们需要在插件中指定我们要增强的类(MonitorFilter),并增强它的方法(invoke)。应该对此方法进行哪些改进?这就是*敏*感*词*(Inteceptor)要做的事情。我们来看看Dubbo插件(DubboInstrumentation)中的插桩。
我们来看看代码中描述的*敏*感*词*(Inteceptor)是干什么的。关键步骤如下:
首先,beforeMethod表示这里的方法会在MonitorFilter的invoke方法执行之前被调用,而afterMethod与之对应,表示invoke方法执行之后才会执行增强逻辑。
其次,从第2点和第3点我们可以看出,无论是消费者还是提供者,其全局ID都做了相应的处理,以保证到达真正的业务层时,全局traceid是可用的。在定义了 Instrumentation 和 Interceptor 之后,最后一步是在 skywalking.def 中指定定义的类。
// skywalking-plugin.def 文件
dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation
这样封装的插件会增强MonitorFilter的invoke方法,在invoke方法执行前,将全局的traceId等操作注入到attachment中,对代码都是静默无侵入的。
总结
本文由浅入深地介绍了分布式跟踪系统的原理。相信大家对它的作用和工作机制有了更深入的了解。尤其需要注意的是,在引入某项技术时,一定要结合现有的技术架构,做出最佳方案。一个合理的选择,就像SkyWalking有四个模块,而我们公司只使用它的代理采样功能。
没有最好的技术,只有最合适的技术。通过这篇文章,相信大家应该对SkyWalking的实现机制有了清晰的认识。本文只介绍SkyWalking的插件实现,但毕竟是工业级软件。要了解它的深奥,还需要多阅读源码。
作者丨码海源丨公众号:码海(ID:seaofcode)dbaplus社区欢迎技术人员投稿,投稿邮箱:
操作方法:流量工具流量宝使用方法
流量工具是用来辅助网站增加流量的。有很多交通工具。在之前的文章《辅助网站提升流量有哪些工具》中也提到了几种工具,那么今天我们就来说说其中的一种,说说使用方法以及使用过程中需要注意的事项使用它,这个工具也是很多站长经常使用的,它就是“流量宝”。
FlowBao在一些免费工具中算是比较强大的,包括提升流量、增加人气、广告优化、提升电商人气、关键词排名、使用Alexa等功能。功能很多,但是在我们seo行业用到的就那么几个,所以就说说seo行业相关功能的使用,其他的就不多说了。
1.刷流量
刷流量可以提高网站的pv。在流量刷卡界面,有基础设置、来源URL设置、点击设置、流量时间控制、ua设置、流量区域设置。
1.基本设置
把我们要刷的网站复制粘贴到“网页地址”写入框里,ip/pv比就是你要刷的ip和pv的比值,比如1:3,那么一个ip被浏览了3次,这里我们设置1:3就好了,PV停留时间可以根据自己的情况选择,我一般是随机选择3-30秒。
2. 源地址设置
如果我们要访问百度用户,可以在“自定义来源”中选择“百度搜索词”。比如我们要增加长沙seo这个词的流量,那么我们就在上面写上“长沙seo”就可以了。注意后面的%,是根据我们自己的字数分配的。比如你想让那个词的流量高,就可以多给分。如果只有一个字,建议不要超过50%。
" />
3.点击设置
如果您不在此处设置点击 URL,该工具将默认刷新主页。如果添加点击网址,它会点击我们填写的网址。点击的百分比要适当添加,同样不要超过50%。如果要点击的页面排名不错,您可以添加更多。
4.流动时间控制
通过流量时间控制,我们可以控制点击的流量。网民可以在上网的时候多浏览,其他时间少用。这样比较自然,效果也不错。
5.ua设置
一般这里不用设置
6.交通区域设置
首先我们要去掉国外和港澳台地区,根据自己的网站选择国内地区。比如我的关键词是“长沙seo”,那么我要选择的地区就是湖南,其他地区就不用选了。,如果你滑动的词不是区域词,你也可以选择更多的区域。
2. 关键词 排名
基本设置:这里的基本设置同上,复制我们要扫描的页面排名的网址关键词,可以扫描专栏,可以扫描文章页,也可以扫描首页页面,然后在“搜索引擎”中选择,比如我们使用360搜索引擎,那就选择360搜索引擎,百度等搜索引擎也一样。
" />
注意:我们刷的页面关键词一定要收录
进去,否则没有效果,否则会影响我们的网站。
3.刷Alexa
刷Alexa并没有那么复杂,填写我们的主域名即可。
4. 最后一步
流量宝首页左下角和右下角都有“优化速度选择”。如果网站SEO基础好,选择高速模式。一般我们选择普通模式,差一点就选择低速模式。
也就是说,一个普通家庭养育一个孩子至少要花费70万元。
对于大多数普通工薪家庭来说,确实是一笔不小的数目。
小夏SEO有话要说:其实不管是什么工具,我们都不能太依赖它。该工具可以在短时间内提高网站的排名,但网站仍然需要优化。没有优化的网站如果只用一些手段,成本会很大,这样就失去了seo的意义。做seo的网站都希望低成本带来转化。
最后提醒,新站一定不要用这些工具,新站要好好优化!