Docker虚拟化实战学习——基础篇

2018年05月26日 02:17:24 北纬34度停留 阅读数:773更多

个人分类: Docker
 

Docker虚拟化实战和企业案例演练

深入剖析虚拟化技术概念和应用场景

虚拟化,一是项技术~~,是一种资源解决方案。

虚拟化技术是将物理资源转变为逻辑上可以管理的资源,以打破物理结构之间的壁垒,使计算元件运行在虚拟的基础上,而不是真实的物理资源上。

通过虚拟化技术,可以将物理资源转变为逻辑资源(虚拟机),应用程序服务运行在虚拟资源上,而不是真实的物理机上。

VMware workstation 属于个人版虚拟化软件,称为虚拟机软件。将物理资源转变为多台虚拟机,应用软件运行在虚拟机中,各个虚拟机共享物理机的资源 (CPU,硬盘,网卡,内存,IO设备...)

虚拟化技术的落地,底层就必须有物理机支撑!

单纯的物理机器是不能直接虚拟化的,都需要虚拟化软件来实现。目前主流的虚拟化软件有:KVM,XEN,ESXI,HP-V,Docker,Virtual BOX等

虚拟化技术的应用场景

企业需求:部署一百套Nginx WEB服务,要求对外端口为80,要求独立服务器部署

  • 传统方案:采购一百台低配硬件物理机,每台物理机部署一套Nginx WEB服务

  • 虚拟化方案:采购10台高配硬件物理机,每台物理机虚拟10台虚拟机,每台虚拟机独立部署一套Nginx WEB服务

很明显,第二种方案,从成本、部署难度、维护等方面,第二种都是比第一种好的。

所以,虚拟化的意义:对于硬件设备资源的最大化利用,降低企业各种费用成本,简化后期资源部署和维护,动态满足企业需求,基于虚拟化资源来代替待淘汰的物理资源

云计算技术概念和应用场景

深入剖析Docker虚拟化概念和底层原理

Docker简介

Docker是虚拟化技术的一种,也是目前使用比较多的一种。Go语言开发引擎

Docker利用“集装箱”(容器)的原理,将系统、开发软件包、依赖环境等统一打包到容器中,将整个容器部署至其他的平台或者服务器上。

容器技术:一种虚拟化的方案,和传统的虚拟机(通过中间层"guerst OS"运行服务)不同,Docker直接运行在操作系统之上。因此容器虚拟化也被称之为操作系统虚拟化。Docker容器依赖于Linux内核特性,Namespace和Cgroups,所以只能运行在Linux之上。

官方定义:Docker是一个开元的应用容器引擎,让开发者可以打包他们呢的应用以及依赖到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化

容器是完全使用沙箱机制,相互之间没有任何接口(iphone的app也是这样),几乎没有性能开销;可以很容易在机器和数据中心运行。最重要的是,他们不依赖任何语言,框架甚至系统

Docker虚拟化技术比传统虚拟化技术的优点

假设基于传统虚拟化和Docker虚拟化部署Nginx WEB服务,两种方案部署如下:

  • 传统虚拟化:硬件服务器-HostOS-VMM-GuestOS-Nginx WEB服务

  • Docker虚拟化:用剑服务器-HostOS-VMM-Nginx WEB服务

传统的虚拟化,不能直接启Nginx WEB,Docker可以直接启动Nginx WEB

如果是传统虚拟化技术,原本只需要很少资源的服务应用,就需要很大的“guestOS“资源来支撑真正的服务

Docker目标

  • 提供简单轻量级的建模方式(docker的启动是毫秒级的)

  • 职责的逻辑分离:开发人员只需要关注容器中运行的程序,运维人员只需要关注对容器的管理。Docker开发提高了开发程序和部署容器的一致性

  • 快速高效的开发声明周期:缩短代码从开发、测试到部署上线的生命周期

  • 鼓励使用面向服务的架构:docker推荐单个容器只运行一个应用程序/进程,这样就形成了一个分布式的应用程序模型,避免服务之间的互相影响。实现 高内聚 低耦合

