k8s 组件介绍-API Server

API Server简介

k8s API Server提供了k8s各类资源对象(pod,RC,Service等)的增删改查及watch等HTTP Rest接口,是整个系统的数据总线和数据中心。

kubernetes API Server的功能:

  1. 提供了集群管理的REST API接口(包括认证授权、数据校验以及集群状态变更);
  2. 提供其他模块之间的数据交互和通信的枢纽(其他模块通过API Server查询或修改数据,只有API Server才直接操作etcd);
  3. 是资源配额控制的入口;
  4. 拥有完备的集群安全机制.

kube-apiserver工作原理图

如何访问kubernetes API

k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。

k8s通过kube-apiserver这个进程提供服务,该进程运行在单个k8s-master节点上。默认有两个端口。

1. 本地端口

  1. 该端口用于接收HTTP请求;
  2. 该端口默认值为8080,可以通过API Server的启动参数“--insecure-port”的值来修改默认值;
  3. 默认的IP地址为“localhost”,可以通过启动参数“--insecure-bind-address”的值来修改该IP地址;
  4. 非认证或授权的HTTP请求通过该端口访问API Server。

2.安全端口

  1. 该端口默认值为6443,可通过启动参数“--secure-port”的值来修改默认值;
  2. 默认IP地址为非本地(Non-Localhost)网络端口,通过启动参数“--bind-address”设置该值;
  3. 该端口用于接收HTTPS请求;
  4. 用于基于Tocken文件或客户端证书及HTTP Base的认证;
  5. 用于基于策略的授权;
  6. 默认不启动HTTPS安全访问控制。

kubernetes API访问方式

Kubernetes REST API可参考https://kubernetes.io/docs/api-reference/v1.6/

1. curl

curl localhost:8080/api

curl localhost:8080/api/v1/pods

curl localhost:8080/api/v1/services

curl localhost:8080/api/v1/replicationcontrollers

2. Kubectl Proxy

Kubectl Proxy代理程序既能作为API Server的反向代理,也能作为普通客户端访问API Server的代理。通过master节点的8080端口来启动该代理程序。

kubectl proxy --port=8080 &

具体见kubectl proxy --help

3. kubectl客户端

命令行工具kubectl客户端,通过命令行参数转换为对API Server的REST API调用,并将调用结果输出。

命令格式:kubectl [command] [options]

具体可参考Kubernetes常用命令

4. 编程方式调用

使用场景:

1、运行在Pod里的用户进程调用kubernetes API,通常用来实现分布式集群搭建的目标。

2、开发基于kubernetes的管理平台,比如调用kubernetes API来完成Pod、Service、RC等资源对象的图形化创建和管理界面。可以使用kubernetes提供的Client Library。

具体可参考https://github.com/kubernetes/client-go。

通过API Server访问Node、Pod和Service

k8s API Server最主要的REST接口是资源对象的增删改查,另外还有一类特殊的REST接口—k8s Proxy API接口,这类接口的作用是代理REST请求,即kubernetes API Server把收到的REST请求转发到某个Node上的kubelet守护进程的REST端口上,由该kubelet进程负责响应。

1. Node相关接口

关于Node相关的接口的REST路径为:/api/v1/proxy/nodes/{name},其中{name}为节点的名称或IP地址。

/api/v1/proxy/nodes/{name}/pods/    #列出指定节点内所有Pod的信息

/api/v1/proxy/nodes/{name}/stats/   #列出指定节点内物理资源的统计信息

/api/v1/prxoy/nodes/{name}/spec/    #列出指定节点的概要信息

这里获取的Pod信息来自Node而非etcd数据库,两者时间点可能存在偏差。如果在kubelet进程启动时加--enable-debugging-handles=true参数,那么kubernetes Proxy API还会增加以下接口:

/api/v1/proxy/nodes/{name}/run      #在节点上运行某个容器

/api/v1/proxy/nodes/{name}/exec     #在节点上的某个容器中运行某条命令

/api/v1/proxy/nodes/{name}/attach   #在节点上attach某个容器

