skywalking源码的搭建
zh
上⾯有两种编译⽅式
第⼀种是通过git clone源码
出现上⾯的提⽰是⽹络原因导致下载失败,可以参考下⾯的解决办法解决
哔哩哔哩上⾯直击痛点:⼀招搞定GitHub开源项⽬下载加速! - 1.开源项⽬下载优化(Av94251133,P1).mp4
接下来我们要切换到tag 为v 8.2.0的代码
执⾏下⾯的两个命令
接下来我们进⼊到skywalking的⽬录执⾏下⾯的两个命令
千万要注意上⾯的两个操作不能出现错误
完成上⾯的动作之后我们就可以开始skywalking的编译了
执⾏编译的命令如下
第⼆在编译的时候⼀定要注意maven地址的下载,不能仅仅只配置阿⾥云的仓库的地址,还需要配置官⽅仓库的下载地址,因为有的插件在阿⾥云上⾯没有必须到官⽹上⾯去下载,这⾥maven的配置仓库地址如下
<!-- 阿⾥云仓库 -->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>maven.aliyun/nexus/content/repositories/central/</url>
</mirror>
<!-- 中央仓库1 -->
<mirror>
<id>repo1</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>/maven2/</url>
</mirror>
<!-- 中央仓库2 -->
<mirror>
<id>repo2</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>/maven2/</url>
</mirror>
在编译的过程中报如下的错误
[ERROR] Failed to execute lstice.maven.plugins:protobuf-maven-plugin:
0.6.1:compile (grpc-build) on project apm-network: protoc did not exit cleanly.
Review output for more information. -> [Help 1]
第⼀种⽹上的说法是升级maven的版本到3.6.3,我们升级了之后还是存在问题
最终的解决办法是重启电脑之后,在执⾏mvn命令居然成功了
在编译skywalking的web模块的时候,npm的仓库我们需要修改下,不能使⽤官⽹的,使⽤官⽹的整个下载会⾮常的缓慢
我们进⼊到apm-webapp模块,修改l⽂件,我们使⽤淘宝的地址
这⾥即使弄成了淘宝的地址也会报错,那么如何解决了
我们⼿动编译前端⼯程
⾸先我们要先安装成功npm⼯具
我们进⼊G:\skywalking-8.2.0-code-1206\skywalking-ui⽬录下
我们执⾏下⾯的命令,我们将npm仓库的地址设置设为
npm config set registry "/"
我们不使⽤淘宝的镜像仓库的地址
接下来我们执⾏npm install命令
执⾏的过程中报下⾯的错误
PS D:\workspace\podcast-oms> npm install --registry=registry.
npm WARN tarball tarball data for postcss@5.2.18 (sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=) seems to be corrupted. Trying one more time.
npm ERR! path D:\workspace\podcast-oms\node_modules\.staging\postcss-8e12407f\lib\parser.js
npm ERR! code EPERM
npm ERR! errno -4048
npm ERR! syscall unlink
npm ERR! Error: EPERM: operation not permitted, unlink 'D:\workspace\podcast-oms\node_modules\.staging\postcss-8e12407f\lib\parser.js'npm ERR! { [Error: EPERM: operation not permitted, unlink 'D:\workspace\podcast-oms\node_modules\ npm ERR! cause:
npm ERR! { Error: EPERM: operation not permitted, unlink 'D:\workspace\podcast-oms\node_modules\.staging\postcss-8e12407f\lib\parser.js'
npm ERR! errno: -4048,
npm ERR! code: 'EPERM',
npm ERR! syscall: 'unlink',
npm ERR! path:
npm ERR! 'D:\\workspace\\podcast-oms\\node_modules\\.staging\\postcss-8e12407f\\lib\\parser.js' },
npm ERR! stack:
npm ERR! 'Error: EPERM: operation not permitted, unlink \'D:\\workspace\\podcast-oms\\node_modules\\.staging\\postcss-8e12407f\\lib\\parser.js\'',
npm ERR! errno: -4048,
npm ERR! code: 'EPERM',
npm ERR! syscall: 'unlink',
npm ERR! path:
npm ERR! 'D:\\workspace\\podcast-oms\\node_modules\\.staging\\postcss-8e12407f\\lib\\parser.js',
npm ERR! parent: 'postcss-minify-gradients' }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).
It's possible that the file was already in use (by a text editor or antivirus)我们把
It's possible that the file was already in use (by a text editor or antivirus)
使⽤了上⾯的办法还是没有解决问题,我们使⽤阿⾥的cnpm来解决
我们进⼊到skywalking-ui
执⾏下⾯的命令
npm install -g cnpm --registry=registry.
看到下⾯的就表⽰执⾏成功了
接下来要在skywalking-ui模块下执⾏cnpm-install命令
接下来我们执⾏打包命令执⾏npm run build命令,执⾏成功之后打包就成功了
会在skywalking-ui下⾯⽣成⼀个dist⽬录
独⽴编译成的UI dist⽂件,也是可以放到apm-webapp中打包的,可以将上图dist中的⽂件拷贝到apm-webapp\target\classes\public下,然后修改l,将npm
install和build过程都注释了:
接下来进⼊到skywalking源码⽬录执⾏下⾯的编译命令进⾏编译
mvn clean package install -Denforcer.skip=true -st.skip=true -Dcheckstyle.skip=true
就可以进⾏打包了,但是在打包的过程中会报错
会报下⾯的错误
[WARNING] The assembly descriptor contains a *nix-specific root-relative-referen
因为当前是在windows环境,在binary,xml中写的确认是linux环境的路径,解决的办法就是
⼿动的apache-skywalking-apm-8.2.0的源码下⾯创建dist⽬录,在dist⽬录下⾯创建下⾯的⽬录,将上⾯编译完成的⽂件按照binary,xml定义的路径拷贝到下⾯的⽂件夹中
接下来我们要在idea中启动skywalking集的源码
接下来我们使⽤idea打开项⽬
然后查看设置⽣成的源代码(主要是看potobuf⽂件编译⽣成的源代码)
apm-protocol/apm-network/target/generated-sources/protobuf 选中这个⽬录下⾯的grpc-java和java,然后右键选择Mark Directory As-->Generated Sources Root如下图所⽰
oap-server/server-core/target/generated-sources/protobuf⽬录的grpc-java和java⽂件夹Mark Directory As-->Generated Sources Root
oap-server/server-receiver-plugin/receiver-proto/target/generated-sources/protobuf ⽬录的grpc-java和java⽂件夹Mark Directory As-->Generated Sources Root
oap-server/exporter/target/generated-sources/protobuf⽬录的grpc-java和java⽂件夹Mark Directory As-->Generated Sources Root
oap-server/server-configuration/grpc-configuration-sync/target/generated-sources/protobuf⽬录的grpc-java和java⽂件夹Mark Directory As-->Generated Sources Root
oap-server/oal-grammar/target/generated-sources⽬录的grpc-java和java⽂件夹Mark Directory As-->Generated Sources Root
这⾥只需要导⼊上⾯的⼏个⽬录作为源码⽬录,如果多导⼊就会代码报错,下⾯我就是多导⼊了下⾯的⽬录结果在编译的时候代码就发⽣了异常,antlr4这个⽬录是不能被导⼊成源码的
第⼆个代码的源码中包下⾯的错误
我⽤的idea版本是2018的版本,我安装了lombook的插件,但是本地使⽤的maven版本是3.6.3版本,我把maven版本更换成3.3.9版本就好了
第⼆种是直接从apache skywalking下载的源码,直接编译
这⾥我采⽤的是第⼆种直接从从apache skywalking下载的源码,直接编译
进⼊到skywalking源码⽬录执⾏下⾯的编译命令进⾏编译
mvn clean package install -Denforcer.skip=true -st.skip=true -Dcheckstyle.skip=true
在编译的过程中报probuffer协议编译失败,⽆论如何都搞不定,结果重启电脑之后,再次编译就好了、
⾸先skywalking中存在前端
⼀定要保证npm 和node已经安装成功
上⾯保存的原因是node-8.17.0-win-x64.zip⽂件下载失败,我们需要⼿动下载node-8.17.0-win-x64.zip放在对应的maven库中,接下来在编译的时候报错
我们需要将npm仓库的地址换成国内的仓库地址
并且需要把 apm-webapp⼯程的pom⽂件中npm的下载地址改成国内的,不然访问在编译过程中会因为访问不了国外的仓库⽽报错
上⾯的编译成功之后,我们需要将代码导⼊到eclipse中
我们在eclipse中需要将编译之后的⽂件夹设置为源码
eclipse设置源码的⽅式如所⽰
设置 gRPC 的⾃动⽣成的代码⽬录,为源码⽬录:
将apm-protocol/apm-network/target/generated-sources/protobuf⽬录下⾯grpc-java和java⽬录右键设置为Generated Rources Root。
将oap-server/server-core/target/generated-sources/protobuf⽬录下⾯grpc-java和java⽬录右键设置为Generated Rources Root。
将oap-server/server-receiver-plugin/skywalking-istio-telemetry-receiver-plugin/target/generated-sources/protobuf⽬录下⾯grpc-java和java⽬录右键设置为Generated Rources Root。
IDEA 运⾏
skywalking 的源码中存在lombok 组件,我们需要安装lombok 的插件
配置注解处理器
lombok 插件的使⽤
apm-agent-core 是skywalking 的核⼼类,打包会⽣产skywalking-agent.jar 这个包
微内核架构SkyWalking Agent 采⽤了微内核架构(Microkernel Architecture ),那什么是微内核架构呢?微内核架构也被称为插件化架构(Plug-in Architecture ),是⼀种⾯向功能进⾏拆分的可扩展性架构。在基于产品的应⽤中通常会使⽤微内核架构,例如,IDEA 、Eclipse 这类 IDE 开发⼯具,内核都是⾮常精简的,对 Maven 、Gradle 等新功能的⽀持都是以插件的形式增加的。
如下图所⽰,微内核架构分为核⼼系统和插件模块两⼤部分。
idea 在编译skywalking 的时候,发现项⽬的java 源码没有编译的情况
第⼀要保证idea 的jdk 设置正确
项⽬⽆法编译运⾏的问题要设置上图保证maven 正确要编译项⽬
⾸先我们需要安装IntelliJ IDEA 中的lombok 插件,打开IntelliJ IDEA 后点击菜单栏中的File-->Settings ,或者使⽤快捷键Ctrl+Alt+S 进⼊到设置页⾯。
我们点击设置中的Plugins 进⾏插件的安装,在右侧选择Browse
<,然后在搜索页⾯输⼊lombok 变可以查询到下⽅的Lombok Plugin ,⿏标点击Lombok
Plugin 可在右侧看到Install 按钮,点击该按钮便可安装。我们在安装页⾯可以看到lombok 具体⽀持的所有注解,在安装过程中有Downloading Plugins 的提⽰,安装过程中进度条会变化。需要提醒的是,在安装过程中⼀定要保证⽹络连接可⽤且良好,否则可能会安装失败。安装成功后我们可以看到右侧的Restart 按钮,此时可先不操作,因为我们还有后续的配置⼯作。安装完成后我们再回到Plugins ,此时在右侧可以搜索到lombok ,⽽安装前是不⾏的。END
同样我们在Settings 设置页⾯,我们点击Build ,Execution ,Deployment-->选择Compiler-->选中Annotation Processors ,然后在右侧勾选Enable annotation processing 即可。
END
使⽤前我们需要说明的是安装的插件只是⼀个调⽤,就像我们使⽤maven 插件⼀样,本机需要安装maven 才⾏。我们在使⽤lombok 前也需要添加lombok 的依赖。lombok 的版本⼀直在更新,⼤家可以在百度搜索框输⼊lombok maven 到最新的依赖版本。
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version
>1.16.10</version></dependency>
接下来我们编辑⼀个实体类Student ,添加三个属性,最后在类上添加@Data 属性,这个注解可以帮我们在.class ⽂件中⽣成类中所有属性的get/set ⽅法、equals 、canEqual 、hashCode 、toString ⽅法等。
2
第⼆
在上图展⽰的微内核架构中,内核功能是⽐较稳定的,只负责管理插件的⽣命周期,不会因为系统功能的扩展⽽不断进⾏修改。功能上的扩展全部封装到插件之中,插件模块是独⽴存在的模块,包含特定的功能,能拓展核⼼系统的功能。通常,不同的插件模块互相之间独⽴,当然,你可以设计成⼀个插件依赖于另外⼀个插件,但应尽量让插件之间的相互依赖关系降低到最⼩,避免繁杂的依赖带来扩展性问题。
最终所有插件会由内核系统统⼀接⼊和管理:
⾸先,内核系统必须知道要加载哪些插件,⼀般会通过配置⽂件或是扫描 ClassPath 的⽅式(例如前⽂介绍的 SPI 技术)确定待加载的插件;
之后,内核系统还需要了解如何使⽤这些插件,微内核架构中需要定义⼀套插件的规范,内核系统会按照统⼀的⽅式初始化、启动这些插件;
最后,虽然插件之间完全解耦,但实际开发中总会有⼀些意想不到的需求会导致插件之间产⽣依赖或是某些底层插件被复⽤,此时内核需要提供⼀套规则,识别插件消息并能正确的在插件之间转发消息,成为插件消息的中转站。
由此可见微内核架构的好处:
源代码下载开源社区测试成本下降。从软件⼯程的⾓度看,微内核架构将变化的部分和不变的部分拆分,降低了测试的成本,符合设计模式中的开放封闭原则。
稳定性。由于每个插件模块相对独⽴,即使其中⼀个插件有问题,也可以保证内核系统以及其他插件的稳定性。
可扩展性。在增加新功能或接⼊新业务的时候,只需要新增相应插件模块即可;在进⾏历史功能下线时,也只需删除相应插件模块即可。
SkyWalking Agent 就是微内核架构的⼀种落地⽅式。在前⾯的课时中我已经介绍了 SkyWalking 中各个模块的功能,其中 apm-agent-core 模块对应微内核架构中的内核系
统,apm-sdk-plugin 模块中的各个⼦模块都是微内核架构中的插件模块。
SkyWalking Agent 启动流程概述
此前,在搭建 SkyWalking 源码环境的最后,我们尝试 Debug 了⼀下 SkyWalking Agent 的源码,其⼊⼝是 apm-agent 模块中 SkyWalkingAgent 类的 premain() ⽅法,其中完成了 Agent 启动的流程:
初始化配置信息。该步骤中会加载 fig 配置⽂件,其中会检测 Java Agent 参数以及环境变量是否覆盖了相应配置项。
查并解析 skywalking-plugin.def 插件⽂件。
AgentClassLoader 加载插件。
PluginFinder 对插件进⾏分类管理。
使⽤ Byte Buddy 库创建 AgentBuilder。这⾥会根据已加载的插件动态增强⽬标类,插⼊埋点逻辑。
使⽤ JDK SPI 加载并启动 BootService 服务。BootService 接⼝的实现会在后⾯的课时中展开详细介绍。
添加⼀个 JVM 钩⼦,在 JVM 退出时关闭所有 BootService 服务。
SkywalkingAgent.premain() ⽅法的具体实现如下,其中省略了 try/catch 代码块以及异常处理逻辑:
复制代码
public static void premain(String agentArgs,
Instrumentation instrumentation) throws PluginException {
// 步骤1、初始化配置信息
SnifferConfigInitializer.initialize(agentArgs);
// 步骤2~4、查并解析skywalking-plugin.def插件⽂件;
// AgentClassLoader加载插件类并进⾏实例化;PluginFinder提供插件匹配的功能
final PluginFinder pluginFinder = new PluginFinder(
new PluginBootstrap().loadPlugins());
/
/ 步骤5、使⽤ Byte Buddy 库创建 AgentBuilder
final ByteBuddy byteBuddy = new ByteBuddy()
.with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));
new AgentBuilder.Default(byteBuddy)...installOn(instrumentation);
// 这⾥省略创建 AgentBuilder的具体代码,后⾯展开详细说
// 步骤6、使⽤ JDK SPI加载的⽅式并启动 BootService 服务。
ServiceManager.INSTANCE.boot();
// 步骤7、添加⼀个JVM钩⼦
public void run() { ServiceManager.INSTANCE.shutdown(); }
}, "skywalking service shutdown thread"));
}
了解了 SkyWalking Agent 启动的核⼼步骤之后,本课时剩余部分将对每个步骤进⾏深⼊分析。
初始化配置
在启动 demo-webapp 和 demo-provider 两个 demo 应⽤的时候,需要在 VM options 中指定 fg 配置⽂件(skywalking_config 参数),fig 配置⽂件中的配置项如下:
复制代码
# 当前应⽤的服务名称,通过Skywalking Agent上报的Metrics、Trace数据都会
# 携带该信息进⾏标识
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
在 SnifferConfigInitializer.initialize() ⽅法中会将最终的配置信息填充到 Config 的静态字段中,填充过程如下:
将 fig ⽂件中全部配置信息填充到 Config 中相应的静态字段中。
解析系统环境变量值,覆盖 Config 中相应的静态字段。
解析 Java Agent 的参数,覆盖 Config 中相应的静态字段。
SnifferConfigInitializer.initialize() ⽅法的具体实现如下:
复制代码
public static void initialize(String agentOptions) {
// 步骤1、加载 fig配置⽂件
InputStreamReader configFileStream = loadConfig();
Properties properties = new Properties();
properties.load(configFileStream);
for (String key : properties.stringPropertyNames()) {
String value = ((key);
/
/ 按照${配置项名称:默认值}的格式解析各个配置项
properties.put(key, PropertyPlaceholderHelper.INSTANCE
.replacePlaceholders(value, properties));
}
// 填充 Config中的静态字段
ConfigInitializer.initialize(properties, Config.class);
// 步骤2、解析环境变量,并覆盖 Config中相应的静态字段
overrideConfigBySystemProp();
// 步骤3、解析 Java Agent参数,并覆盖 Config中相应的静态字段
overrideConfigByAgentOptions(agentOptions);
// 检测SERVICE_NAME和BACKEND_SERVICE两个配置项,若为空则抛异常(略)
IS_INIT_COMPLETED = true; // 更新初始化标记
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论