Docker的使用场景

  1. 使用Docker容器开发、测试、部署服务。

    docker本身是轻量级的,所以本地开发人员可以构建、运行并分享docker容器,容器可以在开发环境中创建,然后提交到测试,在到生产环境。

  2. 创建隔离的运行环境

    在很多企业应用中,同一服务的不同版本可能服务于不同的用户,使用Docker很容易创建不同的环境来运行不同版本的服务

  3. 搭建测试环境

    有于Docker的轻量化,所以开发者很容易在本地搭建测试环境,用来测试程序在不同系统下的兼容性,甚至集群式的测试环境。

  4. 构建多用户的平台服务(PaaS)基础设施

  5. 即同软件即服务(SaaS)应用程序

  6. 高性能、超大规模的宿主机部署

Docker的基本组成

Docker基本组成:

  1. Docker Client 客户端

  2. Docker Daemon 守护进程

  3. Docker Image 镜像

  4. Docker Container 容器

  5. Docker Registry 仓库

  • Docker客户端/守护进程:

    docker是C/S架构的程序,docker客户端向服务端发送请求,守护进程处理完所有的工作,并返回处理结果。客户端对服务端的访问,既可以是本地,也可以通过远程

  • Docker镜像:

    docker镜像是docker容器的基石。跟ISO镜像类似,静止的模版,用于Docker容器的底层基础文件

    docker镜像是一个层叠的只读文件系统:

    最低端是一个引导文件系统 bootfs

    第二层是rootfs,位于引导文件系统之上,可以是一种或多种操作系统(redhat/ubuntu等),在docker中,rootfs永远是只读方式,并且利用联合加载技术(union mount),加载更多的只读文件系统

  • Docker容器:

    docker容器通过docker镜像启动,是将Docker镜像运行的实体,是活动的。

    当一个容器启动时,会再docker镜像的最顶层加载一个读写文件系统,docker中运行的程序就是在该层进行运行的,第一次启动是,初始化的读写层是空的,所有的写操作都应用在该层(从只读的底层复制到读写层(写时复制技术))

    Docker镜像和容器的关系,跟程序和进程的关系类似

  • Docker仓库:

    存放Docker镜像的地方,一般分为公共仓库和私有仓库,docker公司提供了一个自己的仓库"Docker Hub"

Docker的相关技术

Docker依赖Linux的内核特性有:Cgroup(控制组)和Namespace(命名空间)

  • Namespace

命名空间是一种封装的概念,在操作系统层面上,提供了系统资源的隔离,系统资源包括{进程、文件系统、网络等}。Linux实现命名空间的目的:为了实现轻量级虚拟化服务,在不同一命名空间下的进程,彼此毫无关系。

docker使用了五种命名空间:

  1. PID 进程隔离

  2. NET 管理网络接口

  3. IPC 管理进程间通信

  4. MNT 管理挂载点,文件系统间的隔离

  5. UTS 管理内核和版本标示的隔离

  • Cgroup(Control Groups)

Cgroup对隔离的资源进行管理,是一种用来限制、记录,隔离进程组资源的机制。就是为了容器技术而生的。

Cgroup对资源的管理方式:

  1. 资源限制 如:对内存的分配上限

  2. 优先级设定 如:某个进程优先使用cpu时间片

  3. 资源计量 计算进程组使用了多少系统资源,尤其时在记费系统中

  4. 资源控制 将进程组挂起或恢复

Docker容器的能力:

  • 文件系统隔离:每隔容器都有自己的root文件系统

  • 进程隔离:每个容器都运行在自己的进程环境中,互相不影响

  • 网络隔离:容器间的虚拟网络接口和IP地址都是分开的

  • 资源隔离和分组:使用Cgroups将CPU和内存之类的物理资源独立的分配给每个Docker容器

Docker基础命令使用

部署Docker虚拟化平台内核要求:Linux内核版本:3.8+,推荐内核版本3.10+,对应的Linux发行版:RHEL7.x和CentOS7.x;

部署Docker虚拟化技术,对物理机配置容量没有要求,生产环境尽量使用高配物理机。如:京东线上,64C(CPU)+256G(内存)+2T(分布式部署),JDOS2.0弹性云。

Docker的安装与配置

部署环境:

