環境資訊中心綜合外電;姜唯 編譯;林大利 審校
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※超省錢租車方案
※別再煩惱如何寫文案,掌握八大原則!
※回頭車貨運收費標準
※教你寫出一流的銷售文案?
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
北部有線電視-提供穩定的寬頻光纖上網、高畫質HD數位頻道、第四台電視、數位電視,現在申辦免費體驗3個月"HD99高畫質套餐"
本文轉自Rancher Labs
作者介紹
王海龍,Rancher中國社區技術經理,負責Rancher中國技術社區的維護和運營。擁有6年的雲計算領域經驗,經歷了OpenStack到Kubernetes的技術變革,無論底層操作系統Linux,還是虛擬化KVM或是Docker容器技術都有豐富的運維和實踐經驗。
Rancher提供兩種安裝方法,單節點和高可用安裝。單節點安裝允許用戶快速部署適用於短期開發測試為目的的安裝工作。高可用部署明顯更適合Rancher的長期使用。
在實際使用中可能會遇到需要將Rancher Server遷移到其他的節點或local集群去管理的情況。 雖然可以使用最簡單的import集群方式納管,但帶來的問題是後續無法做集群的管理和升級維護,而且一些namespace和project的關聯關係將會消失。所以本文主要介紹如何將Rancher Server遷移到其他節點或local集群。
本文主要針對3個場景去講解如何遷移Rancher Server:
Rancher單節點安裝遷移至其他主機
Rancher單節點安裝遷移至高可用安裝
Rancher高可用安裝遷移至其他Local集群
Rancher 官方文檔文檔中並沒有說明支持以下場景的遷移,本文檔只是利用一些Rancher和RKE現有的功能實現遷移。
如果您在此過程中遇到問題,則應該熟悉Rancher架構/故障排除
遷移非常危險,遷移前一定剛要做好備份,以免發生意外無法恢復
您應該熟悉單節點安裝和高可用安裝之間的體繫結構差異
本文檔基於Rancher 2.4.x測試,其他版本操作可能會略有不同
本文檔主要講解Rancher Server的遷移,遷移過程中不會影響業務集群的使用
默認情況下, Rancher UI 上複製的 kubeconfig 通過cluster agent代理連接到 kubernetes 集群。變更 Rancher Server會導致cluster agent無法連接 Rancher Server,從而導致kubectl無法使用 Rancher UI 上複製的 kubeconfig 去操作 kubernetes 集群。但可以使用kubectl –context <CLUSTER_NAME>-fqdn 直接連接kubernetes集群進行操作。所以在執行遷移之前,請準備好所有集群的直連 kubeconfig 配置文件。
Rancher v2.2.2以及之後的版本,可以直接從UI上下載kubeconfig文件。
Rancher v2.2.2之前的版本,請參考:恢復 kubectl 配置文件
Rancher單節點安裝遷移至其他主機,只需要將舊集群Rancher Server容器的/var/lib/rancher目錄打包,然後替換到新Rancher Server對應的目錄,最後啟動新Rancher Server容器之後再更新agent相關配置即可。
1. Rancher 單節點安裝
提示:以下步驟創建用於演示遷移的 Rancher 單節點環境,如果您需要遷移正式環境可以跳過此步驟。
執行以下 docker 命令運行單節點 Rancher Server 服務
docker run -itd -p 80:80 -p 443:443 --restart=unless-stopped rancher/rancher:v2.4.3
等容器初始化完成后,通過節點 IP 訪問 Rancher Server UI,設置密碼並登錄。
2. 創建自定義集群
提示: 以下步驟創建用於演示的業務集群,用來驗證 Rancher 遷移后數據是否丟失,如果您需要遷移正式環境可以跳過此步驟。
登錄 Rancher UI 后,添加一個自定義集群
授權集群訪問地址設置為啟用,FQDN 和證書可以不用填寫。
注意:
這一步很關鍵。因為Rancher 遷移后,地址或者 token 或者證書的變更,將會導致 agent 無法連接 Rancher Server。遷移后,需要通過 kubectl 去編輯配置文件更新一些 agent 相關的參數。默認 UI 上的 kubeconfig文件是通過 agent 代理連接到 Kubernetes,如果 agent 無法連接 Rancher Server,則通過這個 kubeconfig 文件也無法訪問 Kubernetes 集群。開啟授權集群訪問地址功能會生成多個 Contexts Cluster,這些 Contexts Cluster 是直連 Kubernetes,不通過 agent 代理。如果業務集群未開啟這個功能,可以通過編輯集群來開啟這個功能。
點擊下一步,根據預先分配的節點角色選擇需要的角色,然後複製命令到主機終端執行。
集群部署完成后,進入集群首頁,點擊kubeconfig文件按鈕。在彈窗頁面中複製 kubeconfg 配置文件備用。
3.部署測試應用
部署一個nginx workload。再從應用商店部署一個測試應用。
4. 備份單節點Racher Server數據
docker create --volumes-from <RANCHER_CONTAINER_NAME> --name rancher-data-<DATE> rancher/rancher:<RANCHER_CONTAINER_TAG>
docker run --volumes-from rancher-data-<DATE> -v $PWD:/backup:z busybox tar pzcvf /backup/rancher-data-backup-<RANCHER_VERSION>-<DATE>.tar.gz -C /var/lib rancher
詳細請參考Rancher中文官網單節點備份指南。
5. 將生成的rancher-data-backup-<RANCHER_VERSION>-<DATE>.tar.gz複製到新的Rancher Server節點
scp rancher-data-backup-<RANCHER_VERSION>-<DATE>.tar.gz root@<new_rancher_ip>:/opt/
6. 使用備份數據啟動新節點Rancher Server
如果原Rancher Server通過使用已有的自簽名證書或使用已有的可信證書安裝,遷移時,需要將證書一起複制到新Rancher Server,使用相同啟動命令掛載證書和備份數據啟動Rancher Server。
cd /opt && tar -xvz -f rancher-data-backup-<RANCHER_VERSION>-<DATE>.tar.gz
docker run -itd -p 80:80 -p 443:443 -v /opt/rancher:/var/lib/rancher --restart=unless-stopped rancher/rancher:v2.4.3
7. 更新Rancher Server IP或域名
注意:
如果您的環境使用自簽名證書或Let’s Encrypt 證書,並且配置域名訪問Rancher Server。遷移之後集群狀態為
Active,請直接跳到第9步去驗證集群。
此時訪問新的Rancher Server就可以看見已經被管理的Kubernetes集群了,但此時集群狀態是unavailable,因為agent還連的是舊Rancher Server所以需要更新agent信息。
依次訪問全局 > 系統設置,頁面往下翻找到server-url文件
單擊右側的省略號菜單,選擇升級
修改server-url地址為新Rancher Server的地址
8. 更新agent配置
通過新域名或IP登錄 Rancher Server;
通過瀏覽器地址欄查詢集群ID, c/後面以c開頭的字段即為集群 ID,本例的集群ID為c-4wzvf;
訪問https://<新的server_url>/v3/clusters/<集群ID>/clusterregistrationtokens頁面;
打開clusterRegistrationTokens頁面后,定位到data字段;找到insecureCommand字段,複製 YAML 連接備用;
可能會有多組
"baseType": "clusterRegistrationToken",如上圖。這種情況以createdTS最大、時間最新的一組為準,一般是最後一組。
使用kubectl工具,通過前文中準備的直連kubeconfig配置文件和上面步驟中獲取的 YAML 文件,執行以下命令更新agent相關配置。
curl --insecure -sfL <替換為上面步驟獲取的YAML文件鏈接> | kubectl --context=xxx apply -f -
關於--context=xxx說明請參考直接使用下游集群進行身份驗證。
9. 驗證
過一會,集群變為Active狀態,然後驗證我們之前部署的應用是否可用。
從單個節點遷移到Rancher的高可用性安裝的過程可以概括為以下幾個步驟:
在Rancher單節點實例上:
備份Rancher單節點容器
備份etcd快照
停止舊的Rancher單節點容器
在RKE Local集群上:
使用RKE啟動Rancher Local集群
利用rke etcd snapshot-restore,將單節點備份的etcd快照恢復到RKE HA
在RKE Local集群中安裝Rancher
更新Local集群和業務集群的相關配置,使agent可以連接到正確的Rancher Server
1. Rancher 單節點安裝
提示: 以下步驟創建用於演示遷移的 Rancher 環境,如果您需要遷移正式環境可以跳過此步驟。
執行以下 docker 命令運行單節點 Rancher Server 服務
docker run -itd -p 80:80 -p 443:443 --restart=unless-stopped rancher/rancher:v2.4.3
等容器初始化完成后,通過節點 IP 訪問 Rancher Server UI,設置密碼並登錄。
2. 創建自定義集群
提示: 以下步驟創建用於演示的業務集群,用來驗證 Rancher 遷移后數據是否丟失,如果您需要遷移正式環境可以跳過此步驟。
登錄 Rancher UI 后,添加一個自定義集群
授權集群訪問地址設置為啟用,FQDN 和證書可以不用填寫。
注意: 這一步很關鍵。因為Rancher 遷移后,地址或者 token 或者證書的變更,將會導致 agent 無法連接 Rancher Server。遷移后,需要通過 kubectl 去編輯配置文件更新一些 agent 相關的參數。默認 UI 上的 kubeconfig文件是通過 agent 代理連接到 Kubernetes,如果 agent 無法連接 Rancher Server,則通過這個 kubeconfig 文件也無法訪問 Kubernetes 集群。開啟授權集群訪問地址功能會生成多個 Contexts Cluster,這些 Contexts Cluster 是直連 Kubernetes,不通過 agent 代理。如果業務集群未開啟這個功能,可以通過編輯集群來開啟這個功能。
點擊 下一步 ,根據預先分配的節點角色選擇需要的角色,然後複製命令到主機終端執行。
集群部署完成后,進入集群首頁,點擊kubeconfig文件按鈕。在彈窗頁面中複製 kubeconfg 配置文件備用。
3. 部署測試應用
部署一個nginx workload。再從應用商店部署一個測試應用。
4. 創建將單節點etcd快照
docker exec -it <RANCHER_CONTAINER_NAME> bash
root@78efdcbe08a6:/# cd /
root@78efdcbe08a6:/# ETCDCTL_API=3 etcdctl snapshot save single-node-etcd-snapshot
root@78efdcbe08a6:/# exit
docker cp <RANCHER_CONTAINER_NAME>:/single-node-etcd-snapshot .
5. 關閉單節點Rancher Server
docker stop <RANCHER_CONTAINER_NAME>
1. RKE部署Local Kubernetes 集群
根據RKE示例配置 創建 RKE 配置文件 cluster.yml:
nodes:
- address: 99.79.49.94
internal_address: 172.31.13.209
user: ubuntu
role: [controlplane, worker, etcd]
- address: 35.183.174.120
internal_address: 172.31.8.28
user: ubuntu
role: [controlplane, worker, etcd]
- address: 15.223.49.238
internal_address: 172.31.0.199
user: ubuntu
role: [controlplane, worker, etcd]
執行 rke 命令創建 Local Kubernetes 集群
rke up --config cluster.yml
檢查 Kubernetes 集群運行狀態
使用kubectl檢查節點狀態,確認節點狀態為Ready
kubectl get nodes
NAME STATUS ROLES AGE VERSION
15.223.49.238 Ready controlplane,etcd,worker 93s v1.17.6
35.183.174.120 Ready controlplane,etcd,worker 92s v1.17.6
99.79.49.94 Ready controlplane,etcd,worker 93s v1.17.6
檢查所有必需的 Pod 和容器是否狀況良好,然後可以繼續進行
kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
ingress-nginx default-http-backend-67cf578fc4-9vjq4 1/1 Running 0 67s
ingress-nginx nginx-ingress-controller-8g7kq 1/1 Running 0 67s
ingress-nginx nginx-ingress-controller-8jvsd 1/1 Running 0 67s
ingress-nginx nginx-ingress-controller-lrt57 1/1 Running 0 67s
kube-system canal-68j4r 2/2 Running 0 100s
kube-system canal-ff4qg 2/2 Running 0 100s
kube-system canal-wl9hd 2/2 Running 0 100s
kube-system coredns-7c5566588d-bhbmm 1/1 Running 0 64s
kube-system coredns-7c5566588d-rhjpv 1/1 Running 0 87s
kube-system coredns-autoscaler-65bfc8d47d-tq4gj 1/1 Running 0 86s
kube-system metrics-server-6b55c64f86-vg7qs 1/1 Running 0 79s
kube-system rke-coredns-addon-deploy-job-fr2bx 0/1 Completed 0 92s
kube-system rke-ingress-controller-deploy-job-vksrk 0/1 Completed 0 72s
kube-system rke-metrics-addon-deploy-job-d9hlv 0/1 Completed 0 82s
kube-system rke-network-plugin-deploy-job-kf8bn 0/1 Completed 0 103s
2. 將生成的單節點etcd快照從Rancher單節點實例傳到RKE Local集群節點上
在RKE HA Local節點上創建一個/opt/rke/etcd-snapshots目錄,並將single-node-etcd-snapshot文件複製到該目錄:
mkdir -p /opt/rke/etcd-snapshots
scp root@<old_rancher_ip>:/root/single-node-etcd-snapshot /opt/rke/etcd-snapshots
3. 使用RKE將單節點etcd快照還原到新的HA節點
rke etcd snapshot-restore --name single-node-etcd-snapshot --config cluster.yml
4. Rancher HA 安裝
參考安裝文檔安裝 Rancher HA。
5. 為Rancher HA配置NGINX 負載均衡
參考NGINX 配置示例為Rancher HA配置負載均衡。
Nginx 配置:
worker_processes 4;
worker_rlimit_nofile 40000;
events {
worker_connections 8192;
}
stream {
upstream rancher_servers_http {
least_conn;
server 172.31.11.95:80 max_fails=3 fail_timeout=5s;
server 172.31.0.201:80 max_fails=3 fail_timeout=5s;
server 172.31.15.236:80 max_fails=3 fail_timeout=5s;
}
server {
listen 80;
proxy_pass rancher_servers_http;
}
upstream rancher_servers_https {
least_conn;
server 172.31.11.95:443 max_fails=3 fail_timeout=5s;
server 172.31.0.201:443 max_fails=3 fail_timeout=5s;
server 172.31.15.236:443 max_fails=3 fail_timeout=5s;
}
server {
listen 443;
proxy_pass rancher_servers_https;
}
}
Nginx啟動后,我們就可以通過配置的域名/IP去訪問Rancher UI。可以看到業務集群demo為Unavailable狀態,local集群雖然為Active,但cluster-agent和node-agent均啟動失敗。
這兩種情況都是因為agent依然連接的舊的Rancher Server。
6. 更新Rancher Server IP或域名
依次訪問全局 > 系統設置,頁面往下翻找到server-url文件
單擊右側的省略號菜單,選擇升級
修改server-url地址為新Rancher server的地址
7. 更新local集群和業務集群的agent配置
通過新域名或IP登錄 Rancher Server;
通過瀏覽器地址欄查詢集群ID, c/後面以c開頭的字段即為集群 ID,本例的集群ID為c-hftcn;
訪問https://<新的server_url>/v3/clusters/<集群ID>/clusterregistrationtokens頁面;
打開clusterRegistrationTokens頁面后,定位到data字段;找到insecureCommand字段,複製 YAML 連接備用;
可能會有多組
"baseType": "clusterRegistrationToken",如上圖。這種情況以createdTS最大、時間最新的一組為準,一般是最後一組。
使用kubectl工具,通過前文中準備的直連kubeconfig配置文件和上面步驟中獲取的 YAML 文件,執行以下命令更新agent相關配置。
注意:
更新local集群和業務集群使用的kubeconfig是不同的,請針對不通集群選擇需要的kubeconfig。
關於
--context=xxx說明請參考直接使用下游集群進行身份驗證。
curl --insecure -sfL <替換為上面步驟獲取的YAML文件鏈接> | kubectl --context=xxx apply -f -
業務集群agent更新成功后,使用相同的方法更新local集群agent配置。
9. 驗證
過一會,local和demo集群都變為Active狀態:
Local集群的cluster-agent和node-agent啟動成功
Demo集群的cluster-agent和node-agent啟動成功
然後驗證我們之前部署的應用是否可用。
Rancehr高可用安裝遷移至其他Local集群,可以藉助rke的更新功能完成。通過rke將原來的3節點local集群擴展成6個節點,此時etcd數據將自動同步到local集群內的6個節點上,然後再使用rke將原有的3台節點移除,再次更新。這樣就將Rancher Server可以平滑的遷移到新的Rancher local集群。
1. RKE部署Local Kubernetes 集群
根據RKE示例配置創建 RKE 配置文件 cluster.yml:
nodes:
- address: 3.96.52.186
internal_address: 172.31.11.95
user: ubuntu
role: [controlplane, worker, etcd]
- address: 35.183.186.213
internal_address: 172.31.0.201
user: ubuntu
role: [controlplane, worker, etcd]
- address: 35.183.130.12
internal_address: 172.31.15.236
user: ubuntu
role: [controlplane, worker, etcd]
執行 rke 命令創建 Local Kubernetes 集群
rke up --config cluster.yml
檢查 Kubernetes 集群運行狀態
使用kubectl檢查節點狀態,確認節點狀態為Ready
kubectl get nodes
NAME STATUS ROLES AGE VERSION
3.96.52.186 Ready controlplane,etcd,worker 71s v1.17.6
35.183.130.12 Ready controlplane,etcd,worker 72s v1.17.6
35.183.186.213 Ready controlplane,etcd,worker 72s v1.17.6
檢查所有必需的 Pod 和容器是否狀況良好,然後可以繼續進行
kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
ingress-nginx default-http-backend-67cf578fc4-gnt5c 1/1 Running 0 72s
ingress-nginx nginx-ingress-controller-47p4b 1/1 Running 0 72s
ingress-nginx nginx-ingress-controller-85284 1/1 Running 0 72s
ingress-nginx nginx-ingress-controller-9qbdz 1/1 Running 0 72s
kube-system canal-9bx8k 2/2 Running 0 97s
kube-system canal-l2fjb 2/2 Running 0 97s
kube-system canal-v7fzs 2/2 Running 0 97s
kube-system coredns-7c5566588d-7kv7b 1/1 Running 0 67s
kube-system coredns-7c5566588d-t4jfm 1/1 Running 0 90s
kube-system coredns-autoscaler-65bfc8d47d-vnrzc 1/1 Running 0 90s
kube-system metrics-server-6b55c64f86-r4p8w 1/1 Running 0 79s
kube-system rke-coredns-addon-deploy-job-lx667 0/1 Completed 0 94s
kube-system rke-ingress-controller-deploy-job-r2nw5 0/1 Completed 0 74s
kube-system rke-metrics-addon-deploy-job-4bq76 0/1 Completed 0 84s
kube-system rke-network-plugin-deploy-job-gjpm8 0/1 Completed 0 99s
2. Rancher HA 安裝
參考安裝文檔安裝 Rancher HA。
3. 為Rancher HA配置NGINX 負載均衡
參考NGINX 配置示例為Rancher HA配置負載均衡。
Nginx 配置:
worker_processes 4;
worker_rlimit_nofile 40000;
events {
worker_connections 8192;
}
stream {
upstream rancher_servers_http {
least_conn;
server 172.31.11.95:80 max_fails=3 fail_timeout=5s;
server 172.31.0.201:80 max_fails=3 fail_timeout=5s;
server 172.31.15.236:80 max_fails=3 fail_timeout=5s;
}
server {
listen 80;
proxy_pass rancher_servers_http;
}
upstream rancher_servers_https {
least_conn;
server 172.31.11.95:443 max_fails=3 fail_timeout=5s;
server 172.31.0.201:443 max_fails=3 fail_timeout=5s;
server 172.31.15.236:443 max_fails=3 fail_timeout=5s;
}
server {
listen 443;
proxy_pass rancher_servers_https;
}
}
Nginx啟動后,我們就可以通過配置的域名/IP去訪問Rancher UI。可以導航到local->Nodes 查看到local集群三個節點的狀態:
4. 部署測試集群及應用
添加測試集群,Node Role同時選中etcd、Control Plane、Worker
等待測試集群添加成功后,部署一個nginx workload。再從應用商店部署一個測試應用。
5. 將新集群的節點添加到Local集群
修改剛才創建local集群所使用的rke配置文件,增加新集群的配置。
cluster.yml:
nodes:
- address: 3.96.52.186
internal_address: 172.31.11.95
user: ubuntu
role: [controlplane, worker, etcd]
- address: 35.183.186.213
internal_address: 172.31.0.201
user: ubuntu
role: [controlplane, worker, etcd]
- address: 35.183.130.12
internal_address: 172.31.15.236
user: ubuntu
role: [controlplane, worker, etcd]
# 以下內容為新增節點的配置
- address: 52.60.116.56
internal_address: 172.31.14.146
user: ubuntu
role: [controlplane, worker, etcd]
- address: 99.79.9.244
internal_address: 172.31.15.215
user: ubuntu
role: [controlplane, worker, etcd]
- address: 15.223.77.84
internal_address: 172.31.8.64
user: ubuntu
role: [controlplane, worker, etcd]
更新集群,將local集群節點擴展到6個
rke up --cluster.yml
檢查 Kubernetes 集群運行狀態
使用kubectl測試您的連通性,並確認原節點(3.96.52.186、35.183.186.213、35.183.130.12)和新增節點(52.60.116.56、99.79.9.244、15.223.77.84)都處於Ready狀態
kubectl get nodes
NAME STATUS ROLES AGE VERSION
15.223.77.84 Ready controlplane,etcd,worker 33s v1.17.6
3.96.52.186 Ready controlplane,etcd,worker 88m v1.17.6
35.183.130.12 Ready controlplane,etcd,worker 89m v1.17.6
35.183.186.213 Ready controlplane,etcd,worker 89m v1.17.6
52.60.116.56 Ready controlplane,etcd,worker 101s v1.17.6
99.79.9.244 Ready controlplane,etcd,worker 67s v1.17.6
檢查所有必需的 Pod 和容器是否狀況良好,然後可以繼續進行
kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
cattle-system cattle-cluster-agent-68898b5c4d-lkz5m 1/1 Running 0 46m
cattle-system cattle-node-agent-9xrbs 1/1 Running 0 109s
cattle-system cattle-node-agent-lvdlf 1/1 Running 0 46m
cattle-system cattle-node-agent-mnk76 1/1 Running 0 46m
cattle-system cattle-node-agent-qfwcm 1/1 Running 0 75s
cattle-system cattle-node-agent-tk66h 1/1 Running 0 2m23s
cattle-system cattle-node-agent-v2vpf 1/1 Running 0 46m
cattle-system rancher-749fd64664-8cg4w 1/1 Running 1 58m
cattle-system rancher-749fd64664-fms8x 1/1 Running 1 58m
cattle-system rancher-749fd64664-rb5pt 1/1 Running 1 58m
ingress-nginx default-http-backend-67cf578fc4-gnt5c 1/1 Running 0 89m
ingress-nginx nginx-ingress-controller-44c5z 1/1 Running 0 61s
ingress-nginx nginx-ingress-controller-47p4b 1/1 Running 0 89m
ingress-nginx nginx-ingress-controller-85284 1/1 Running 0 89m
ingress-nginx nginx-ingress-controller-9qbdz 1/1 Running 0 89m
ingress-nginx nginx-ingress-controller-kp7p6 1/1 Running 0 61s
ingress-nginx nginx-ingress-controller-tfjrw 1/1 Running 0 61s
kube-system canal-9bx8k 2/2 Running 0 89m
kube-system canal-fqrqv 2/2 Running 0 109s
kube-system canal-kkj7q 2/2 Running 0 75s
kube-system canal-l2fjb 2/2 Running 0 89m
kube-system canal-v7fzs 2/2 Running 0 89m
kube-system canal-w7t58 2/2 Running 0 2m23s
kube-system coredns-7c5566588d-7kv7b 1/1 Running 0 89m
kube-system coredns-7c5566588d-t4jfm 1/1 Running 0 89m
kube-system coredns-autoscaler-65bfc8d47d-vnrzc 1/1 Running 0 89m
kube-system metrics-server-6b55c64f86-r4p8w 1/1 Running 0 89m
kube-system rke-coredns-addon-deploy-job-lx667 0/1 Completed 0 89m
kube-system rke-ingress-controller-deploy-job-r2nw5 0/1 Completed 0 89m
kube-system rke-metrics-addon-deploy-job-4bq76 0/1 Completed 0 89m
kube-system rke-network-plugin-deploy-job-gjpm8 0/1 Completed 0 89m
從上面的信息可以確認現在local集群已經擴展到6個,並且所有workload均正常運行。
6. 再次更新集群,剔除掉原Local集群節點
再次修改local集群所使用的rke配置文件,將原local集群節點配置註釋掉。
cluster.yml:
nodes:
# - address: 3.96.52.186
# internal_address: 172.31.11.95
# user: ubuntu
# role: [controlplane, worker, etcd]
# - address: 35.183.186.213
# internal_address: 172.31.0.201
# user: ubuntu
# role: [controlplane, worker, etcd]
# - address: 35.183.130.12
# internal_address: 172.31.15.236
# user: ubuntu
# role: [controlplane, worker, etcd]
# 以下內容為新增節點
- address: 52.60.116.56
internal_address: 172.31.14.146
user: ubuntu
role: [controlplane, worker, etcd]
- address: 99.79.9.244
internal_address: 172.31.15.215
user: ubuntu
role: [controlplane, worker, etcd]
- address: 15.223.77.84
internal_address: 172.31.8.64
user: ubuntu
role: [controlplane, worker, etcd]
更新集群,完成遷移。
rke up --cluster.yml
檢查 Kubernetes 集群運行狀態
使用kubectl檢查節點狀態為Ready,可以看到local集群的節點已經替換成了以下3個:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
15.223.77.84 Ready controlplane,etcd,worker 11m v1.17.6
52.60.116.56 Ready controlplane,etcd,worker 13m v1.17.6
99.79.9.244 Ready controlplane,etcd,worker 12m v1.17.6
檢查所有必需的 Pod 和容器是否狀況良好,然後可以繼續進行
kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
cattle-system cattle-cluster-agent-68898b5c4d-tm6db 1/1 Running 3 3m14s
cattle-system cattle-node-agent-9xrbs 1/1 Running 0 14m
cattle-system cattle-node-agent-qfwcm 1/1 Running 0 14m
cattle-system cattle-node-agent-tk66h 1/1 Running 0 15m
cattle-system rancher-749fd64664-47jw2 1/1 Running 0 3m14s
cattle-system rancher-749fd64664-jpqdd 1/1 Running 0 3m14s
cattle-system rancher-749fd64664-xn6js 1/1 Running 0 3m14s
ingress-nginx default-http-backend-67cf578fc4-4668g 1/1 Running 0 3m14s
ingress-nginx nginx-ingress-controller-44c5z 1/1 Running 0 13m
ingress-nginx nginx-ingress-controller-kp7p6 1/1 Running 0 13m
ingress-nginx nginx-ingress-controller-tfjrw 1/1 Running 0 13m
kube-system canal-fqrqv 2/2 Running 0 14m
kube-system canal-kkj7q 2/2 Running 0 14m
kube-system canal-w7t58 2/2 Running 0 15m
kube-system coredns-7c5566588d-nmtrn 1/1 Running 0 3m13s
kube-system coredns-7c5566588d-q6hlb 1/1 Running 0 3m13s
kube-system coredns-autoscaler-65bfc8d47d-rx7fm 1/1 Running 0 3m14s
kube-system metrics-server-6b55c64f86-mcx9z 1/1 Running 0 3m14s
從上面的信息可以確認現在local集群已經遷移成功,並且所有workload均正常運行。
修改nginx負載均衡配置,將新節點的信息更新到nginx配置文件中
worker_processes 4;
worker_rlimit_nofile 40000;
events {
worker_connections 8192;
}
stream {
upstream rancher_servers_http {
least_conn;
server 172.31.14.146:80 max_fails=3 fail_timeout=5s;
server 172.31.8.64:80 max_fails=3 fail_timeout=5s;
server 172.31.15.215:80 max_fails=3 fail_timeout=5s;
}
server {
listen 80;
proxy_pass rancher_servers_http;
}
upstream rancher_servers_https {
least_conn;
server 172.31.14.146:443 max_fails=3 fail_timeout=5s;
server 172.31.8.64:443 max_fails=3 fail_timeout=5s;
server 172.31.15.215:443 max_fails=3 fail_timeout=5s;
}
server {
listen 443;
proxy_pass rancher_servers_https;
}
}
7. 驗證
確認local集群和業務集群狀態為Active
確認Local集群節點已被替換
原集群節點IP分別為:3.96.52.186、35.183.186.213、35.183.130.12
然後驗證我們之前部署的應用是否可用。
開源一直是Rancher的產品理念,我們也一向重視與開源社區用戶的交流,為此創建了20個微信交流群。本篇文章的誕生源於和社區用戶的多次交流,發現許多Rancher用戶都有類似的問題。於是,我總結了三個場景並經過反覆測試,最終完成這篇教程。我們也十分歡迎各位Rancher用戶以各種形式分享自己的使用經驗,一起共建愉快的開源社區。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
如果你對性能測試感興趣,但是又不熟悉理論知識,可以看下面的系列文章
https://www.cnblogs.com/poloyy/category/1620792.html
通常我們會從兩個層面定義性能場景的需求指標,它們有映射關係,技術指標不能脫離業務指標
指同一個時間點執行相同的操作(如:秒殺)
高速公路上,同時有多少輛車經過同一個關卡,但不一定是同一個牌子的汽車
同一時間點,發出請求的用戶數,一個用戶可以發出多個請求
假設有 10 個用戶數,每個用戶同一時間點內發起 2 個請求,那麼服務器收到的請求併發數就是 20
jmerter 中,默認一個接口請求,就是一個事務;但也支持多個接口整合成一個事務
若一個業務或事務有多個接口,那麼多個單接口的性能指標值相加 ≠ 業務或事務的性能指標值
概念:從發起請求到收到請求響應的時間
包含:Request Time 和 Response Time
等價:發起請求網絡傳輸時間 + 服務器處理時間 + 返迴響應網絡傳輸時間
在做性能測試時,要盡可能的降低網絡傳輸時間,這樣最終得出的 RT 會無限接近服務器處理時間,所以我們要把網絡環境搞好
完成單個事務所用的時間,可能包含了多個請求
服務器每秒處理事務數,衡量服務器處理能力的最主要指標
如果要單獨測試接口 1、2、3,那麼 T 就是接口級
如果從用戶角度下訂單,那 1、2、3 都在一個 T 中,就是業務級
結合實際業務設計,庫存服務一定是同步,而積分服務可以是異步,所以這個下單業務,可以只看作由 1、2 這兩個接口組成,但是 3 接口還是要監控分析的
所以,性能中 TPS 中 T 的定義取決於場景的目標和 T 的作用
——事務 start(接口 1)
接口 1 腳本
——事務 end(接口 1)
——事務 start(接口 2)
接口 2 腳本
——事務 end(接口 2)
——事務 start(接口 3)
接口 3 腳本
——事務 end(接口 3)
——事務 start(業務 A)
接口 1 腳本 – 接口 2(同步調用)
接口 1 腳本 – 接口 3(異步調用)
——事務 end(業務 A)
——事務 start(業務 A)
點擊 0 – 接口 1 腳本 – 接口 2(同步調用)
點擊 0 – 接口 1 腳本 – 接口 3(異步調用)
——事務 end(業務 A)
一般情況下,我們會按從上到下的順序一一來測試,這樣路徑清晰地執行,容易定位問題
每秒請求數,用戶從客戶端發起的請求數
對於請求數來說,也要看是哪個層面的請求,把上面的圖做一點點變化來描述請求數
如果一個用戶點擊了一次,發出來 3 個 HTTP Request,調用了 2 次訂單服務,調用了 2 次庫存服務,調用了 1 次積分服務
問:Request 數量如何計算
答:3+2+2+1 = 8?不, 應該是 3,因為發出了 3 個 Request,而調用服務會有單獨的描述,以便做性能統計
上圖的訂單服務、庫存服務、積分服務,各調用了2、2、1次,還是比較好理解的
有很多維度可以衡量一個系統的性能能力,但是如果把五個指標同時都拿來描述系統性能能力的話,未必太混亂了
單位時間內,網絡處理的請求數量(事務/s)
網絡沒有瓶頸時,吞吐量≈TPS
單位時間內,在網絡傳輸的數據量的平均速率(kB/s)
結尾
本篇博文,部分參考了高老師的《性能測試實戰30講》,因為指標那一塊講的特別好哦~
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※教你寫出一流的銷售文案?
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※回頭車貨運收費標準
※別再煩惱如何寫文案,掌握八大原則!
※超省錢租車方案
※產品缺大量曝光嗎?你需要的是一流包裝設計!
一直以來對於.NETCore微服務相關的技術棧都處於一個淺嘗輒止的了解階段,在現實工作中也對於微服務也一直沒有使用的業務環境,所以一直也沒有整合過一個完整的基於.NETCore技術棧的微服務項目。正好由於最近剛好辭職,有了時間可以寫寫自己感興趣的東西,所以在此想把自己了解的微服務相關的概念和技術框架使用實現記錄在一個完整的工程中,由於本人技術有限,所以錯誤的地方希望大家指出。\
項目地址:https://github.com/yingpanwang/fordotnet/tree/dev
由於微服務把具體的業務分割成單獨的服務,所以如果直接將每個服務都與調用者直接,那麼維護起來將相當麻煩與頭疼,Api網關擔任的角色就是整合請求並按照路由規則轉發至服務的實例,並且由於所有所有請求都經過網關,那麼網關還可以承擔一系列宏觀的攔截功能,例如安全認證,日誌,熔斷
因為Api網關可以提供安全認證,日誌,熔斷相關的宏觀攔截的功能,也可以屏蔽多個下游服務的內部細節
Ocelot.json
{
"ReRoutes": [
// Auth
{
"UpstreamPathTemplate": "/auth/{action}", // 上游請求路徑模板
"UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ], // 上游請求方法
"ServiceName": "Auth", // 服務名稱
"UseServiceDiscovery": true, // 是否使用服務發現
"DownstreamPathTemplate": "/connect/{action}", // 下游匹配路徑模板
"DownstreamScheme": "http", // 下游請求
"LoadBalancerOptions": { // 負載均衡配置
"Type": "RoundRobin"
}
//,
// 如果不採用服務發現需要指定下游host
//"DownstreamHostAndPorts": [
// {
// "Host": "10.0.1.10",
// "Port": 5000
// },
// {
// "Host": "10.0.1.11",
// "Port": 5000
// }
//]
}
],
"GlobalConfiguration": { // 全局配置信息
"BaseUrl": "http://localhost:5000", // 請求 baseurl
"ServiceDiscoveryProvider": { //服務發現提供者
"Host": "106.53.199.185",
"Port": 8500,
"Type": "Consul" // 使用Consul
}
}
}
將Config目錄下的ocelot.json添加到項目中
我這裏自己封裝了一個註冊服務的擴展(寫的比較隨意沒有在意細節)
appsettings.json 中添加註冊服務配置信息
"ServiceOptions": {
"ServiceIP": "localhost",
"ServiceName": "Auth",
"Port": 5800,
"HealthCheckUrl": "/api/health",
"ConsulOptions": {
"Scheme": "http",
"ConsulIP": "localhost",
"Port": 8500
}
}
擴展代碼 ConsulExtensions(注意:3.1中 IApplicationLifetime已廢棄 所以使用的是IHostApplicationLifetime 作為程序生命周期注入的方式)
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
namespace ForDotNet.Common.Consul.Extensions
{
/// <summary>
/// 服務配置信息
/// </summary>
public class ServiceOptions
{
/// <summary>
/// 服務ip
/// </summary>
public string ServiceIP { get; set; }
/// <summary>
/// 服務名稱
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 協議類型http or https
/// </summary>
public string Scheme { get; set; } = "http";
/// <summary>
/// 端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 健康檢查接口
/// </summary>
public string HealthCheckUrl { get; set; } = "/api/values";
/// <summary>
/// 健康檢查間隔時間
/// </summary>
public int HealthCheckIntervalSecond { get; set; } = 10;
/// <summary>
/// consul配置信息
/// </summary>
public ConsulOptions ConsulOptions { get; set; }
}
/// <summary>
/// consul配置信息
/// </summary>
public class ConsulOptions
{
/// <summary>
/// consul ip
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// consul 端口
/// </summary>
public int Port { get; set; }
/// <summary>
/// 協議類型http or https
/// </summary>
public string Scheme { get; set; } = "http";
}
/// <summary>
/// consul註冊客戶端信息
/// </summary>
public class ConsulClientInfo
{
/// <summary>
/// 註冊信息
/// </summary>
public AgentServiceRegistration RegisterInfo { get; set; }
/// <summary>
/// consul客戶端
/// </summary>
public ConsulClient Client { get; set; }
}
/// <summary>
/// consul擴展(通過配置文件配置)
/// </summary>
public static class ConsulExtensions
{
private static readonly ServiceOptions serviceOptions = new ServiceOptions();
/// <summary>
/// 添加consul
/// </summary>
public static void AddConsulServiceDiscovery(this IServiceCollection services)
{
var config = services.BuildServiceProvider().GetService<IConfiguration>();
config.GetSection("ServiceOptions").Bind(serviceOptions);
//config.Bind(serviceOptions);
if (serviceOptions == null)
{
throw new Exception("獲取服務註冊信息失敗!請檢查配置信息是否正確!");
}
Register(services);
}
/// <summary>
/// 添加consul(通過配置opt對象配置)
/// </summary>
/// <param name="app"></param>
/// <param name="life">引用生命周期</param>
/// <param name="options">配置參數</param>
public static void AddConsulServiceDiscovery(this IServiceCollection services, Action<ServiceOptions> options)
{
options.Invoke(serviceOptions);
Register(services);
}
/// <summary>
/// 註冊consul服務發現
/// </summary>
/// <param name="app"></param>
/// <param name="life"></param>
public static void UseConsulServiceDiscovery(this IApplicationBuilder app, IHostApplicationLifetime life)
{
var consulClientInfo = app.ApplicationServices.GetRequiredService<ConsulClientInfo>();
if (consulClientInfo != null)
{
life.ApplicationStarted.Register( () =>
{
consulClientInfo.Client.Agent.ServiceRegister(consulClientInfo.RegisterInfo).Wait();
});
life.ApplicationStopping.Register( () =>
{
consulClientInfo.Client.Agent.ServiceDeregister(consulClientInfo.RegisterInfo.ID).Wait();
});
}
else
{
throw new NullReferenceException("未找到相關consul客戶端信息!");
}
}
private static void Register(this IServiceCollection services)
{
if (serviceOptions == null)
{
throw new Exception("獲取服務註冊信息失敗!請檢查配置信息是否正確!");
}
if (serviceOptions.ConsulOptions == null)
{
throw new ArgumentNullException("請檢查是否配置Consul信息!");
}
string consulAddress = $"{serviceOptions.ConsulOptions.Scheme}://{serviceOptions.ConsulOptions.ConsulIP}:{serviceOptions.ConsulOptions.Port}";
var consulClient = new ConsulClient(opt =>
{
opt.Address = new Uri(consulAddress);
});
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(10), // 服務啟動多久后註冊
Interval = TimeSpan.FromSeconds(serviceOptions.HealthCheckIntervalSecond), // 間隔
HTTP = $"{serviceOptions.Scheme}://{serviceOptions.ServiceIP}:{serviceOptions.Port}{serviceOptions.HealthCheckUrl}",
Timeout = TimeSpan.FromSeconds(10)
};
var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = Guid.NewGuid().ToString(),
Name = serviceOptions.ServiceName,
Address = serviceOptions.ServiceIP,
Port = serviceOptions.Port,
};
services.AddSingleton(new ConsulClientInfo()
{
Client = consulClient,
RegisterInfo = registration
});
}
}
}
為了方便演示這裡是以開發者啟動的consul
在consul.exe的目錄下執行
consul agent -dev -ui // 開發者模式運行帶ui
啟動項目和可以發現我的們Auth服務已經註冊進來了
我們這裏訪問 http://localhost:5000/auth/token 獲取token
我們可以看到網關項目接收到了請求並在控制台中打印出以下信息
然後在Auth項目中的控制台中可以看到已經成功接收到了請求並響應
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※超省錢租車方案
※別再煩惱如何寫文案,掌握八大原則!
※回頭車貨運收費標準
※教你寫出一流的銷售文案?
※產品缺大量曝光嗎?你需要的是一流包裝設計!
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
摘錄自2020年10月7日中央社報導
歐洲聯盟地球觀測計畫(Earth Observation Programme)今(7日)表示,今年9月地球表面的氣溫較歷來的9月溫暖,且1月以來的氣溫和史上最熱的2016年同一期間相差無幾。
根攄歐盟氣候監測機構「哥白尼氣候變化服務」(Copernicus Climate Change Service),今年有三個月創下高溫紀錄,分別是1月、5月和9月。
從去年9月至今年9月,地球溫度比工業化前高出將近攝氏1.3度。這項發現令人非常憂心,因為非常接近聯合國政府間氣候變遷問題小組(IPCC)2018年報告提出的攝氏1.5度門檻。報告中闡述地球升溫攝氏1.5度後將產生的重大衝擊。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
摘錄自2020年10月7日自由時報報導
聯合國世界氣象組織(WMO)宣布,南極臭氧層破洞已經創下近年來的「最大最深」,破洞於8月中旬起迅速變大,10月初面積達2400萬平方公里,以台灣面積為3.6萬平方公里來看,相當於666個台灣。
根據美國《ABC新聞》報導,聯合國世界氣象組織指出,目前出現在南極上空的破洞是近幾年來「最大」和「最深」的,強烈的極地渦流是此次臭氧層的導火線,負78度的極度低溫條件下形成「極地平流層雲」,雲中含有冰晶,經太陽光照射後就會產生化學反應,開始大量消耗臭氧。
美國太空總署表示,異常的南極天氣是造成這種情況的原因;歐洲中期天氣預報中心哥白尼大氣監測局局長佩奇(Vincent-Henri Peuch)認為,每年發生的南極臭氧層破洞事件都有很大的差異,這也表明人們需要持續減少排放有害物質,繼續執行《蒙特婁議定書》的規範事項。
本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※教你寫出一流的銷售文案?
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※回頭車貨運收費標準
※別再煩惱如何寫文案,掌握八大原則!
※超省錢租車方案
※產品缺大量曝光嗎?你需要的是一流包裝設計!
6L的動力版本,會讓你在日常代步之餘,也能享受到小鋼炮的魅力。至於1。5T的,朋友,秋名山見。福克斯的短板在於儲物空間較為一般,後排在兩廂車這個級別裏面算是表現一般,中下的水平。致悅,沒錯,不是致炫,是來自菲亞特选手的致悅,至於為啥會推薦它,不是它表現的多突出,主要是價格便宜,優惠還大,這是許多人買車考慮的問題之一。
緊湊型車三廂的感覺操控不過來?
有便宜的兩廂車推薦嗎?
想買兩廂車怎麼辦?
有哪些兩廂車選擇?
首先是來自馬自達选手帶來的昂科賽拉,對於這款車大家都不陌生,操控就不說了,兩廂車操控還不好也不好意思推薦了,昂科賽拉的底盤懸挂是想要表揚的,一個字,穩,即使是高速過彎,你也不會覺得虛。
在眾多車企紛紛投入渦輪增壓發動機的大軍中去是,馬自達堅持做自吸發動機,這簡直是個異類,但是馬自達憑藉創馳藍天技術使得昂科賽拉在動力方面不遜色於搭載渦輪發動機的車型,而且還省油,這也是馬自達敢拿自吸發動機打着運動旗號的原因了。
後排較小,是昂科賽拉的短板,這也是許多馬自達車型的短板了,買馬自達的朋友們要注意哦~
另外是昂科賽拉在胎躁控制方面的還是不夠,這是許多車主反應的問題了。
福特选手帶來的則是福克斯,福克斯是大家心目中的理想車型之一了,美系車的隔音好,配置豐富的特點都具備,還有眾多的動力選擇。
1.0T的動力總成,對於日常上下班代步通勤的朋友們,會說,夠用!1.6L的動力版本,會讓你在日常代步之餘,也能享受到小鋼炮的魅力!至於1.5T的,朋友,秋名山見!
福克斯的短板在於儲物空間較為一般,後排在兩廂車這個級別裏面算是表現一般,中下的水平。
致悅,沒錯,不是致炫,是來自菲亞特选手的致悅,至於為啥會推薦它,不是它表現的多突出,主要是價格便宜,優惠還大,這是許多人買車考慮的問題之一。
除了價格之外,致悅的空間表現以及動力表現也是挺不錯的,全系搭載1.4T渦輪增壓發動機,動力能說不夠嗎?用車主的話說,就是一給油就跑!
從車身尺寸以及乘坐空間測試來看,致悅的表現在同級別不能說最好,但是中上水平還是可以有的。而讓人不滿意的是所搭配的DCT雙離合變速器在低擋換擋的時候頓挫感比較明顯。
以上三款車都是所推薦的兩廂車,綜合實力來說都是比較強的,各位看官可以根據自己的需求來挑選喲!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
最近,一位讀者出去面試前準備了很久,信心滿滿的去面試。沒想到面試官的一個問題把他難住了。面試官的問題是這樣的:如何使用Spring將Service注入到Servlet中呢?這位讀者平時也是很努力的,看什麼源碼啊、多線程啊、高併發啊、設計模式啊等等。沒想到卻在一個很簡單的問題上栽了跟頭,這就說明學習知識要系統化,要有條理,切忌東學一點,西記一點,否則,到頭來,啥也學不到。
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation
這裏,我們列舉兩種解決方法(推薦使用第二種)
直接重寫Servlet的Init()方法,代碼如下:
public void init(ServletConfig servletConfig) throws ServletException {
ServletContext servletContext = servletConfig.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils
.getWebApplicationContext(servletContext);
AutowireCapableBeanFactory autowireCapableBeanFactory = webApplicationContext
.getAutowireCapableBeanFactory();
autowireCapableBeanFactory.configureBean(this, BEAN_NAME);
}
這裏的BEAN_NAME即為我們需要注入到Spring容器中的服務,但這並不是一個好的方法,因為我們需要在每一個Servlet中都進行這樣的操作。
我們可以寫一個類似於“org.springframework.web.struts.DelegatingRequestProcessor”的委託的Bean,然後通過配置的方法把我們的服務注入到servlet中,具體方法如下,
Step 1:編寫委託類DelegatingServletProxy
package com.telek.pba.base.util;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* 以下是類似org.springframework.web.struts.DelegatingRequestProcessor的一個委託
* 用於通過配置的方法,在Servlet中注入Service
* @author binghe
* */
public class DelegatingServletProxy extends GenericServlet{
private static final long serialVersionUID = 1L;
private String targetBean;
private Servlet proxy;
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException{
proxy.service(req, res);
}
/**
* 初始化
*/
public void init() throws ServletException {
this.targetBean = getServletName();
getServletBean();
proxy.init(getServletConfig());
}
/**
* 獲取Bean
*/
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
}
Step 2:修改Web.xml配置
在純Servlet模式下,我們的配置方式如下(以下由於代碼高亮插件的問題,請將代碼中的#替換成尖括號)
<servlet>
<description>活動發起模塊活動查詢分頁Servlet</description>
<display-name>launchActivityQueryServlet</display>
<servlet-name>LaunchActivityQueryServlet</servlet-name>
<servlet-class>com.telek.pba.launch.servlet.LaunchActivityQueryServlet</servlet-class>
<servlet>
<servlet-mapping>
<servlet-name>LaunchActivityQueryServlet</servlet-name>
<url-pattern>/servlet/launch/LaunchActivityQueryServlet</url-pattern>
</servlet-mapping>
</servlet>
如果採用我們這種代理的方法,則配置應該修改為:
<servlet>
<description>活動發起模塊活動查詢分頁Servlet</description>
<display-name>launchActivityQueryServlet</display>
<servlet-name>launchActivityQueryServlet</servlet-name>
<servlet-class>com.telek.pba.base.util.DelegatingServletProxy</servlet-class>
<servlet>
<servlet-mapping>
<servlet-name>launchActivityQuery</servlet-name>
<url-pattern>/servlet/launch/LaunchActivityQueryServlet</url-pattern>
</servlet-mapping>
</servlet>
注意:默認情況下,Servlet的配置中,LaunchActivityQuery的首字母一般為大寫,而我們的標題中已註明,我們採用Spring的註解模式,如果是自動掃描註解的話,默認情況下,註解的value值為首字母小寫,即:launchActivityQuery,因此,在我們新的配置中,要注意將首字母改為小寫,否則會報無法找到Bean的錯誤。
Step 3:至此,我們就可以像SSH的注入方式一樣,注入Servlet了,以下是個小示例:
package com.telek.pba.launch.servlet;
import java.io.IOException;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import com.telek.pba.base.model.PbaUserInfo;
import com.telek.pba.launch.dao.IPbaActivityInfoCurrentDAO;
@Component
public class LaunchActivityQueryServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//注入IPbaActivityInfoCurrentDAO
@Resource
private IPbaActivityInfoCurrentDAO pbaActivityInfoCurrentDAO;
public LaunchActivityQueryServlet() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//sth to do
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//sth to do
}
public void init() throws ServletException {
// Put your code here
}
}
最後,請留心在Spring配置文件中,配置上自動掃描包的路徑:
<context:component-scan base-package="com.telek.pba.*.dao.impl,
com.telek.pba.*.service.impl,
com.telek.pba.*.servlet"/>
大功告成!
好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!
項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation
如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※台北網頁設計公司這麼多該如何選擇?
※智慧手機時代的來臨,RWD網頁設計為架站首選
※評比南投搬家公司費用收費行情懶人包大公開
※回頭車貨運收費標準
Hi,好久不見,我是CPU一號車間的阿Q,不認識我的話,可以看看:完了!CPU一味求快出事兒了!
真的是好久不見了,人類有個說法叫天上一天,地上一年,而在我們的世界里,人類一天,我們不知要過多少年~~
在我所在的CPU這座工廠里,時間的概念有些不太一樣。工廠大門外的中央廣場上掛着一個大大的鐘錶,整個計算機世界里的居民能夠掐着時間過日子全都仰仗它,你們人類把它叫做晶振。
這個鐘錶每隔66000000分之一秒就會報一次時,比人類的鐘錶不知道快到哪裡去了。
早些年還是夠用的,不過隨着我們CPU工廠生產效率的不斷提升,我們多次向晶振提出提升報時的精度,想讓他報時報的的更快一些,不過都被拒絕了。給我們的理由是內存那傢伙聯合主板上其他單位帶頭反對,說他們受條件限制,沒辦法像我們這麼快。
靠人不如靠己,為此,咱們工廠專門設立了一個叫倍頻器的部門進一步把這個報時細分,達到了3600000000分之1秒,作為我們工廠內部工作作息的時鐘周期,這数字實在是太長了,人類為了好記,取了一個叫主頻的名字,表示1秒鐘報時的次數,就是3.6GHz。
一不小心扯遠了,這次想給大家說一件事兒······
我們這座工廠的任務就是不斷的執行人類編寫的程序指令,咱廠里有8個車間,大家開足了馬力,就能同時執行8個線程,那速度那叫一個快。
可是廠里的老闆還是嫌我們不夠快,那天居然告訴我們要每個車間執行兩個線程,實現八核十六線程,是要把我們的勞動力壓榨到極致!我們都滿肚子怨言······
事情的起因是這樣的~~
有一次,我們一號車間的四人組趁着工作的空當,又鬥起了地主,突然領導過來視察。
“你們怎麼又在玩?是工作量不飽和嗎?”,見我們幾個閑着,領導一下就不高興了。
我趕緊上前解釋到:“不好意思領導,咱們剛剛執行了一條指令,需要內存中的一塊數據,剛好又不在緩存中,所以找內存那傢伙要數據去了,這不您也知道那傢伙向來很慢,我們閑着也是閑着所以就稍微放鬆了一下······”
聽了我的話領導一下皺起了眉頭,“還給我狡辯,廠里現在不是用上了亂序執行技術嗎?有這閑功夫你們可以先執行後面的指令啊”
“這我們當然知道,這不您看,我們把後面那幾條指令也都處理了,現在遇到了一條沒法提前執行的指令才停下來的”
領導看了一下問到:“為啥那條不能提前執行?”
“那是一個加法指令,加數依賴於現在正在處理的指令的運算結果呢,所以內存那傢伙不來消息,我們只能擱置着了”,我繼續解釋到。
領導聽完,一臉不高興的離開了。
過了幾天,領導又來到咱們一號車間來了,也不知道怎麼回事,這明明有八個車間,領導怎麼老愛往我們這邊跑。
不過這一次,我們沒有斗地主,正在辛辛苦苦的工作着。
當時,我正在執行一個浮點數運算,領導過來一看,拍了拍我的肩膀說到:“喲,阿Q,忙着吶,這是在做什麼啊?”
我笑着說到:“領導好,我剛剛用浮點數運算電路單元做了一個浮點數乘法,正在等待計算結果呢”
領導點了點頭,往周邊巡視一圈,指着一堆設備問到:“這一堆是什麼?”
“哦,那是整數運算電路單元,這條指令用不到它”
領導再次點了點頭,若有所思的離開了。
又過了幾天,廠里召開了一次會議,八個車間都派了代表參會。
會上,領導發話了:“前段時間我到各個車間視察,發現現在咱們廠里資源浪費的情況很嚴重!”
二號車間的虎子一聽就坐不住了,“領導,咱們大傢伙工作都挺賣力的,哪裡有浪費啊?”
領導瞥了一眼,繼續說到:“一方面,廠里的計算資源——電路設備得不到充分利用,另一方面,又因為內存讀取緩慢、指令依賴等方面的原因,浪費大家太多時間花在等待上”
八號車間的代表向來愛拍馬屁,接着領導的話問到:“領導是有什麼指示?我們八號車間絕對支持!”
“我們幾個管理層經過討論,決定讓你們一個車間由現在執行一個線程,變成執行兩個線程!”
領導這話一出,會場竊竊私語此起彼伏。虎子偏頭小聲對我說到:“這資本家改不了剝削的本色,這壓榨的也太狠了!”
領導咳嗽了幾聲,會場再次安靜了下來。
我起身問到:“領導,這咱們一個車間怎麼能執行兩個線程呢,每個車間的寄存器只有一套,這用起來豈不是要亂掉?”
“這個你不用擔心,我們會給每個車間配兩套寄存器!”
五號車間的代表一聽說到:“要不再給我們添點人手吧,這樣效率肯定提升快!”
領導一聽笑着說到:“還添人手?要不要再給你們添點運算設備?那我不如再增加幾個車間,還開這會幹嘛?這次會議的主題就是如何讓我們現有的資源得到最大程度的利用,減少浪費現象!”
會場一度陷入了尷尬又緊張的氛圍。
還是虎子打破了安靜,“領導,這兩個線程的工作該怎麼開展,我們心底沒有數啊!”
領導滿意的笑了一下:“這才是你們該問的問題嘛!每個車間回去重新分配一下工作,劃分為兩套班子,各自維護一套寄存器,對外宣稱你們是兩個不同的物理核心,但各車間的緩存和計算資源還是只有一套。你們內部協調好,在執行代碼指令的時候,充分利用等待的時間執行另一個線程的指令,這樣也不用擔心指令依賴的問題。”
大家一邊聽一邊做着筆記。
“還有,如果遇到資源閑置的情況,也可以同時執行兩個線程的指令。比如一個線程是執行整數運算指令,一個線程是執行浮點數運算指令,就可以一起來,讓工廠的計算資源充分用起來,別閑置。”
看我們都認真的記着筆記,領導露出了滿意的笑容,“都記好了吧,我們給這項革命性的技術取了個特別酷的名字,叫超線程技術!”
散會後,大家都紛紛抱怨,把大家逼得這麼緊,以後上班看來是沒法摸魚了,這日子真是越來越難過了。
不過,抱怨歸抱怨,大家還是得按照新規來執行。
很快,廠里就落地了這項技術,咱們一個車間搖身一變,變成了倆,咱們原來八核八線程的CPU一下變成了八核十六線程。操作系統那幫人都被我們給騙了,還以為咱們是十六核的CPU呢!
不過畢竟計算資源還是只有一份,遇到兩個線程都要使用同樣的計算單元時,還是得要排隊,還要花時間在兩個線程之前的協調工作上,所以整體工作效率的根本沒有2倍,絕大多數時候能提升個20%-30%就不錯了。
不僅如此,車間改造后,增加了新的邏輯電路單元,咱這CPU工廠的功耗也更大了,工廠門口那座巨大的風扇也得加大馬力給我們降溫了。
廠子里對這項技術的反對聲音開始不絕於耳。
不過後來發生了一件事,讓人們不得不關閉這項技術。聽聞這個消息,我們都樂開了花,看來又可以繼續摸魚了······
每當有網絡數據包到來,網卡那傢伙就通過中斷告訴我們CPU去處理。
可咱明明有8個車間,它非得一個勁的只給我們車間發中斷,搞得我們都沒法好好工作。
終於,我忍不住了······
預知後事如何,請關注後續精彩······
說明:
超線程技術出現時間其實早於多核技術。本故事僅為敘述方便,不代表二者真實的發展順序。
真慘!連各大編程語言都擺起地攤了!
因為一個跨域請求,我差點丟了飯碗
完了!CPU一味求快出事兒了!
哈希表哪家強?幾大編程語言吵起來了!
一個HTTP數據包的奇幻之旅
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※教你寫出一流的銷售文案?
※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益
※回頭車貨運收費標準
※別再煩惱如何寫文案,掌握八大原則!
※超省錢租車方案
※產品缺大量曝光嗎?你需要的是一流包裝設計!