前言
Contents
现在好多文章,在教大家如何面试,跳槽。跳了之后呢,如何快速熟悉项目,通过试用期呢。
大家在入职都会面对一个问题,就是熟悉项目。那么熟悉
相信大家都在看到一座代码大(shi)山放到自己面前,都不知从何下手。如果有老同事讲解,健全的文档供查阅,那么入手起来就很方便。但就我入职以来多年经验,大部分公司的项目文档不全。你一入职,老同事就甩手(对,你是去接锅的);除了HR姐姐的入职培训,没有更多的信息;这种情况下,该如何快速入手项目呢。
这里代码部分拿PHP项目举例,其他语言的读者也可借鉴思想。
何谓熟悉了项目
一个项目,它的存在就是为了解决问题,那么熟悉项目就是,了解他能解决什么问题。
那么就需要向这个 项目提问–发起请求。再看我们能得到什么样的回答–响应。
那么我们能提什么问题呢?比如,Android APP问:现在手机手机壳是什么颜色?我要根据这个颜色变换壁纸。显然向项目提出这样的我问题,项目是不能回答的。
那么我们得到了什么回答(响应)呢,我得到了它返回给我的参数。哦不仅仅是这些,这背后它查阅了什么数据,或者更改了什么数据,还给其他项目发送了请求,或者消息,这都是这项目的响应。
所以熟悉项目我们要知道:
- 可以解决什么问题
- 解决问题过程中做了什么?
把项目当黑盒
这里我们抽象一下,参考 冯·诺伊曼结构
不论我们的http服务,Api服务,Rpc服务,都可以抽象成如上模型。
http服务的输入就是http请求
,运算器是php-fpm
程序,控制其表现的是php
代码,储存是磁盘,内存,或是redis,输出是http响应
。
Rpc服务的输入就是TCP
报文, 运算器是php
常驻程序。
MySQL服务也能这样抽象,输入是MySQL格式编码的TCP
报文,运算器,控制器是MySQL
程序,存储是磁盘,内存。输出也是TCP报文
, 然后在php
程序解码出数据。
那么熟悉项目就是可抽象为:
- 了解系统的I/O
什么是输入输出
一个项目运算器,控制器,就是这个项目的程序
和代码
。存储器就是数据
。这就好比一个线团,不知从哪开始理,如果你立马就能看懂咋回事,那么这篇文字你看到这里就可以关了。
在抽丝剥茧时,我们会先找到一个线头作为开始,而代码,就需要找到输入。
网页,APP是项目里所见即所得的输入
,也是最容易理解的,从这个方向输入
可以看到用户用例。
php
我么这里把它作为运算器,php代码
作为控制器。
php内部自己实现了一个Zend虚拟机,能编译php代码成opcode并运行。可以把它比做运算器
产生的日志,图片等文件写入,作为项目里面的存储器
。
数据,不论本地还是远程的,我们都作为输出
。(输出数据保存,输出数据查询请求)。特别是关系型数据库,从关系结构可推测出系统建模。
一个具体的项目对用户提供服务,在多服务的架构里,同样它也会是一个请求发出者,此时它发出的请求作为输出
。例如:Rpc请求,Redis操作。
自己熟悉项目时,第一时间就开始啃代码是很难的,这是把它当作一个黑盒,从什么样输入,会得到什么样的输出,开始理解系统,只有这中间代码做了什么不用第一时间关心。
就像
TDD
一样,接到的是需求,不那么关心中间实现过程。这样的参数输入能得到那样的数据返还,这个代码的happy-path
就算过关了。
所以接下来,我开始从项目,输入,输出,存储开始给大家讲解快速熟悉项目。
输入
有哪些输入呢?
http
请求,tcp
,websocket
, 自定义rpc
请求。还有消息,cron都是输入。
这里我联想到
ServerLess
,只关心输入输出
输出
SQL
,Redis
, Curl
, RPC
,文件写入,应用对外发出的请求都是输出。
配置日志记录
Http 日志
- 在浏览器端开启请求记录
例:
这里只是抓了http请求,还有个websocket容易被忽略,可以通过WS
标签过滤查看。
在浏览器端开启产看http请求是相较于抓包,避免了添加https证书问题。
- 在服务端开启日志记录
## file: /etc/nginx/nginx.conf
http {
...
## 这是默认的日志
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
## 注意这里新增了一个 $request_body
log_format log_requets '$remote_addr - $remote_user [$time_local] '
'"$request" "$request_body" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
...
}
nginx
的access_log
会记录GET请求以及参数,POST请求就需要额外配置,这里我们新增了一种日志格式——log_requets
。
## file: /etc/nginx/conf.d/www.conf
server
{
...
root /usr/share/nginx/html/xiunobbs/;
## 这里使用新的格式日志
access_log /var/log/nginx/access_xiuno.log log_requests;
error_log /var/log/nginx/error_xiuno.log;
...
例:
图中最后一行POST
,日志请求记录了提交的内容。
消息队列和Cron输入
消息队列一般要通过查日志记录来查阅。cron这块除了一般的Linux crontab,还有一些专门的cron管理工具。这点需要询问IT运维部门得知。
SQL日志
拿MySQL
举例,数据库软件会有日志记录,为了debug,我们把一般的操作日志打开。这样就能,记录所有提交到该数据库的sql记录。
## file /etc/mysql/my.cnf
general_log_file = /var/log/mysql/mysql.log
general_log = 1
log_output = FILE
配置好,重启数据库,再运行项目就能记录代码的SQL操作了。
例:
至于bin-log,这个只记录编辑操作,不记录查询操作。
Redis日志
monitor
是redis
的调试命令,输入后,当前窗口会返回redis
处理的每一个命令,它能帮助我们了解在redis
上发生了什么操作。redis是没有任何配置能够将操作命令记录到日志。
Redis 能够记录一些服务状态改变日志,以及慢日志。
登陆到redis-cli,然后键入monitor
,\n
这里我们可以用这个命令将日志操作日志记录到文件里。
nohup redis-cli monitor > /var/log/redis/redis_op.log 2>&1 &
Memecached日志
在启动memcaced
是带上参数-vv
memcached -vv
通过如下配置把Memcached
的日志记录到文件里。
memcached -m 64 -l 0.0.0.0 -p 11211 -u memcache -vv > /var/log/memcached.log 2>&1
RPC 日志
如果该Web项目依赖了RPC,需要也需要进行记录。
日志汇总
捕获到以上日志后,就能知道这个Web项目,接收到到了什么请求,查了什么DB,操作了Redis什么,请求了什么RPC
但是在3个窗口来回切换,有些不便,接下来我们想办法让他们在展示在一个窗口内。
tail -f -q /var/log/nginx/access_xiuno.log /var/log/mysql/mysql.log /var/log/redis/redis_op.log /var/log/memcached.log
效果如下:
好的这里就是通过日志,配置请求来熟悉代码。
AOP日志
好了到这里,这篇文章就快结束了,什么,以上日志方式你都没发实现,Http网关,数据库,消息队列都是运维在负责,他们做的日志级别不够,或者没有收集。以上都搞不定。
那就要祭出大招,PHP-AOP
,这个利器了。在不影响原代码逻辑,注解方式侵入代码,无需DBA,运维配合就能通过PHP代码,完成Requst,MySQL请求,Redis请求的日志记录。
详情看我的文章:PHP7中使用AOP
这里就不做展开了。哦,如果你要熟悉的代码是 函数式编程风格,那么这个Go!AOP就无能为力。动手该代码加日志吧。
文档和代码的关系
Jira/RedMind/Tower/禅道/Teambition 等也存有很多信息,不过这太依赖于公司制度和员工态度,有的人全是口头交流,软件只是用来记录状态的;有的员工事无巨细都记录在案,经手过的任务,都自带Wiki。
代码,于任务管理工具之间的联系,一般是在提交记录或分支名命名带有任务ID号。这样可以通过代码找到任务ID,再查阅当时的备注信息。
最后
通过如上操作,你已能够通过日志,了解到这段代码做了什么,梳理出主要业务。快速上手。至于参数校验,逻辑判断,最总都会落实到I/O操作的不同上。
祝愿你早日熟悉公司业务,扛起大梁。