OS:RedHat7.3

  1. 下载安装Docker软件包

    [root@docker mnt]# yum install docker*
    。。。
    Installing:
    docker-engine         x86_64 1.13.1-1.el7.centos /docker-engine-1.13.1-1.el7.centos.x86_64
                                                                              65 M
    docker-engine-selinux noarch 1.13.1-1.el7.centos /docker-engine-selinux-1.13.1-1.el7.centos.noarch
                                                                              43 k
    Installing for dependencies:
    audit-libs-python     x86_64 2.6.5-3.el7         rhel7.3                 70 k
    checkpolicy           x86_64 2.5-4.el7           rhel7.3               290 k
    libcgroup             x86_64 0.41-11.el7         rhel7.3                 65 k
    libseccomp             x86_64 2.3.1-2.el7         rhel7.3                 56 k
    libsemanage-python     x86_64 2.5-4.el7           rhel7.3               103 k
    libtool-ltdl           x86_64 2.4.2-21.el7_2     rhel7.3                 49 k
    policycoreutils-python x86_64 2.5-8.el7           rhel7.3               444 k
    python-IPy             noarch 0.75-6.el7         rhel7.3                 32 k
    setools-libs           x86_64 3.3.8-1.1.el7       rhel7.3               610 k
    。。。

    [root@docker mnt]# rpm -qa | grep docker
    docker-engine-1.13.1-1.el7.centos.x86_64
    docker-engine-selinux-1.13.1-1.el7.centos.noarch

  2. 启动Docker

    [root@docker mnt]# systemctl start doceker
    Failed to start doceker.service: Unit not found.
    [root@docker mnt]# systemctl start docker
    [root@docker mnt]# ps -ax | grep docker
    11435 ?       Ssl   0:00 /usr/bin/dockerd
    11438 ?       Ssl   0:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc
    11544 pts/0   R+     0:00 grep --color=auto docker

    [root@docker mnt]# docker version
    Client:
    Version:     1.13.1
    API version: 1.26
    Go version:   go1.7.5
    Git commit:   092cba3
    Built:       Wed Feb 8 06:38:28 2017
    OS/Arch:     linux/amd64

    Server:
    Version:     1.13.1
    API version: 1.26 (minimum version 1.12)
    Go version:   go1.7.5
    Git commit:   092cba3
    Built:       Wed Feb 8 06:38:28 2017
    OS/Arch:     linux/amd64
    Experimental: false

  3. 基于Docker引擎启动Nginx容器,并且实现通过物理机wget、curl实现访问

    首先,需要从Docker官网获取Docker镜像,docker search nginx | more

    docker search nginx | more
    docker pull docker.io/nginx

    由于国外网站下载速度比较慢,所以可以替换为国内的docker仓库,具体方法:

    [root@docker ~]# cat >/etc/docker/daemon.json << EOF
    {
    "registry-mirrors": ["https://registry.docker-cn.com"]
    }
    EOF
    [root@docker ~]# cat /etc/docker/daemon.json
    {
    "registry-mirrors": ["https://registry.docker-cn.com"]
    }
    重启Docker服务,这样就可以取下载Docker镜像了

    为什么要为Docker配置国内镜像???在正常情况下,docker有一个默认连接的国外官方镜像,在国外的网友访问该官方镜像自然不成问题,但是国内毕竟不是国外,由于国情不同,中国的网络访问国外官方镜像网速一向很慢,而且往往还会遭遇断网的窘境,所以说我们要想正常使用docker的镜像,那么我们就不得不配置相应的国内镜像。

    Docker可以配置的国内镜像有很多可供选择,比如说:阿里云,网易蜂巢,DaoCloud,Docker中国区官方镜像等,这些都是可以提供给大家随意选择的不错的镜像仓库。

Docker容器的基本操作

将本地tar包载入到本地镜像库使用docker load命令

[root@localhost packages]# docker load --input ubuntu.tar
454970bd163b: Loading layer [==================================================>] 196.8 MB/196.8 MB
38112156678d: Loading layer [==================================================>] 208.9 kB/208.9 kB
4e1f7c524148: Loading layer [==================================================>] 4.608 kB/4.608 kB
56063ad57855: Loading layer [==================================================>] 1.024 kB/1.024 kB
[root@localhost packages]# docker images
REPOSITORY         TAG                 IMAGE ID           CREATED             SIZE
ubuntu             latest             07c86167cdc4       2 years ago         188 MB

启动容器:

docker run IMAGE [COMMAND] [ARG...]

