虚拟化技术浅析第二弹之初识Kubernetes

作者:京东物流 杨建民

一、微服务架构起源

单体架构:可以理解为主要业务逻辑模块(我们编写的代码模块,不包括独立的中间件)运行在一个进程中的应用,最典型的是运行在一个Tomcat容器中,位于一个进程里。单体架构好处是技术门槛低、编程工作量少、开发简单快捷、调试方便、环境容易搭建、容易发布部署及升级,开发运维等总体成本很低、见效快。其缺点也明显:

(1)单体应用系统比较膨胀与臃肿,耦合度高,导致进行可持续开发和运维很困难。

(2)单体应用难以承载迅速增长的用户请求和需求。

基于Spring Framework的单体应用架构图

分布式架构核心思想是把一个单一进程的系统拆分为功能上相互协作又能独立部署在多个服务器上的一组进程,这样一来,系统可以根据实际业务需要,通过以下两种方式实现某些独立组件的扩容,提升吞吐量。

  • 水平扩展:通过增加服务器数量进行扩容

  • 垂直扩展:给系统中的某些特殊业务分配更好的机器,提供更多资源,从而提升这些业务的系统负载和吞吐

分布式架构是将一个庞大的单体应用拆分成多个独立运行的进程,这些进程能通过某种方式实现远程调用,因此,分布式架构要解决的第一个核心技术问题就是独立进程之间的远程通信。该问题的最早答案就是RPC技术(Remote Procedure Call),一种典型的微服务架构平台的结构示意图如下:

大家比较熟知的微服务架构框架有Dubbo与Spring Cloud,之后比较成功的微服务架构基本都和容器技术挂钩了,其中最成功的、影响最大的当属Kubernetes平台了,与之相似的还有Docker公司推出的Docker Swarm(在2017年底,Docker Swarm也支持Kubernetes了)。

关于微服务架构的优势由于文章篇幅有限,不再展开,但任何技术都存在两面性,微服务架构具有一定的复杂性,如开发者必须掌握某种RPC技术,并且必须通过写代码来处理RPC速度过慢或者调用失败等复杂问题。为了解决微服务带来的编程复杂性问题,一种新的架构设计思想出现了,这就是Service Mesh,Service Mesh定义是:一个用于处理服务于服务之间通信(调用)的复杂的基础架构设施。从本质上看,Service Mesh是一组网络代理程序组成的服务网络,这些代理会与用户程序部署在一起,充当服务代理,这种代理后来在Google的Istio产品架构中称为“Sidecar”,其实就是采用了代理模式的思想去解决代码入侵及重复编码的问题,。下图给出了Service Mesh最简单的架构图。Servie Mesh同样不是本次的主角,感兴趣的小伙伴可自行学习。

二、初识k8s

官方原文是:K8s is an abbreviation derived by replacing the 8 letters “ubernete” with 8.

k8s全称kubernetes,名字来源于希腊语,意思为“舵手”或“领航员”,它是第一代容器技术的微服务架构(第二代是Servie Mesh)。

Kubernetes最初源于谷歌内部的Borg,提供了面向应用的容器集群部署和管理系统。Kubernetes 的目标旨在消除编排物理/虚拟计算,网络和存储基础设施的负担,并使应用程序运营商和开发人员完全将重点放在以容器为中心的原语上进行自助运营。Kubernetes 也提供稳定、兼容的基础(平台),用于构建定制化的workflows 和更高级的自动化任务。

Kubernetes 具备完善的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建负载均衡器、故障发现和自我修复能力、服务滚动升级和在线扩容、可扩展的资源自动调度机制、多粒度的资源配额管理能力。

Kubernetes 还提供完善的管理工具,涵盖开发、部署测试、运维监控等各个环节。

2.1 k8s架构与组件

Kubernetes主要由以下几个核心组件组成:

  1. etcd保存了整个集群的状态;
  2. apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
  3. controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
  4. scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
  5. kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
  6. Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
  7. kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;

2.2 k8s设计理念

API设计原则

API对象是k8s集群中的管理操作单元。k8s集群系统每支持一项新功能,引入一项新技术,一定会新引入对应的API对象,支持对该功能的管理操作。例如副本集Replica Set对应的API对象是RS。

