如何进行源码分析Detect

107次阅读
没有评论

共计 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 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计4508字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)