run 在新容器中执行命令

IMAGE 指定的镜像

COMMAND 命令

ARG 参数

[root@localhost packages]# docker run ubuntu echo "hello world"
hello world

一次启动执行一个命令的容器是docker中最基本的运行方式,docker提供了一个交互式启动容器的方式

docker run -i -t IMAGE /bin/bash

-i 为容器始终打开标准输入

-t 为创建的容器的tty终端

[root@localhost packages]# docker run -it ubuntu /bin/bash
root@855833c3672f:/# echo "hello docker"
hello docker
root@855833c3672f:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

查看容器:

docker ps [-a] [-l]

-a 列出所有容器

-l 列出最新创建的容器

[root@localhost packages]# docker ps -a
CONTAINER ID       IMAGE               COMMAND               CREATED             STATUS                         PORTS               NAMES
855833c3672f       ubuntu             "/bin/bash"           45 seconds ago       Exited (0) 10 seconds ago                           flamboyant_rosalind
797239db86e0       ubuntu             "echo 'hello world'"   About a minute ago   Exited (0) About a minute ago                       flamboyant_khorana
77b29f9efa08       b809f199bbb9       "/bin/bash"           6 minutes ago       Created                                             stoic_leavitt

执行结果参数:

[root@localhost packages]# docker ps -a
CONTAINER ID(docker守护进程在启动容器时为容器分配的唯一ID)
IMAGE()
COMMAND()
CREATED()
STATUS()
PORTS()
NAMES(docekr守护进程为容器自动分配的名字)

docker inspect查看容器后面添加容器的唯一ID或者NAMES

docker自定义容器名字

docker run --name=vector_name -i -t ubuntu /bin/bash

[root@localhost packages]# docker run --name=fsx_docker -it ubuntu /bin/bash
root@304d46ba1c87:/# exit
exit
[root@localhost packages]# docker ps -l
CONTAINER ID       IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
304d46ba1c87       ubuntu             "/bin/bash"         11 seconds ago     Exited (0) 7 seconds ago                       fsx_docker

重新启动已经停止的容器

docker start [-i] vector_name

-i 以交互模式启动

删除容器

仅仅用来删除的容器,不能删除正在用运行的命令

[root@localhost packages]# docker ps -a
CONTAINER ID       IMAGE               COMMAND               CREATED             STATUS                     PORTS               NAMES
304d46ba1c87       ubuntu             "/bin/bash"           2 minutes ago       Up 39 seconds                                 fsx_docker
855833c3672f       ubuntu             "/bin/bash"           5 minutes ago       Exited (0) 4 minutes ago                       flamboyant_rosalind
797239db86e0       ubuntu             "echo 'hello world'"   5 minutes ago       Exited (0) 5 minutes ago                       flamboyant_khorana
77b29f9efa08       b809f199bbb9       "/bin/bash"           10 minutes ago     Created                                       stoic_leavitt
[root@localhost packages]# docker rm 855833c3672f
855833c3672f
[root@localhost packages]# docker rm 797239db86e0
797239db86e0
[root@localhost packages]# docker ps -a
CONTAINER ID       IMAGE               COMMAND             CREATED             STATUS             PORTS               NAMES
304d46ba1c87       ubuntu             "/bin/bash"         3 minutes ago       Up About a minute                       fsx_docker
77b29f9efa08       b809f199bbb9       "/bin/bash"         11 minutes ago     Created                                 stoic_leavitt

总结

docker load --input 将本地容器仓库的tar包导入成镜像

docker run -it --name 启动一个新的容器

docker ps -a -l 查看容器

docker inspect 查看具体容器的信息

docker start -i 启动已经存在的容器

docker rm 删除一个容器

Docker守护式容器

我们需要一个长期运行的容器提供服务,这就是守护式容器;可以长期运行

docker run -it IMAGE /bin/bash

ctrl+p ctrl+q

[root@localhost packages]# docker ps -a
CONTAINER ID       IMAGE               COMMAND             CREATED             STATUS             PORTS               NAMES
[root@localhost packages]# docker run -it --name=fsx1 ubuntu /bin/bash
root@dcbb80e0404b:/# [root@localhost packages]# docker ps
CONTAINER ID       IMAGE               COMMAND             CREATED             STATUS             PORTS               NAMES
dcbb80e0404b       ubuntu             "/bin/bash"         26 seconds ago     Up 25 seconds                           fsx1
//注意:此时的容器仍是启动状态,就意味着它还在运行