/api/v1/proxy/nodes/{name}/portForward   #实现节点上的Pod端口转发

/api/v1/proxy/nodes/{name}/logs     #列出节点的各类日志信息

/api/v1/proxy/nodes/{name}/metrics  #列出和该节点相关的Metrics信息

/api/v1/proxy/nodes/{name}/runningpods  #列出节点内运行中的Pod信息

/api/v1/proxy/nodes/{name}/debug/pprof  #列出节点内当前web服务的状态,包括CPU和内存的使用情况

2. Pod相关接口

/api/v1/proxy/namespaces/{namespace}/pods/{name}/{path:*}      #访问pod的某个服务接口

/api/v1/proxy/namespaces/{namespace}/pods/{name}               #访问Pod

#以下写法不同,功能一样

/api/v1/namespaces/{namespace}/pods/{name}/proxy/{path:*}      #访问pod的某个服务接口

/api/v1/namespaces/{namespace}/pods/{name}/proxy               #访问Pod

3. Service相关接口

/api/v1/proxy/namespaces/{namespace}/services/{name}

Pod的proxy接口的作用:在kubernetes集群之外访问某个pod容器的服务(HTTP服务),可以用Proxy API实现,这种场景多用于管理目的,比如逐一排查Service的Pod副本,检查哪些Pod的服务存在异常问题。

集群功能模块之间的通信

kubernetes API Server作为集群的核心,负责集群各功能模块之间的通信,集群内各个功能模块通过API Server将信息存入etcd,当需要获取和操作这些数据时,通过API Server提供的REST接口(GET\LIST\WATCH方法)来实现,从而实现各模块之间的信息交互。

1. kubelet与API Server交互

每个Node节点上的kubelet定期就会调用API Server的REST接口报告自身状态,API Server接收这些信息后,将节点状态信息更新到etcd中。kubelet也通过API Server的Watch接口监听Pod信息,从而对Node机器上的POD进行管理。

监听信息

kubelet动作

备注

新的POD副本被调度绑定到本节点执行POD对应的容器的创建和启动逻辑 
POD对象被删除删除本节点上相应的POD容器 
修改POD信息修改本节点的POD容器 

2. kube-controller-manager与API Server交互

kube-controller-manager中的Node Controller模块通过API Server提供的Watch接口,实时监控Node的信息,并做相应处理。

3. kube-scheduler与API Server交互

Scheduler通过API Server的Watch接口监听到新建Pod副本的信息后,它会检索所有符合该Pod要求的Node列表,开始执行Pod调度逻辑。调度成功后将Pod绑定到目标节点上。

 

 

API Server参数介绍

API Server 主要是和 etcd 打交道,并且对外提供 HTTP 服务,以及进行安全控制,因此它的命令行提供的参数也主要和这几个方面有关。下面是一些比较重要的参数以及说明(不同版本参数可能会有不同):

参数含义默认值
–advertise-address通过该 ip 地址向集群其他节点公布 api server 的信息,必须能够被其他节点访问nil
–allow-privileged是否允许 privileged 容器运行false
–admission-control准入控制AlwaysAdmit
–authorization-mode授权模式 ,安全接口上的授权AlwaysAllow
–bind-addressHTTPS 安全接口的监听地址0.0.0.0
–secure-portHTTPS 安全接口的监听端口6443
–cert-dirTLS 证书的存放目录/var/run/kubernetes
–etcd-prefix信息存放在 etcd 中地址的前缀“/registry”
–etcd-servers逗号分割的 etcd server 地址[]
–insecure-bind-addressHTTP 访问的地址127.0.0.1
–insecure-portHTTP 访问的端口8080
–log-dir日志存放的目录 
–service-cluster-ip-rangeservice 要使用的网段,使用 CIDR 格式,参考 kubernetes 中 service 的定义 

API Server安装和运行