k8s采用声明式操作,由用户定义yaml,k8s的API负责创建。每个对象都有3大类属性:元数据metadata、规范spec和状态status。元数据是用来标识API对象的,每个对象都至少有3个元数据:namespace,name和uid;除此以外还有各种各样的标签labels用来标识和匹配不同的对象,例如用户可以用标签env来标识区分不同的服务部署环境,分别用env=dev、env=testing、env=production来标识开发、测试、生产的不同服务。规范描述了用户期望k8s集群中的分布式系统达到的理想状态(Desired State),例如用户可以通过复制控制器Replication Controller设置期望的Pod副本数为3;status描述了系统实际当前达到的状态(Status),例如系统当前实际的Pod副本数为2;那么复制控制器当前的程序逻辑就是自动启动新的Pod,争取达到副本数为3。

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80


  • apiVersion - 创建对象的Kubernetes API 版本

  • kind - 要创建什么样的对象?

  • metadata- 具有唯一标示对象的数据,包括 name(字符串)、UID和Namespace(可选项)

使用上述.yaml文件创建Deployment,是通过在kubectl中使用kubectl create命令来实现。将该.yaml文件作为参数传递。如下例子:

$ kubectl create -f docs/user-guide/nginx-deployment.yaml --record


k8s常见对象:Pod、复制控制器(Replication Controller,RC)、副本集(Replica Set,RS)、部署(Deployment)、服务(Service)、任务(Job)、存储卷(Volume)、持久存储卷和持久存储卷声明(Persistent Volume,PV、Persistent Volume Claim,PVC)、节点(Node)、ConfigMap、Endpoint等。

控制机制设计原则

  • 每个模块都可以在必要时优雅地降级服务控制逻辑应该只依赖于当前状态。这是为了保证分布式系统的稳定可靠,对于经常出现局部错误的分布式系统,如果控制逻辑只依赖当前状态,那么就非常容易将一个暂时出现故障的系统恢复到正常状态,因为你只要将该系统重置到某个稳定状态,就可以自信的知道系统的所有控制逻辑会开始按照正常方式运行。

  • 假设任何错误的可能,并做容错处理。在一个分布式系统中出现局部和临时错误是大概率事件。错误可能来自于物理系统故障,外部系统故障也可能来自于系统自身的代码错误,依靠自己实现的代码不会出错来保证系统稳定其实也是难以实现的,因此要设计对任何可能错误的容错处理。

  • 尽量避免复杂状态机,控制逻辑不要依赖无法监控的内部状态。因为分布式系统各个子系统都是不能严格通过程序内部保持同步的,所以如果两个子系统的控制逻辑如果互相有影响,那么子系统就一定要能互相访问到影响控制逻辑的状态,否则,就等同于系统里存在不确定的控制逻辑。

  • 假设任何操作都可能被任何操作对象拒绝,甚至被错误解析。由于分布式系统的复杂性以及各子系统的相对独立性,不同子系统经常来自不同的开发团队,所以不能奢望任何操作被另一个子系统以正确的方式处理,要保证出现错误的时候,操作级别的错误不会影响到系统稳定性。

  • 每个模块都可以在出错后自动恢复。由于分布式系统中无法保证系统各个模块是始终连接的,因此每个模块要有自我修复的能力,保证不会因为连接不到其他模块而自我崩溃。

  • 每个模块都可以在必要时优雅地降级服务。所谓优雅地降级服务,是对系统鲁棒性的要求,即要求在设计实现模块时划分清楚基本功能和高级功能,保证基本功能不会依赖高级功能,这样同时就保证了不会因为高级功能出现故障而导致整个模块崩溃。根据这种理念实现的系统,也更容易快速地增加新的高级功能,以为不必担心引入高级功能影响原有的基本功能。

三、资源管理

容器云平台如何对租户可用资源进行精细管理,对平台的可用性、可维护性和易用性起着至关重要的作用,是容器云平台能够为用户提供丰富的微服务管理的基石。在云计算领域,资源可被分为计算资源、网络资源和存储资源三大类,也可被分别称作计算云、网络云和存储云。

3.1、计算资源管理

Namespace

在k8s集群中,提供计算资源的实体叫做Node,Node既可以是物理机服务器,也可以是虚拟机服务器,每个Node提供了CPU、内存、磁盘、网络等资源。每个Node(节点)具有运行pod的一些必要服务,并由Master组件进行管理,Node节点上的服务包括Docker、kubelet和kube-proxy。

通过引入Namespace,k8s将集群近一步划分为多个虚拟分组进行管理,Namespace所实现“分区”是逻辑上的,并不与实际资源绑定,它用于多租户场景实现资源分区和资源最大化利用。

大多数Kubernetes资源(例如pod、services、replication controllers或其他)都在某些Namespace中,但Namespace资源本身并不在Namespace中。而低级别资源(如Node和persistentVolumes)不在任何Namespace中。Events是一个例外:它们可能有也可能没有Namespace,具体取决于Events的对象。

Pod

Pod是Kubernetes创建或部署的最小/最简单的基本单位,一个Pod代表集群上正在运行的一个进程。