再次进入退出(仍在启动中)的容器(附加到运行中的容器)

docker attach docker_name

[root@localhost packages]# docker attach fsx1
root@dcbb80e0404b:/#

启动守护式容器

docker run -d IMAGE COMMAND ARG...

-d 在启动容器时,使用后台

这是启动守护式容器最重要的命令

[root@localhost packages]# docker run --name=fsx2 -d ubuntu /bin/bash -c "while true;do echo hello;sleep 1;done"
529cea9c4075854083e1d025f5639055a8cde98d17fe4d6d74a208215d706427
[root@localhost packages]# docker ps
CONTAINER ID       IMAGE               COMMAND                 CREATED             STATUS             PORTS               NAMES
529cea9c4075       ubuntu             "/bin/bash -c 'whi..."   5 seconds ago       Up 3 seconds                           fsx2
//容器一直在运行

使用log命令查看容器内部运行状况

docker logs -f -t --tail vector_name

-f 一直跟踪logs,时时更新

-t 在返回结果上加上时间戳

--tail 返回结尾出多少书量的日志,不指定返回全部

[root@localhost packages]# docker logs -f -t --tail 5 fsx2
2018-05-24T03:35:35.642795622Z hello
2018-05-24T03:35:36.643727589Z hello
2018-05-24T03:35:37.644724326Z hello
2018-05-24T03:35:38.645707632Z hello
2018-05-24T03:35:39.646708718Z hello
2018-05-24T03:35:40.647727168Z hello
2018-05-24T03:35:41.648612161Z hello
2018-05-24T03:35:42.649668735Z hello
^C

查看容器内部进程

docker top vector_name

[root@localhost packages]# docker top fsx2
UID                 PID                 PPID               C                   STIME               TTY                 TIME               CMD
root               11775               11758               0                   11:32               ?                   00:00:00           /bin/bash -c while true;do echo hello;sleep 1;done
root               13142               11775               0                   11:37               ?                   00:00:00           sleep 1

在docker运行中的容器启动新的进程(docker的理念是一个容器运行一个服务):

docker exec -d -i -t vector_name COMMAND ARG...

与run命令相似

[root@localhost packages]# docker exec -it fsx2 /bin/bash
root@529cea9c4075:/# echo hello fsx
hello fsx
root@529cea9c4075:/# [root@localhost packages]# docker top fsx2
UID                 PID                 PPID               C                   STIME               TTY                 TIME               CMD
root               11775               11758               0                   11:32               ?                   00:00:00           /bin/bash -c while true;do echo hello;sleep 1;done
root               13440               13423               0                   11:40               pts/5               00:00:00           /bin/bash
root               13475               11775               0                   11:40               ?                   00:00:00           sleep 1
//这里使用ctrl+p ctrl+q

停止守护式容器

docker stop vector_name

docker kill vector_name

stop是发送一个信号给容器,等待停止

kill直接停止容器

[root@localhost packages]# docker ps
CONTAINER ID       IMAGE               COMMAND                 CREATED             STATUS             PORTS               NAMES
529cea9c4075       ubuntu             "/bin/bash -c 'whi..."   9 minutes ago       Up 9 minutes                           fsx2
dcbb80e0404b       ubuntu             "/bin/bash"             18 minutes ago     Up 18 minutes                           fsx1
[root@localhost packages]# docker stop fsx1
fsx1
[root@localhost packages]# docker kill fsx2
fsx2

总结

ctrl+p ctrl+q 将交互式容器转到后台

docker run -d 创建一个守护式容器

docker logs 查看容器日志

docker top 查看容器内部进程

docker exec 为运行中的容器启动一个新进程

docker stop/kill 停止一个容器

这里只介绍一些常见的docker命令,及子命令使用;更多信息可以使用docker帮助文件

man docker-run(logs、stop、exec...)