API Server 是通过提供的 kube-apiserver 二进制文件直接运行的,下面的例子指定了 service 分配的 ip 范围,etcd 的地址,和对外提供服务的 ip 地址:

  1. /usr/bin/kube-apiserver \
  2. --service-cluster-ip-range=10.20.0.1/24 \
  3. --etcd-servers=http://127.0.0.1:2379 \
  4. --advertise-address=192.168.8.100 \
  5. --bind-address=192.168.8.100 \
  6. --insecure-bind-address=192.168.8.100 \
  7. --v=4

直接访问 8080 端口,API Server 会返回它提供了哪些接口:

  1. [root@localhost vagrant]# curl http://192.168.8.100:8080
  2. {
  3. "paths": [
  4. "/api",
  5. "/api/v1",
  6. "/apis",
  7. "/apis/apps",
  8. "/apis/apps/v1alpha1",
  9. "/apis/autoscaling",
  10. "/apis/autoscaling/v1",
  11. "/apis/batch",
  12. "/apis/batch/v1",
  13. "/apis/batch/v2alpha1",
  14. "/apis/extensions",
  15. "/apis/extensions/v1beta1",
  16. "/apis/policy",
  17. "/apis/policy/v1alpha1",
  18. "/apis/rbac.authorization.k8s.io",
  19. "/apis/rbac.authorization.k8s.io/v1alpha1",
  20. "/healthz",
  21. "/healthz/ping",
  22. "/logs/",
  23. "/metrics",
  24. "/swaggerapi/",
  25. "/ui/",
  26. "/version"
  27. ]
  28. }

而目前最重要的路径是 /api/v1,里面包含了 kubernetes 所有资源的操作,比如下面的 nodes:

  1. ➜ ~ http http://192.168.8.100:8080/api/v1/nodes
  2. HTTP/1.1 200 OK
  3. Content-Length: 112
  4. Content-Type: application/json
  5. Date: Thu, 08 Sep 2016 08:14:45 GMT
  6. {
  7. "apiVersion": "v1",
  8. "items": [],
  9. "kind": "NodeList",
  10. "metadata": {
  11. "resourceVersion": "12",
  12. "selfLink": "/api/v1/nodes"
  13. }
  14. }

 API 以 json 的形式返回,会通过 apiVersion 来说明 API 版本号,kind 说明请求的是什么资源。不过这里面的内容是空的,因为目前还没有任何 kubelet 节点接入到我们的 API Server。对应的,pod 也是空的:

  1. ➜ ~ http http://192.168.8.100:8080/api/v1/pods
  2. HTTP/1.1 200 OK
  3. Content-Length: 110
  4. Content-Type: application/json
  5. Date: Thu, 08 Sep 2016 08:18:53 GMT
  6. {
  7. "apiVersion": "v1",
  8. "items": [],
  9. "kind": "PodList",
  10. "metadata": {
  11. "resourceVersion": "12",
  12. "selfLink": "/api/v1/pods"
  13. }
  14. }

添加节点

添加节点也非常简单,启动 kubelet 的时候使用 --api-servers 指定要接入的 API Server 就行。kubelet 启动之后,会把自己注册到指定的 API Server,然后监听 API 对应 pod 的变化,根据 API 中 pod 的实际信息来管理节点上 pod 的生命周期。

