SonarQube是如何工作的
SonarQube是代码检查工具的技术标杆之一,除了用来检查项目,它本身也是开源的,源码(代码结构/技术文档等)也必然是值得一读。
通过阅读源码,我们可以学到
- 一款顶尖复杂的软件项目的结构与模块如何划分
- 一个复杂前端的React实现
- 如何混合使用ES与数据库
在阅读本文前,众所周知源码分析非常耗费时间,重复一下源码分析方法论
- 能够充分使用过此项目,并阅读文档,这一步主要掌握上下文与术语
- 分析项目的依赖,并全部过一遍
- 找到免编译的路由断点与关键日志位置
- 充分使用FindUsage快速Jump
预先准备
由于编译SonarQube非常繁琐耗时,我建议提前下载好编译好的二进制文件,导入源码后配置Remote断点以实现降低分析耗时(类似以前写的通过GDB断点JVM)
下载源码
- 下载SonarQube编译好的二进制文件,并确保已经有数据
- 通过Github下载源码,导入IDEA中,并将Head切到与二进制一样的版本
配置断点
在IDEA中配置Remote断点,并在源码中如下位置打下断点
org.sonar.ce.app.CeServer#start |
在SonarQube中配置sonar.properties
sonar.ce.javaOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006 sonar.web.javaOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5007 |
然后运行SonarQube,如果Ok的话断点就断上了
SonarQube组件构成
服务端(ServerSide)
在服务端(org.sonar.application.App)启动时,会依此启动如下Process(通过ps aux|grep sonar
分析)
org.sonar.application.Apporg.elasticsearch.bootstrap.Elasticsearchorg.sonar.ce.app.CeServerorg.sonar.server.app.WebServer |
它们的作用分别是
- ElasticSearch: 内嵌的ElasticSearch,版本为5,它内部还没有用推荐的
_doc
作为type - Compute Engine(CE): 计算引擎,通过解析计算客户端上传的Zip,显示到前端
- Web: 本质是数据仓库的前台。主要有用React实现的前端与API代理,通过内嵌的Tomcat实现部署
它们的PID分别如下
p_es=`ps aux|grep Elasticsearch|grep java |awk '{print $2}'` p_ce=`ps aux|grep CeServer|grep java |awk '{print $2}'` p_web=`ps aux|grep WebServer|grep java |awk '{print $2}'` |
通过lsof查看每个服务的监听情况,并在源码中全局搜索
lsof -i -n -P |grep java|grep LISTEN|grep ${p_es} # --> 9001(Elastic默认TCP端口) lsof -i -n -P |grep java|grep LISTEN|grep ${p_ce} # --> 54918(没查到,可能是随机端口) lsof -i -n -P |grep java|grep LISTEN|grep ${p_web} # --> 9000(HTTP端口), 9092(H2数据库端口) |
客户端(ScannerSide)
- Analyser: 源码分析器,在客户机上计算,通过HTTP将ZIP发给WebServer
组件实现
内嵌H2数据库
直接免密码访问如下JDBC即可
jdbc:h2:tcp://127.0.0.1:9092/sonar |
ElasticSearch里存的啥
在SonarQube中,ElasticSearch的配置文件是程序生成的。由于默认关闭了HTTP端口的,导致难以通过外部工具进行连接,我们可以进行如下Hack实现在启动ElasticSearch前修改配置
# vi elasticsearch/bin/elasticsearch # 这里改成你的安装位置 SONAR_HOME=Downloads/sonarqube-7.4 sed -i -e 's/false/true/g' ${SONAR_HOME}/temp/conf/es/elasticsearch.yml echo "http.host: 'localhost'" >> ${SONAR_HOME}/temp/conf/es/elasticsearch.yml echo "http.port: '9300'" >> ${SONAR_HOME}/temp/conf/es/elasticsearch.yml |
这样启动后,通过Elasticsearch Head
等工具访问http://localhost:9300/
就可以知道里面存的啥了。至于存了什么,请接着看下面具体分析。
WebServer
它部署了一个嵌入的Tomcat,通过Java(而不是通过Spring的DSL)手动实现添加webApp
org.sonar.server.app.TomcatContexts#addContext |
等Tomcat部署后,将调用PlatformServletContextListener
启动Platform(这里并没有使用Spring作为依赖注入,而是使用了picocontainer
实现,使用Java编码而没有用注解/XML等DSL进行描述依赖关系),启动API业务
最终部署如下业务
部署类型 | ContextPath | ByWho |
---|---|---|
API业务 | /api | WebServiceFilter, 类似于Struts |
React静态文件 |
默认是/ , 详见sonar.web.context
|
web |
插件Jar仓库静态文件 | /deploy | data/web/deploy |
所有的API请求均可以通过如下位置进行断点分析到业务中
org.sonar.server.ws.WebServiceEngine#execute |
这样本文的引导作用就达到了,剩下具体业务自行断点分析
我在这里耗费了较多时间,本以为API业务是由Servlet进行处理,没想到居然是通过全手写Filter与Action的方法处理(10年前这种方法很先进),可以看出SonarQube也是有历史债务的,但是它的代码质量经过长期maintain后仍然清晰。
注意项目中的
StaticResourcesServlet
已经事实上废弃,因为已经没有static
文件夹了
CE如何录入计算结果?
总流程如下
Scanner-(HTTP)->Web-(MQ)->CE |
首先在Scanner通过Maven等工具在Jenkins等平台(占用这些平台的计算资源)计算出项目的各种分析报告,然后Scanner调用Web中如下接口
// http://localhost:9000/api/ce/submit?projectKey=xxx&projectName=yyy org.sonar.server.ce.ws.SubmitAction#handle |
WebServer将原始RAW文件录入ce_task_input
,接着通过消息队列(DB Based)
org.sonar.ce.queue.CeQueueImpl#submit(org.sonar.ce.queue.CeTaskSubmit) |
CE侧通过线程池每隔两秒轮询查询任务
org.sonar.ce.taskprocessor.CeWorkerImpl#call |
最终任务将通过路由到如下位置,执行数据仓库录入等任务
org.sonar.ce.task.step.ComputationStepExecutor#executeStep |
疑问解答
SonarQube如何实现存储源码?
通过访问表file_sources
中的BINARY_DATA
与protobuf实现存储,它与File通过FILE_UUID
进行关联
org.sonar.server.source.ws.LinesAction#handle |
SonarQube与Markdown
通过基于正则表达式的规则引擎实现,这个做的比较简单,没有实现AST
org.sonar.channel.ChannelDispatcher#consume |
SonarQube的React如何实现
前台使用了React与JSX实现业务,使用Webpack进行打包,使用WebPackDevServer作为API代理,前端通过如下启动外壳业务,打包脚本见server/sonar-web/config/webpack.config.js
# 启动业务(使用NodeJS提供Server) node server/sonar-web/scripts/start.js # 打包(后续交给Tomcat处理) node server/sonar-web/scripts/build.js |
SonarQube如何分析代码AST?
这里采用插件实现,比如Java在这里可以找到,分析后将转为通用格式发给Web进行处理
如果项目组需要定制Custom Rule,就可以通过访问onMethodInvocationFound
实现自己的规则
Appendix
学到的其它技巧
// ThreadLocal更优雅的启动方法 ThreadLocal<Boolean> CACHING_ENABLED = ThreadLocal.withInitial(() -> Boolean.FALSE); |
SonarQube是如何工作的相关推荐
- SonarQube使用介绍
目录 SonarQube使用介绍 工作流程: 工作流程介绍 主要作用 衡量代码质量的几个指标 SonarQube的UI界面: 个人解决项目中的bug,异味总结 ①:变量声明后不使用,多余变量 ②:方法 ...
- sonar检测java vue项目_Jenkins集成SonarQube 实现构建项目同时审查代码
软件版本: SonarQube:7.7 Jenkins:2.164.3 一.简介 SonarQube是一个开源的代码质量分析平台,便于管理代码的质量,可检查出项目代码的漏洞和潜在的逻辑问题.同时,它提 ...
- 代码审查工具 sonarqube 简介
目录 1. 什么是SonarQube? SonarQube的功能 1.糟糕的复杂度分布 2.重复 3.缺乏单元测试 4.没有代码标准 5.没有足够的或者过多的注释 6.潜在的bug 7.糟糕的设计(原 ...
- 【代码审计】使用SonarQube进行代码质量分析管理
2019独角兽企业重金招聘Python工程师标准>>> 在之前的开发中,代码的工作量化和质量化都是一个问题,随着近几年互联网行业的快速发展,代码已经可以来工作量化和质量化,今天我们来 ...
- 如何搭建安卓开发持续化集成环境(Ubuntu + Jenkins + SonarQube)
本文讲的是如何搭建安卓开发持续化集成环境(Ubuntu + Jenkins + SonarQube), 我最近换了一台新的 MacBook Pro 作为我的 Android 开发机.旧的 Mac Bo ...
- SonarQube 代码扫描任务集成
1. SonarQube 是一种自动代码审查工具,用于检测代码中的错误,漏洞和代码异味.它可以与您现有的工作流程集成,以便在项目分支和拉取请求之间进行连续的代码检查. 2. SonarQube 分为四 ...
- SonarQube系列二、分析dotnet core/C#代码
来源:https://www.cnblogs.com/7tiny/p/11342902.html [前言] 本系列主要讲述sonarqube的安装部署以及如何集成jenkins自动化分析.netcor ...
- SonarQube系列一、Linux安装与部署
来源:https://www.cnblogs.com/7tiny/p/11269774.html [前言] 随着项目团队规模日益壮大,项目代码量也越来越多.且不说团队成员编码水平层次不齐,即便是老手, ...
- sonar扫描普通JAVA执行,SonarQube扫描源代码的方法
SonarQube扫描源代码的方法 雷建锋 一.分析源代码综述 一旦成功安装了SonarQube平台,您就可以开始安装一个分析器并开始创建项目了.在第一次分析时,该平台会自动创建一个项目.如果您需要在 ...
最新文章
- 学习jvm(一)--java内存区域
- 2021年春季学期-信号与系统-第十四次作业参考答案-第九小题参考答案
- 大作完成了一部分,陆续往上放吧
- 【周报6.10-6.16】NLP,RL,GAN,DL框架等重磅专栏齐上线,这个月的有三AI你值得拥有...
- function module COM_PRODUCT_GETDETAIL_INTERNAL的内存分配问题
- 项目管理 计算机仿真,分析计算机仿真技术在工程项目施工管理中的运用.pdf
- 【HDU - 4635】Strongly connected(缩点,新图性质,建图,Tarjan求强连通分量)
- cocos2d-x的popScene的动画效果
- 1090. Highest Price in Supply Chain (25) dfs
- c语言输出教学日历表 节假日突出,[蓝桥杯][算法提高VIP]任意年月日历输出 (C语言代码)...
- 用MobaXterm远程连接Centos系统_使用技巧---Linux工作笔记047
- Anaconda 安装教程(Win10环境) Tensorflow安装
- element 使用阿里图标变形了_2TB不限速的阿里网盘App来了 终于不再忍受众生平等盘...
- Request header field storeid is not allowed by Access-Control-Allow-Headers in preflight response.
- Redis4.0之持久化存储
- 【原创】flv文件的三种下载方法
- element 日期选择器不能选择当天日期以后的日期
- 打印幻灯片去掉空白边缘
- 每日一犬 · 猴头梗
- 淘宝运营 钻展、智钻的定义 优势所在
热门文章
- 皮一皮:论家庭地位...
- Redis主从握手流程,你真的了解了吗?
- 原来这就是Java代码生成器的原理啊,太简单了
- 以为是行废代码,原来有这作用!
- MongoDB Server 3.4版本将于2020年1月31日停止支持
- 一点小兴趣,一份小生意
- linux服务器密码策略,windows与linux服务器平台密码策略管理
- yii2 mysql gone away,yii2 console MySQL server
- eclipse java代码某一行需要修改注释_看看这些Java代码开发规范吧!你好,我好,大家好!...
- linux设备模型 字符设备,Linux 字符设备驱动模型之框架解说