Docker虚拟化实战学习——基础篇(转)的更多相关文章

  1. [转]C++学习–基础篇(书籍推荐及分享)

    C++入门 语言技巧,性能优化 底层硬货 STL Boost 设计模式 算法篇 算起来,用C++已经有七八年时间,也有点可以分享的东西: 以下推荐的书籍大多有电子版.对于技术类书籍,电子版并不会带来一 ...

  2. Linux虚拟网络:Docker网络知识之基础篇

    我们在工作中应用了docker容器化技术,服务的部署.维护和扩展都方便了很多.然而,近期在私有化部署过程中,由于不同服务器环境的复杂多变,常常遇到网络方面的问题,现象为容器服务运行正常,但宿主机.容器 ...

  3. 新一代Java程序员必学的Docker容器化技术基础篇

    Docker概述 **本人博客网站 **IT小神 www.itxiaoshen.com Docker文档官网 Docker是一个用于开发.发布和运行应用程序的开放平台.Docker使您能够将应用程序与 ...

  4. [性能测试] locust学习-基础篇

    在本文中,我将介绍一个名为Locust的性能测试工具.我将从Locust的功能特性出发,结合实例对Locust的使用方法进行介绍. 概述 Locust主要有以下的功能特性: 在Locust测试框架中, ...

  5. ios学习基础篇一

    搜集的不错的oc学习资料 大概总结: http://my.oschina.net/luoguankun/blog/208526 详细教程: http://www.w3cschool.cc/ios/io ...

  6. Laravel学习基础篇之--路由

    终于还是决定再多学一门重量级框架,当然首选必备还是被称为最优雅的Web开发框架--Laravel 对于框架的入门,首先了解它的路由规则是先前必备的,以下是laravel 中几种常见的基础路由规则 // ...

  7. Flume搭建及学习(基础篇)

    转载请注明原文出处:http://www.cnblogs.com/lighten/p/6830439.html 1.简介 该文主要是翻译官方的相关文档,源地址点击这里.介绍一下Flume的一些基本知识 ...

  8. Bat 脚本学习 (基础篇)

    [转]Bat 脚本学习 2015-01-05 14:13 115人阅读 评论(0) 收藏 举报 基础部分: ============================================== ...

  9. Python ( 学习 基础篇第一部 )

    目录 注释 注释的分类 注释的注意点 变量 变量的概念 变量的声明 变量的命名 变量的交换 变量的缓存机制 常量 进制 进制的转换 原码 反码 补码 六大数据类型 Number 的四大类 字符串 st ...

随机推荐

  1. 过滤access日志前5条数据

    cat /usr/local/nginx/logs/access.log|awk '{print $1}'|sort|uniq -c|sort -n -r|head -5 找不到的话可以find查找a ...

  2. 03_java基础(二)之jdk的安装与环境变量配置

    1.语言与机器语言 语言 : 通常说的语言其实就是人与人之间沟通的一种方式计算机编程语言: 可以看成是人与计算机之间交流的一种方式 C,C++,C#,PHP,Java等 2.Java语言的历史 是SU ...

  3. Bootstrap Tooltip

    [Bootstrap Tooltip] 1.设置Tooltip: 1)data-toggle="tooltip" 2)data-placement="top", ...

  4. 【Scheme】序列的操作

    1.序列的表示 序列 序列(表)是由一个个序对组合而成的,具体来说就是让每个序对的car部分对应这个链的条目,cdr部分则是下一个序对. 对于1->2->3->4这个序列我们可以表示 ...

  5. x86寄存器总结

    X86寄存器 ·x86寄存器分类: 8个通用寄存器:EAX.EBX.ECX.EDX.ESI.EDI.ESP.EBP 1个标志寄存器:EFLAGS 6个段寄存器:CS.DS.ES.FS.GS.SS 5个 ...

  6. 第十一章 串 (c3)KMP算法:理解next[]表

  7. racktables 后期维护

    一.网站与数据库分离 vim secret.php #$pdo_dsn = 'mysql:host=localhost;dbname=racktables'; #$db_username = 'roo ...

  8. NumPy 切片和索引

    NumPy 切片和索引 ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样. ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以 ...

  9. TOJ 2755 国际象棋(搜索)

    传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=2755 思路:对起点到终点进行广搜, ...

  10. RxJS之AsyncSubject

    AsyncSubject 是另一个 Subject 变体,只有当 Observable 执行完成时(执行 complete()),它才会将执行的最后一个值发送给观察者. import { Compon ...