现在访问 /api/v1/nodes 就能看到已经添加进来的节点:

  1. ➜ ~ http http://192.168.8.100:8080/api/v1/nodes
  2. HTTP/1.1 200 OK
  3. Content-Type: application/json
  4. Date: Thu, 08 Sep 2016 08:27:44 GMT
  5. Transfer-Encoding: chunked
  6. {
  7. "apiVersion": "v1",
  8. "items": [
  9. {
  10. "metadata": {
  11. "annotations": {
  12. "volumes.kubernetes.io/controller-managed-attach-detach": "true"
  13. },
  14. "creationTimestamp": "2016-09-08T08:23:01Z",
  15. "labels": {
  16. "beta.kubernetes.io/arch": "amd64",
  17. "beta.kubernetes.io/os": "linux",
  18. "kubernetes.io/hostname": "192.168.8.100"
  19. },
  20. "name": "192.168.8.100",
  21. "resourceVersion": "65",
  22. "selfLink": "/api/v1/nodes/192.168.8.100",
  23. "uid": "74e16eba-759d-11e6-b463-080027c09e5b"
  24. },
  25. "spec": {
  26. "externalID": "192.168.8.100"
  27. },
  28. "status": {
  29. "addresses": [
  30. {
  31. "address": "192.168.8.100",
  32. "type": "LegacyHostIP"
  33. },
  34. {
  35. "address": "192.168.8.100",
  36. "type": "InternalIP"
  37. }
  38. ],
  39. "allocatable": {
  40. "alpha.kubernetes.io/nvidia-gpu": "0",
  41. "cpu": "1",
  42. "memory": "502164Ki",
  43. "pods": "110"
  44. },
  45. "capacity": {
  46. "alpha.kubernetes.io/nvidia-gpu": "0",
  47. "cpu": "1",
  48. "memory": "502164Ki",
  49. "pods": "110"
  50. },
  51. "conditions": [
  52. {
  53. "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  54. "lastTransitionTime": "2016-09-08T08:23:01Z",
  55. "message": "kubelet has sufficient disk space available",
  56. "reason": "KubeletHasSufficientDisk",
  57. "status": "False",
  58. "type": "OutOfDisk"
  59. },
  60. {
  61. "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  62. "lastTransitionTime": "2016-09-08T08:23:01Z",
  63. "message": "kubelet has sufficient memory available",
  64. "reason": "KubeletHasSufficientMemory",
  65. "status": "False",
  66. "type": "MemoryPressure"
  67. },
  68. {
  69. "lastHeartbeatTime": "2016-09-08T08:27:36Z",
  70. "lastTransitionTime": "2016-09-08T08:24:56Z",
  71. "message": "kubelet is posting ready status",
  72. "reason": "KubeletReady",
  73. "status": "True",
  74. "type": "Ready"
  75. }
  76. ],
  77. "daemonEndpoints": {
  78. "kubeletEndpoint": {
  79. "Port": 10250
  80. }
  81. },
  82. "images": [
  83. {
  84. "names": [
  85. "172.16.1.41:5000/nginx:latest"
  86. ],
  87. "sizeBytes": 425626718
  88. },
  89. {
  90. "names": [
  91. "172.16.1.41:5000/hyperkube:v0.18.2"
  92. ],
  93. "sizeBytes": 207121551
  94. },
  95. {
  96. "names": [
  97. "172.16.1.41:5000/etcd:v3.0.4"
  98. ],
  99. "sizeBytes": 43302056
  100. },
  101. {
  102. "names": [
  103. "172.16.1.41:5000/busybox:latest"
  104. ],
  105. "sizeBytes": 1092588
  106. },
  107. {
  108. "names": [
  109. "172.16.1.41:5000/google_containers/pause:0.8.0"
  110. ],
  111. "sizeBytes": 241656
  112. }
  113. ],
  114. "nodeInfo": {
  115. "architecture": "amd64",
  116. "bootID": "48955926-11dd-4ad3-8bb0-2585b1c9215d",
  117. "containerRuntimeVersion": "docker://1.10.3",
  118. "kernelVersion": "3.10.0-123.13.1.el7.x86_64",
  119. "kubeProxyVersion": "v1.3.1-beta.0.6+fbf3f3e5292fb0",
  120. "kubeletVersion": "v1.3.1-beta.0.6+fbf3f3e5292fb0",
  121. "machineID": "b9597c4ae5f24494833d35e806e00b29",
  122. "operatingSystem": "linux",
  123. "osImage": "CentOS Linux 7 (Core)",
  124. "systemUUID": "823EB67A-057E-4EFF-AE7F-A758140CD2F7"
  125. }
  126. }
  127. }
  128. ],
  129. "kind": "NodeList",
  130. "metadata": {
  131. "resourceVersion": "65",
  132. "selfLink": "/api/v1/nodes"
  133. }
  134. }

 我们可以看到,kubelet 收集了很多关于自身节点的信息,这些信息也会不断更新。这些信息里面不仅包含节点的系统信息(系统架构,操作系统版本,内核版本等)、还有镜像信息(节点上有哪些已经下载的 docker 镜像)、资源信息(Memory 和 Disk 的总量和可用量)、以及状态信息(是否正常,可以分配 pod等)。