一个Pod封装一个应用容器(也可以有多个容器),存储资源、一个独立的网络IP以及管理控制容器运行方式的策略选项。Pod代表部署的一个单位:Kubernetes中单个应用的实例,它可能由单个容器或多个容器共享组成的资源。

每个Pod都是运行应用的单个实例,如果需要水平扩展应用(例如,运行多个实例),则应该使用多个Pods,每个实例一个Pod。在Kubernetes中,这样通常称为Replication。Replication的Pod通常由Controller创建和管理。Controller可以创建和管理多个Pod,提供副本管理、滚动升级和集群级别的自愈能力。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。

Container

docker本身比较重,2015年OCI(Open ContainerInitiative)诞生,它定义了镜像标准、运行时标准和分发标准,由于k8s 本身不具备创建容器的能力,是通过 kubelet 组件调用容器运行时 API 接口和命令来创建容器,Kubernete 与 容器运行时的关系是历史性的,也很复杂。但是随着 Kubernete 弃用 Docker ,目前主流的运行时主要是 containerd 和 CRI-O

“one-container-per-Pod”模式是Kubernetes最常见的用法,一个Pod也可以有多个容器。

三个级别的计算资源管理

在k8s中,可以从Namespace、Pod和Container三个级别区管理资源的配置和限制。例如:

  • 容器级别可以通过Resource Request、Resource Limits配置项
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-3
spec:
  containers:
  - name: memory-demo-3-ctr
    image: vish/stress
    resources:
      limits:
        memory: "1000Gi"
      requests:
        memory: "1000Gi"
    args:
    - -mem-total
    - 150Mi
    - -mem-alloc-size
    - 10Mi
    - -mem-alloc-sleep
    - 1s


  • Pod级别可以通过创建LimitRange对象完成设置,这样可以对Pod所含容器进行统一配置
apiVersion: v1
kind: LimitRange
metadata:
  name: mylimits
spec:
  limits:
  - max:
      cpu: "4"
      memory: 2Gi
    min:
      cpu: 200m
      memory: 6Mi
    maxLimitRequestRatio:
      cpu: 3
      memory: 2
    type: Pod
  - default:
      cpu: 300m
      memory: 200Mi
    defaultRequest:
      cpu: 200m
      memory: 100Mi
    max:
      cpu: "2"
      memory: 1Gi
    min:
      cpu: 100m
      memory: 3Mi
    maxLimitRequestRatio:
      cpu: 5
      memory: 4
    type: Container


  • Namespace级别可以通过对ReSourceQuota资源对象的配置,提供一个总体的资源使用量限制,这个限制可以是对所有Poid使用的计算资源总量上限,也可以是对所有Pod某种类型对象的总数量上限(包括可以创建的Pod、RC、Service、Secret、ConfigMap及PVC等对象的数量)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-demo
spec:
  hard:
  request.cpu: "4"
  request.memory: 8GB
  limit.memory:16GB
  pods: "2"


3.2 网络资源管理

k8s的ip模型

node Ip:node节点的ip,为物理ip.

pod Ip:pod的ip,即docker 容器的ip,为虚拟ip。

cluster Ip:service 的ip,为虚拟ip。提供一个集群内部的虚拟IP以供Pod访问。实现原理是通过Linux防火墙规则,属于NAT技术。当访问ClusterIP时,请求将被转发到后端的实例上,如果后端实例有多个,就顺便实现了负载均衡,默认是轮训方式。

跨主机容器网络方案

在k8s体系中,k8s的网络模型设计的一个基本原则:每个pos都拥有一个独立的IP地址,而且假定所有的Pod都在一个可以直接联通的、扁平的网络空间中,不管它们是否运行在同一个Node(宿主机)中,都可以直接通过对方的IP进行访问。但k8s本身并不提供跨主机的容器网络解决方案。公有云环境(例如AWS、Azure、GCE)通常都提供了容器网络方案,但是在私有云环境下,仍然需要容器云平台位不同的租户提供各种容器网络方案。

目前,为容器设置Overlay网络是最主流的跨主机容器网络方案。Overlay网络是指在不改变原有网络配置的前提下,通过某种额外的网络协议,将原IP报文封装起来形成一个逻辑上的网络。在k8s平台上,建议通过CNI插件的方式部署容器网络。

CNI(Container Network Interface)是CNCF基金会下的一个项目,由一组用于配置容器的网络接口的规范和库组成,它定义的是容器运行环境与网络插件之间的接口规范,仅关心容器创建时的网络配置和容器被销毁是网络资源的释放,并且一个容器可以绑定多个CNI网络插件加入网络中,如下图。

目前比较流程的CNI插件实现方式有Flannel、Calico、macvlan、Open vSwitch、直接路由。

