提交 57a7b2ea 编写于 作者: 骆昊的技术专栏's avatar 骆昊的技术专栏

增加了团队项目开发相关文档

上级 0c25a31f
此差异已折叠。
## Docker入门
### Docker简介
软件开发中最为麻烦的事情可能就是配置环境了。由于用户使用的操作系统具有多样性,即便使用跨平台的开发语言(如Java和Python)都不能保证代码能够在各种平台下都可以正常的运转,而且可能在不同的环境下我们的软件需要依赖的其他软件包也是不一样的。
那么问题来了,我们再安装软件的时候可不可以把软件运行的环境一并安装课?也就是说在安装软件的时候,我们是不是可以把原始环境一模一样地复制过来呢?
虚拟机(virtual machine)就是带环境安装的一种解决方案,它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统,在macOS上运行Windows,而应用程序对此毫无感知。使用过虚拟机的人都知道,虚拟机用起来跟真实系统一模一样,而对于虚拟机的宿主系统来说,虚拟机就是一个普通文件,不需要了就删掉,对宿主系统或者其他的程序并没有影响。但是虚拟机通常会占用较多的系统资源,启动和关闭也非常的缓慢,总之用户体验没有想象中的那么好。
Docker属于对Linux容器技术的一种封装,它提供了简单易用的容器使用接口,是目前最流行的 Linux 容器解决方案。Docker将应用程序与该程序的依赖打包在一个文件里面,运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了Docker就再也不用担心环境问题了。
![](./res/docker_vs_vm.png)
目前,Docker主要用于几下几个方面:
1. 提供一次性的环境。
2. 提供弹性的云服务(利用Docker很容易实现扩容和收缩)。
3. 实践微服务架构(隔离真实环境在容器中运行多个服务)。
### CentOS下的安装和使用
下面的讲解以CentOS为例,使用[Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/)[macOS](https://docs.docker.com/docker-for-mac/install/)[Windows](https://docs.docker.com/docker-for-windows/install/)的用户可以通过点击链接了解这些平台下如何安装和使用Docker。
0. 确定操作系统内核版本(CentOS 7要求64位,内核版本3.10+;CentOS 6要求64位,内核版本2.6+)。
```Shell
uname -r
```
1. 在CentOS下使用yum安装Docker并启动。
```Shell
yum -y install docker-io
systemctl start docker
```
2. 检视Docker的信息和版本。
```Shell
docker version
docker info
```
3. 运行Hello-World项目来测试Docker。第一次运行时由于本地没有hello-world的镜像因此需要联网进行下载。
```Shell
docker run hello-world
```
也可以先用下面的命令下载镜像,然后再来运行。
```Shell
docker pull <name>
```
4. 运行镜像文件。
```Shell
docker run <image-id>
docker run -p <port1>:<port2> <name>
```
6. 查看镜像文件。
```Shell
docker image ls
docker images
```
7. 删除镜像文件。
```Shell
docker rmi <name>
```
8. 查看正在运行容器。
```Shell
docker ps
```
9. 停止运行的容器。
```Shell
docker stop <container-id>
docker stop <name>
```
对于那些不会自动终止的容器,就可以用下面的方式来停止。
```Shell
docker container kill <container-id>
```
在Ubuntu(内核版本3.10+)下面安装和启动Docker,可以按照如下的步骤进行。
```Shell
apt update
apt install docker-ce
service docker start
```
在有必要的情况下,可以更换Ubuntu软件下载源来提升下载速度,具体的做法请参照<https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/>
安装Docker后,由于直接访问dockerhub下载镜像会非常缓慢,建议更换国内镜像,可以通过修改`/etc/docker/daemon.js`文件来做到。
```JavaScript
{
"registry-mirrors": [
"http://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
]
}
```
### Docker实战
#### 安装Nginx
Docker的使用肯定不止上面这点东西,但是有了这些知识之后,我们已经可以开始感受Docker的强大之处。下面我们就基于Docker来搭建HTTP服务器(Nginx)环境。
```Shell
docker container run -d -p 80:80 --rm --name mynginx nginx
```
> 说明:上面的参数`-d`表示容器在后台运行;`-p`是用来映射容器的端口到宿主机的端口;`--rm`表示容器停止后自动删除容器,例如通过`docker container stop mynginx`以后,容器就没有了;`--name`是自定义容器的名字。
如果需要将自己的页面部署到Nginx上,可以使用容器的拷贝命令将当前文件夹下所有的文件和文件夹拷贝到容器的指定目录中。当然也可以从容器中拷贝文件到我们指定的路径下。
```Shell
docker container cp ./index.html mynginx:/usr/local/nginx/html
```
如果不愿意拷贝文件也可以将文件夹映射到Nginx保存页面文件的目录。
```Shell
docker container run -d -p 80:80 --rm --name mynginx --volume "$PWD/html":/usr/share/nginx/html nginx
```
#### 安装MySQL
下载MySQL镜像。
```Shell
docker search mysql
docker pull mysql:5.7
docker images
```
启动容器运行MySQL。
```Shell
docker run --name mysql-docker -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
```
在使用MySQL 8.x时可能会遇到“error 2059: Authentication plugin 'caching_sha2_password' cannot be loaded”的问题,这是因为MySQL 8.x默认使用了名为“caching_sha2_password”的机制对用户口令进行了更好的保护,但是如果客户端没有更新有可能无法基于这种方式进行身份验证,可以按照下面的方式加以解决。
```Shell
docker exec -it mysql8-docker /bin/bash
```
进入容器的交互式Shell之后,可以首先利用MySQL的客户端工具连接MySQL服务器。
```Shell
mysql -u root -p
Enter password:
Your MySQL connection id is 16
Server version: 8.0.12 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
```
接下来通过SQL来修改用户口令就可以了。
```SQL
alter user 'root'@'%' identified with mysql_native_password by '123456' password expire never;
```
当然,如果愿意你也可以查看一下用户表检查是否修改成功。
```SQL
use mysql;
select user, host, plugin, authentication_string from user where user='root';
+------+-----------+-----------------------+-------------------------------------------+
| user | host | plugin | authentication_string |
+------+-----------+-----------------------+-------------------------------------------+
| root | % | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| root | localhost | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+------+-----------+-----------------------+-------------------------------------------+
2 rows in set (0.00 sec)
```
## 团队项目开发
我们经常听到个人开发和团队开发这两个词,所谓个人开发就是一个人把控产品的所有内容;而团队开发则是由多个人组成团队并完成产品的开发。要实施团队开发以下几点是必不可少的:
1. 必须对开发过程中的各种事件(例如:谁到什么时间完成了什么事情)进行管理和共享。
2. 各类工作成果以及新的知识技巧等必须在团队内部共享。
3. 管理工作成果的变更,既要防止成果被破坏,又要保证各个成员利用现有成果并行作业。
4. 能够证明团队开发出的软件在任何时候都是可以正常运行的。
5. 尽可能的使用自动化的工作流程,让团队成员能够正确的实施开发、测试和部署。
### 团队项目开发常见问题
#### 问题1:传统的沟通方式无法确定处理的优先级
例如:使用邮件进行沟通可能出现邮件数量太多导致重要的邮件被埋没,无法管理状态,不知道哪些问题已经解决,哪些问题尚未处理,如果用全文检索邮件的方式来查询相关问题效率过于低下。
解决方案:使用缺陷管理工具。
#### 问题2:没有能够用于验证的环境
例如:收到项目正式环境中发生的故障报告后,需要还原正式环境需要花费很长的时间。
解决方法:实施持续交付。
#### 问题3:用别名目录管理项目分支
解决方法:实施版本控制。
#### 问题4:重新制作数据库非常困难
例如:正式环境和开发环境中数据库表结构不一致或者某个表列的顺序不一致。
解决方法:实施版本控制。
#### 问题5:不运行系统就无法察觉问题
例如:解决一个bug可能引入其他的bug或者造成系统退化,不正确的使用版本系统覆盖了其他人的修改,修改的内容相互发生了干扰,如果问题不能尽早发现,那么等过去几个月后再想追溯问题就非常麻烦了。
解决方法:实施持续集成,将团队成员的工作成果经常、持续的进行构建和测试。
#### 问题6:覆盖了其他成员修正的代码
解决方法:实施版本控制。
#### 问题7:无法实施代码重构
重构:在不影响代码产生的结果的前提下对代码内部的构造进行调整。
例如:在实施代码重构时可能引发退化。
解决方法:大量的可重用的测试并实施持续集成。
#### 问题8:不知道bug的修正日期无法追踪退化
解决方法:版本控制系统、缺陷管理系统和持续集成之间需要交互,最好能够和自动化部署工具集成到一起来使用。
#### 问题9:发布过程太复杂
解决方法:实施持续交付。
基于对上述问题的阐述和分析,我们基本上可以得到以下的结论,在团队开发中版本控制、缺陷管理和持续集成都是非常重要且不可或缺的。
### 版本控制
针对上面提到的一些问题,在团队开发的首要前提就是实施版本控制,对必要的信息进行管理,需要管理的内容包括:
1. 代码。
2. 需求和设计的相关文档。
3. 数据库模式和初始数据。
4. 配置文件。
5. 库的依赖关系定义。
#### Git简介
![Logo of Git](http://upload-images.jianshu.io/upload_images/1279331-df4dada955ca9052.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Git是诞生于2005年的一个开源分布式版本控制系统,最初是Linus Torvalds(Linux之父) 为了帮助管理Linux内核开发而开发的一个版本控制软件。Git与常用的版本控制工具Subversion等不同,它采用了分布式版本控制的方式,在没有中央服务器支持的环境下也能够实施版本控制。
对于有使用Subversion(以下简称为SVN)经验的人来说,Git和SVN一样摒弃了基于锁定模式的版本控制方案(早期的CVS和VSS使用的就是锁定模式)采用了合并模式,而二者的区别在于:
1. Git是分布式的,SVN是集中式的,SVN需要中央服务器才能工作。
2. Git把内容按元数据方式存储,而SVN是按文件,即把文件的元信息隐藏在一个.svn文件夹里。
3. Git分支和SVN的分支不同。
4. Git没有一个全局版本号而SVN有。
5. Git的内容完整性要优于SVN,Git的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
#### 安装Git
可以在[Git官方网站](http://git-scm.com/)找到适合自己系统的Git下载链接并进行安装,安装成功后可以在终端中键入下面的命令检查自己的Git版本。
```Shell
git --version
```
如果之前完全没有接触过Git,可以先阅读[《git - 简易指南》](http://www.bootcss.com/p/git-guide/)来对Git有一个大致的了解。
#### 本地实施版本控制
可以使用下面的命令将目录创建为Git仓库。
```Shell
git init
```
当你完成了上述操作后,本地目录就变成了下面的样子,左边是你正在操作的工作目录,而右边是你的本地仓库,中间是工作目录和本地仓库之间的一个暂存区(也称为缓存区)。
![](./res/git_repository.png)
通过`git add`可以将文件添加到暂存区。
```Shell
git add <file> ...
```
可以用下面的方式将暂存区的指定文件恢复到工作区。
```Shell
git checkout -- <file>
```
通过下面的命令可以将暂存区的内容纳入本地仓库。
```Shell
git commit -m '本次提交的说明'
```
可以使用下面的命令查看文件状态和进行版本比较。
```Shell
git status -s
git diff
```
可以通过`git log`查看提交日志。
```Shell
git log
git log --graph --pretty=oneline --abbrev-commit
```
如果要回到历史版本,可以使用下面的命令。
```Shell
git reset --hard <commit-id>
git reset --hard HEAD^
```
其他的一些命令可以参考阮一峰老师的[《常用Git命令清单》](http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html)或者是码云上的[《Git大全》](https://gitee.com/all-about-git)
#### Git服务器概述
对于Git来说不像SVN那样一定需要一个中心服务器,刚才我们的操作都是在本地执行的,如果你想通过Git分享你的代码或者与其他人协作,那么就需要服务器的支持。Github为Git提供了远程仓库,它是一个基于Git的代码托管平台,企业用户(付费用户)可以创建仓库,普通用户只能创建公开仓库(代码是可以是他人可见的)。Github是在2008年4月创办的,它上面代码库惊人的增长速度已经证明了它是非常成功的,在2018年6月,微软以75亿美元的天价收购了Github。国内也有类似的代码托管平台,最有名的当属[码云](https://gitee.com/)[CODING](https://coding.net/),目前码云和CODING对注册用户都提供了受限的使用私有仓库的功能,同时还提供了对Pull Request的支持(后面会讲到),而且目前提供代码托管服务的平台都集成了“缺陷管理”、“WebHook”等一系列的功能,让我们能做的事情不仅仅是版本控制。当然,如果公司需要也可以搭建自己的Git服务器,具体的方式我们就不在这里进行介绍了,有兴趣的可以自行了解。
![](./res/git_logo.png)
我们可以在码云或者CODING上注册账号,也可以使用第三方登录(github账号、微信账号、新浪微博账号、CSDN账号等)的方式。登录成功后就可以创建项目,创建项目几乎是“傻瓜式”的,我们只说几个值得注意的地方。
1. 添加项目成员。创建项目后,可以在项目的“设置”或“管理”中找到“成员管理”功能,这样就可以将其他开发者设置为项目团队的成员,项目成员通常分为“所有者”、“管理者”、“普通成员”和“受限成员”几种角色。
2. 设置公钥实现免密操作。在项目的“设置”或“管理”中我们还可以找到“部署公钥管理”的选项,通过添加部署公钥,可以通过SSH(安全远程连接)的形式访问服务器而不用每次输入用户名和口令。可以使用`ssh-keygen`命令来创建密钥对。
```Shell
ssh-keygen -t rsa -C "your_email@example.com"
```
#### 使用Git进行开发
克隆服务器上的代码到本地机器。
```Shell
git clone <url>
```
在自己的分支上进行开发。
```Shell
git branch <branch-name>
git checkout <branch-name>
```
或者
```Shell
git checkout -b <branch-name>
```
接下来可以先在本地实施版本控制(操作的方式与前面相同不再赘述),然后再将自己的分支Push到服务器。
```Shell
git push origin <branch-name>
```
最后,当工作完成时,可以发起一个Pull Request,请求将代码合并到master分支。
#### 分支策略的模式
上面讲解的方式,其实是一种称为github-flow的分支策略模式,这种模式的操作步骤包括:
1. master的内容都是可以进行发布的内容。
2. 开发时应该以master为基础建立新分支。
3. 分支先在本地实施版本控制,然后以同名分支定期向服务器进行Push。
4. 开发结束后向master发送Pull Request。
5. Pull Request通过代码审查之后合并到master,并从master向正式环境发布。
在使用github-flow时的注意事项有以下三点:
1. master是用于发布的,不能直接在master上进行修改。
2. 开始日常开发工作时要首先建立分支。
3. 工作完成后向master发送Pull Request。
除了上述的github-flow工作方式外,还有一种名为git-flow的分支策略模式,它借鉴了中央集权型版本控制系统的长处,为团队内部统一管理建立分支的方法、合并操作和关闭分支的方法。在这种模式下,项目有两个长线分支,分别是master和develop,其他的都是临时的、短暂的辅助分支,包括feature(开发特定功能的分支,开发结束后合并到develop)、release(从develop分离出来的为发布做准备的分支,发布结束后合并到master和develop)和hotfix(产品发布后出现问题时紧急建立的分支,直接从master分离,问题修复后合并到master并打上标签,同时还要合并到develop来避免将来的版本遗漏了这个修复工作,如果此时有正在发布中的release分支,还要合并到release分支)。这套方式分支策略简单清晰且容易理解,但是在运用上会稍微有些复杂,需要一些脚本来辅助版本控制的实施。
### 缺陷管理
没有好的团队管理工具必然导致项目进展不顺利,任务管理困难,而引入缺陷管理系统正好可以解决这些问题,通常一个缺陷管理系统都包含了以下的功能:
1. 任务管理(包括必须做什么、谁来做、什么时候完成、现在处于什么状态等)。
2. 直观而且可以检索过去发生的各种问题。
3. 能够对信息进行统一的管理和共享。
4. 能够生成各类报表。
5. 能够关联到其他系统,具有可扩展性。
Redmine是基于Ruby on Rails框架的开源缺陷管理系统,提供了问题管理、代码管理、Wiki等必要的功能,而且支持插件系统,扩展起来也非常容易。
![](./res/redmine_new_issue.png)
如果希望了解和使用Redmine,可以关注[Redmine中文网](http://www.redmine.org.cn/),上面提供了视频教程、经验分享以及其他的安装和使用上的指导。
### 持续集成
为了快速的产生高品质的软件,在团队开发中,持续集成(CI)也是一个非常重要的基础。按照经典的软件过程模型(瀑布模型),集成的工作一般要等到所有的开发工作都结束后才能开始,但这个时候如果发现了问题,修复问题的代价是非常具体的。基本上,集成实施得越晚,代码量越大,解决问题就越困难。持续集成将版本控制、自动化构建、代码测试融入到一起,让这些工作变得自动化和可协作。
在所有的CI工具中,Jenkins和TravisCI是最具有代表性的。
![](./res/jenkins_new_project.png)
\ No newline at end of file
## 团队项目开发
### Day01
1. 企业项目开发团队构成和角色:帮助学生了解项目中的角色及其关系,以小组为单位定义角色。
2. 项目开发流程(软件过程模型)以及各个阶段涉及的相关文档。
3. 团队开发相关工具介绍和环境搭建。
4. 项目选题和理解业务。
### Day02
1. 业务讲解和需求评审。
2. 数据库设计、接口设计、接口文档编撰。
3. 模块划分、任务分配和项目进度安排。
### Day03~Day07
1. 日常开发,每日代码和进度审查。
2. 集中解决项目开发中遇到的公共问题。
3. 项目技术重点难点及其相关技术剖析。
4. 之前未覆盖到的新技术讲解(例如:第三方授权登录、推送机制、消息队列的应用)。
### Day08
1. 单元测试。
2. 集成测试。
3. 接口测试。
4. Selenium自动化测试。
5. 性能测试(压力测试)及其相关工具。
- Apache Benchmark
- SQLSlap
- WebBench
### Day09
1. MySQL性能优化相关。
- SQL优化(执行计划、慢查询分析)
- 读写分离
- 集群配置
- 架构优化
2. 基于Redis的缓存、主从复制、哨兵和集群配置、切片。
3. 日志分析和漏洞分析。
### Day10
1. 项目部署环境搭建。
2. Nginx反向代理配置。
3. Nginx+KeepAlived集群环境配置。
4. HTTPS配置(密钥、证书、配置)。
5. 项目运维相关。
### Day11
1. 虚拟化技术和虚拟化容器。
2. Docker的安装和使用。
3. Docker镜像和虚拟化部署。
### Day12
1. ShowCase
2. 项目评审和总结
### Day13~Day15
1. 模拟面试。
2. 简历指导。
## 团队项目开发
### Day01
1. 企业项目开发团队构成和角色:帮助学生了解项目中的角色及其关系,以小组为单位定义角色。
2. 项目开发流程(软件过程模型)以及各个阶段涉及的相关文档。
3. 团队开发相关工具介绍和环境搭建。
4. 项目选题和理解业务。
### Day02
1. 业务讲解和需求评审。
2. 数据库设计、接口设计、接口文档编撰。
3. 模块划分、任务分配和项目进度安排。
### Day03~Day07
1. 日常开发,每日代码和进度审查。
2. 集中解决项目开发中遇到的公共问题。
3. 项目技术重点难点及其相关技术剖析。
4. 之前未覆盖到的新技术讲解(例如:第三方授权登录、推送机制、消息队列的应用)。
### Day08
1. 单元测试。
2. 集成测试。
3. 接口测试。
4. Selenium自动化测试。
5. 性能测试(压力测试)及其相关工具。
- Apache Benchmark
- SQLSlap
- WebBench
### Day09
1. MySQL性能优化相关。
- SQL优化(执行计划、慢查询分析)
- 读写分离
- 集群配置
- 架构优化
2. 基于Redis的缓存、主从复制、哨兵和集群配置、切片。
3. 日志分析和漏洞分析。
### Day10
1. 项目部署环境搭建。
2. Nginx反向代理配置。
3. Nginx+KeepAlived集群环境配置。
4. HTTPS配置(密钥、证书、配置)。
5. 项目运维相关。
### Day11
1. 虚拟化技术和虚拟化容器。
2. Docker的安装和使用。
3. Docker镜像和虚拟化部署。
### Day12
1. ShowCase
2. 项目评审和总结
### Day13~Day15
1. 模拟面试。
2. 简历指导。
## 团队项目开发
### Day01
1. 企业项目开发团队构成和角色:帮助学生了解项目中的角色及其关系,以小组为单位定义角色。
2. 项目开发流程(软件过程模型)以及各个阶段涉及的相关文档。
3. 团队开发相关工具介绍和环境搭建。
4. 项目选题和理解业务。
### Day02
1. 业务讲解和需求评审。
2. 数据库设计、接口设计、接口文档编撰。
3. 模块划分、任务分配和项目进度安排。
### Day03~Day07
1. 日常开发,每日代码和进度审查。
2. 集中解决项目开发中遇到的公共问题。
3. 项目技术重点难点及其相关技术剖析。
4. 之前未覆盖到的新技术讲解(例如:第三方授权登录、推送机制、消息队列的应用)。
### Day08
1. 单元测试。
2. 集成测试。
3. 接口测试。
4. Selenium自动化测试。
5. 性能测试(压力测试)及其相关工具。
- Apache Benchmark
- SQLSlap
- WebBench
### Day09
1. MySQL性能优化相关。
- SQL优化(执行计划、慢查询分析)
- 读写分离
- 集群配置
- 架构优化
2. 基于Redis的缓存、主从复制、哨兵和集群配置、切片。
3. 日志分析和漏洞分析。
### Day10
1. 项目部署环境搭建。
2. Nginx反向代理配置。
3. Nginx+KeepAlived集群环境配置。
4. HTTPS配置(密钥、证书、配置)。
5. 项目运维相关。
### Day11
1. 虚拟化技术和虚拟化容器。
2. Docker的安装和使用。
3. Docker镜像和虚拟化部署。
### Day12
1. ShowCase
2. 项目评审和总结
### Day13~Day15
1. 模拟面试。
2. 简历指导。
## 网络API接口设计
手机App以及使用了Ajax技术或做了前后端分离的页面都需要通过网络API(Application Programming Interface)和后台进行交互,所谓API,指的应用程序的编程接口;而网络API通畅指的是基于HTTP或HTTPS协议的一个URL(统一资源定位符),通过这个URL我们可以让服务器对某个资源进行操作并返回操作的结果。基于HTTP(S)协议最大的好处就在于访问起来非常的简单方便,而且没有编程语言和应用环境上的差别。
### 设计原则
#### 关键问题
为移动端或者PC端设计网络API接口一个非常重要的原则是:根据业务实体而不是用户界面或操作来设计。如果API接口的设计是根据用户的操作或者界面上的功能设置来设计,随着需求的变更,用户界面也会进行调整,需要的数据也在发生变化,那么后端开发者就要不停的调整API,或者给一个API设计出多个版本,这些都会使项目的开发和维护成本增加。
下面是某个网站开放API的接口,可以看出API的设计是围绕业务实体来进行的,而且都做到了“见名知意”。
| 评论 | |
| ----------------- | ---------------------- |
| comments/show | 获取某条微博的评论列表 |
| comments/by_me | 自己的评论列表 |
| comments/to_me | 收到的评论列表 |
| comments/mentions | @了自己的评论列表 |
| comments/create | 创建一条评论 |
| comments/destroy | 删除一条评论 |
| comments/reply | 回复一条评论 |
注意:上面的API接口并不是REST风格的,关于REST的知识,可以阅读阮一峰老师的[《理解RESTful架构》](http://www.ruanyifeng.com/blog/2011/09/restful.html)以及[《RESTful API设计指南》](http://www.ruanyifeng.com/blog/2014/05/restful_api.html)
API接口返回的数据通常都是JSON或XML格式,我们这里不讨论后者。对于JSON格式的数据,我们需要做到不要返回null这的值,因为这样的值一旦处置失当,会给移动端的开发带来麻烦(移动端可能使用强类型语言)。要解决这个问题可以从源头入手,在设计数据库的时候,尽量给每个字段都加上“not null”约束或者设置合理的默认值约束。
#### 其他问题
1. 更新提示问题:设计一个每次使用系统首先要访问的API,该API会向移动端返回系统更新的相关信息,这样就可以提升用户更新App了。
2. 版本升级问题:API版本升级时应该考虑对低版本的兼容,同时要让新版本和旧版本都能够被访问,可以在URL中包含版本信息或者在将版本号放在HTTP(S)协议头部,关于这个问题有很多的争论,有兴趣的可以看看[stack overflow](https://stackoverflow.com/questions/972226/how-to-version-rest-uris)上面对这个问题的讨论。
3. 图片尺寸问题:移动端对于一张图片可能需要不同的尺寸,可以在获取图片时传入尺寸参数并获取对应的资源;更好的做法是直接使用云存储或CDN(直接提供了图片缩放的功能),这样可以加速对资源的访问。
### 文档撰写
下面以设计评论接口为例,简单说明接口文档应该如何撰写。
#### 评论接口
全局返回状态码
| 返回码 | 返回信息 | 说明 |
| ------ | ------------ | ---------------------------------- |
| 10000 | 获取评论成功 | |
| 10001 | 创建评论成功 | |
| 10002 | 无法创建评论 | 创建评论时因违反审核机制而无法创建 |
| 10003 | 评论已被删除 | 查看评论时评论因不和谐因素已被删除 |
| 10004 | …… | …… |
1. **GET** `/comments/{article-id}`
开发者:王大锤
最后更新时间:2018年8月10日
标签:v 1.0
接口说明:获取指定文章的所有评论
使用帮助:默认返回20条数据,需要在请求头中设置身份标识(key)
请求参数:
| 参数名 | 类型 | 是否必填 | 参数位置 | 说明 |
| ------ | ------ | -------- | -------- | ------------------------------------ | |
| page | 整数 | 否 | 查询参数 | 页码,默认值1 |
| size | 整数 | 否 | 查询参数 | 每次获取评论数量(10~100),默认值20 |
响应信息:
```JSON
{
"code": 10000,
"message": "获取评论成功",
"page": 1,
"size": 10,
"contents": [
{
"userId": 1700095,
"nickname": "王大锤",
"pubDate": "2018年7月31日",
"content": "小编是不是有病呀"
/* ... */
},
{
"userId", 1995322,
"nickname": "白元芳",
"pubDate": "2018年8月2日",
"content": "楼上说得好"
/* ... */
}
]
/* ... */
}
```
2. **POST** `/comments/{article-id}`
开发者:王大锤
最后更新时间:2018年8月10日
标签:v 1.0
接口说明:为指定的文章创建评论
使用帮助:暂无
请求参数:
| 参数名 | 类型 | 是否必填 | 参数位置 | 说明 |
| ------- | ------ | -------- | -------- | ------------------------------------ |
| userId | 字符串 | 是 | 消息体 | 用户ID |
| token | 字符串 | 是 | 消息体 | 用户的令牌或URL的签名 |
| content | 字符串 | 是 | 消息体 | 评论的内容 |
响应信息:
```JSON
{
"code": 10001,
"message": "创建评论成功",
"comment": {
"pubDate": "2018年7月31日",
"content": "小编是不是有病呀"
/* ... */
}
/* ... */
}
```
\ No newline at end of file
## 团队项目开发
### Day01
1. 企业项目开发团队构成和角色:帮助学生了解项目中的角色及其关系,以小组为单位定义角色。
2. 项目开发流程(软件过程模型)以及各个阶段涉及的相关文档。
3. 团队开发相关工具介绍和环境搭建。
4. 项目选题和理解业务。
### Day02
1. 业务讲解和需求评审。
2. 数据库设计、接口设计、接口文档编撰。
3. 模块划分、任务分配和项目进度安排。
### Day03~Day07
1. 日常开发,每日代码和进度审查。
2. 集中解决项目开发中遇到的公共问题。
3. 项目技术重点难点及其相关技术剖析。
4. 之前未覆盖到的新技术讲解(例如:第三方授权登录、推送机制、消息队列的应用)。
### Day08
1. 单元测试。
2. 集成测试。
3. 接口测试。
4. Selenium自动化测试。
5. 性能测试(压力测试)及其相关工具。
- Apache Benchmark
- SQLSlap
- WebBench
### Day09
1. MySQL性能优化相关。
- SQL优化(执行计划、慢查询分析)
- 读写分离
- 集群配置
- 架构优化
2. 基于Redis的缓存、主从复制、哨兵和集群配置、切片。
3. 日志分析和漏洞分析。
### Day10
1. 项目部署环境搭建。
2. Nginx反向代理配置。
3. Nginx+KeepAlived集群环境配置。
4. HTTPS配置(密钥、证书、配置)。
5. 项目运维相关。
### Day11
1. 虚拟化技术和虚拟化容器。
2. Docker的安装和使用。
3. Docker镜像和虚拟化部署。
### Day12
1. ShowCase
2. 项目评审和总结
### Day13~Day15
1. 模拟面试。
2. 简历指导。
## 项目实战 - 开启团队项目
### 创建项目
我们的项目使用Git作为版本控制工具,首先可以在代码托管平台上创建一个新项目。这里我们使用了国内的[“码云”](https://gitee.com)来创建项目,并通过该平台实现版本控制和缺陷管理,当然如果愿意也可以使用[github](https://github.com/)或者国内的[CODING](https://coding.net/))来做同样的事情,当然也可以自己用诸如[Gitlab](https://gitlab.com)这样的工具来搭建自己的代码仓库。创建好项目之后,我们先为项目添加一个名为`.gitignore`文件,该文件用来忽略掉那些不需要纳入版本控制系统的文件,如果不知道怎么编写该文件,可以使用gitignore.io](https://www.gitignore.io/)网站提供的在线生成工具,如下所示。
![](./res/gitignore_io.png)
### 初始版本
接下来,我们将项目克隆到本地,并为项目创建真正意义上的初始版本。
```Shell
git clone https://gitee.com/jackfrued/fang.com.git
cd fang.com
python3 -m venv venv
source venv/bin/activate
pip install -U pip
pip install django django-celery django-redis djangorestframework pymysql redis pillow
pip freeze > requirements.txt
```
**提示**:在使用pip安装依赖项以后,可以通过`pip check`来检查依赖项是否兼容,确保万无一失。如果希望使用国内的PyPI源,可以按照如下所示的方式进行配置。在用户主目录下找到或创建名为`.pip`的文件夹,并在该文件夹中添加一个`pip.conf`文件,其内容如下所示。
```INI
[global]
trusted-host=mirrors.aliyun.com
index-url=http://mirrors.aliyun.com/pypi/simple/
# index-url=https://pypi.tuna.tsinghua.edu.cn/simple/
# index-url=https://mirrors.ustc.edu.cn/pypi/web/
# index-url=https://pypi.douban.com/simple
```
上面的配置文件中使用了阿里云的PyPI镜像,由于该镜像没有使用HTTPS,所以要先将其设置为受信任的站点,当然也可以直接使用下面提供的其他HTTPS镜像。使用Windows的用户可以在用户主目录下创建`pip`文件夹(注意前面有没有点)并添加该配置文件,文件名为`pip.ini`
接下来创建项目和应用,通常我们会对项目中的功能进行垂直拆分,因此需要创建多个应用来对应不同的功能模块。
```Shell
django-admin startproject fang .
python manage.py startapp common
python manage.py startapp forum
python manage.py startapp rent
```
对项目的公共配置文件进行必要修改后,就可以通过反向工程(根据关系型数据库中的表来生成模型从而减少不必要的重复劳动)完成对模型类的创建,反向工程生成的模型可能需要适当的修改和调整才能应用于项目,尤其是存在多对多关系的时候。
```Shell
python manage.py inspectdb > common/models.py
```
如果需要使用Django的admin项目或者第三方xadmin,还需要执行迁移操作来创建额外的数据库表。
```Shell
python manage.py migrate
```
至此,我们就可以将当前的工作纳入版本控制并同步到服务器。
```Shell
git add .
git commit -m '项目初始版本'
git push
```
### 日常开发
不管是使用“git-flow”还是“github-flow”,都不能够在master上面直接进行开发,对于后者要创建自己的分支并在上面进行开发。
```Shell
git checkout -b jackfrued
git add .
git commit -m '提交的原因'
git push origin jackfrued
git branch -d jackfrued
git checkout master
git pull
git checkout -b jackfrued
```
## 项目部署上线指南
### 更新Python环境到3.x
```Shell
yum -y install gcc zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
xz -d Python-3.7.0.tar.xz
tar -xvf Python-3.7.0.tar
cd Python-3.7.0
./configure --prefix=/usr/local/python3 --enable-optimizations
make && make install
cd ~
vim .bash_profile
export PATH=$PATH:/usr/local/python3/bin
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
```
### 项目目录结构
下面是项目的目录结构,四个文件夹`conf``logs``src``venv`分别用来保存项目的配置文件、日志文件、源代码和虚拟环境。`conf`目录下的子目录`cert`中保存了配置HTTPS需要使用的证书和密钥。
```
project
├── conf
│   ├── cert
│   │   ├── 214915882850706.key
│   │   └── 214915882850706.pem
│   ├── nginx.conf
│   └── uwsgi.ini
├── logs
│   ├── access.log
│   ├── error.log
│   └── uwsgi.log
├── requirements.txt
├── src
│   └── fang
│   ├── common
│   ├── fang
│   ├── forum
│   ├── manage.py
│   ├── README.md
│   ├── rent
│   ├── static
│   └── templates
│  
└── venv
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── celery
│   ├── celerybeat
│   ├── celeryd
│   ├── celeryd-multi
│   ├── coverage
│   ├── coverage3
│   ├── coverage-3.7
│   ├── django-admin
│   ├── django-admin.py
│   ├── easy_install
│   ├── easy_install-3.7
│   ├── pip
│   ├── pip3
│   ├── pip3.7
│   ├── __pycache__
│   ├── pyrsa-decrypt
│   ├── pyrsa-decrypt-bigfile
│   ├── pyrsa-encrypt
│   ├── pyrsa-encrypt-bigfile
│   ├── pyrsa-keygen
│   ├── pyrsa-priv2pub
│   ├── pyrsa-sign
│   ├── pyrsa-verify
│   ├── python -> python3
│   ├── python3 -> /usr/bin/python3
│   └── uwsgi
├── include
├── lib
│   └── python3.7
├── lib64 -> lib
├── pip-selfcheck.json
└── pyvenv.cfg
```
### uWSGI的配置
可以激活项目的虚拟环境并通过pip安装uWSGI。
```Shell
pip install uwsgi
```
`/root/project/conf/uwsgi.ini`
```INI
[uwsgi]
# 配置前导路径
base=/root/project
# 配置项目名称
name=fang
# 守护进程
master=true
# 进程个数
processes=4
# 虚拟环境
pythonhome=%(base)/venv
# 项目地址
chdir=%(base)/src/%(name)
# 指定python解释器
pythonpath=%(pythonhome)/bin/python
# 指定uwsgi文件
module=%(name).wsgi
# 通信的地址和端口(自己服务器的IP地址和端口)
socket=172.18.61.250:8000
# 日志文件地址
logto = %(base)/logs/uwsgi.log
```
可以先将“通信的地址和端口”项等号前面改为http来进行测试,如果没有问题再改回成socket,然后通过Nginx来实现项目的“动静分离”(静态资源交给Nginx处理,动态内容交给uWSGI处理)。
```Shell
uwsgi --ini uwsgi.ini &
```
### Nginx的配置
#### 全局配置
`/etc/nginx/nginx.conf`
```Nginx
# 全局配置
# 用户(可以设置为)
user root;
# 工作进程数(建议跟CPU的核数量一致)
worker_processes auto;
# 错误日志
error_log /var/log/nginx/error.log;
# 进程文件
pid /run/nginx.pid;
# 包含其他的配置
include /usr/share/nginx/modules/*.conf;
# 工作模式和连接上限
events {
use epoll;
worker_connections 1024;
}
# HTTP服务器相关配置
http {
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 访问日志
access_log /var/log/nginx/access.log main;
# 开启高效文件传输模式
sendfile on;
# 用sendfile传输文件时有利于改善性能
tcp_nopush on;
# 禁用Nagle来解决交互性问题
tcp_nodelay on;
# 客户端保持连接时间
keepalive_timeout 15;
types_hash_max_size 2048;
# 包含MIME类型的配置
include /etc/nginx/mime.types;
# 默认使用二进制流格式
default_type application/octet-stream;
# 包含其他配置文件
include /etc/nginx/conf.d/*.conf;
# 包含项目的Nginx配置文件
include /root/project/conf/*.conf;
}
```
#### 局部配置
`/root/project/conf/nginx.conf`
```Nginx
server {
listen 80;
server_name _;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
location / {
include uwsgi_params;
uwsgi_pass 172.18.61.250:8000;
}
location /static/ {
alias /root/project/src/fang/static/;
expires 30d;
}
}
```
到此为止,我们可以启动Nginx来访问我们的应用程序,HTTP和HTTPS都是没有问题的,如果Nginx已经运行,在修改配置文件后,我们可以用下面的命令重新启动Nginx。
```Shell
nginx -s reload
```
#### 负载均衡配置
下面的配置中我们使用Nginx为HTTP、HTTPS以及Redis配置负载均衡。
```Nginx
user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
stream {
upstream redis.local {
server 172.18.61.250:36379;
server 172.18.61.250:46379;
server 172.18.61.250:56379;
}
server {
listen 6379;
proxy_pass redis.local;
}
}
http {
upstream fang.com {
server 172.18.61.250:801;
server 172.18.61.250:802;
server 172.18.61.250:803;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
ssl_certificate /root/project/conf/cert/214915882850706.pem;
ssl_certificate_key /root/project/conf/cert/214915882850706.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_pass http://fang.com;
}
}
}
```
> 说明:上面的配置文件中的Nginx服务器(3个节点)和Redis服务器(2个节点,每个节点是1个master和2个slave的配置)都是通过Docker来创建的,实际部署的时候无论是否使用Docker进行部署,这些主机应该都是独立的服务器。
### Keepalived
当使用Nginx进行负载均衡配置时,要考虑负载均衡服务器宕机的情况。为此可以使用Keepalived来实现负载均衡主机和备机的热切换,从而保证系统的高可用性。Keepalived的配置还是比较复杂,通常由专门做运维的人进行配置,一个基本的配置可以参照[《Keepalived的配置和使用》](https://www.jianshu.com/p/dd93bc6d45f5)
### Docker
事实上,项目上线中最为麻烦的事情就是配置软件运行环境,环境的差异会给软件的安装和部署带来诸多的麻烦,而Docker正好可以解决这个问题。关于Docker在之前的文档中我们已经介绍过了,接下来我们对Docker的知识做一些必要的补充。
1. 创建镜像文件。
将容器保存成镜像:
```Shell
docker commit -m "..." -a "..." <container-name> jackfrued/<image-name>
```
使用Dockerfile构建镜像:
```Dockerfile
# 指定基础镜像文件
FROM centos:latest
# 指定维护者信息
MAINTAINER jackfrued
# 执行命令
RUN yum -y gcc
RUN cd ~
RUN mkdir -p project/src
RUN mkdir -p project/logs
# 拷贝文件
COPY ...
# 暴露端口
EXPOSE ...
# 在容器启动时执行命令
CMD ~/init.sh
```
```Shell
docker build -t jackfrued/<image-name> .
```
2. 镜像的导入和导出。
```Shell
docker save -o <file-name>.tar <image-name>:<version>
docker load -i <file-name>.tar
```
3. 推送到DockerHub服务器。
```Shell
docker tag <image-name>:<version> jackfrued/<name>
docker login
docker push jackfrued/<name>
```
4. 容器之间的通信。
```Shell
docker run --link <container-name>:<alias-name>
```
我们在Docker中完成项目的部署,并且将整个部署好的容器打包成镜像文件进行分发和安装,这样就可以解决项目在多个节点上进行部署时可能遇到的麻烦。
\ No newline at end of file
## 团队项目开发
### Day01
1. 企业项目开发团队构成和角色:帮助学生了解项目中的角色及其关系,以小组为单位定义角色。
2. 项目开发流程(软件过程模型)以及各个阶段涉及的相关文档。
3. 团队开发相关工具介绍和环境搭建。
4. 项目选题和理解业务。
### Day02
1. 业务讲解和需求评审。
2. 数据库设计、接口设计、接口文档编撰。
3. 模块划分、任务分配和项目进度安排。
### Day03~Day07
1. 日常开发,每日代码和进度审查。
2. 集中解决项目开发中遇到的公共问题。
3. 项目技术重点难点及其相关技术剖析。
4. 之前未覆盖到的新技术讲解(例如:第三方授权登录、推送机制、消息队列的应用)。
### Day08
1. 单元测试。
2. 集成测试。
3. 接口测试。
4. Selenium自动化测试。
5. 性能测试(压力测试)及其相关工具。
- Apache Benchmark
- SQLSlap
- WebBench
### Day09
1. MySQL性能优化相关。
- SQL优化(执行计划、慢查询分析)
- 读写分离
- 集群配置
- 架构优化
2. 基于Redis的缓存、主从复制、哨兵和集群配置、切片。
3. 日志分析和漏洞分析。
### Day10
1. 项目部署环境搭建。
2. Nginx反向代理配置。
3. Nginx+KeepAlived集群环境配置。
4. HTTPS配置(密钥、证书、配置)。
5. 项目运维相关。
### Day11
1. 虚拟化技术和虚拟化容器。
2. Docker的安装和使用。
3. Docker镜像和虚拟化部署。
### Day12
1. ShowCase
2. 项目评审和总结
### Day13~Day15
1. 模拟面试。
2. 简历指导。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册