mongo
setup
1 | curl -O https://repo.mongodb.org/apt/ubuntu/dists/bionic/mongodb-org/4.4/multiverse/binary-amd64/mongodb-org-server_4.4.30_amd64.deb |
1 | curl -O https://repo.mongodb.org/apt/ubuntu/dists/bionic/mongodb-org/4.4/multiverse/binary-amd64/mongodb-org-server_4.4.30_amd64.deb |
Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A.
Since the answer may be large, return the answer modulo 10^9 + 7.
本体的解题方法有多种,不同的解题思路具有不同的时间复杂度。
此解法是一个简单可行的的算法,具有很小的实现难度,本文在此只略微讲述该算法的设计思路,由于该算法时间复杂度较高,不能在时间限制内跑完所有的Leetcode所有test case,不推荐使用。
本算法中引入两个索引,分别从0n-1,和in-1进行遍历,每次遍历更新当前子序列的最小值并加入最终和中,即可得出求和。还有一个细节需要注意的是,由于数列的最小值和是一个很大的数字,可能会超出int的数值范围(-2^31 ~ 2^31)),所以需要在循环体中增加对int MAX值/modulo值的比较,保证没有溢出造成结果错误。
本体也可以用动态规划的思路进行解题。动态规划采用的思想是归纳法思想,将第i规模的问题化简成第i-1规模的问题,由此递推能将问题层层迭套从而减少计算的时间复杂度。 通过公式推导,不难得出,本题长度为n的数列A的解集可以拆分为如下子解集的并集:
1 | f(n) = N(0) U N(1) U ... U N(n-1), |
对于N(i)的求解,可以通过如下递归关系得到:
1 | N(i) = { A(i), min(N(i-1), A(i)) } |
本算法不是最佳解法,实际的比较次数还是O(n^2)复杂度。
要想减少元素的比较次数,必须将连续子数组的特性发挥到极致。Leetcode提出了一种寻找以A[i]为最小元素的子数组计数法,也就是说,找到A数组中以每个元素为最小值的子数组个数通过加权求和,就能算出最终答案。
为了找到A数组中以每个元素为最小值的子数组个数,只需要维护一个长度与A等长的数组即可。经过一次遍历,便可以将数组中各个子数组最小值计数完成。因而本算法的时间复杂度为O(n)。
本题的算法的关键
微服务是可以快速构建、修改和部署到独立生产环境中的小型代码单元。可以快速进行迭代开发和交付,从而部署应该也具有如下特征:
容器是镜像的运行时实例。容器虚拟化操作系统资源,容器引擎划分操作系统资源(比如进程树,文件系统,网络栈等),将其打包到成为容器的虚拟操作系统中,运行一个应用。
容器技术不同于Hypervisor技术,后者将物理资源划分为虚拟机的虚拟版本,前者将操作系统本身划分为容器的虚拟版本。
Dockerfile是镜像构建的描述文件,以易于阅读的格式准确描述了应用及其依赖。Dockerfile由一系列指令组成,每条指令构建镜像的一层。镜像构建的基础目录就是Dockerfile所在的目录。
Dockerfile的构建指令包括:
元数据指令包括:
Docker镜像的构建是分层叠加文件系统的过程,每条指令构建一层,镜像构建完成后,可以运行容器。文件是增量叠加的,删除上层镜像中的文件目录并不能真正的删除文件本身,而是在顶层layout中将文件隐藏,所以镜像文件并不能真正的变小。
多段构建有多个FROM命令,每一个FROM命令都会构建一个WORKINGDIR,以及一个独立的镜像,这为灵活运用镜像构建WORKSPACE提供了能力,甚至最终的运行时镜像可以引用完全不同的净化的base image,从而构建出与开发环境完全不同的运行时镜像。
同时也可以用 –target prod-client -f Dockerfile-final来灵活指定构建生产环境的客户端镜像。
Docker网络是基于容器网络模型的开源可插拔架构。libnetwork是CNM的实现,提供了docker的核心网络能力。Linux OS层面提供网络虚拟化的基础是VLAN,这是对eth0的拆分,每个VLAN都是一个独立的虚拟网络绑定到eth0.100等等,每个VLAN的流量都是隔离的,这是因为网桥间的隔离。Docker网络虚拟化基于VLAN,但是VLAN的隔离粒度是二层,而Docker网络虚拟化可以支持三层隔离,即每个容器可以拥有独立的IP地址,从而实现容器之间的子网隔离,也就是说在VLAN内部,即使可以将容器放在不同的子网段,保证网络间的相互通信。
对于操作系统能L2的链路设计,是基于802.11Q扩展协议,让网卡从硬件上支持虚拟化,从而实现VLAN的隔离。VLAN不直连,并不代表两边的容器不同相互通信,如果VLAN是连向公网的,就可以通过公网通信。
虚拟子网一般是一个私网,类似于一个k8s cluster的所有容器都会在同一个VNET中,对于集群向外的通信,不要一个网关(也就是路由器)同时拥有私网IP(一般是网关IP)和公网IP(普通IP)从而可以建立路由规则,将私网向外访问的流量转发到网关,转发出去。类似于cluster的Egress IP。Ingress则是负载均衡的入口,对于外网的客户端,需要访问cluster内部的应用,必须通过Ingress负载均衡反向代理流量进入容器,从而达到通信的目的,客户端只能发现到Ingress的IP。
runc是开放容器计划OCI运行时规范的实现。它的任务是与底层OS交互,启动和停止容器,docker每个容器都是runc创建的。OCI包括镜像规范,运行时规范,分发规范。
containerd管理容器的生命周期,包括拉取镜像和管理runc实例。
dockerd执行更高级别的任务,如暴露docker API,管理镜像,管理卷,管理网络等。
flowchart TD;
A[runc内核级工作] --> B[containerd容器生命周期管理]
B --> C[Docker守护进程CLI/API/Image/Network/Storage]

Helm是一种业界常用的容器打包技术,通过templates方式定义了一个服务所需要的资源定义。
FluxCD是gitops repo的执行程序,以函数定义形式定义了定义每一个helm chart的部署定义,但是以目前的FluxCD集成设计模式,是更加机械的容器provision能力,而并没有提供更加灵活的容器阶段式定义。资源映射的的过程更像是资源展开的过程,从Kustomization=>HelmChart=>HelmRelease=>K8S RD的映射过程。
Ansible是Ansible Automation Platform的简称,提供了灵活的自动化部署过程设计,基本的可部署单元是Ansible Playbook,而不同组需要灵活管理的是自己的playbook repo。而本repo的git tag正是决定了该release的版本,从而能够解耦平台playbook和team playbook的版本发布周期。