Ingress

在k8s集群内,应用默认以Service的形式提供服务,有kube-proxy实现Service到容器的负载均衡器的功能,如下图定义一个mysql service:

kind: Service
apiVersion: v1
metadata:
  name: mysql-master
spec:
  selector:
    app: mysql-master
  ports:
      port: 3306
      targetPort: 3306


此时,集群外是无法访问这个Service的。对于需要k8s集群外的客户端提供服务的Service,可以通过Ingress将服务暴露出去,并且如果该集群(网络)拥有真实域名,则还能将Service直接与域名进行对接。

k8s将一个Ingress资源对象的定义和一个具体的Ingress Controller相结合来实现7层负载均衡器。Ingress Controller在转发客户请求到后端服务时,将跳过kube-proxy提供的4层负载均衡器的功能,直接转发到Service的后端Pod(Endpoints),以提高网络转发效率。

如上图展示了一个典型的HTTP层路由的Ingress例子,其中:

  • 对http://mywebsite.com/api的访问将被路由到后端名为“api”的Service;

  • 对http://mywebsite.com/web的访问将被路由到后端名为“web”的Service;

  • 对http://mywebsite.com/doc的访问将被路由到后端名为“doc”的Service。

如下是一个典型的Ingress策略定义,Ingress Controller将对目标地址http://mywebsite.com/demo的访问请求转发到集群内部服务的webapp(webapp:8080/demo)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
   name: mywebsite-ingress
spec:
   rules:
   -host:mywebsite.com
    http:
       paths:
      - path: /demo
          backend:
           serviceName: webapp
           servicePort: 8080


常用的Ingress Controller有:Nginx、HAProxy、Traefik、apisix等。

3.3 存储资源

k8s支持的Volume类型

临时目录(emptyDir)

使用emptyDir,当Pod分配到Node上时,将会创建emptyDir,并且只要Node上的Pod一直运行,Volume就会一直存。当Pod(不管任何原因)从Node上被删除时,emptyDir也同时会删除,存储的数据也将永久删除。注:删除容器不影响emptyDir。

配置类

  • ConfigMap:将保存在ConfigMap资源对象中的配置文件信息挂载到容器的某个目录下

  • Secret:将保存在Secret资源对象中的密码密钥等信息挂载到容器内的某个文件中

  • DownwardApI:将downward API的数据以环境变量或文件的形式注入容器中

  • gitRepo:将某Git代码库挂载到容器内的某个目录下

本地存储类

  • hostPath:将宿主机的目录或文件挂载到容器内进行使用

  • local:从v1.9版本引入,将本地存储以PV形式提供给容器使用,并能够给实现存储空间的管理

共享存储类

  • PV(Persistne Volume):将共享存储定义为一种“持久存储卷”,可以被多个容器共享使用

  • PVC(Persistne Volume Claim):用户对存储资源的一次“申请”,PVC申请的对象是PV,一旦申请成功,应用就能够想使用本地目录一样使用共享存储卷。下图是一个PV对象ymal定义:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
  annotations:
        "volume.alpha.kubernetes.io/node-affinity": '{
            "requiredDuringSchedulingIgnoredDuringExecution": {
                "nodeSelectorTerms": [
                    { "matchExpressions": [
                        { "key": "kubernetes.io/hostname",
                          "operator": "In",
                          "values": ["example-node"]
                        }
                    ]}
                 ]}
              }'
spec:
    capacity:
      storage: 100Gi
    accessModes:
    - ReadWriteOnce
    persistentVolumeReclaimPolicy: Delete
    storageClassName: local-storage
    local:
      path: /mnt/disks/ssd1


PV与PVC

PV和PVC相互关系生命周期如上图所示,k8s的共享存储供应模式包括静态模式(Static)和动态模式(Dynamic),资源供应的结果就是创建好的PV。运维人员手动创建PV就是静态,而动态模式的关键就是StorageClass,它的作用就是创建PV模板。

创建StorageClass里面需要定义PV属性比如存储类型、大小等;另外创建这种PV需要用到存储插件。最终效果是,用户提交PVC,里面指定存储类型,如果符合我们定义的StorageClass,则会为其自动创建PV并进行绑定。

下图通过ymal创建一个StorageClass对象

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs    // 存储分配器
parameters:
  type: gp2
reclaimPolicy: Retain   // 回收策略
mountOptions:
  - debug


StorageClass和PV、PVC之间的运作关系如下图所示:

CSI

CSI(Container Storage Interface)与k8s的关系与CNI有点类似,CSI旨在容器和共享存储之间建议一套标准的存储访问接口。在它诞生前,经历了“in-tree”方式、FlexVolume模式。

