第1次实践作业
一、课程调查
在开始这门课之前,我们已经接触了计算机系统结构这门课,对系统的一些方面有了一定的了解,所以对这门系统综合实践课程的初印象就是一门比较偏向硬件的课程,应该是要了解及掌握一些硬件系统的一些操作,最后应该会尝试实现一个系统吧。当然,这只是我个人的一个猜想。上学期的软工实践感觉像是放养型的,什么都要靠自己去学,说实话,想想还是有点害怕。而这门课感觉应该也是比较需要自己花时间去学习的,但是还是希望老师在实践的过程中可以给予一些相应的指导,相信在课程结束之后自己也会收获很多的。
二、了解微服务
1、微服务是什么
微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每一个服务运行在自己的进程中,服务间通信采用的轻量级通信机制(通常用Http资源API),这些服务围绕业务能力构建并且可通过全自动部署机制独立部署,这些服务公用一个最小型的集中式的管理,服务可用不同的语言开发,使用不同的数据存储技术。
2、微服务的特点
- 系统由多个服务组成,每个服务有明确的边界;
- 服务独立开发、编译、部署、测试、发布,有独立工程、独立版本、接口契约化,进程隔离;
- 服务小且灵活,由一个10人以下团队全生命周期负责,团队的目标负责产品的全生命周期,而不是负责一个短期的项目;
- 技术中立,不要求服务的编程语言统一。不同服务可以采用不同的编程语言实现,有利于逐步引入新技术。
- 智能服务端点和轻量级高性能通信机制。服务开发框架内置服务基本功能,如日志、度量、数据访问、输入校验、权限等,使得开发人员可以聚焦于业务服务的业务逻辑代码开发,降低了服务开发的门槛。
- 服务无状态,服务自动弹性伸缩。服务的无状态通过业务逻辑与数据分离,数据、会话保存在DB、Cache、对象存储等服务来实现;服务实例按需进行伸缩。
- 服务数据去中心化。每个服务拥有自己的数据库,服务不能直接访问其它服务的数据库,只能通过服务接口方案其它服务的数据。
- 服务去中心化治理。服务支持多版本并存、灰度发布、依赖关系管理、调用链分析快速故障定界。
- Design for failure。任意服务节点失效、网络闪断等故障不影响业务正常运行。
- 重用、组合已有的服务实现新的业务功能服务。业务应用在实现功能时,会调用已有的服务,如Cache、MQ、IAM等公共服务,实现自己的业务功能。
3、相较于传统的软件架构的优缺点
传统软件架构
优点:
- 开发简单,集中式管理
- 基本不会重复开发
- 功能都在本地,没有分布式的管理和调用消耗
缺点:
- 效率低:开发都在同一个项目改代码,相互等待,冲突不断
- 维护难:代码功功能耦合在一起,新人不知道何从下手
- 不灵活:构建时间长,任何小修改都要重构整个项目,耗时
- 稳定性差:一个微小的问题,都可能导致整个应用挂掉
- 扩展性不够:无法满足高并发下的业务需求
微服务软件架构
优点:
- 每个服务独立存在,所以可以单独部署,不用每次发布某个功能都经历一次全服务发布。
- 遵循单一zd功能原则,服务之间可以通过RESTFUL或者RPC调用,功能解藕。
- “细粒度” 的高可扩展性,每个服务都可以单独版扩展,单独负载均衡。
- 去中心化,尽可能地实现 “自服务”。
- 有利于简化单独的开发测试以及部署,对开发团队友好。
缺点:
- 服务的可用性和维护性高度依赖于服务治权理,如果治理得不好将会是灾难。
- 某些服务可能造成性能瓶颈,某些服务的宕机可能导致很多服务受影响。
- 服务配置繁琐。
4、微服务架构部署
(1)单主机单服务
在一台主机上部署一个服务。
优点:
- 服务实例互相分离。
- 没有资源请求冲突或者依赖版本冲突的风险。
- 一个服务实例只能消耗最多一台主机的资源。
- 很容易监控、管理、重新部署。
缺点:
- 资源利用率可能不如单主机多服务高。
(2)单主机多个服务
在一台主机(物理机或者虚拟机)上运行多个不同服务的实例。
有几种不同的方法来把一个服务部署在一台共享的主机上,包括:
- 把每个service实例部署成JVM实例。
- 把多个service实例部署在同一个JVM里。
优点:
- 比单主机单服务有更好的资源利用。
缺点:
- 有资源需求冲突的风险。
- 有依赖版本。冲突的风险。
- 难以限制一个服务实例的资源使用。
- 难以监控每个服务的资源使用情况。
(3)单虚拟机单服务
把服务打包成一个虚拟机的Image,然后部署在一个单独的VM上。
优点:
- 可以直接通过提高虚拟机个数的方式来做scale,Amazon Autoscaling Groups甚至可以根据负载做自动化的调节。
- VM包含了构建这个service的所有技术细节,所有的service都用同样的方法来开始和停止。
- 每个service实例是分离的。
- VM会限制一个service实例所消耗的CPU和内存资源。
缺点:
- 构建一个VM的Image比较花时间。
(4)每个容器一个服务
把service打包成(Docker)容器的Image, 然后把service实例部署成一个容器。现在有几个Docker集群管理的解决方案, 包括 Kubernetes(k8s)、 Marathon/Mesos、 Amazon EC2 Container Service(ECS)。
优点:
- 可以直接通过改变容器实例的方式来做scale。
- 容器包含了构建这个service的所有技术细节,所有的service都用同样的方法来开始和停止。
- 每个service实例是分离的。
- 容器会限制一个service实例所消耗的CPU和内存资源。
- Container构建和启动很快。
缺点:
- 部署容器的基础设置不如部署VM的基础设置丰富。
(5)Serverless架构的方式
使用一个隐藏了任务服务器的概念的部署的基础设施。这个基础设施拿到你的service的代码,然后运行。为了使用这种方式部署,你需要打包你的代码,把它上传到基础设施,然后描述你想要的性能指标。
这个部署的基础设施由公有云提供商来操作。它一般使用容器或者虚拟机的方式来分离服务,但是这些细节你并不需要知道。你不需要负责管理操作系统等等。现在有一些不同的serverless部署的环境: AWS Lambda、Google Cloud Functions、 Azure Functions, 他们提供了类似的功能,但是AWS有最丰富的功能。
优点:
- 不需要关心底层架构,只要关注代码。
- 非常有弹性,根据负载自动scale。
- 只要为请求数付钱, 便宜。
缺点:
- 这种架构比VM或者容器有更多的限制。比如说,AWS只支持很少几种语言,只适用于部署响应请求的无状态应用,你不能部署一个长期运行的有状态的应用如数据库、消息代理。
- 输入源有限制。比如说AWS Lambda不能订阅一个像RabbitMQ那样的消息代理。
- 应用必须快速启动。Serverless 架构不适用于花很多时间启动的service。
- 高延迟的风险。基础设施在为你的function启动一个instance、function 初始化的时间可能比较长。当突发的、大量请求进来的时候,一开始会比较缓慢。
三、学习Docker技术
1、学习了解docker的相关概念
(1)Docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
Docker包括以下三个基本概念:
- 镜像(Image):一个特殊的文件系统。Docker 镜像(Image),就相当于是一个 root 文件系统。Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建之后也不会被改变。
- 容器(Container):镜像运行的实体。镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等 。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。
- 仓库(Repository):集中存放镜像文件的地方。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。
(2)Docker compose
Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。
Compose 通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。
(3)Dockerfile
Dockerfile是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile从FROM命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。
(4)Docker machine
Docker Machine是Docker官方提供的一个工具,它可以帮助我们在远程的机器上安装 Docker,或者在虚拟机 host 上直接安装虚拟机并在虚拟机中安装 Docker。我们还可以通过 docker-machine 命令来管理这些虚拟机和 Docker。
(5)Swarm
Swarm是Docker官方提供的一款集群管理工具,其主要作用是把若干台Docker主机抽象为一个整体,并且通过一个入口统一管理这些Docker主机上的各种Docker资源。Swarm和Kubernetes比较类似,但是更加轻,具有的功能也较kubernetes更少一些。
(6)k8s
Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg)。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等一系列完整功能,提高了大规模容器集群管理的便捷性。
2、搭建Docker环境
2.1 Ubuntu Docker安装
2.1.1 使用Docker仓库安装
在新主机上首次安装 Docker Engine-Community 之前,需要设置Docker仓库。
(1)设置仓库
- 更新 apt 包索引。
sudo apt-get update
- 安装 apt 依赖包,用于通过HTTPS来获取仓库:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
- 添加 Docker 的官方 GPG 密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 设置稳定版仓库
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
(2)安装 Docker Engine-Community
- 更新 apt 包索引
sudo apt-get update
- 安装最新版本的 Docker Engine-Community 和 containerd ,或者转到下一步安装特定版本:
sudo apt-get install docker-ce docker-ce-cli containerd.io
- 在仓库中列出可用版本
apt-cache madison docker-ce
- 安装特定版本
sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
在这一步的时候遇到了困难,明明有相应的版本却一直出错
最后用以下语句进行解决:
sudo apt-get install -y docker-ce
- 测试 Docker 是否安装成功
sudo docker run hello-world
耗时一个早上,终于安装成功了!
2.2 Docker容器的使用
(1)获取镜像
没有 ubuntu 镜像,使用 docker pull 命令来载入 ubuntu 镜像
sudo docker pull ubuntu
(2)启动容器
docker run -it ubuntu /bin/bash
参数说明:
- -i: 交互式操作。
- -t: 终端。
- ubuntu: ubuntu 镜像。
- /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
运行命令查看当前系统的版本信息
cat /proc/version
创建一个文件夹,并进入
mkdir test
cd test
退出容器
exit
(3)启动已停止运行的容器
查看所有的容器命令如下:
docker ps -a
使用 docker start 启动一个已停止的容器:
sudo docker start <容器 ID>
再次查看容器状态可知容器被启动:
(4)后台运行
创建后台运行容器
sudo docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello; sleep 1; done"
查看所有容器并获得容器ID
查看容器内的标准输出
sudo docker logs <容器 ID>
(5)停止和重启容器
sudo docker stop <容器ID>
查看容器状态已知被停止
sudo docker restart <容器ID>
查看容器状态已知被启动
(6)进入容器
在使用-d参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
- docker attach
- docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。
attach命令
sudo docker attach <容器 ID>
exec命令
sudo docker exec -it <容器 ID> /bin/bash
查看容器可知容器没有停止工作:
(7)更新容器
查看可选操作
docker container update --help
sudo docker container update [操作参数] CONTAINER [容器id]
sudo docker container update --memory-reservation 300M CONTAINER b88174412d14
(8)删除容器
sudo docker rm -f <容器 ID>
查看所有容器得知已删除
2.3 Docker镜像的使用
(1)列出镜像列表
使用如下命令来列出本地主机上的镜像
sudo docker images
(2)获取一个新的镜像
当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。
sudo docker pull
(3)查找镜像
我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: https://hub.docker.com/
我们也可以使用 docker search 命令来搜索镜像。比如我们需要一个 httpd 的镜像来作为我们的 web 服务。我们可以通过 docker search 命令搜索 httpd 来寻找适合我们的镜像。
sudo docker search httpd
(4)拖取镜像
我们决定使用上图中的 httpd 官方版本的镜像,使用命令 docker pull 来下载镜像。
sudo docker pull httpd
下载完成后,用如下命令使用镜像
sudo docker run httpd
(5)删除镜像
镜像删除使用 docker rmi 命令,比如我们删除 hello-world 镜像:
sudo docker rmi hello-world
用如下命令删除镜像创建的容器
sudo docker rm -f <容器 ID>
2.4 Docker仓库管理
(1)登录
sudo docker login
(2)push本地镜像到私有仓库
sudo docker tag ubuntu username/ubuntu
sudo docker push username/ubuntu
在Docker hub中发现在仓库中多了一个名为“031702311/ubuntu”的镜像,证明push成功
(3)从仓库中获取镜像
sudo docker pull username/ubuntu
四、实验小结
通过本次实验,初步了解了微服务,对docker的一些相关知识也有了一定的了解,掌握了docker环境的搭建、容器的基本操作、镜像的拉取等一些操作,虽然实验不是特别顺利,但是还是收获满满!