和 API Server 通信

编写的 yaml 文件转换成 json 格式,保存到文件里。主要注意的是,我们指定了 nodeName 的名字,这个名字必须和之前通过 /api/v1/nodes 得到的结果中 metadata.labels.kubernetes.io/hostname 保持一致:

  1. [root@localhost vagrant]# cat nginx_pod.yml
  2. apiVersion: v1
  3. kind: Pod
  4. metadata:
  5. name: nginx-server
  6. spec:
  7. NodeName: 192.168.8.100
  8. containers:
  9. - name: nginx-server
  10. image: 172.16.1.41:5000/nginx
  11. ports:
  12. - containerPort: 80
  13. volumeMounts:
  14. - mountPath: /var/log/nginx
  15. name: nginx-logs
  16. - name: log-output
  17. image: 172.16.1.41:5000/busybox
  18. command:
  19. - bin/sh
  20. args: [-c, 'tail -f /logdir/access.log']
  21. volumeMounts:
  22. - mountPath: /logdir
  23. name: nginx-logs
  24. volumes:
  25. - name: nginx-logs
  26. emptyDir: {}

 

使用 curl 执行 POST 请求,设置头部内容为 application/json,传过去文件中的 json 值,可以看到应答(其中 status 为 pending,表示以及接收到请求,正在准备处理):

  1. # curl -s -X POST -H "Content-Type: application/json" http://192.168.8.100:8080/api/v1/namespaces/default/pods --data @nginx_pod.json
  2. {
  3. "kind": "Pod",
  4. "apiVersion": "v1",
  5. "metadata": {
  6. "name": "nginx-server",
  7. "namespace": "default",
  8. "selfLink": "/api/v1/namespaces/default/pods/nginx-server",
  9. "uid": "888e95d0-75a9-11e6-b463-080027c09e5b",
  10. "resourceVersion": "573",
  11. "creationTimestamp": "2016-09-08T09:49:28Z"
  12. },
  13. "spec": {
  14. "volumes": [
  15. {
  16. "name": "nginx-logs",
  17. "emptyDir": {}
  18. }
  19. ],
  20. "containers": [
  21. {
  22. "name": "nginx-server",
  23. "image": "172.16.1.41:5000/nginx",
  24. "ports": [
  25. {
  26. "containerPort": 80,
  27. "protocol": "TCP"
  28. }
  29. ],
  30. "resources": {},
  31. "volumeMounts": [
  32. {
  33. "name": "nginx-logs",
  34. "mountPath": "/var/log/nginx"
  35. }
  36. ],
  37. "terminationMessagePath": "/dev/termination-log",
  38. "imagePullPolicy": "Always"
  39. }
  40. ],
  41. "restartPolicy": "Always",
  42. "terminationGracePeriodSeconds": 30,
  43. "dnsPolicy": "ClusterFirst",
  44. "nodeName": "192.168.8.100",
  45. "securityContext": {}
  46. },
  47. "status": {
  48. "phase": "Pending"
  49. }
  50. }

返回中包含了我们提交 pod 的信息,并且添加了 statusmetadata 等额外信息。