CSI规范用语将存储供应商代码与k8s代码完全解耦,存储插件的代码由存储供应商自行维护。

和kube-apiserver直接进行交互的是K8S官方直接提供的一些sidecar容器,这些sidecar直接部署即可。这些sidecar容器(主要是上图的三个主要部件)监听自己对应的CRD,触发对应的操作,通过UDS接口直接调用CSI driver的接口(例如CreateVolume() 、NodePublishVolme()等)来实现对卷的操作。

要开发CSI Drivers一般来说实现以下几个服务:

  • CSI Identity service

允许调用者(Kubernetes组件和CSI sidecar容器)识别驱动程序及其支持的可选功能。

  • CSI Node service

NodePublishVolume, NodeUnpublishVolume 和 NodeGetCapabilities 是必须的。

所需的方法使调用者能够使卷在指定的路径上可用,并发现驱动程序支持哪些可选功能。

  • CSI Controller Service

实现CreateVolume、DeleteVolume接口

3.4 多集群资源管理方案-集群联邦(Federation)

Federation是Kubernetes的子项目,其设计目标是对多个Kubernetess集群进行统一管理,将用户的应用部署到不同地域的数据中心。Federation引入了一个位于Kubernetes集群只上的控制平面,屏蔽了后端各k8s子集群,向客户提供了统一的管理入口,如下图:

Federation控制平面“封装”了多个k8s集群的Master角色,提供了统一的Master,包括Federation API Server、Federation Controller Manafer,用户可以向操作单个集群一样操作Federation,还统一了全部k8s集群的DNS、ConfigMap,并将数据保存在集中的etcd数据库中。

写给读者

对于k8s初学者来说,对k8s的第一印象应该是概念多,名词多。《kubernetes权威指南:企业级容器云实战》这本书从企业实践角度入手,讲述了技术的演进,并在很多场景提供了不同技术实现的对比,结合k8s中文社区,这本书可以作为学习k8s的入门书籍。本文实际上是此书的一篇读书笔记,文章从计算资源、网络资源、存储资源三个方向展开,介绍了k8s里一些常见的概念和对象。由于篇幅问题,很多也很重要的概念并没有在文中详细介绍,读者可根据自身情况展开补充学习。关于k8s核心组件及工作原理将在后续陆续推出。

本文转载于网络 如有侵权请联系删除

