共计 4508 个字符,预计需要花费 12 分钟才能阅读完成。
本篇文章给大家分享的是有关如何进行源码分析 Detect,丸趣 TV 小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着丸趣 TV 小编一起来看看吧。
Detect
该 buildpack 的探测的内容包含:容器,JRE,框架。具体内容在 components.yml 中可以看到:
# Configuration for components to use in the buildpack
containers:
- JavaBuildpack::Container::DistZip
- JavaBuildpack::Container::Groovy
- JavaBuildpack::Container::JavaMain
- JavaBuildpack::Container::PlayFramework
- JavaBuildpack::Container::Ratpack
- JavaBuildpack::Container::SpringBoot
- JavaBuildpack::Container::SpringBootCLI
- JavaBuildpack::Container::Tomcat
# In order to use Oracle JREs instead of OpenJDK, you must comment out the OpenJDK line and uncomment the Oracle line.
# Please see the documentation for more detail.
jres:
- JavaBuildpack::Jre::OpenJdkJRE
# - JavaBuildpack::Jre::OracleJRE
frameworks:
- JavaBuildpack::Framework::AppDynamicsAgent
- JavaBuildpack::Framework::JavaOpts
- JavaBuildpack::Framework::MariaDbJDBC
- JavaBuildpack::Framework::NewRelicAgent
- JavaBuildpack::Framework::PlayFrameworkAutoReconfiguration
- JavaBuildpack::Framework::PlayFrameworkJPAPlugin
- JavaBuildpack::Framework::PostgresqlJDBC
- JavaBuildpack::Framework::SpringAutoReconfiguration
- JavaBuildpack::Framework::SpringInsight
由该文件可以知道该 buidpack 支持的容器,JRE 和框架。当然你可以自己添加。
detect 的入口是 bin/detect,该脚本非常简单,调用 JavaBuildpack 的 with_buildpack 静态方法创建实例,然后在代码块里调用 JavaBuildpack.detect 方法。最后将 detect 的结果组成一个字符串输出,如果探测不对,则什么也不输出。
components = JavaBuildpack::Buildpack.with_buildpack(build_dir, Detect failed with exception %s) do |buildpack| # 这里 with_buildpack 创建了一个 JavaBuildpack::Buildpack 的实例,查看 buildpack.rb 可以看到
buildpack.detect
end.compact
接下来看 JavaBuildpack::Buildpack 类,在 buildpack.rb 中。
with_buildpack 方法
是在 class self 中的,因此它是一个静态方法,在看方法定义:
def with_buildpack(app_dir, message)
app_dir = Pathname.new(File.expand_path(app_dir)) # app_dir 变成一个 Pathname 实例
application = Component::Application.new(app_dir) # 创建 application 实例
Logging::LoggerFactory.instance.setup app_dir # 初始化日志
yield new(app_dir, application) if block_given? # ** 创建一个对象,并且调用外部给的代码块 **
rescue = e
handle_error(e, message)
end
特别注意其中注释加 ** 的那句,语法比较绕
detect 方法
detect 方法分别对应用使用的容器,JRE,框架探测
def detect
tags = tag_detection(container , @containers, true)
tags.concat tag_detection(JRE , @jres, true) unless tags.empty? # 如果不为空则连接 tags
tags.concat tag_detection(framework , @frameworks, false) unless tags.empty?
tags java-buildpack=#{@buildpack_version.to_s false} unless tags.empty? # 加上 buildpack 版本
tags = tags.flatten.compact.sort
@logger.debug { Detection Tags: #{tags} }
tags
end
detection 方法
调用每个组件的 detect 方法,这些其实是子组件(如:容器大项中的 tomcat 子项),并将结果集合返回。
def detection(type, components, unique)
detected = []
tags = []
components.each do |component|
result = component.detect
next unless result # 如果结果不为空则跳出循环
detected component
tags result
end
fail Application can be run by more than one #{type}: #{names detected} if unique detected.size 1
[detected, tags]
end
具体项目的 detect 方法
这里重点关注下 tomcat 的 detect 方法,tomcat.rb
tomcat 的类定义:
class Tomcat JavaBuildpack::Component::ModularComponent
初始化方法
def initialize(context, version_validator)
super(context, version_validator)
@sub_components = supports? ? sub_components(context) : [] # tomcat 支持吗?,如果支持,初始化子项目,注意:这里两个问号,前一个是方法 support? 后一个是问号表达式
end
可以知道 Tomcat 是继承自 ModularComponent,detect 方法是在 ModularComponent 中定义的,
def detect
supports? ? @sub_components.map(:detect).flatten.compact : nil # 如果支持探测子项目
end
tomcat 的 support? 方法
def supports?
web_inf? !JavaBuildpack::Util::JavaMainUtils.main_class(@application) # WEB-INF 目录存在,且不存在 Main 方法
private
def web_inf?
(@application.root + WEB-INF).exist? # 其实检查的是,WEB-INF 目录是否存在
end
再看子项目有哪些?
def sub_components(context)
[ TomcatInstance.new(sub_configuration_context(context, tomcat)),
TomcatLifecycleSupport.new(sub_configuration_context(context, lifecycle_support)),
TomcatLoggingSupport.new(sub_configuration_context(context, logging_support)),
TomcatAccessLoggingSupport.new(sub_configuration_context(context, access_logging_support)),
TomcatRedisStore.new(sub_configuration_context(context, redis_store)),
TomcatInsightSupport.new(context)
]
end
TomcatInstance 的 detect
先从配置文件 config/tomcat.yml 中找到 tomcat 的版本及下载路径
tomcat:
version: 8.0.+
repository_root: {default.repository.root}/tomcat
然后从 repository_root(默认是:https://download.run.pivotal.io/) 下载 tomcat/index.yml,该文件包含了所有版本的 tomcat 的下载路径,找到具体的版本,如:8.0+ 指,8.0 以上的版本,找到了 8.0.14。
需要说明的是:
tomcat 支持之后,TomcatInstance 是默认支持的,因为 tomcat instance 就是基本的 tomcat 包, TomcatLifecycleSupport,TomcatLoggingSupport,TomcatAccessLoggingSupport 也是默认支持的。
如果需要会话共享,复制,设置了 service 环境变量,TomcatRedisStore 则是支持的。
而 TomcatInsightSupport 尚不支持。
以上就是如何进行源码分析 Detect,丸趣 TV 小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注丸趣 TV 行业资讯频道。