等一段时间去查询 pod,就可以看到 pod 的状态已经更新了:

  1. ➜ http http://192.168.8.100:8080/api/v1/namespaces/default/pods
  2. HTTP/1.1 200 OK
  3. Content-Type: application/json
  4. Date: Thu, 08 Sep 2016 09:51:29 GMT
  5. Transfer-Encoding: chunked
  6. {
  7. "apiVersion": "v1",
  8. "items": [
  9. {
  10. "metadata": {
  11. "creationTimestamp": "2016-09-08T09:49:28Z",
  12. "name": "nginx-server",
  13. "namespace": "default",
  14. "resourceVersion": "592",
  15. "selfLink": "/api/v1/namespaces/default/pods/nginx-server",
  16. "uid": "888e95d0-75a9-11e6-b463-080027c09e5b"
  17. },
  18. "spec": {
  19. "containers": [
  20. {
  21. "image": "172.16.1.41:5000/nginx",
  22. "imagePullPolicy": "Always",
  23. "name": "nginx-server",
  24. "ports": [
  25. {
  26. "containerPort": 80,
  27. "protocol": "TCP"
  28. }
  29. ],
  30. "resources": {},
  31. "terminationMessagePath": "/dev/termination-log",
  32. "volumeMounts": [
  33. {
  34. "mountPath": "/var/log/nginx",
  35. "name": "nginx-logs"
  36. }
  37. ]
  38. },
  39. {
  40. "args": [
  41. "-c",
  42. "tail -f /logdir/access.log"
  43. ],
  44. "command": [
  45. "bin/sh"
  46. ],
  47. "image": "172.16.1.41:5000/busybox",
  48. "imagePullPolicy": "Always",
  49. "name": "log-output",
  50. "resources": {},
  51. "terminationMessagePath": "/dev/termination-log",
  52. "volumeMounts": [
  53. {
  54. "mountPath": "/logdir",
  55. "name": "nginx-logs"
  56. }
  57. ]
  58. }
  59. ],
  60. "dnsPolicy": "ClusterFirst",
  61. "nodeName": "192.168.8.100",
  62. "restartPolicy": "Always",
  63. "securityContext": {},
  64. "terminationGracePeriodSeconds": 30,
  65. "volumes": [
  66. {
  67. "emptyDir": {},
  68. "name": "nginx-logs"
  69. }
  70. ]
  71. },
  72. "status": {
  73. "conditions": [
  74. {
  75. "lastProbeTime": null,
  76. "lastTransitionTime": "2016-09-08T09:49:28Z",
  77. "status": "True",
  78. "type": "Initialized"
  79. },
  80. {
  81. "lastProbeTime": null,
  82. "lastTransitionTime": "2016-09-08T09:49:44Z",
  83. "status": "True",
  84. "type": "Ready"
  85. },
  86. {
  87. "lastProbeTime": null,
  88. "lastTransitionTime": "2016-09-08T09:49:44Z",
  89. "status": "True",
  90. "type": "PodScheduled"
  91. }
  92. ],
  93. "containerStatuses": [
  94. {
  95. "containerID": "docker://8b79eeea60f27b6d3f0a19cbd1b3ee3f83709bcf56574a6e1124c69a6376972d",
  96. "image": "172.16.1.41:5000/busybox",
  97. "imageID": "docker://sha256:8c566faa3abdaebc33d40c1b5e566374c975d17754c69370f78c00c162c1e075",
  98. "lastState": {},
  99. "name": "log-output",
  100. "ready": true,
  101. "restartCount": 0,
  102. "state": {
  103. "running": {
  104. "startedAt": "2016-09-08T09:49:43Z"
  105. }
  106. }
  107. },
  108. {
  109. "containerID": "docker://96e64cdba7b05d4e30710a20e958ff5b8f1f359c8d16d32622b36f0df0cb353c",
  110. "image": "172.16.1.41:5000/nginx",
  111. "imageID": "docker://sha256:51d764c1fd358ce81fd0e728436bd0175ff1f3fd85fc5d1a2f9ba3e7dc6bbaf6",
  112. "lastState": {},
  113. "name": "nginx-server",
  114. "ready": true,
  115. "restartCount": 0,
  116. "state": {
  117. "running": {
  118. "startedAt": "2016-09-08T09:49:36Z"
  119. }
  120. }
  121. }
  122. ],
  123. "hostIP": "192.168.8.100",
  124. "phase": "Running",
  125. "podIP": "172.17.0.2",
  126. "startTime": "2016-09-08T09:49:28Z"
  127. }
  128. }
  129. ],
  130. "kind": "PodList",
  131. "metadata": {
  132. "resourceVersion": "602",
  133. "selfLink": "/api/v1/namespaces/default/pods"
  134. }
  135. }