相关文章

  • 从0到1了解ElasticSearch文档写入

    简介这篇文章主要讨论一下ElasticSearch文档写入的关键步骤以及在使用ESClient使用过程的一些需要主要的问题。如果对ElasticSearch的基础概念不熟悉的同学可以先看一下上一篇文章【从0到1理解ElasticSearch文档写入和检索原理】。创建索引创建索引脚本#创建索引 PUT/product_v1?pretty #定义索引的mapping PUT/product_v1/_doc/_mapping?pretty { "_doc":{ "dynamic":false, "properties":{ "productOuterId":{ "type":"keyword" }, "productName":{ "type":"text", "fields":{ "raw":{ "type":"keyword" }

  • 介绍一个小工具:网络策略可视化编辑器

    引子跳过本节不影响阅读既然是牛年第一篇,总要写点废话起个头。另外写小工具系列经常面对的一个难题就是——怎样凑够300字的原创门槛。2020年有大半年我都在唠叨云原生安全的事情,现在的情况按照我的理解,有点像2000年附近的互联网——各种东西都在往新瓶子里装,那时候的新瓶子是互联网,现在的新瓶子是云原生;那时候的旧酒是邮件、留言板、传呼机,现在的旧酒除了这些生活内容之外,多了更多的ToB/G的内容;从前的较大规模的公开互联网服务多数是自建自维护的,现在的公开服务则往往会用到大量的公有云、SaaS/PaaS服务以及第三方交付项目。在Kubernetes来说:推出了CKS认证OPA毕业Kyverno进入沙箱Redhat收购StackRox综上,经过轰轰烈烈的云原生运动之后,安全问题就已经被怼到了我们面前,很多时候一些重点服务一旦遭到破坏,虽说安全相关的黑产已经有了成熟的获利链条;然而在责任方来说,的确可以挤出一句——这不是钱的事儿。正文言归正传,今天要介绍的是一个安全相关的网络策略小工具。网络策略是Kubernetes内置的重要安全机制之一,用它可以轻松地使用Namespace、LabelS

  • 腾讯云大学大咖分享 | 探索云直播技术

    点击观看完整课程直播行业规模逐年增加,但行业增速却在逐步放缓,视频直播的平台对于各大厂商的解决方案提出了更多、更个性化的要求。是什么样的技术和服务在背后支撑着我们日常直播内容发布和播放呢?今天我们通过腾讯云大学和云+社区共同整理的云直播技术课程的干货内容进一步了解!在2019年,直播行业规模已突破600亿元,随着移动带宽和移动互联网的互相加持,移动互联网的用户和流量进一步增加。预计到2020年直播行业规模将突破700亿元。但随着带宽规模的不断上升,直播行业增速在逐年放缓。放缓的原因主要有以下几个。在成本方面,用户和流量的增加导致各大平台的成本越来越高。并且目前国内对直播行业有了更加明确的监管手段,监管越来越严格,网络直播已经从野蛮增长阶段变为健康监管阶段。直播行业的人口红利已经见顶,用户向头部平台集中,直播直播行业已进入下半场。但随着新技术的不断产生和发展,人工智能,5G技术,增强现实等持续创新,行业迎来新的发展机会。目前直播行业有一些较为典型的应用场景:游戏(虎牙、企鹅电竞)、秀场(映客、花椒)、新闻(CNTV)、教育(新东方在线)、旅游(游云南)、金融(大智慧)、电商(蘑菇街)、赛

  • java 单元测试

    在测试文件夹下新建测试基础类,内容为//指定bean注入的配置文件 @ContextConfiguration(locations={"classpath:application.xml"}) //使用标准的JUnit@RunWith注释来告诉JUnit使用SpringTestRunner @RunWith(SpringJUnit4ClassRunner.class) publicabstractclassSpringTestCaseextendsAbstractJUnit4SpringContextTests{ protectedLoggerlogger=LoggerFactory.getLogger(getClass()); }复制此测试类用于spring配置的项目,需加载xml文件时用到,测试程序继承此类即可测试,比如:publicclassUserServiceTestextendsSpringTestCase{ @Resource privateUserServiceuserService; Loggerlogger=Logger.getLogger(Us

  • Windows下Ionic 开发环境搭建

    Ionic介绍首先,Ionic是什么。Ionic是一款基于Cordova及Angular开发Hybrid/WebAPP的前端框架,类似的其他框架有:IntelXDK等。简单来说就是可以将你的Web应用打包发布成IOS/AndroidAPP,并且提供了Cordova之外很多强大的服务和新的特性。听起来还是很诱人的,事实上这也是目前最火的一种HybridAPP开发方式。接下来介绍如何在Windows下搭建Ionic开发环境。在开始之前我假设你已经了解了如下概念:JavaJDKApacheAntAndroidSDKNodeJS以上名词这里就不赘述,如果有不清楚的可以自行查阅安装步骤Ionic官方教程:http://learn.ionicframework.com/videos/windows-android/以下内容参考官方教程得出:下载JDK并配置好Java运行环境下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html(请注意选择您电脑的对应版本)Java环境变量的配置

  • 安装虚拟机VMware详解

    安装VMware详解1双击安装程序2点击下一步3选择接受,点击下一步4选择自定义安装5根据自己硬盘的大小更改安装【核心组件】的目录 6选择【VIX应用程序编程接口】的目录,点击下一步 根据自己硬盘的大小更改安装【VIX应用程序编程接口】的目录,点击下一步 7选择【共享虚拟机】的存放目录,点击下一步 根据自己硬盘的大小更改【共享虚拟机】的存放目录,点击下一步 8把【启动时检查产品更新】前的复选框√去掉9【帮助改善VMwareWorkstation】前的复选框√去掉 10直接下一步11等待,点击下一步这里需要的时间稍长一些,一般会在3到5分钟左右,完成后点击下一步12要求输入密钥,(此时不要关闭窗口也不要跳过) 13双击VMwareWorkstation10.0注册机.exe 14拷贝红色框里的密钥15粘贴到刚才的页面中,点击输入 16完成,点击完成关闭窗口

  • MIT 6.828 笔记——环境配置

    6.828labtoolsguide(官方环境配置文档) 基本环境 操作系统 首先需要一个Linux环境(物理机、虚拟机都可以),我的环境是Ubuntu20.10的物理机。 编译工具链 也就是GCC、GDB等一系列工具,以下安装命令都以Debian系为例: sudoaptinstallbuild-essentialgdb 复制 32位支持库 sudoapt-getinstallgcc-multilib 复制 获取JOS源码 使用Git将源码克隆到本地。 gitclonehttps://pdos.csail.mit.edu/6.828/2018/jos.gitlab 复制 QEMU QEMU是一款开源的模拟处理器,课程使用它来进行X86仿真。强烈建议使用MIT提供的魔改版。 gitclonehttps://github.com/mit-pdos/6.828-qemu.gitqemu 复制 编译QEMU 代码可能比较老了,编译中会出现一些问题。 configure忽略所有Warning: CFLAGS=-Wno-error./configure--disable-kvm--target-l

  • 我在用的mac软件(1)--终端环境之iTerm2

      之前一直有朋友要我分享下在用的mac软件,今天有空就来写一下,可能不止于软件,会有一些配置或者工具,或者叫环境更合适。有些可能一句话带过,有些会详细介绍。也不分类了,想到哪个就写出来。如果已经写的足够长了,就会分几篇来写。 iTerm2+zsh+tmux的终端环境 iTerm2 其实现在osx的terminal已经做的很好了,但是iTerm2的功能依然要更强大一些。简述下优点和常用功能: 开源免费。 兼容性比默认Terminal更好。 对于经常要远程使用的情况下,默认的Terminal在使用vi时经常出现不兼容的问题,而iTerm2在这方面显然做的更好。 快捷键丰富。 ⌘+数字:切换标签页。⌘+方向键按方向切换标签页。 ⌘+enter:切换全屏 ⌘+f:查找。支持正则。其中查找的内容会被自动复制。省去了再去⌘+c的步骤。同样,鼠标去选中的内容也会自动复制,也可以鼠标中键直接粘贴。一般在使用时,键入搜索关键词,然后用shift-tab或者tab左右自动补全,option+enter则自动将搜索结果键入,并且复制到剪贴板。 ⌘+d:垂直分屏,⌘+shift+d

  • 如果你也会C#,那不妨了解下F#(3):F#集合类型和其他核心类型

    *本文链接:http://www.cnblogs.com/hjklin/p/fs-for-cs-dev-3.html* 在第一篇中,我们介绍了一些基础数据类型,其实那篇标题中不应该含有“F#”字眼,因为并不是特有的。 在本篇中,我们介绍如数组这些集合类型以及部分F#特有的类型。 在第一篇里我们列了一个从0加到100的代码段,了解函数式编程的同学会说那个F#代码不正宗。 而现在的C#开发一般也会使用Linq的方式来代替循环,其实F#天生就是使用这种方式的,下面我们先介绍F#的集合类型,在之后会介绍相关集合的函数操作。 集合类型 列表:List 声明List 注意,F#中的List不是C#中常用的System.Collections.Generic.List<T>,虽然后者你也可以在F#里使用。 F#中的List是有序,不可变的,且每一项的类型必须一致。我们先看看怎么定义列表。以下代码以>开头的为输入,之后的一行则为输出结果。 >letcharList=['a';'o';'e';'i';'u';'ü'];; valcharList:charlist=['a';'o'

  • 关于非标准json格式转变为json对象

    eval('('+tempData+')') 只需要这一句

  • 我所了解的JavaScript糟粕和鸡肋

    糟粕 全局变量 众所周知,全局变量在很小的程序中可能会带来方便,但随着程序变得越来大,全局变量将难以处理,全局变量将降低程序的可靠性。 在js中有3种方式定义全局变量 脱离任何函数安排一个var语句   //varfoo=value; 直接添加一个属性到全局对象上  //window.foo=value; 直接使用未经声明的变更(其实这叫隐匿全局变量)   //foo=value;     作用域  众所周知,在JavaScript中没有块级作用域,而且在JavaScript有提升变量声明的功能,所以最好的方式是在每个函数的开头部分声明所有变量。 自动插入分号  JavaScript会试图通过自动插入分号来修正有缺损的程序。 return { status:true };复制 上面的代码大家自然的会想到会返回一个包含status成员元素的对象。但是由于JavaScript自动插入让它变成了一个返回undefined。 所以把{放在上一行的尾部而不是下一行

  • python中的StringIO模块

    StringIO经常被用来作为字符串的缓存,应为StringIO有个好处,他的有些接口和文件操作是一致的,也就是说用同样的代码,可以同时当成文件操作或者StringIO操作。一、例子12345678910111213141516171819202122import StringIO s = StringIO.StringIO()s.write('www.baidu.com\r\n')s.write('news.realsil.com.cn')s.seek(0)print '*' * 20print s.tell()print s.read() print '*' * 20print s.tell()print s.read() print '*' * 20print s.tell()print s.getvalue() print '*' *&nbs

  • Python笔记_5变量之面向对象类的总结

    前言导读 本章收录了类的功能,以前看过很多版本讲的类的功能,都没有看懂 后来看到一篇文章写的很好,于是乎就看懂了,然后就整理好收录在这里 一类的完整格式 #创造一个种类一个框架:构造类中的各种元素 class类: #1构造_类属性 类属性1='这就是类属性1' 类属性2='这就是类属性2' #2构造_初始化方法 def__init__(self,实例属性1,实例属性2,实例属性3): #3构造_实例属性 self.实例属性1=实例属性1 self.实例属性1=实例属性1 self.实例属性1=实例属性1 #4构造_实例方法(同类) def实例方法1(self): print('这就是实例方法') print(self.实例属性1) def实例方法2(self): print('这就是实例方法') print(self.实例属性1) def实例方法3(self): print('这就是实例方法') print(self.实例属性1) #5构造_类方法 @classmethod def类方法(cls)#cls类方法的第一个参数,固定格式 print('这就是类方法

  • IntelliJ IDEA 下载安装以及破解

    转载自:http://blog.csdn.net/my_jack/article/details/69248495 IDEA开发工具是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn、github等)、JUnit、CVS整合、代码分析、创新的GUI设计等方面的功能可以说是超常的。IDEA是JetBrains公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。它的旗舰版本还支持HTML,CSS,PHP,MySQL,Python等。免费版只支持Java等少数语言。如今的AndroidStudio也是在基于idea的基础上开发的,所以当你用惯了IDEA的话,再去使用AS,感觉是那么的熟悉。 先附上idea的官方下载地址:https://www.jetbrains.com/idea/download/#section=windows 各种平台都有自行进行下载就可以了,说明一下idea分为两种版本社区版和商业版,商业版付费的功能多

  • 【建议收藏】技术面必考题:多线程、多进程

    软件质量保障 专注测试圈,自动化测试、测试平台开发、测试新技术、大厂测试岗面经分享,可以帮忙内推BATJ等大厂!欢迎加VX沟通交流:ISTE1024 多进程篇​ 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。 Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。 与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。 守护进程 主进程创建守护进程守护进程会在主进程代码执行结束后就终止 守护进程内无法再开启子进程,否则抛出异常:AssertionError:daemo

  • 学习一下mef

    微软 http://msdn.microsoft.com/zh-cn/magazine/ee291628.aspx mef http://biancheng.dnbcw.info/net/370552.html

  • jQuery中Ajax的应用

    这部分知识,消化起来有点费劲了。。有点看不透了。。。 步入代码的世界,改变自己,追求想要到达的地方!

  • vs2015运行时提示未加载vcruntime140.adm64.pb

       后调试查看发现 vs2015运行时提示未加载vcruntime140.adm64.pb     解决方案:去微软官网下载安装vc_redist.exe,安装就可以了。有64位版和32位版,根据计算机配置进行下载 下载链接参考网址中有或者去我的CSDN中下载:https://download.csdn.net/my   参考: https://blog.csdn.net/weixin_42591308/article/details/100728021

  • 复杂网络分析-个人笔记 总结

    一.工具 1.Python3.7 2.NetworkX2.3 这是一个专门用于复杂网络分析的包,执行pipinstallnetworkx即可安装。 二、网络基本性质 1.节点数 网络中包含的节点个数。 2.连接数 网络中包含的边的个数。 3.密度 网络中包含的边的个数占网络中所有可能的边的个数的比例。 4.聚集系数 也称为局部聚集系数,是网络中每个节点的聚集系数的平均值。节点的聚集系数为,将该节点的所有邻居两两组合,则共有种组合,组合中的两个节点为邻居的组合数占所有组合数的比例即为该节点的聚集系数。 5.传递性 也称为全局聚集系数,即网络中的三角形结构占所有可能的三角形结构的比例。 6.互惠性 互惠性是有向图的性质,即在有向图中,双向连接的边占所有边的比例。 三、中心性分析 中心性分析包括两方面,分别是节点的中心度和整体网络的中心势。 1.点度中心性(degreecentrality) 在无向网络中,我们可以用一个节点的度数(相当于你的微信好友数)来衡量中心性。在微博中,谢娜的粉丝数9千多万,她的点度中心性就很高。 这一指标背后的假设是:重要的节点就是拥有许多连接的节点。你的社会关系越

  • java-信息安全(二十)国密算法 SM1,SM2,SM3,SM4

    一、概述 国密即国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位。目前主要使用公开的SM2、SM3、SM4三类算法,分别是非对称算法、哈希算法和对称算法。 SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。不讨论 SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。ECC256位(SM2采用的就是ECC256位的一种)安全强度比RSA2048位高,但运算速度快于RSA。   SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。 SM3 消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。  

  • css多背景平铺效果

    //从上至下平铺 background-repeat:no-repeat; background-image:url('../../assets/images/spring/bg1.png'),url('../../assets/images/spring/bg2.png'),url('../../assets/images/spring/bg3.png'); background-size:100%30px,100%calc(100%-60px),100%30px; background-position:top,0px30px,bottom;  

相关推荐

推荐阅读