docker筆記33-排程器、預選策略及優選函式
master是工作平面,上面執行著三個最核心的元件,apiserver、scheduler、controller manager。除此之外,master還依賴於ectd儲存節點,最好ectd是有冗餘能力的叢集,
排程器(scheduler)
master上的 scheduler控制著pod執行在哪個node上的。不指定就用default scheduler。
排程器的功能就是排程Pod在哪個Node上執行,這些排程資訊儲存在master上的etcd裡面。能夠和etcd打交道的只有apiserver。
kubelete執行在node節點上,監控著Node節點上的pod狀態,並參與pod的建立等工作。
kube-proxy也執行在node節點上,它監控著service資源的變動。
kubelete和kube-proxy都要連線master上的apiserver去獲取定義資訊。
預選步驟
default scheduler是透過三個步驟來實現排程的:
a)、預選策略(predicate):先排除那些完全不符合此pod執行法則的節點,有兩個維度來排除,一個是最低資源需求,即節點必須滿足此Pod的最低資源;第二個是資源限額,即當前節點最多能給pod提供的資源。
b)、優選(priority):在符合節點找到最佳匹配的節點。
c)、繫結(select):把pod繫結到優選的節點上。
[root@master ~]# kubectl explain pod.spec nodeName:指定pod執行在指定節點上 nodeSelector:用nodeSelector指定Pod執行在擁有某種selector 標籤的節點上。
在k8s上,排程方式有這麼幾類:
1、nodeaffinity,表示node親和性排程,表示這個pod對這個節點有一定的傾向性。我們透過上面的nodeselector來完成這類排程
2、podaffinity或podunaffinity:pod親和性或者pod反親和性排程,有時我們期望某些Pod執行在同一個節點上或者是相鄰的節點上,或者我們期望某些Pod不要執行在某些節點上。
3、taints和tolerations:汙點和汙點容忍排程:可以在某些節點上打上汙點,表示這些節點不讓pod在其上面執行。taints是定義在節點之上的,tolerations是定義在pod之上的。
常用的預選策略
訪問 ,檢視k8s原始碼,可以看到這些策略。
1、ChekNodeCondition
表示檢查是否可以在節點磁碟、網路不可用,或未準備好的前提下,能夠把pod排程到上去。
2、GeneralPredicate
a) hostname預選策略,表示如果pod定義了hostname屬性(pod.spec.hostname),則檢查節點的名字跟pod的hostname是否想匹配,但這裡並不是定義這個pod必須執行在這些節點上。
b)PodFitsHostPorts:如果節點定義了hostport屬性(pod.spec.containers.ports.hostPort),表示指定在節點的哪個埠上。如果這個節點的埠被佔用了,那麼這個節點就不適合執行這個pod。
c)MatchNodeSelector:檢查pods.spec.nodeSelector這個欄位你是否定義了,執行在攜有這有這些標籤選擇器的節點上。
d) PodFitsResources:檢查節點是否有足夠的資源來支援這個pod執行。
[root@master ~]# kubectl describe nodes node1 Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests(需求量) Limits(限額) -------- -------- ------ cpu 360m (9%) 110m (2%) memory 70Mi (1%) 70Mi (1%) Events: <none>
e)NoDiskConfict:檢查Pod所請求儲存卷在此節點上是否不可用。 注意NoDiskConfict排程策略預設沒有啟用。
f) PodToleratesNodeTaints:如果Pod定義了Tolerates(容忍度),即 pods.spec.tolerations,那麼就看pod能不能容忍節點上的汙點,如果是,表示這個節點可以被選定;
g) PodToleratesNodeNoExecuteTaints:檢查pod是否容忍節點上有NoExecute汙點。NoExecute這個汙點是啥意思呢。如果一個pod上執行在一個沒有汙點的節點上後,這個節點又給加上汙點了,那麼NoExecute表示這個新加汙點的節點會祛除其上正在執行的pod;不加NoExecute不會祛除節點上執行的pod,表示接受既成事實,這是預設策略。
h) CheckNodeLabelPresence:檢查節點上指定標籤的存在性,如果節點有pod指定的標籤,那麼這個節點就被選中。
這個排程策略預設沒有啟用。
i) CheckServceAffinity:一個service下可以有多個pod,比如這些pod都執行在1、2、3機器上,而沒有執行在4、5、6機器上,那麼CheckServceAffinity就表示新加入的pod都集中執行在1、2、3機器上,這樣集中好處是一個service下pod之間內部通訊的效率變高了。 這個策略預設也是沒有啟用的。
j)MaxEBSVolumeCountPred:檢查節點上掛載的EBS儲存器(亞馬遜的彈性塊儲存)的數量是否超出了最大的設定值。一般來說,一個節點上最多可以掛載39個儲存卷。可以編譯安裝k8s指定該值。
k) MaxGCEPDVolumeCountPred:GCE是谷歌的雲端儲存引擎。可以編譯安裝k8s指定該值。
l) MaxAzureDiskVolumeCountPred:pod會選擇掛載足量Azure儲存卷的節點。
m) CheckVolumeBinding:檢查節點上的pvc是否被別的pod繫結了
n) NoVolumeZoneConfict: 檢查節點上的pod是否與pod的需求衝突。
o) CheckNodeMemoryPressure:檢查節點記憶體是否存在壓力
p) CheckNodePIDpressure:檢查節點pid數量是否壓力過大,但一般pid是可以重複使用的。
q)CheckNodeDiskPressure:
r) MatchInterPodAffinity:檢查Pod是否滿足親和性或者反親和性。
如果一個節點的第一個策略符合了,k8s
常用的優選函式
訪問 可以看到k8s原始碼裡面的優選函式。
balanced_resource_allocation.go:均衡資源的使用方式,表示以cpu和記憶體佔用率的相近程度作為評估標準,二者佔用越接近,得分就越高,得分高的勝出。
image_locality.go:表示根據滿足當前pod物件需求的已有鏡的體積大小之和來選擇節點的。
least_requested.go:最少請求,空閒比例。對cpu來說,用cpu((capacity-sum(requested))*10/capacity)方式進行評估,得分最高的勝出。
most_requested.go:表示儘可能的把一個節點的資源先用完,這個和least_requested相反,二者不能同時使用。
node_prefer_avoid_pods.go:看節點是否有註解資訊"scheduler.alpha.kubernetes.io/preferAvoidPods"。沒有這個註解資訊,說明這個節點是適合執行這個pod的。
node_affinity.go:根據pod物件中的nodeselector,對節點進行匹配度檢查,能夠成功匹配的數量越多,得分就越高。
taint_toleration.go:將pod物件的spec.toleration與節點的taint列表項進行匹配度檢查,匹配的條目越多,得分越低。
selector_spreading.go:spreading是散開的意思,查詢當前pod物件對應的service,statefulset,replicatset等所匹配的標籤選擇器,在節點上執行的帶有這樣標籤的pod越少得分越高,這樣的pod優選被選出。 這就是說我們要把同一個標籤選擇器下執行的pod散開(spreading)到多個節點上。
interpod_affinity.go:遍歷Pod物件親和性的條目,並將那些能夠匹配到節點權重相加,值越大的得分越高,得分高的勝出。
node_label.go:根據節點是否擁有標籤,來評估分數。
高階排程方式
包括兩類:
節點選擇器:nodeSelector(給node打上標籤,pod透過標籤預選節點),nodeName
節點親和排程:nodeAffinity
節點選擇器(nodeSelector,nodeName)
[root@master ~]# kubectl explain pods.spec.nodeSelector
[root@master scheduler]# cat pod-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 nodeSelector: #指定該pod執行在有disktype=ssd標籤的node節點上 disktype: harddisk #自己隨便寫
[root@master scheduler]# kubectl apply -f pod-demo.yaml pod/pod-demo created
[root@master scheduler]# kubectl get pods -o wide |grep demo
pod-demo 0/1 Pending 0 14s <none> <none>
可見,我們的pod-demo沒有執行起來,這是因為沒有任何節點打了disktype=harddisk標籤。
那我們就給node2節點打disktype=harddisk標籤試試:
[root@master scheduler]# kubectl label nodes node2 disktype=harddisk node/node2 labeled
[root@master scheduler]# kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS master Ready master 34d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master= node1 Ready <none> 34d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node1 node2 Ready <none> 34d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=harddisk,kubernetes.io/hostname=node2
[root@master scheduler]# kubectl get pods -o wide |grep demo pod-demo 1/1 Running 0 5m 10.244.2.29 node2 0 3m 10.244.1.51 node1
可以看到,我們新建立的pod-demo執行在node2節點上,因為只有node2才有disktype=harddisk標籤。
節點親和排程(nodeAffinity)
[root@master scheduler]# kubectl explain pods.spec.affinity [root@master scheduler]# kubectl explain pods.spec.affinity.nodeAffinity preferredDuringSchedulingIgnoredDuringExecution:軟親和,可以滿足,也可以不滿足 requiredDuringSchedulingIgnoredDuringExecution:硬親和,表示必須滿足 [root@master ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
[root@master scheduler]# cat pod-nodeaffinity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-node-affinity-demo namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: #硬親和性 nodeSelectorTerms: - matchExpressions: - key: zone operator: In values: - foo - bar
[root@master scheduler]# kubectl apply -f pod-nodeaffinity-demo.yaml pod/pod-node-affinity-demo created
[root@master ~]# kubectl get pods -o wide |grep affinity pod-node-affinity-demo 0/1 Pending 0 15s <none> <none>
因為我們沒有任何一個節點擁有zone這個標籤,所以pod-node-affinity-demo執行不起來。
下面我們再建立一個軟親和性的pod。
[root@master scheduler]# cat pod-nodeaffinity-demo2.yaml apiVersion: v1 kind: Pod metadata: name: pod-node-affinity-demo-2 namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: #軟親和性 - preference: matchExpressions: - key: zone operator: In values: - foo - bar weight: 60
[root@master scheduler]# kubectl apply -f pod-nodeaffinity-demo2.yaml pod/pod-node-affinity-demo-2 created
[root@master scheduler]# kubectl get pods -o wide |grep affinity-demo-2 pod-node-affinity-demo-2 1/1 Running 0 1m 10.244.2.30 node2
看到pod-node-affinity-demo-2 執行起來了,因為這個pod我們是定義的軟親和性,表示即使任何節點都沒有zone標籤,也會找個節點讓Pod執行起來。
pod親和排程
rack是機櫃的意思,如果是用rack1、rack2、rack3、rack4這樣表示節點,那麼每個節點都是不同的位置;可是我們給每個節點都打一個row=row1,即表示這些機器都在第一排機櫃上,那麼這四個機器又在同一位置,即第一排。所以我們可以用row這樣的方式來做親和性。
[root@master scheduler]# kubectl explain pods.spec.affinity.podAffinity preferredDuringSchedulingIgnoredDuringExecution:軟親和,儘量滿足標籤 requiredDuringSchedulingIgnoredDuringExecution:硬親和,必須滿足標籤
[root@master scheduler]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution topologyKey:定義上圖row那樣的鍵 labelSelector:表示選定一組資源,跟哪些pod進行親和; namespaces:指定Pod屬於哪個名稱空間中,一般我們不跨名稱空間去引用。
[root@master scheduler]# cat pod-required-affnity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-first namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second namespace: default labels: app: db #kv格式的,也可以用花括號表示 tier: backend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: busybox #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: #硬親和性 - labelSelector: matchExpressions: #匹配pod的,而不是匹配節點 - {key: app, operator: In, values: ["myapp"]} #意思是當前這個pod要跟一個有著標籤app=myapp(要和上面pod-first的metadata裡面的標籤一致)的pod在一起 topologyKey: kubernetes.io/hostname
[root@master scheduler]# kubectl apply -f pod-required-affnity-demo.yaml pod/pod-first unchanged pod/pod-second created
[root@master scheduler]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE pod-first 1/1 Running 0 2m 10.244.2.33 node2 pod-second 1/1 Running 0 1m 10.244.2.34 node2
上面看到我們的兩個pod都執行在同一個節點了,這是因為pod-second會和pod-first執行在同一個節點上。
pod反親和排程
[root@master ~]# kubectl explain pods.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution
[root@master scheduler]# cat pod-required-anti-affnity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-first namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second namespace: default labels: app: db #kv格式的,也可以用花括號表示 tier: backend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: busybox #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: #硬親和性 - labelSelector: matchExpressions: #匹配pod的,而不是匹配節點 - {key: app, operator: In, values: ["myapp"]} #意思是當前這個pod要跟一個有著標籤app=myapp(要和上面pod-first的metadata裡面的標籤一致)的pod在一起 topologyKey: kubernetes.io/hostname
[root@master scheduler]# kubectl apply -f pod-required-anti-affnity-demo.yaml pod/pod-first created pod/pod-second created
[root@master scheduler]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE pod-first 1/1 Running 0 1m 10.244.2.35 node2 pod-second 0/1 Running 0 1m 10.244.2.36 node1
上面可以看到pod-first和pod-second就不會被排程到同一個節點上。
下面給兩個節點打標籤,給兩個節點打一樣的標籤
[root@master scheduler]# kubectl label nodes node2 zone=foo node/node2 labeled [root@master scheduler]# kubectl label nodes node1 zone=foo node/node1 labeled
[root@master scheduler]# cat pod-required-anti-affnity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-first namespace: default labels: app: myapp #kv格式的,也可以用花括號表示 tier: frontend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: myapp #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second namespace: default labels: app: db #kv格式的,也可以用花括號表示 tier: backend #定義所屬的層次 annotations: chenzx.com/created-by: "cluster-admin" #這是註解的鍵值對 spec: containers: - name: busybox #前面的-號表示這是一個列表格式的,也可以用中括號表示 image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: #硬親和性 - labelSelector: matchExpressions: #匹配pod的,而不是匹配節點 - {key: app, operator: In, values: ["myapp"]} #意思是當前這個pod要跟一個有著標籤app=myapp(要和上面pod-first的metadata裡面的標籤一致)的pod在一起 topologyKey: zone
上面把topologyKey(標籤選擇器的值)的值改成zone,而pod排程策略是podAntiAffinity反親和性,所以pod-first和pod-second不能同時執行在標有zone標籤的節點上。所以最終出現的現場就是有一個pod-first能成功執行,而另外一個pod-second因為是反親和的,沒有節點可以執行而處於pending狀態。
[root@master scheduler]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE pod-first 1/1 Running 0 10m 10.244.2.37 node2 pod-second 0/1 Pending 0 10m <none> <none>
汙點排程
前面幾種排程方式都是讓pod來選擇節點。汙點是讓節點來選擇哪些pod能執行在其上面。
汙點也是鍵值對。
[root@master scheduler]# kubectl explain nodes.spec.taints effect:表示當pod不能容忍節點上汙點時的行為是什麼,主要有三種行為: NoSchedule:僅影響排程過程,不影響現存pod。沒排程過來的就排程不過來了。如果對節點新加了汙點,那麼對節點上現存的Pod沒有影響。 NoExecute:既影響排程過程,也影響現存Pod,沒排程過來的就排程不過來了,如果對節點新加了汙點,那麼對現存的pod物件將會被驅逐 PreferNoSchedule:不能容忍就不能排程過來,但是實在沒辦法也是能排程過來的。對節點新加了汙點,那麼對節點上現存的pod沒有影響。
檢視節點的汙點:
[root@master scheduler]# kubectl describe node node1 Taints: <none>
檢視pod的容忍度:
[root@master scheduler]# kubectl describe pods myapp-0 Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s
每次都要檢查pod的容忍度是否和節點的汙點匹配。
下面我們給node1打上汙點node-type=production:NoSchedule,注意汙點和容忍度都是自定義的鍵值對。
[root@master scheduler]# kubectl taint node node1 node-type=production:NoSchedule node/node1 tainted
[root@master scheduler]# kubectl explain pods.spec.tolerations tolerationSeconds:表示寬限多長時間pod被驅逐 operator:運算子,其值有Exists表示只要節點有這個汙點的key,pod都能容忍;Equal表示只要節點必須精確匹配汙點的key和value才能容忍,
[root@master scheduler]# cat pod-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 tolerations: - key: "node-type" operator: "Equal" #表示只要節點必須精確匹配汙點的key和value才能容忍 value: "production" effect: "NoSchedule"
[root@master scheduler]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE myapp-deploy-98fddd79f-6dzbg 1/1 Running 0 9s 10.244.1.58 node1 myapp-deploy-98fddd79f-8fqn4 1/1 Running 0 12s 10.244.1.57 node1 myapp-deploy-98fddd79f-cqnbj 1/1 Running 0 6s 10.244.1.59 node1
看到pod能容忍node1的汙點node-type=production:NoSchedule,所以pod可以被排程到node1上執行。
下面我們把operator: "Equal"改成operator: "Exists"
[root@master scheduler]# cat pod-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: canary template: metadata: labels: app: myapp release: canary spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 tolerations: - key: "node-type" operator: "Exists" #表示只要節點匹配key: node-type,不管其value是什麼,pod都能容忍節點上的汙點 value: "" effect: "NoSchedule"
[root@master scheduler]# kubectl apply -f pod-demo.yaml
[root@master scheduler]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE myapp-deploy-7dd988dc9d-747t4 1/1 Running 0 51s 10.244.2.45 node2 myapp-deploy-7dd988dc9d-cl4ft 1/1 Running 0 47s 10.244.1.60 node1 myapp-deploy-7dd988dc9d-hnrr5 1/1 Running 0 49s 10.244.2.46 node2
最後,我們去掉節點上的汙點:
[root@master metrics]# kubectl taint node node1 node-type- node/node1 untainted
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28916011/viewspace-2215522/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- RxJava排程器的選擇RxJava
- Flink排程之排程器、排程策略、排程模式模式
- css 選擇器及權重筆記CSS筆記
- css樣式選擇器學習筆記CSS筆記
- CSS選擇器筆記CSS筆記
- 排程器簡介,以及Linux的排程策略Linux
- Go runtime 排程器精講(五):排程策略Go
- jQuery----函式和選擇器jQuery函式
- Docker 與 K8S學習筆記(二十五)—— Pod的各種排程策略(上)DockerK8S筆記
- Linux排程策略及執行緒優先順序設定Linux執行緒
- OS學習筆記三:處理器排程筆記
- CSS筆記——屬性選擇器CSS筆記
- 筆記-10.2、HTML-CSS選擇器筆記筆記HTMLCSS
- 開源分散式任務排程系統就選:DolphinScheduler分散式
- go lang學習筆記——channel機理及排程理解Go筆記
- TypeScript 函式可選引數和預設引數TypeScript函式
- CSS 小結筆記之選擇器CSS筆記
- Jquery基礎筆記二(選擇器)jQuery筆記
- 【函式式 Swift】可選值函式Swift
- VueJs開發筆記—IDE選擇和優化、框架特性、資料呼叫、路由選項及使用VueJS筆記IDE優化框架路由
- 前端筆記之jQuery(上)載入函式的區別&物件&操作HTML/CSS&動畫&選擇器前端筆記jQuery函式物件HTMLCSS動畫
- CSS3選擇器及優先順序CSSS3
- 新生賽及預選賽 10
- Linux程式排程策略Linux
- 容器化RDS|排程策略
- css 選擇器優先順序的計算過程CSS
- goroutine排程原始碼閱讀筆記Go原始碼筆記
- 【智慧優化演算法】遺傳演算法的精英選擇策略、期望選擇策略優化演算法
- 重學前端筆記21-css選擇器前端筆記CSS
- jQuery入門筆記之(一)選擇器引擎jQuery筆記
- UX策略選用:重用 vs 優化設計UX優化
- 實戰Docker容器排程Docker
- Linux排程器:程序優先順序Linux
- MySQL函式索引及優化MySql函式索引優化
- JVM記憶體分配機制與回收策略選擇-JVM學習筆記(2)JVM記憶體筆記
- 稀疏感知&稀疏預定義資料排程器
- CSS樣式選擇器CSS
- 4月10日學習筆記——jQuery選擇器筆記jQuery