可以看到 pod 已经在运行,并且给分配了 ip:172.17.0.2,通过 curl 也可以访问它的服务:

  1. [root@localhost vagrant]# curl -s http://172.17.0.2 | head -n 5
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <title>Welcome to nginx on Debian!</title>
  6. <style>

kubectl -s http://ip:8080 get pods

转载于:https://www.cnblogs.com/Su-per-man/p/10942783.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式版本控制系统入门

简介 在过去几年&#xff0c;对于分布式版本控制可以给开发过程提供的益处有许多争论。最近&#xff0c;分布式工具已经很成熟了。尽管分布式工具的一些优点最初可能不明显&#xff0c;但是从长期来看&#xff0c;它们提供的灵活性是非常有意义的。阅读完本文之后&#xff0c;您…

Hadoop源生实用工具之distcp

1 概览 DistCp&#xff08;Distributed Copy&#xff09;是用于大规模集群内部或者集群之间的高性能拷贝工具。 它使用Map/Reduce实现文件分发&#xff0c;错误处理和恢复&#xff0c;以及报告生成。 它把文件和目录的列表作为map任务的输入&#xff0c;每个任务会完成源列表中…

如何使用spy ++ (How to use Spy ++)

一个网友在我的一篇随笔后问道&#xff0c;如何使用spy 查找要用到的窗体类名以及相关信息 现把相关作法整理如下 如果你装了vs.net&#xff0c;在vs.net的工具里面就可以看到spy 打开spy &#xff0c;会以树状图显示当前系统所有的窗体信息&#xff0c;如下所示 然后找到…

PL/SQL Developer 9 注册机

软件下载&#xff1a;下载 注册机下载&#xff1a;下载 说明&#xff1a;测试版本--9.0.1.1613&#xff08;无需替换文件&#xff0c;输入注册信息即可&#xff09; 附图&#xff1a; 转载于:https://www.cnblogs.com/zhanqi/archive/2011/10/12/2208750.html

程序图片运行效果存在偏差问题

2019独角兽企业重金招聘Python工程师标准>>> 当图片放到高分辨率的文件夹下&#xff0c;运行程序的手机却是低分辨率时就会出现该问题。解决办法很容易&#xff0c;就是把图片换个文件夹。比如图片放到drawable-xhdpi下&#xff0c;而模拟器是480*800&#xff0c;图…

如何将android例子程序添加到Eclipse进行调试运行

website&#xff1a;http://blog.csdn.net/whwzm88/article/details/6342583 1、打开Eclipse,选择File->new->Android Project,如附图所示窗口: 2、选择Create project from existing source单选框,然后点击->Browse..., 找到想要查看的android例子目录: 备注&…

坦克大战 Java版

由于博客开通不久&#xff0c;以前没有博客&#xff0c;顺便把以前做的项目也介绍下 希望大家支持&#xff0c;谢谢 坦克大战 IDE&#xff1a;MyEclipse 9.0 语言&#xff1a;Java SE 数据库&#xff1a;由于是单机版&#xff0c;不需要较高的安全性&#xff0c;且数据量较小&a…

c# 扩展方法奇思妙用高级篇五:ToString(string format) 扩展

在.Net中&#xff0c;System.Object.ToString()是用得最多的方法之一&#xff0c;ToString()方法在Object类中被定义为virtual&#xff0c;Object类给了它一个默认实现&#xff1a; 1 publicvirtualstringToString()2 {3 returnthis.GetType().ToString();4 }.Net中原生的class…

PHP使用CURL抓取页面

cURL的基本原理 curl是利用URL语法在命令行方式下工作的开源文件传输工具&#xff0c;他能够从互联网上获得各种各样的网络资源。简单来说&#xff0c;curl就是抓取页面的升级版。 <?php//1.初始化&#xff0c;创建一个新cURL资源$ch curl_init(); //2.设置URL和相应的选…

Lync Server 2010迁移至Lync Server 2013故障排错 Part3 :内外网共享PPT提示证书问

