diff --git "a/Day76-90/code/.ipynb_checkpoints/1-pandas\345\205\245\351\227\250-checkpoint.ipynb" "b/Day76-90/code/.ipynb_checkpoints/1-pandas\345\205\245\351\227\250-checkpoint.ipynb" new file mode 100644 index 0000000000000000000000000000000000000000..b5b3acc8b66de0cdcc01778d81d566fdc93bed4e --- /dev/null +++ "b/Day76-90/code/.ipynb_checkpoints/1-pandas\345\205\245\351\227\250-checkpoint.ipynb" @@ -0,0 +1,631 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from pandas import Series,DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Math 120\n", + "Python 136\n", + "En 128\n", + "Chinese 99\n", + "dtype: int64" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# 创建\n", + "# Series是一维的数据\n", + "s = Series(data = [120,136,128,99],index = ['Math','Python','En','Chinese'])\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(4,)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([120, 136, 128, 99], dtype=int64)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v = s.values\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "numpy.ndarray" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "120.75" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "136" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.max()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15.903353943953666" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.std()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Math 14400\n", + "Python 18496\n", + "En 16384\n", + "Chinese 9801\n", + "dtype: int64" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s.pow(2)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
PythonEnMath
a11311675
b1914523
c57107113
d95366
e28121120
f14185132
h1243910
i803517
j689931
k741211
\n", + "
" + ], + "text/plain": [ + " Python En Math\n", + "a 113 116 75\n", + "b 19 145 23\n", + "c 57 107 113\n", + "d 95 3 66\n", + "e 28 121 120\n", + "f 141 85 132\n", + "h 124 39 10\n", + "i 80 35 17\n", + "j 68 99 31\n", + "k 74 12 11" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# DataFrame是二维的数据\n", + "# excel就非常相似\n", + "# 所有进行数据分析,数据挖掘的工具最基础的结果:行和列,行表示样本,列表示的是属性\n", + "df = DataFrame(data = np.random.randint(0,150,size = (10,3)),index = list('abcdefhijk'),columns=['Python','En','Math'])\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(10, 3)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[113, 116, 75],\n", + " [ 19, 145, 23],\n", + " [ 57, 107, 113],\n", + " [ 95, 3, 66],\n", + " [ 28, 121, 120],\n", + " [141, 85, 132],\n", + " [124, 39, 10],\n", + " [ 80, 35, 17],\n", + " [ 68, 99, 31],\n", + " [ 74, 12, 11]])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v = df.values\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Python 79.9\n", + "En 76.2\n", + "Math 59.8\n", + "dtype: float64" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Python 141\n", + "En 145\n", + "Math 132\n", + "dtype: int32" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.max()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
PythonEnMath
a11311675
b1914523
c57107113
d95366
e28121120
f14185132
h1243910
i803517
j689931
k741211
\n", + "
" + ], + "text/plain": [ + " Python En Math\n", + "a 113 116 75\n", + "b 19 145 23\n", + "c 57 107 113\n", + "d 95 3 66\n", + "e 28 121 120\n", + "f 141 85 132\n", + "h 124 39 10\n", + "i 80 35 17\n", + "j 68 99 31\n", + "k 74 12 11" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Python 79.9\n", + "En 76.2\n", + "Math 59.8\n", + "dtype: float64" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.mean(axis = 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "a 101.333333\n", + "b 62.333333\n", + "c 92.333333\n", + "d 54.666667\n", + "e 89.666667\n", + "f 119.333333\n", + "h 57.666667\n", + "i 44.000000\n", + "j 66.000000\n", + "k 32.333333\n", + "dtype: float64" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.mean(axis = 1)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git "a/Day76-90/code/1-pandas\345\205\245\351\227\250.ipynb" "b/Day76-90/code/1-pandas\345\205\245\351\227\250.ipynb" index 2f2567007853f7788b25f35afa871ffa59b1136e..b5b3acc8b66de0cdcc01778d81d566fdc93bed4e 100644 --- "a/Day76-90/code/1-pandas\345\205\245\351\227\250.ipynb" +++ "b/Day76-90/code/1-pandas\345\205\245\351\227\250.ipynb" @@ -322,7 +322,7 @@ ], "source": [ "# DataFrame是二维的数据\n", - "# excel就非诚相似\n", + "# excel就非常相似\n", "# 所有进行数据分析,数据挖掘的工具最基础的结果:行和列,行表示样本,列表示的是属性\n", "df = DataFrame(data = np.random.randint(0,150,size = (10,3)),index = list('abcdefhijk'),columns=['Python','En','Math'])\n", "df" @@ -623,7 +623,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.5" + "version": "3.7.3" } }, "nbformat": 4, diff --git "a/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\345\207\206\345\244\207.md" "b/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\345\207\206\345\244\207.md" deleted file mode 100644 index d9acf2e1e9272fed9de3b8d5f7189d4bdf2870fd..0000000000000000000000000000000000000000 --- "a/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\345\207\206\345\244\207.md" +++ /dev/null @@ -1,233 +0,0 @@ -## 团队项目开发准备 - -我们经常听到个人开发和团队开发这两个词,所谓个人开发就是一个人把控产品的所有内容;而团队开发则是由多个人组成团队并完成产品的开发。要实施团队开发以下几点是必不可少的: - -1. 必须对开发过程中的各种事件(例如:谁到什么时间完成了什么事情)进行管理和共享。 -2. 各类工作成果以及新的知识技巧等必须在团队内部共享。 -3. 管理工作成果的变更,既要防止成果被破坏,又要保证各个成员利用现有成果并行作业。 -4. 能够证明团队开发出的软件在任何时候都是可以正常运行的。 -5. 尽可能的使用自动化的工作流程,让团队成员能够正确的实施开发、测试和部署。 - -### 团队项目开发常见问题 - -#### 问题1:传统的沟通方式无法确定处理的优先级 - -例如:使用邮件进行沟通可能出现邮件数量太多导致重要的邮件被埋没,无法管理状态,不知道哪些问题已经解决,哪些问题尚未处理,如果用全文检索邮件的方式来查询相关问题效率过于低下。 - -解决方案:使用缺陷管理工具。 - -#### 问题2:没有能够用于验证的环境 - -例如:收到项目正式环境中发生的故障报告后,需要还原正式环境需要花费很长的时间。 - -解决方法:实施持续交付。 - -#### 问题3:用别名目录管理项目分支 - -解决方法:实施版本控制。 - -#### 问题4:重新制作数据库非常困难 - -例如:正式环境和开发环境中数据库表结构不一致或者某个表列的顺序不一致。 - -解决方法:实施版本控制。 - -#### 问题5:不运行系统就无法察觉问题 - -例如:解决一个bug可能引入其他的bug或者造成系统退化,不正确的使用版本系统覆盖了其他人的修改,修改的内容相互发生了干扰,如果问题不能尽早发现,那么等过去几个月后再想追溯问题就非常麻烦了。 - -解决方法:实施持续集成,将团队成员的工作成果经常、持续的进行构建和测试。 - -#### 问题6:覆盖了其他成员修正的代码 - -解决方法:实施版本控制。 - -#### 问题7:无法实施代码重构 - -重构:在不影响代码产生的结果的前提下对代码内部的构造进行调整。 - -例如:在实施代码重构时可能引发退化。 - -解决方法:大量的可重用的测试并实施持续集成。 - -#### 问题8:不知道bug的修正日期无法追踪退化 - -解决方法:版本控制系统、缺陷管理系统和持续集成之间需要交互,最好能够和自动化部署工具集成到一起来使用。 - -#### 问题9:发布过程太复杂 - -解决方法:实施持续交付。 - -基于对上述问题的阐述和分析,我们基本上可以得到以下的结论,在团队开发中版本控制、缺陷管理和持续集成都是非常重要且不可或缺的。 - -### 版本控制 - -针对上面提到的一些问题,在团队开发的首要前提就是实施版本控制,对必要的信息进行管理,需要管理的内容包括: - -1. 代码。 -2. 需求和设计的相关文档。 -3. 数据库模式和初始数据。 -4. 配置文件。 -5. 库的依赖关系定义。 - -#### Git简介 - -![](./res/git-logo.png) - -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 ... -``` - -可以用下面的方式将暂存区的指定文件恢复到工作区。 - -```Shell -git checkout -- -``` - -通过下面的命令可以将暂存区的内容纳入本地仓库。 - -```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 -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 -``` - -在自己的分支上进行开发。 - -```Shell -git branch -git checkout -``` - -或者 - -```Shell -git checkout -b -``` - -接下来可以先在本地实施版本控制(操作的方式与前面相同不再赘述),然后再将自己的分支Push到服务器。 - -```Shell -git push origin -``` - -最后,当工作完成时,可以发起一个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)也是一个非常重要的基础。按照经典的软件过程模型(瀑布模型),集成的工作一般要等到所有的开发工作都结束后才能开始,但这个时候如果发现了问题,修复问题的代价是非常具体的。基本上,集成实施得越晚,代码量越大,解决问题就越困难。持续集成将版本控制、自动化构建、代码测试融入到一起,让这些工作变得自动化和可协作。由于其频繁重复整个开发流程(在指定时间内多次pull源代码并运行测试代码),所以能帮助开发者提早发现问题。 - -在所有的CI工具中,Jenkins和TravisCI是最具有代表性的。 - -![](./res/jenkins_new_project.png)Jenkins 是基 Java的开源CI工具,其安装和操作都很简单。另外,Jenkins不仅能在面板上轻松看出任务成功或失败,还可以借助通知功能将结果以邮件或RSS订阅的形式发给用户。与此同时,Jenkins也允许通过插件进行功能扩展,所需功能可以随用随添加,而且还支持主从式集群,能够轻松的进行水平扩展。 \ No newline at end of file diff --git "a/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\347\232\204\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263\346\226\271\346\241\210.md" "b/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\347\232\204\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263\346\226\271\346\241\210.md" new file mode 100644 index 0000000000000000000000000000000000000000..f26d0ec616ee0471bac0ac25bf3af663ba1728d0 --- /dev/null +++ "b/Day91-100/91.\345\233\242\351\230\237\351\241\271\347\233\256\345\274\200\345\217\221\347\232\204\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263\346\226\271\346\241\210.md" @@ -0,0 +1,363 @@ +## 团队项目开发的问题和解决方案 + +我们经常听到个人开发和团队开发这两个词,所谓个人开发就是一个人把控产品的所有内容;而团队开发则是由多个人组成团队并完成产品的开发。要实施团队开发以下几点是必不可少的: + +1. 对开发过程中的各种事件(例如:谁到什么时间完成了什么事情)进行管理和共享。 +2. 在团队内部共享各类工作成果以及新的知识技巧等。 +3. 管理工作成果的变更,既要防止成果被破坏,又要保证各个成员利用现有成果并行作业。 +4. 证明团队开发出的软件在任何时候都是可以正常运行的。 +5. 使用自动化的工作流程,让团队成员能够正确的实施开发、测试和部署。 + +### 团队项目开发常见问题 + +#### 问题1:传统的沟通方式无法确定处理的优先级 + +例如:使用邮件进行沟通可能出现邮件数量太多导致重要的邮件被埋没,无法管理状态,不知道哪些问题已经解决,哪些问题尚未处理,如果用全文检索邮件的方式来查询相关问题效率过于低下。 + +解决方案:使用缺陷管理工具。 + +#### 问题2:没有能够用于验证的环境 + +例如:收到项目正式环境中发生的故障报告后,需要还原正式环境需要花费很长的时间。 + +解决方法:实施持续交付。 + +#### 问题3:用别名目录管理项目分支 + +解决方法:实施版本控制。 + +#### 问题4:重新制作数据库非常困难 + +例如:正式环境和开发环境中数据库表结构不一致或者某个表列的顺序不一致。 + +解决方法:实施版本控制。 + +#### 问题5:不运行系统就无法察觉问题 + +例如:解决一个bug可能引入其他的bug或者造成系统退化,不正确的使用版本系统覆盖了其他人的修改,修改的内容相互发生了干扰,如果问题不能尽早发现,那么等过去几个月后再想追溯问题就非常麻烦了。 + +解决方法:实施持续集成,将团队成员的工作成果经常、持续的进行构建和测试。 + +#### 问题6:覆盖了其他成员修正的代码 + +解决方法:实施版本控制。 + +#### 问题7:无法实施代码重构 + +重构:在不影响代码产生的结果的前提下对代码内部的构造进行调整。 + +例如:在实施代码重构时可能引发退化。 + +解决方法:大量的可重用的测试并实施持续集成。 + +#### 问题8:不知道bug的修正日期无法追踪退化 + +解决方法:版本控制系统、缺陷管理系统和持续集成之间需要交互,最好能够和自动化部署工具集成到一起来使用。 + +#### 问题9:发布过程太复杂 + +解决方法:实施持续交付。 + +基于对上述问题的阐述和分析,我们基本上可以得到以下的结论,在团队开发中版本控制、缺陷管理和持续集成都是非常重要且不可或缺的。 + +### 版本控制 + +针对上面提到的一系列问题,我们可以得出一个简单的结论,版本控制是实施团队开发的首要前提,必须通过版本控制对产品研发过程中产生的各种信息进行管理,这些内容包括: + +1. 代码。 +2. 需求和设计的相关文档。 +3. 数据库模式和初始数据。 +4. 配置文件。 +5. 库的依赖关系定义。 + +#### Git简介 + +![](./res/git-logo.png) + +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下载链接并进行安装,macOS和Windows平台下安装Git都非常简单,Linux下如果要安装官方最新的版本,建议通过官方提供的Git源代码进行构建安装,步骤如下所示(以CentOS为例)。 + +下载Git源代码压缩文件。 + +```Shell +wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.23.0.tar.xz +``` + +解压缩和解归档。 + +```Shell +xz -d git-2.23.0.tar.xz +tar -xvf git-2.23.0.tar +``` + +安装底层依赖库。 + +```Shell +yum -y install libcurl-devel +``` + +安装前的配置。 + +```Shell +cd git-2.23.0 +./configure --prefix=/usr/local +``` + +构建和安装。 + +```Shell +make && make install +``` + +安装成功后可以在终端中键入下面的命令检查自己的Git版本。 + +```Shell +git --version +``` + +如果之前完全没有接触过Git,可以先阅读[《git - 简易指南》](http://www.bootcss.com/p/git-guide/)来对Git有一个大致的了解。 + +#### Git本地操作 + +可以使用下面的命令将一个文件夹变成Git仓库。 +```Shell +git init +``` + +当你完成了上述操作后,本地目录就变成了下面的样子,下图左边是你的工作区(正在操作的工作目录),而右边是你的本地仓库,中间是工作区和本地仓库之间的暂存区(也称为缓存区)。 + +![](./res/git_repository.png) + +> **提示**:用`ls -la`查看所有文件会发现在执行完上面的命令后,文件夹下多了一个名为`.git`的隐藏文件夹,这个文件夹就是Git版本仓库。 + +通过`git add`可以将指定的文件或所有文件添加到暂存区。 + +```Shell +git add +git add . +``` + +这个时候使用下面的命令可以查看工作区、暂存区和本地仓库的状态。 + +```Shell +git status +``` + +如果不希望将文件添加到暂存区,可以按照提示,使用下面的命令将文件从暂存区放回到工作区。 + +```Shell +git rm --cached +``` + +如果这个时候对工作区的文件又进行了修改使得工作区和暂存区的内容并不相同了,再次执行`git status`可以看到哪个或哪些文件被修改了,如果希望用暂存区的内容恢复工作区,可以使用下面的命令。 + +```Shell +git restore +git restore . +``` + +> 提示:上面的命令目前仍然处于试验性阶段,在Git较早的版本中对应的命令是`git checkout -- `。由于`git checkout`这个命令还可以用于切换分支,容易引起混淆,所以Git最新版本中将这个命令的两项功能分别赋予两个新的命令,一个就是上面的`git restore`,另一个是`git switch`。 + +如果第一次使用Git,需要配置用户名和邮箱,然后才能将代码提交到仓库。 + +```Shell +git config --global user.name "jackfrued" +git config --global user.email "jackfrued@126.com" +``` + +> **提示**:可以用`git config --list`来查看Git的配置信息。 + +通过下面的命令可以将暂存区的内容纳入本地仓库, + +```Shell +git commit -m '本次提交的说明' +``` + +可以通过`git log`查看提交日志。 + +```Shell +git log +git log --graph --pretty=oneline --abbrev-commit +``` + +如果要回到历史版本,可以使用下面的命令。 + +```Shell +git reset --hard +git reset --hard HEAD^ +``` + +#### Git服务器概述 + +Git不像SVN那样一定需要中央服务器才能工作,上面我们演示的版本控制操作都是在本地执行的,但是对于企业开发多人协作这样的环境就必须中央服务器的支持。通常,企业可以选择使用像Github这样的代码托管平台或自己搭建Git私服的方式来建立中央服务器。Github是一个基于Git的代码托管平台,企业用户(付费用户)可以创建私有仓库(仓库内容不对外公开),普通用户只能创建公开仓库(仓库内容对他人可见)。Github创办于2008年4月,目前是全世界最大的代码托管平台,它上面代码库惊人的增长速度也证明了它是非常成功的,在2018年6月被微软以75亿美元的天价收购,目前该平台已经向非企业用户开放了受限使用私有仓库的功能。 + +国内也有不少类似Github的代码托管平台,最有名的当属[码云](https://gitee.com/)和[CODING](https://coding.net/),目前码云和CODING对注册用户都提供了受限的使用私有仓库的功能,支持**Pull Request**(本质是一种对话机制,可以在提交你的工作成果时让相关人员或团队注意到这件事情),同时还提供了对**缺陷管理**、**Web Hook**等功能支持,这些使得版本控制系统还具备了缺陷管理和持续集成的能力。当然,很多公司都不愿意将自己的商业代码托管于别人的平台,对于这样的公司可以使用[Gitlab]()来搭建公司内部的Git私服,具体的做法在下一章为大家介绍。 + +![](./res/gitlab-about.png) + +这里我们直接以码云为例来说明Git服务器使用的一些注意事项。首先需要在码云上注册账号,当然也可以使用第三方登录(github账号、微信账号、新浪微博账号、CSDN账号等),登录成功后就可以创建项目,创建项目几乎是“傻瓜式”的,无需赘述,我们只对几个地方加以说明。 + +1. 创建项目时不建议勾选如下图所示的这些选项,编程语言可以暂时不做选择,而`.gitignore`模板也可以稍后自己编写或者通过更专业的工具(如:网站)自动生成。 + + ![](./res/gitee-create-project.png) + +2. 添加项目成员。创建项目后,可以在项目的“设置”或“管理”中找到“成员管理”功能,这样就可以将其他开发者设置为项目团队的成员,项目成员通常分为“所有者”、“管理者”、“普通成员”和“受限成员”几种角色。 + + ![](./res/gitee-add-members.png) + +3. 项目的分支。创建项目后,项目只有一个默认的**master**分支,应该将该分支设置为“保护分支”来避免项目管理者之外的成员修改该分支。 + +4. 设置公钥实现免密访问。在项目的“设置”或“管理”中我们还可以找到“部署公钥管理”的选项,通过添加部署公钥,可以通过SSH(安全远程连接)的方式访问服务器而不用每次输入用户名和口令。可以使用`ssh-keygen`命令来创建密钥对。 + + ```Shell + ssh-keygen -t rsa -b 2048 -C "your_email@example.com" + ``` + + > **说明**:上面命令生成的密钥对在`~/.ssh`目录下,公钥文件默认的名字为`id_rsa.pub`,可以通过`cat id_rsa.pub`来查看自己的公钥。Windows用户在安装Git之后,可以通过**Git Bash**来输入上面的命令。 + +#### Git远程操作 + +在拥有了Git服务器之后,我们就可以通过Git的远程操作将自己的工作成果推到服务器上,也可以将他人的工作成果从服务器更新到本地,我们还是以刚才在码云上创建的名为`python`的仓库为例来说明如何进行远程操作。 + +1. 指定远程主机(Git服务器)。 +2. 将本地代码(工作成果)推送到远程主机。 +3. 从远程主机取回代码。 + +#### Git分支操作 + +1. 创建分支和切换分支。 + + ```Shell + git branch + git switch + ``` + + 或 + + ```Shell + git switch -c + ``` + + > **提示**:在之前的Git版本中,切换分支使用`git checkout `命令,也可以通过`git checkout -b `来创建并切换分支。`git switch`命令目前仍然处于试验性阶段,但很明显这个命令更加清晰的表达了它要做的事情。 + +2. 分支合并和变基。 + +3. + +#### Git工作流程(分支管理策略) + +既然Git是团队开发必备的工具,那么在团队协作时就必须有一个规范的工作流程,这样才能让团队高效的工作,让项目顺利的进展下去,否则工具再厉害但团队成员各自为战,冲突就会无处不在,协作更加无从谈起。我们仍然以刚才码云上创建的`python`项目为例,来说明Git的分支管理策略。 + +##### Github-flow + +1. 克隆服务器上的代码到本地。 + + ```Shell + git clone + ``` + +2. 创建并切换到自己的分支。 + + ```Shell + git switch -c + ``` + +3. 在自己的分支上开发并在本地做版本控制。 + +4. 将自己的分支(工作成果)推到服务器。 + + ```Shell + git push + ``` + +5. 在线发起一次合并请求(通常称之为**Pull Request**,有的地方称为**Merge Request**),请求将自己的工作成果合并到master分支,合并之后可以删除该分支。 + + ![](./res/gitee-pull-request.png) + +上面这种分支管理策略就是被称为github-flow或PR的流程,它非常简单容易理解,只需要注意以下几点: + +1. master的内容都是可以进行发布的内容(不能直接在master上进行修改)。 +2. 开发时应该以master为基础建立新分支(日常开发任务在自己的分支上进行)。 +3. 分支先在本地实施版本控制,然后以同名分支定期向服务器进行push操作。 +4. 开发任务完成后向master发送合并请求。 +5. 合并请求通过审查之后合并到master,并从master向正式环境发布。 + +当然,github-flow的缺点也很明显,master分支默认就是当前的线上代码,但是有的时候工作成果合并到master分支,并不代表它就能立刻发布,这样就会导致线上版本落后于master分支。 + +##### Git-flow + +除了上述的github-flow分支管理策略外,还有一种名为git-flow的分支管理策略,它也是大多数公司愿意使用的一套流程。Git-flow借鉴了中央集权型版本控制系统的长处,为团队内部统一建立、合并和关闭分支的方法,如下图所示。 + +![](./res/git-flow.png) + +在这种模式下,项目有两个长线分支,分别是master和develop,其他都是临时的的辅助分支,包括feature(开发特定功能的分支,开发结束后合并到develop)、release(从develop分离出来的为发布做准备的分支,发布结束后合并到master和develop)和hotfix(产品发布后出现问题时紧急建立的分支,直接从master分离,问题修复后合并到master并打上标签,同时还要合并到develop来避免将来的版本遗漏了这个修复工作,如果此时有正在发布中的release分支,还要合并到release分支)。这套分支管理策略比较容易控制各个分支的状况,但是在运用上github-flow要复杂得多,所以实际使用的时候可以安装名为`gitflow`的命令行工具或者使用图形化的Git工具(如:SmartGit、SourceTree等),这样可以大幅度的简化版本控制操作,具体的可以参考[《git-flow 的工作流程》]()一文。 + +### 缺陷管理 + +没有好的团队管理工具必然导致项目进展不顺利,任务管理困难,而引入缺陷管理系统正好可以解决这些问题,通常一个缺陷管理系统都包含了以下的功能: + +1. 任务管理(包括必须做什么、谁来做、什么时候完成、现在处于什么状态等)。 +2. 直观而且可以检索过去发生的各种问题。 +3. 能够对信息进行统一的管理和共享。 +4. 能够生成各类报表。 +5. 能够关联到其他系统,具有可扩展性。 + +#### Redmine + +Redmine是基于Ruby on Rails框架的开源缺陷管理系统,提供了问题管理、代码管理、Wiki等必要的功能,而且支持插件系统,扩展起来也非常容易。 + +![](./res/redmine_new_issue.png) + +如果希望了解和使用Redmine,可以关注[Redmine中文网](http://www.redmine.org.cn/),上面提供了视频教程、经验分享以及其他安装和使用上的指导。 + +#### 禅道 + +[禅道]()是国产的专业项目管理软件,它不仅仅是缺陷管理工具,它提供了完整软件生命周期管理功能,支持Scrum敏捷开发,能够实现需求管理、缺陷管理、任务管理等一系列的功能,而且拥有强大的扩展机制和丰富的功能插件。可以从禅道的官方网站提供的[下载链接]()来下载禅道,推荐使用一键安装包。 + +下面仍然以CentOS Linux为例,讲解如何利用官方提供的一键安装包来安装禅道。 + +```Shell +cd /opt +wget http://dl.cnezsoft.com/zentao/pro8.5.2/ZenTaoPMS.pro8.5.2.zbox_64.tar.gz +gunzip ZenTaoPMS.pro8.5.2.zbox_64.tar.gz +tar -xvf ZenTaoPMS.pro8.5.2.zbox_64.tar +``` + +我们在`/opt`目录下(官方推荐使用这个目录)下载了禅道的归档压缩文件,并进行了解压缩和解归档的操作,完成上述步骤后,会看到一个名为`zbox`的文件夹。一键安装包中内置了Apache、MySQL、PHP等应用,也就是说这些都不需要单独安装部署了,接下来我们通过下面的命令来启动禅道。 + +```Shell +/opt/zbox/zbox -ap 8080 -mp 3307 +/opt/zbox/zbox start +``` + +> 说明:上面使用`zbox`文件夹下的`zbox`命令,其中`-ap`是为了指定Apache服务器使用的端口,`-mp`是为了指定MySQL数据库使用的端口;`start`表示启动服务,`stop`可以用来停止服务。此外,需要打开防火墙8080端口以便访问禅道(Apache服务器)。 + +打开浏览器,输入服务器的IP地址就可以访问禅道,如果愿意,也可以通过DNS解析绑定一个域名来进行访问,禅道的首页如下图所示,默认的管理员是`admin`,口令是`123456`。 + +![](./res/zentao-login.png) + +第一次使用禅道时,建议通过点击用户名,然后通过“帮助”菜单的“新手教程”来迅速了解禅道。官方网站的文档链接中提供了[视频教程](),初学者也可以通过视频教程来上手。 + +![](./res/zentao-index.png) + +#### Gitlab + + + +### 持续集成 + +为了快速的产生高品质的软件,在团队开发中,持续集成(CI)也是一个非常重要的基础。按照经典的软件过程模型(瀑布模型),集成的工作一般要等到所有的开发工作都结束后才能开始,但这个时候如果发现了问题,修复问题的代价是非常具体的。基本上,集成实施得越晚,代码量越大,解决问题就越困难。持续集成将版本控制、自动化构建、代码测试融入到一起,让这些工作变得自动化和可协作。由于其频繁重复整个开发流程(在指定时间内多次pull源代码并运行测试代码),所以能帮助开发者提早发现问题。 + +在所有的CI工具中,Jenkins和[TravisCI]()是最具有代表性的,前者是基于 Java的开源CI工具,后者是新晋的在线CI工具。我们可以借助Docker来安装Jenkins(下一章节讲解),安装后……。Jenkins不仅能在面板上轻松看出任务成功或失败,还可以借助通知功能将结果以邮件或RSS订阅的形式发给用户。与此同时,Jenkins也允许通过插件进行功能扩展,所需功能可以随用随添加,而且还支持主从式集群,能够轻松的进行水平扩展。 + +![](./res/jenkins_new_project.png) \ No newline at end of file diff --git "a/Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\346\234\215\345\212\241.md" "b/Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\345\272\224\347\224\250.md" similarity index 93% rename from "Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\346\234\215\345\212\241.md" rename to "Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\345\272\224\347\224\250.md" index 33481d85ca6c3347f888f31533315ad08744f4ed..be4b3c28efb5817b2aba0c878c5b1519ee94ec72 100644 --- "a/Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\346\234\215\345\212\241.md" +++ "b/Day91-100/92.\344\275\277\347\224\250Docker\351\203\250\347\275\262\345\272\224\347\224\250.md" @@ -1,4 +1,4 @@ -## 使用Docker部署服务 +## 使用Docker部署应用 ### Docker简介 @@ -112,7 +112,7 @@ docker rmi hello-world > > 国内用户可以通过更换Ubuntu软件下载源来提升下载速度,具体请参照清华大学开源软件镜像站上的[《Ubuntu镜像使用帮助》]()。 -安装Docker后,由于直接访问[dockerhub](https://hub.docker.com/)下载镜像会非常缓慢,建议将服务器更换为国内镜像,可以通过修改 `/etc/docker/daemon.js` 文件来做到。 +安装Docker后,由于直接访问[dockerhub](https://hub.docker.com/)下载镜像会非常缓慢,建议将服务器更换为国内镜像,可以通过修改 `/etc/docker/daemon.js` 文件来做到。一般的云服务器会有自己专属的镜像,就不需要手动修改了。 ```JavaScript { @@ -125,9 +125,11 @@ docker rmi hello-world ### 使用Docker -#### 安装Nginx +想要玩转Docker,最简单的办法就是马上用Docker创建一些自己学习和工作中需要用到的容器,接下来我们就带着大家一起来创建这些容器。 -下面我们就基于Docker来创建一台HTTP服务器,我们选择用Nginx来搭建该服务,因为Nginx是高性能的Web服务器,同时也是做反向代理服务器的上佳选择。要做到这件事情,只需要使用下面的命令在Docker中创建一个容器即可。 +#### 运行Nginx + +Nginx是高性能的Web服务器,同时也是做反向代理服务器的上佳选择。使用Docker可以非常简单的创建一个运行Nginx的容器,命令如下所示。 ```Shell docker container run -d -p 80:80 --rm --name mynginx nginx @@ -191,7 +193,7 @@ docker rm mynginx docker rm -f mynginx ``` -#### 安装MySQL +#### 运行MySQL 我们再来尝试用Docker安装一台MySQL服务器,首先可以先检查一下有没有MySQL的镜像文件。 @@ -231,7 +233,9 @@ docker.io/mysql 5.7 f6509bac4980 3 weeks ago docker run -d -p 3306:3306 --name mysql57 -v $PWD/mysql/conf:/etc/mysql/mysql.cnf.d -v $PWD/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 ``` -注意,上面创建容器时我们又一次使用了数据卷操作,那是因为通常容器是随时创建随时删除的,而数据库中的数据却是需要保留下来的,所以上面的两个数据卷操作一个是映射了MySQL配置文件所在的文件夹,一个是映射了MySQL数据所在的文件夹,这里的数据卷操作非常重要。我们可以将MySQL的配置文件放在`$PWD/mysql/conf`目录下,配置文件的具体内容如下所示: +> **注意**:上面创建容器时我们又一次使用了数据卷操作,那是因为通常容器是随时创建随时删除的,而数据库中的数据却是需要保留下来的。 + +上面的两个数据卷操作一个是映射了MySQL配置文件所在的文件夹,一个是映射了MySQL数据所在的文件夹,这两个数据卷操作非常重要。我们可以将MySQL的配置文件放在`$PWD/mysql/conf`目录下,配置文件的具体内容如下所示: ```INI [mysqld] @@ -289,7 +293,7 @@ select user, host, plugin, authentication_string from user where user='root'; 在完成上面的步骤后,现在即便不更新客户端工具也可以连接MySQL 8.x了。 -#### 安装Redis +#### 运行Redis 接下来我们试一试运行多个容器并让多个容器之间通过网络通信。我们创建4个Redis容器来实现一主三从的主从复制结构。 @@ -329,9 +333,19 @@ repl_backlog_first_byte_offset:1 repl_backlog_histlen:1988 ``` +#### 运行Gitlab + + + +#### 运行Jenkins + + + ### 构建镜像 -Docker镜像是由文件系统叠加而成的,系统的最底层是bootfs,相当于就是Linux内核的引导文件系统;接下来第二层是rootfs,这一层可以是一种或多种操作系统(如Debian或Ubuntu文件系统),Docker中的rootfs是只读状态的;Docker利用联合挂载技术将各层文件系统叠加到一起,最终的文件系统会包含有底层的文件和目录,这样的文件系统就是一个镜像,如下图所示。 +通过上面的讲解,我们已经掌握了如何通过官方提供的镜像来创建容器。当然如果愿意,我们也可以用配置好的容器来生成镜像。简而言之,Docker镜像是由文件系统叠加而成的,系统的最底层是bootfs,相当于就是Linux内核的引导文件系统;接下来第二层是rootfs,这一层可以是一种或多种操作系统(如Debian或Ubuntu文件系统),Docker中的rootfs是只读状态的;Docker利用联合挂载技术将各层文件系统叠加到一起,最终的文件系统会包含有底层的文件和目录,这样的文件系统就是一个镜像,如下图所示。 + +![](./res/docker-image.png) 之前我们讲过了如何查找、列出镜像和拉取(下载)镜像,接下来看看构建镜像的两种方式: @@ -391,11 +405,9 @@ jackfrued/mywebserver latest 795b294d265a 14 seconds ago 189 MB Dockerfile使用DSL(Domain Specific Language)来构建一个Docker镜像,只要编辑好了Dockerfile文件,就可以使用`docker build`命令来构建一个新的镜像。 -我们先创建一个新的文件夹并在文件夹下创建名为Dockerfile的文件。 +我们先创建一个空文件夹并在文件夹下创建名为Dockerfile的文件。 ```Shell -mkdir test -cd test touch Dockerfile ``` @@ -422,6 +434,8 @@ EXPOSE 80 docker build -t="jackfrued/webserver" . ``` +> 提示:上面的命令最后面的`.` 千万不要漏掉了哦,它表示从当前路径下寻找Dockerfile。 + 通过下面的命令可以查看创建好的镜像。 ```Shell @@ -795,5 +809,5 @@ docker push jackfrued/webserver ... ... ``` - +### 集群管理 diff --git "a/Day91-100/94.\347\275\221\347\273\234API\346\216\245\345\217\243\350\256\276\350\256\241.md" "b/Day91-100/94.\347\275\221\347\273\234API\346\216\245\345\217\243\350\256\276\350\256\241.md" index df05a3f384f020e398b6037fa64f7eafe35b1ed3..22b20a9d1b2d2e7b723bcc83ac6eed5ccfad0aa5 100644 --- "a/Day91-100/94.\347\275\221\347\273\234API\346\216\245\345\217\243\350\256\276\350\256\241.md" +++ "b/Day91-100/94.\347\275\221\347\273\234API\346\216\245\345\217\243\350\256\276\350\256\241.md" @@ -1,6 +1,14 @@ ## 网络API接口设计 -手机App以及使用了Ajax技术或做了前后端分离的页面都需要通过网络API(Application Programming Interface)和后台进行交互,所谓API,指的应用程序的编程接口;而网络API通畅指的是基于HTTP或HTTPS协议的一个URL(统一资源定位符),通过这个URL我们可以让服务器对某个资源进行操作并返回操作的结果。基于HTTP(S)协议最大的好处就在于访问起来非常的简单方便,而且没有编程语言和应用环境上的差别。 +目前许多的Web应用和移动应用都使用了前后端分离的开发模式,前后端分离简单的说就是前端或移动端通过网络API接口和后台进行交互。API是应用程序的编程接口的缩写;网络API通常指的是基于一个URL(统一资源定位符)可以访问到的资源,也就是说通过这个URL我们可以让服务器对某个资源进行操作并返回操作的结果,复杂的业务逻辑被隐藏在简单的API接口中。URL的通用格式如下所示: + +``` +协议://用户名:口令@主机:端口/路径1/.../路径N/资源名 +``` + +> 说明:URL中的用户名(有可能不需要提供用户名)、口令(有可能不需要提供口令)、端口(有可能使用默认端口)、路径(资源有可能直接位于根路径`/`下)并不是必需的部分,可以根据需要进行设置。 + +网络API通常基于HTTP或HTTPS进行访问,基于HTTP/HTTPS最大的好处就在于访问起来非常的简单方便,而且可以跨语言、跨应用进行访问和互操作。 ### 设计原则 @@ -20,9 +28,9 @@ | 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接口并不是REST风格的。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”约束或者设置合理的默认值约束。 +API接口返回的数据通常都是**JSON**或**XML**格式,我们这里不会讲述XML的知识,因为这种格式几乎已经被淘汰掉了。对于JSON格式的数据,我们需要做到不要返回null这的值,因为这样的值一旦处置失当,会给前端和移动端开发带来不必要的麻烦(因为开发者有可能会使用强类型语言)。要解决这个问题可以从源头入手,在设计数据库的时候,尽量给每个字段都加上“not null”约束或者设置合理的默认值约束。 #### 其他问题 diff --git a/Day91-100/res/git-flow.png b/Day91-100/res/git-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..8426a5bdb6463a030156de444fcfa9c15f1294a1 Binary files /dev/null and b/Day91-100/res/git-flow.png differ diff --git a/Day91-100/res/git_logo.png b/Day91-100/res/git_logo.png deleted file mode 100644 index 04b0f00916355a6e8663e7c7cfe5096a14a9fb41..0000000000000000000000000000000000000000 Binary files a/Day91-100/res/git_logo.png and /dev/null differ diff --git a/Day91-100/res/gitee-add-members.png b/Day91-100/res/gitee-add-members.png new file mode 100644 index 0000000000000000000000000000000000000000..129926d7ed15c533a6a23c6682c2ce652af48507 Binary files /dev/null and b/Day91-100/res/gitee-add-members.png differ diff --git a/Day91-100/res/gitee-create-project.png b/Day91-100/res/gitee-create-project.png new file mode 100644 index 0000000000000000000000000000000000000000..c632d634a22834b92250f7ed7af8e8e36438dedb Binary files /dev/null and b/Day91-100/res/gitee-create-project.png differ diff --git a/Day91-100/res/gitlab-about.png b/Day91-100/res/gitlab-about.png new file mode 100644 index 0000000000000000000000000000000000000000..b4ba6c11d8df406ad3b7f115b7cead251efbb9d2 Binary files /dev/null and b/Day91-100/res/gitlab-about.png differ diff --git a/Day91-100/res/unlock-jenkins.png b/Day91-100/res/unlock-jenkins.png new file mode 100644 index 0000000000000000000000000000000000000000..9b88c19c40b419e6e3afe0edbdcd1ab89005217f Binary files /dev/null and b/Day91-100/res/unlock-jenkins.png differ diff --git a/Day91-100/res/zentao-index.png b/Day91-100/res/zentao-index.png new file mode 100644 index 0000000000000000000000000000000000000000..5c8491b8500fe5c42dd689fc673283897b169854 Binary files /dev/null and b/Day91-100/res/zentao-index.png differ diff --git a/Day91-100/res/zentao-login.png b/Day91-100/res/zentao-login.png new file mode 100644 index 0000000000000000000000000000000000000000..532700ad5b7b49a91cb0e4cd8d2358dd5dd02cd5 Binary files /dev/null and b/Day91-100/res/zentao-login.png differ diff --git a/README.md b/README.md index 8a9f100e26df9091d8620035afe969bc9d0972b4..79b0db52e16bda9179e49578c7d094357840442b 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ > 作者:骆昊 > -> 最近有很多想学习Python的小伙伴陆陆续续加入我们的交流群,目前我们的交流群人数已经超过一万人,光靠我自己已经无法及时处理小伙伴们的入群申请,更无法及时为大家解答问题。目前我的想法是分技术方向建立讨论群并安排专门的人来管理这些群,群管理者应该具备专业的知识并有相对充裕的时间,可以解答小伙伴们提出的问题。当然,我会向这些管理者支付报酬,如果有兴趣成为管理者的可以跟我私聊。但愿通过这种方式,我们的群能汇聚更多优秀的Python开发者,一方面打造一个优质的沟通和交流的平台,另一方面让新入行的开发者获得问道的途径并藉此迅速成长。我会继续努力做好线上公开课以及线下技术交流活动,也希望各位小伙伴一如既往的支持我们。创作不易,感谢大家的打赏支持,这些钱不会用于购买咖啡而是通过腾讯公益平台捐赠给需要帮助的人([点击](./更新日志.md)了解捐赠情况)。感谢**北京千锋互联科技有限公司**对[公开课](https://ke.qq.com/course/406954)提供的支持。 +> 最近有很多想学习Python的小伙伴陆陆续续加入我们的交流群,目前我们的交流群人数已经超过一万人。我们的目标是打造一个优质的Python交流社区,一方面为想学习Python的初学者扫平入门过程中的重重障碍;另一方为新入行的开发者提供问道的途径,帮助他们迅速成长为优秀的职业人;此外,有经验的开发者可以利用这个平台把自己的工作经验无偿分享或有偿提供出来,让大家都能够得到职业技能以及综合素质的全面提升。之前的公开课和线下技术交流活动因为工作的关系荒废了一段时间了,但是各位小伙伴仍然活跃在交流群并一如既往的支持我们,在此向大家表示感谢。近期开始持续更新前15天和最后10天的内容,前15天是写给初学者的,我希望把上手的难度进一步降低,例子程序更加简单清晰;最后10天是Python项目实战和面试相关的东西,我希望内容更详实和完整,尤其是第100天的面试题部分;创作不易,感谢大家的打赏支持,这些钱不会用于购买咖啡而是通过腾讯公益平台捐赠给需要帮助的人([点击](./更新日志.md)了解捐赠情况)。感谢**北京千锋互联科技有限公司**对[公开课](https://ke.qq.com/course/406954)提供的支持。 -![](./res/python_qq_group.jpg) +![](./res/python-qq-group.png) ### Python应用领域和就业形势分析 @@ -456,7 +456,7 @@ ### Day91~100 - [团队项目开发](./Day91-100) -#### 第91天:[团队项目开发准备](./Day91-100/91.团队项目开发准备.md) +#### 第91天:[团队项目开发的问题和解决方案](./Day91-100/91.团队项目开发的问题和解决方案.md) 1. 软件过程模型 - 经典过程模型(瀑布模型) @@ -568,11 +568,19 @@ python manage.py inspectdb > app/models.py ``` +#### 第92天:[使用Docker部署应用](./Day91-100/92.使用Docker部署应用.md) -#### 第92天:[Docker的使用](./Day91-100/92.Docker在项目中的应用.md) +1. Docker简介 +2. 安装Docker +3. 使用Docker创建容器(Nginx、MySQL、Redis、Gitlab、Jenkins) +4. 构建Docker镜像(Dockerfile的编写和相关指令) +5. 容器编排(Docker-compose) +6. 集群管理 #### 第93天:[MySQL性能优化](./Day91-100/93.MySQL性能优化.md) +1. + #### 第94天:[网络API接口设计](./Day91-100/94.网络API接口设计.md) #### 第95天:[使用Django开发商业项目](./Day91-100/95.使用Django开发商业项 目.md) diff --git a/res/python-qq-group.png b/res/python-qq-group.png new file mode 100644 index 0000000000000000000000000000000000000000..023d21d6159cfec1884a69a01ba3ec8e01adb900 Binary files /dev/null and b/res/python-qq-group.png differ diff --git a/res/python_qq_group.JPG b/res/python_qq_group.JPG deleted file mode 100644 index aeb364c9f4b27ddf4b976410e05544c4a6ae3755..0000000000000000000000000000000000000000 Binary files a/res/python_qq_group.JPG and /dev/null differ