最近在公司生产环境中部署Lync Server 2013并对公网发布后&#xff0c;发现公网未加域客户端在与内网用户共享PPT时&#xff0c;会报证书错误&#xff0c;如下图所示&#xff1a;但是内网是正确的&#xff0c;经过查询了一下Lync 客户端自身的日志信息后发现&#xff0c;公网客…

用WinInet开发Internet客户端应用指南

一&#xff1a;http://www.vckbase.com/document/viewdoc/?id545 二&#xff1a;http://www.vckbase.com/document/viewdoc/?id546 用WinInet开发Internet客户端应用指南&#xff08;一&#xff09; 编译/NorthTibet 一、概述一个Internet客户端程序的目的是通过Internet…

关于Android错误 View requires API level 14 (current...

2019独角兽企业重金招聘Python工程师标准>>> 问题描述&#xff1a;在界面配置文件main.xml中&#xff0c;可能用上某些控件&#xff08;例如GridLayout&#xff09;遇上下面所说的错误:View requires API level 14(current min is 8), 但将项目clear后&#xff0c;再…

javascript 基础 转

最近面试过一些人, 发现即使经验丰富的开发人员, 对于一些基础的理论和细节也常常会模糊. 写本文是因为就我自己而言第一次学习下面的内容时发现自己确实有所收获和感悟. 其实我们容易忽视的javascript的细节还有更多, 本文仅是冰山一角. 希望大家都能通过本文有所斩获.一. Jav…

2019春第二次课程设计实验报告

2019春第二次课程设计实验报告 一、实验项目名称 用数组实现反弹球消砖块 二、实验项目功能描述 利用键盘按键控制小球方向让小球碰到挡板后反弹上去消除砖块。 三、项目模块结构介绍 四、实现界面展示 五、代码托管链接 https://gitee.com/huangxuannn/events 六、实验总结 上…

nodejs+redis

为什么80%的码农都做不了架构师&#xff1f;>>> redis可以用来管理session http://www.csser.com/board/4f77e6f996ca600f78000936 然后使用的时候redis-server这个服务进程得开着&#xff0c;不然会悲剧的 转载于:https://my.oschina.net/kiloct/blog/137629

FxCAD 实验三 实现对象的【属性】事件

接着实验三&#xff0c;本次实验&#xff0c;实现鼠标右键点击【图形对象时】可以弹出一个【WinForm】属性界面 添加一个WindowsForm 界面&#xff0c;如图。类名字&#xff1a;FormBox 回到FxBox类文件 覆盖 SelectEvent 方法&#xff0c;添加上面的代码 运行程序&#xff0c;…

图像的灰度处理

图像的灰度处理的三种方法&#xff1a; 1.imread的方法将像素值修改为0 2.调用一个RGB转灰度的方法实现灰度转化&#xff08;cv2.COLOR_BGR2GRAY&#xff09; 3.R G B 的均值取灰度值来灰度转化&#xff08;原理&#xff09; 处理结果 如下: 转载于:https://www.cnblogs.com/Ja…

面向对象基础-委托与事件

首先举一个实例&#xff1a;创建一个控制台程序&#xff0c;需求是&#xff1a;有一只猫Tom&#xff0c;有两只老鼠Jerry和Jack&#xff0c;Tom只叫一声“喵&#xff0c;我是Tom”&#xff0c;两只老鼠就说“老猫来了&#xff0c;快跑”&#xff0c;我们来分析一下&#xff1a;…

linux下wget的用法

2019独角兽企业重金招聘Python工程师标准>>> Linux wget是一个下载文件的工具&#xff0c;它用在命令行下。对于Linux用户是必不可少的工具&#xff0c;尤其对于网络管理员&#xff0c;经常要下载一些软件或从远程服务器恢复备份到本地服务器。如果我们使用虚拟主机…

【传智播客】Libevent学习笔记(三):事件循环

目录 00. 目录01. event_base_loop函数02. event_base_dispatch函数03. event_base_loopexit函数04. event_base_loopbreak函数05. event_base_got_exit函数06. event_base_got_break函数07. event_base_dump_events函数08. event_base_dump_events函数09. 废弃的事件循环函数1…