環保局回應指出,9日下午會同農田水利會沙鹿站前往稽查,在梧棲大排(鄰近中華路一段1001-2號旁)發現死魚約50隻

環保局回應指出,9日下午會同農田水利會沙鹿站前往稽查,在梧棲大排(鄰近中華路一段1001-2號旁)發現死魚約50隻,零星分佈在約500公尺長的河段,經檢視魚屍已腐爛,且因河岸高度,考量人員安全,無法採集魚體送驗。

現場水質檢測結果,水色正常,水流緩慢且水位偏低,水質pH7.9、溶氧4.4mg/L、水溫22.5℃、重金屬及氰化物未檢出,未有異常反應。因現場仍有活魚悠遊,研判疑為上游水質異常,致魚群適應不良暴斃,因農田水利會近日於上游開啟水閘門,導致魚屍沖刷而下累積在現場,已請水保科通知管理單位儘速清理,以維持水體品質。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※使用真空封口機常見問題?

※高價位跟低價位的示波器又有何差異?

※各大百貨每波促銷贈品活動,限量知名LOGOL型資料夾,獨家販售中!!

※哪裡有合版印刷優惠,尋找L夾客製化印刷廠商?

※如何正確使用開飲機?

洗滌塔運作原理介紹

國立暨南國際大學參與2019年世界綠色大學評比再傳捷報,在全球排名第45名,較去年進步9名

國立暨南國際大學參與2019年世界綠色大學評比再傳捷報,在全球排名第45名,較去年進步9名,也首度擠進全球前50大,亞洲則是排名第8,成績亮眼;暨大表示,今年評比結果,該校在基礎建設的環境友善性表現突出,在台灣排名第1,全球也排名第5,未來也將持續加強各項環保措施,讓排名再精進。

暨大校園佔地約150公頃,在基礎建設的環境友善性表現突出,校園綠美化成果豐碩,已成為中部地區知名的賞櫻景點,動物植資源豐碩,校園還可見穿山甲等保育類動物,校方積極維護棲地安全,也強調未來會持續加強其他項目的改善,讓綠色大學的精神成為暨大的DNA。

本站聲明:網站內容來源於https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※一般小吃店常見使用的nbr耐油手套,是否有含耐酸鹼作用?

迴轉式空壓機性能介紹 !

海線倉儲類人員薪水待遇最新情報

※(全省)堆高機租賃保養一覽表

※高效率洗滌塔活性碳設備,能去除多少有機溶劑?

射出成型技師工作甘苦談

020.掌握Pod-Pod基礎使用

一 Pod定義詳解

1.1 完整Pod定義文件

  1 apiVersion: v1			#必選,版本號,例如v1,版本號必須可以用 kubectl api-versions 查詢到
  2 kind: Pod				#必選,Pod
  3 metadata:				#必選,元數據
  4   name: string			#必選,Pod名稱,需符合RFC 1035規範
  5   namespace: string			#必選,Pod所屬的命名空間,默認為"default"
  6   labels:				#自定義標籤
  7     - name: string			#自定義標籤名字
  8   annotations:			#自定義註釋列表
  9     - name: string
 10 spec:				#必選,Pod中容器的詳細定義
 11   containers:			#必選,Pod中容器列表
 12   - name: string			#必選,容器名稱,需符合RFC 1035規範
 13     image: string			#必選,容器的鏡像名稱
 14     imagePullPolicy: [ Always|Never|IfNotPresent ]	#獲取鏡像的策略,Alawys表示每次都嘗試下載鏡像,IfnotPresent表示優先使用本地鏡像,否則下載鏡像,Nerver表示僅使用本地鏡像
 15     command: [string]		#容器的啟動命令列表,如不指定,使用打包時使用的啟動命令
 16     args: [string]			#容器的啟動命令參數列表
 17     workingDir: string		#容器的工作目錄
 18     volumeMounts:			#掛載到容器內部的存儲卷配置
 19     - name: string			#引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名
 20       mountPath: string		#存儲卷在容器內mount的絕對路徑,應少於512字符
 21       readOnly: boolean		#是否為只讀模式,默認為讀寫模式
 22     ports:				#需要暴露的端口庫號列表
 23     - name: string			#端口的名稱
 24       containerPort: int		#容器需要監聽的端口號
 25       hostPort: int		        #容器所在主機需要監聽的端口號,默認與Container相同
 26       protocol: string		#端口協議,支持TCP和UDP,默認TCP
 27     env:				#容器運行前需設置的環境變量列表
 28     - name: string			#環境變量名稱
 29       value: string		        #環境變量的值
 30     resources:			#資源限制和請求的設置
 31       limits:			#資源限制的設置
 32         cpu: string		        #CPU的限制,單位為core數,將用於docker run --cpu-shares參數
 33         memory: string		#內存限制,單位可以為Mib/Gib,將用於docker run --memory參數
 34       requests:			#資源請求的設置
 35         cpu: string		        #CPU請求,容器啟動的初始可用數量
 36         memory: string		#內存請求,容器啟動的初始可用數量
 37     livenessProbe:			#對Pod內各容器健康檢查的設置,當探測無響應幾次后將自動重啟該容器,檢查方法有exec、httpGet和tcpSocket,對一個容器只需設置其中一種方法即可
 38       exec:			        #對Pod容器內檢查方式設置為exec方式
 39         command: [string]		#exec方式需要制定的命令或腳本
 40       httpGet:			#對Pod內個容器健康檢查方法設置為HttpGet,需要制定Path、port
 41         path: string
 42         port: number
 43         host: string
 44         scheme: string
 45         HttpHeaders:
 46         - name: string
 47           value: string
 48       tcpSocket:			#對Pod內個容器健康檢查方式設置為tcpSocket方式
 49          port: number
 50        initialDelaySeconds: 0	#容器啟動完成后首次探測的時間,單位為秒
 51        timeoutSeconds: 0		#對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
 52        periodSeconds: 0		#對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
 53        successThreshold: 0
 54        failureThreshold: 0
 55        securityContext:
 56          privileged: false
 57     restartPolicy: [Always | Never | OnFailure]	#Pod的重啟策略,Always表示一旦不管以何種方式終止運行,kubelet都將重啟,OnFailure表示只有Pod以非0退出碼退出才重啟,Nerver表示不再重啟該Pod
 58     nodeSelector: obeject		#設置NodeSelector表示將該Pod調度到包含這個label的node上,以key:value的格式指定
 59     imagePullSecrets:		#Pull鏡像時使用的secret名稱,以key:secretkey格式指定
 60     - name: string
 61     hostNetwork: false		#是否使用主機網絡模式,默認為false,如果設置為true,表示使用宿主機網絡
 62     volumes:			#在該pod上定義共享存儲卷列表
 63     - name: string			#共享存儲卷名稱 (volumes類型有很多種)
 64       emptyDir: {}			#類型為emtyDir的存儲卷,與Pod同生命周期的一個臨時目錄。為空值
 65       hostPath: string		#類型為hostPath的存儲卷,表示掛載Pod所在宿主機的目錄
 66         path: string		#Pod所在宿主機的目錄,將被用於同期中mount的目錄
 67       secret:			#類型為secret的存儲卷,掛載集群與定義的secre對象到容器內部
 68         scretname: string
 69         items:
 70         - key: string
 71           path: string
 72       configMap:			#類型為configMap的存儲卷,掛載預定義的configMap對象到容器內部
 73         name: string
 74         items:
 75         - key: string
 76           path: string

二 Pod的基本用法

2.1 創建Pod


Pod可以由1個或多個容器組合而成,通常對於緊耦合的兩個應用,應該組合成一個整體對外提供服務,則應該將這兩個打包為一個pod。

屬於一個Pod的多個容器應用之間相互訪問只需要通過localhost即可通信,這一組容器被綁定在一個環境中。

  1 [root@k8smaster01 study]# vi frontend-localredis-pod.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: redis-php
  6   label:
  7     name: redis-php
  8 spec:
  9   containers:
 10   - name: frontend
 11     image: kubeguide/guestbook-php-frontend:localredis
 12     ports:
 13     - containersPort: 80
 14   - name: redis-php
 15     image: kubeguide/redis-master
 16     ports:
 17     - containersPort: 6379
 18 
 19 [root@k8smaster01 study]# kubectl create -f frontend-localredis-pod.yaml
 20 


2.2 查看Pod

  1 [root@k8smaster01 study]# kubectl get pods	                #READY為2/2,表示此Pod中運行了yaml定義的兩個容器
  2 NAME        READY   STATUS    RESTARTS   AGE
  3 redis-php   2/2     Running   0          7m45s
  4 [root@k8smaster01 study]# kubectl describe pod redis-php	#查看詳細信息
  5 


三 靜態Pod

3.1 靜態Pod概述


靜態pod是由kubelet進行管理的僅存在於特定Node的Pod上,他們不能通過API Server進行管理,無法與ReplicationController、Deployment或者DaemonSet進行關聯,並且kubelet無法對他們進行健康檢查。靜態Pod總是由kubelet進行創建,並且總是在kubelet所在的Node上運行。

創建靜態Pod有兩種方式:配置文件或者HTTP方式。

3.2 配置文件方式創建

  1 [root@k8snode01 ~]# mkdir -p /etc/kubelet.d
  2 [root@k8snode01 ~]# vi /etc/kubelet.d/static-web.yaml
  3 apiVersion: v1
  4 kind: Pod
  5 metadata:
  6   name: static-web
  7   label:
  8     name: static-web
  9 spec:
 10   containers:
 11   - name: static-web
 12     image: nginx
 13     ports:
 14     - name: web
 15       containersPort: 80
 16 
 17 [root@k8snode01 ~]# vi /etc/systemd/system/kubelet.service
 18 ……
 19   --config=/etc/kubelet.d/ \·				#加入此參數
 20 ……
 21 [root@k8snode01 ~]# systemctl daemon-reload
 22 [root@k8snode01 ~]# systemctl restart kubelet.service	#重啟kubelet
 23 [root@k8snode01 ~]# docker ps				#查看創建的pod



提示:由於靜態pod不能通過API Server進行管理,因此在Master節點執行刪除操作後會變為Pending狀態,且無法刪除。刪除該pod只能在其運行的node上,將定義POD的yaml刪除。

3.3 HTTP方式


通過設置kubelet的啟動參數–mainfest-url,會定期從該URL下載Pod的定義文件,並以.yaml或.json文件的格式進行解析,從而創建Pod。

四 Pod容器共享Volume

4.1 共享Volume


在同一個Pod中的多個容器能夠共享Pod級別的存儲就Volume。Volume可以被定義為各種類型,多個容器各自進行掛載操作,將一個Volume掛載為容器內部需要的目錄。


示例1:

Pod級別設置Volume “app-logs”,同時Pod包含兩個容器,Tomcat向該Volume寫日誌,busybox讀取日誌文件。

  1 [root@k8smaster01 study]# vi pod-volume-applogs.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: volume-pod
  6 spec:
  7   containers:
  8   - name: tomcat
  9     image: tomcat
 10     ports:
 11     - containerPort: 8080
 12     volumeMounts:
 13     - name: app-logs
 14       mountPath: /usr/local/tomcat/logs
 15   - name: logreader
 16     image: busybox
 17     command: ["sh","-c","tail -f /logs/catalina*.log"]
 18     volumeMounts:
 19     - name: app-logs
 20       mountPath: /logs
 21   volumes:
 22   - name: app-logs
 23     emptyDir: {}

解釋:

Volume名:app-logs;

emptyDir:為Pod分配到Node的時候創建。無需指定宿主機的目錄文件,為Kubernetes自動分配的目錄。

  1 [root@k8smaster01 study]# kubectl create -f pod-volume-applogs.yaml	#創建
  2 [root@k8smaster01 study]# kubectl get pods				#查看
  3 [root@k8smaster01 study]# kubectl logs volume-pod -c busybox	#讀取log




  1 [root@k8smaster01 study]# kubectl exec -it volume-pod -c tomcat -- ls /usr/local/tomcat/logs
  2 catalina.2019-06-29.log      localhost_access_log.2019-06-29.txt
  3 host-manager.2019-06-29.log  manager.2019-06-29.log
  4 localhost.2019-06-29.log
  5 [root@k8smaster01 study]# kubectl exec -it volume-pod -c tomcat -- tail /usr/local/tomcat/logs/catalina.2019-06-29.log



提示:通過tomcat容器可查看日誌,對比busybox通過共享Volume查看的日誌是否一致。

五 Pod配置管理

5.1 Pod配置概述


應用部署的一個最佳實踐是將應用所需的配置信息與程序進行分離,使程序更加靈活。將相應的應用打包為鏡像,可以通過環境變量或者外掛volume的方式在創建容器的時候進行配置注入,從而實現更好的復用。

Kubernetes提供一種統一的應用配置管理方案:ConfigMap。

5.2 ConfigMap概述


ConfigMap供容器使用的主要場景:

  • 生成容器內部的環境變量;
  • 設置容器的啟動命令的參數(需設置為環境變量);
  • 以volume的形式掛載為容器內部的文件或者目錄。


ConfigMap以一個或多個key:value的形式定義。value可以是string也可以是一個文件內容,可以通過yaml配置文件或者通過kubectl create configmap 的方式創建configMap。

5.3 創建ConfigMap資源對象——yaml方式

  1 [root@k8smaster01 study]# vi cm-appvars.yaml
  2 apiVersion: v1
  3 kind: ConfigMap
  4 metadata:
  5   name: cm-appvars
  6 data:
  7   apploglevel: info
  8   appdatadir: /var/data
  9 
 10 [root@k8smaster01 study]# kubectl create -f cm-appvars.yaml
 11 configmap/cm-appvars created
 12 [root@k8smaster01 study]# kubectl get configmaps
 13 NAME         DATA   AGE
 14 cm-appvars   2      8s
 15 [root@k8smaster01 study]# kubectl describe configmaps cm-appvars



  1 [root@k8smaster01 study]# kubectl get configmaps cm-appvars -o yaml


5.4 創建ConfigMap資源對象——命令行方式


語法1

  1 # kubectl create configmap NAME --from-file=[key=]source --from-file=[key=]source



解釋:通過–from-file參數從文件中創建,可以指定key名稱,也可以制定多個key。

語法2

  1 # kubectl create configmap NAME --from-file=config-files-dir



解釋:通過–from-file參數從目錄中創建,該目錄下的每個配置文件名都被設置為key,文件的內容被設置為value。

語法3

  1 # kubectl create configmap NAME --from-literal=key1=value1 --from-literal=key2=value2



解釋:通過–from-literal參數從文本中創建,直接將指定的key#=value#創建為ConfigMap的內容。

5.5 Pod使用ConfigMap


容器應用使用ConfigMap有兩種方式:

  • 通過環境變量獲取ConfigMap中的內容;
  • 通過Volume掛載的方式將ConfigMap中的內容掛載為容器內容的文件或目錄。

  1 [root@k8smaster01 study]# vi cm-test-pod.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: cm-test-pod
  6 spec:
  7   containers:
  8   - name: cm-test
  9     image: busybox
 10     command: ["/bin/sh","-c","env|grep APP"]	#容器里執行查看環境變量的命令
 11     env:
 12     - name: APPLOGLEVEL				#定義容器環境變量名稱
 13       valueFrom:
 14         configMapKeyRef:			#環境變量的值來自ConfigMap
 15           name: cm-appvars			#指定來自cm-appvars的ConfigMap
 16           key: apploglevel			#key為apploglevel
 17     - name: APPDATADIR
 18       valueFrom:
 19         configMapKeyRef:
 20           name: cm-appvars
 21           key: appdatadir
 22 
 23 [root@k8smaster01 study]# kubectl create -f cm-test-pod.yaml
 24 [root@k8smaster01 study]# kubectl get pods
 25 NAME          READY   STATUS      RESTARTS   AGE
 26 cm-test-pod   0/1     Completed   2          24s



【掛載形式-待補充】

5.6 ConfigMap限制


  • Configmap必須在pod創建之間創建;
  • ConfigMap受到namespace的限制,只有同一個命名空間下才能引用;
  • ConfigMap暫時無法配置配額;
  • 靜態的pod無法使用ConfigMap;
  • 在使用volumeMount掛載的時候,configMap基於items創建的文件會整體的將掛載數據卷的容器的目錄下的文件全部覆蓋。

六 Pod獲取自身信息

6.1 Downward API


pod擁有唯一的名字、IP地址,並且處於某個Namespace中。pod的容器內獲取pod的信息科通過Downward API實現。具體有以下兩種方式:

  • 環境變量:用於單個變量,可以將pod信息和container信息注入容器內部;
  • volume掛載:將數組類信息生成為文件,掛載至容器內部。


舉例1:通過Downward API將Pod的IP、名稱和所在的Namespace注入容器的環境變量。

  1 [root@k8smaster01 study]# vi dapi-test-pod.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: dapi-test-pod
  6 spec:
  7   containers:
  8     - name: test-container
  9       image: busybox
 10       command: [ "/bin/sh", "-c", "env" ]
 11       env:
 12         - name: MY_POD_NAME
 13           valueFrom:
 14             fieldRef:
 15               fieldPath: metadata.name
 16         - name: MY_POD_NAMESPACE
 17           valueFrom:
 18             fieldRef:
 19               fieldPath: metadata.namespace
 20         - name: MY_POD_IP
 21           valueFrom:
 22             fieldRef:
 23               fieldPath: status.podIP
 24   restartPolicy: Never



提示:Downward API提供如下變量:

metadata.name:Pod的名稱,當Pod通過RC生成時,其名稱是RC隨機產生的唯一名稱;

status.podIP:Pod的IP地址,POd的IP屬於狀態數據,而非元數據;

metadata.namespace:Pod所在的namespace。

  1 [root@k8smaster01 study]# kubectl create -f dapi-test-pod.yaml
  2 [root@k8smaster01 study]# kubectl logs dapi-test-pod | grep MY_POD
  3 MY_POD_NAMESPACE=default
  4 MY_POD_IP=172.30.240.4
  5 MY_POD_NAME=dapi-test-pod
  6 



舉例2:通過Downward API將Container的自願請求和限制信息注入容器的環境變量。

  1 [root@k8smaster01 study]# vi dapi-test-pod-container-vars.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: dapi-test-pod-container-vars
  6 spec:
  7   containers:
  8     - name: test-container
  9       image: busybox
 10       imagePullPolicy: Never
 11       command: [ "/bin/sh", "-c" ]
 12       args:
 13       - while true; do
 14           echo -en '\n';
 15           printenv MY_CPU_REQUEST MY_CPU_LIMIT;
 16           printenv MY_MEM_REQUEST MY_MEM_LIMIT;
 17           sleep 3600;
 18         done;
 19       resources:
 20         requests:
 21           memory: "32Mi"
 22           cpu: "125m"
 23         limits:
 24           memory: "64Mi"
 25           cpu: "250m"
 26       env:
 27         - name: MY_CPU_REQUEST
 28           valueFrom:
 29             resourceFieldRef:
 30               containerName: test-container
 31               resource: requests.cpu
 32         - name: MY_CPU_LIMIT
 33           valueFrom:
 34             resourceFieldRef:
 35               containerName: test-container
 36               resource: limits.cpu
 37         - name: MY_MEM_REQUEST
 38           valueFrom:
 39             resourceFieldRef:
 40               containerName: test-container
 41               resource: requests.memory
 42         - name: MY_MEM_LIMIT
 43           valueFrom:
 44             resourceFieldRef:
 45               containerName: test-container
 46               resource: limits.memory
 47   restartPolicy: Never



提示:Downward API提供如下變量:

requests.cpu:容器的CPU請求值;

limits.cpu:容器的CPU限制值;

requests.memory:容器的內存請求值;

limits.memory:容器的內存限制值。

  1 [root@k8smaster01 study]# kubectl create -f dapi-test-pod-container-vars.yaml
  2 [root@k8smaster01 study]# kubectl logs dapi-test-pod-container-vars
  3 1
  4 1
  5 33554432
  6 67108864



舉例3:通過Downward API將Pod的Label、Annotation列表通過Volume掛載為容器內的一個文件。

  1 [root@k8smaster01 study]# vi dapi-test-pod-volume.yaml
  2 apiVersion: v1
  3 kind: Pod
  4 metadata:
  5   name: dapi-test-pod-volume
  6   labels:
  7     zone: us-est-coast
  8     cluster: test-cluster1
  9     rack: rack-22
 10   annotations:
 11     build: two
 12     builder: john-doe
 13 spec:
 14   containers:
 15     - name: test-container
 16       image: busybox
 17       imagePullPolicy: Never
 18       command: [ "/bin/sh", "-c" ]
 19       args:
 20       - while true; do
 21           if [[ -e /etc/labels ]]; then
 22             echo -en '\n\n'; cat /etc/labels; fi;
 23           if [[ -e /etc/annotations ]]; then
 24             echo -en '\n\n'; cat /etc/annotations; fi;
 25           sleep 3600;
 26         done;
 27       volumeMounts:
 28         - name: podinfo
 29           mountPath: /etc
 30           readOnly: false
 31   volumes:
 32     - name: podinfo
 33       downwardAPI:
 34         items:
 35           - path: "labels"
 36             fieldRef:
 37               fieldPath: metadata.labels
 38           - path: "annotations"
 39             fieldRef:
 40               fieldPath: metadata.annotations



注意:Volume中的ddownwardAPI的items語法,將會以path的名稱生成文件。如上所示,會在容器內生產/etc/labels和/etc/annotations兩個文件,分別包含metadata.labels和metadata.annotations的全部Label。

  1 [root@k8smaster01 study]# kubectl create -f dapi-test-pod-volume.yaml
  2 [root@k8smaster01 study]# kubectl logs dapi-test-pod-volume
  3 



提示:DownwardAPI意義:

在某些集群中,集群中的每個節點需要將自身的標識(ID)及進程綁定的IP地址等信息事先寫入配置文件中,進程啟動時讀取此類信息,然後發布到某個類似註冊服務中心。此時可通過DowanwardAPI,將一個預啟動腳本或Init Container,通過環境變量或文件方式獲取Pod自身的信息,然後寫入主程序配置文件中,最後啟動主程序。本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步”網站設計“幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※試算大陸海運運費!

SpringBoot基本配置詳解

SpringBoot項目有一些基本的配置,比如啟動圖案(banner),比如默認配置文件application.properties,以及相關的默認配置項。

示例項目代碼在:

一、啟動圖案banner

編寫banner.txt放入resources文件夾下,然後啟動項目即可修改默認圖案。

關於banner的生成,可以去一些專門的網站。

比如:https://www.bootschool.net/ascii

二、配置文件application

2.1 application.properties/yml

resources下通常會默認生成一個application.properties文件,這個文件包含了SpringBoot項目的全局配置文件。裏面的配置項通常是這樣的:

server.port=8080

在這個文件里我們可以添加框架支持的配置項,比如項目端口號、JDBC連接的數據源、日誌級別等等。

現在比較流行的是將properties文件改為yml文件。yml文件的格式yaml是這樣的:

server:
    port: 8080

yml和properties的作用是一樣的。而yml的好處是顯而易見的——更易寫易讀。

屬性之間互相調用使用${name}:

eknown:
    email: eknown@163.com
    uri: http://www.eknown.cn
    title: 'hello, link to ${eknown.uri} or email to ${eknown.email}'

鏈接:

2.2 多環境配置文件

通常開發一個應用會有多個環境,常見如dev/prod,也會有test,甚至其他一些自定義的環境,SpringBoot支持配置文件的靈活切換。

定義新配置文件需要遵循以下格式:application-{profile}.properties 或者application-{profile}.yml

比如現在有dev和prod兩個環境,我需要在application.yml文件之外新建兩個文件:

  1. application-dev.yml

    server:
       port: 8080
  2. application-prod.yml

    server:
      port: 8081

然後在application.yml中通過application.profiles.active={profile}指明啟用那個配置:

application:
    profiles:
      active: dev

除了在application.yml中指定配置文件外,還可以通過啟動命令指定:java -jar xxx.jar --spring.profiles.active=dev

2.2 自定義配置項並獲取它

主要介紹兩種方式,獲取單個配置項和獲取多個配置項。

舉例:

eknown:
    email: eknown@163.com
    uri: http://www.eknown.cn

2.2.1 使用@Value註解獲取單個配置項

@Value("${eknown.email}")
private String email;

@Value("${eknown.uri}")
private String url;

注意:使用@Value註解的時候,所在類必須被Spring容器管理,也就是被@Component、@Controller、@Service等註解定義的類。

2.2.2 獲取多個配置項

第一種,定義一個bean類,通過@Value獲取多個配置項:

@Component
public class MyConfigBean {
  
}

然後我們通過get方法來獲取這些值:

@RestController
public class BasicAction {
  
  @Autowired
  private MyConfigBean myConfigBean;

}

第二種,使用註解@ConfigurationProperties:

@Component
@ConfigurationProperties(perfix="eknown")
public class MyConfigBean {

  private String email;
  private String uri;
}

這裏只需要通過prefix指定前綴即可,後面的值自動匹配。

這裏我們還使用了@Component註解來讓spring容器管理這個MyConfigBean。

此外,我們可以不需要引入@Component,轉而在Application啟動類上加上@EnableConfigurationProperties({MyConfigBean.class})來啟動這個配置。

注意:我們這裡是從主配置文件,也就是SpringBoot默認的application-profile文件中獲取配置數據的。

而從自定義的配置文件,比如test.yml這種形式中獲取配置項時,情況是有點不大一樣的。

三、自定義配置文件

上面介紹的配置文件都是springboot默認的application開頭的文件。如果要自定義一個配置文件呢,比如test.yml或test.properties,怎麼獲取其中的配置項呢?

使用@PageResource註解即可。

首先我們來看一下讀取自定義的properties文件里的內容:

test.properties

hello.time=2019.11.19
hello.name=eknown

定義Configuration類:

@Configuration
@PropertySource("classpath:test.properties")
//@PropertySource("classpath:test.yml") // 注意,yml文件不能直接這樣寫,會讀不出數據
@ConfigurationProperties(prefix = "hello")
public class TestConfiguration {
    private String name;
    private String time;

    // hide get and set methods
}

測試一下:

@RestController
@RequestMapping(value = "test")
public class TestAction {

    @Autowired
    private TestConfiguration testConfiguration;

    @GetMapping(value = "config")
    public String test() {
        return testConfiguration.getName() + "<br/>" + testConfiguration.getTime();
    }
}

如果將properties文件換成yml文件呢?

我們嘗試一下,發現:

讀不出數據?

分析一下@PropertySource註解,發現其使用的PropertySourceFactory是DefaultPropertySourceFactory.

這個類的源碼如下:

public class DefaultPropertySourceFactory implements PropertySourceFactory {
    public DefaultPropertySourceFactory() {
    }

    public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
        return name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource);
    }
}

這個類只能處理properties文件,無法處理yml文件。所以我們需要自定義一個YmlSourceFactory。

public class YamlSourceFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        return new YamlPropertySourceLoader().load(resource.getResource().getFilename()
                , resource.getResource()).get(0);
    }
}

然後定義test.yml文件的config類:

@Configuration
@PropertySource(value = "classpath:test.yml", encoding = "utf-8", factory = YamlSourceFactory.class)
@ConfigurationProperties(prefix = "yml.hello")
public class TestYamlConfiguration {
    private String name;
    private String time;

    // hide get and set methods
}

注:為了區分test.properties和test.yml,這裏的test.yml中的屬性以yml.hello開頭。

編寫一下測試:

    @Autowired
    private TestYamlConfiguration ymlConfiguration;

    @GetMapping(value = "yml")
    public String testYml() {
        return "yml config: <br/>" + ymlConfiguration.getName() + "<br/>" + ymlConfiguration.getTime();
    }

訪問:

四、補充@ConfigurationProperties

網上一些資料中,為配合使用@ConfigurationProperties,還使用了@EnableConfigurationProperties註解。

經過測試發現:

  1. 從SpringBoot默認配置文件讀取配置信息,使用@ConfigurationProperties + @Component/@Configuration,或者@ConfigurationProperties + 在啟動類添加@EnableConfigurationProperties({class})。這兩種方式都能解決問題

  2. 從非默認配置文件讀取配置信息,需要利用@PropertySource註解。同樣兩種方式:

    2.1 @PropertySource + @ConfigurationProperties + @Component/@Configuration

    2.2 @PropertySource + @ConfigurationProperties + @Component/@Configuration + @EnableConfigurationProperties,第二種方式存在一個問題,即還是必須要使用@Component註解,如果不使用,則會導致讀取配置信息為null,但程序不會報錯;而如果採用了,則會導致bean類的set方法被執行兩次(也就是生成了兩個同樣類型的bean類)。這種方式不建議!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

※專營大陸快遞台灣服務

台灣快遞大陸的貨運公司有哪些呢?

Appium+python自動化(四十一)-Appium自動化測試框架綜合實踐 – 即將落下帷幕(超詳解)

1.簡介

  今天我們緊接着上一篇繼續分享Appium自動化測試框架綜合實踐 – 代碼實現。到今天為止,大功即將告成;框架所需要的代碼實現都基本完成。

2.data數據封裝

2.1使用背景

在實際項目過程中,我們的數據可能是存儲在一個數據文件中,如txt,excel、csv文件類型。我們可以封裝一些方法來讀取文件中的數據來實現數據驅動。

2.2案例

將測試賬號存儲在account.csv文件,內容如下:

account.csv

hg2018

hg2018

hg2019

zxw2019

666

222

參考代碼

2.3enumerate()簡介

enumerate()是python的內置函數

  • enumerate在字典上是枚舉、列舉的意思
  • 對於一個可迭代的(iterable)/可遍歷的對象(如列表、字符串),enumerate將其組成一個索引序列,利用它可以同時獲得索引和值
  • enumerate多用於在for循環中得到計數。

2.4enumerate()使用

如果對一個列表,既要遍歷索引又要遍曆元素時,首先可以這樣寫:

參考代碼
list = ["", "", "一個", "測試","數據"]

for i in range(len(list)):

    print(i,list[i])

上述方法有些累贅,利用enumerate()會更加直接和優美:

參考代碼
list1 = ["", "", "一個", "測試","數據"]

for index, item in enumerate(list1):

        print(index,item)

3.數據讀取方法封裝

  數據讀取方法也屬於公共方法,這裏我們首先實現一下,然後將其封裝到裡邊即可。

3.1數據讀取方法實現的參考代碼

import csv


     def get_csv_data(csv_file,line):

        with open(csv_file, 'r', encoding='utf-8-sig') as file:

            reader=csv.reader(file)

            for index, row in enumerate(reader,1):

                if index == line:

                    return row

 

    csv_file='../data/account.csv'

    data=get_csv_data(csv_file,3)

    print(data)

3.2封裝

將其封裝在公共方法中,在其他地方用到的時候,直接導入調用即可。

4.utf-8與utf-8-sig兩種編碼格式的區別

UTF-8以字節為編碼單元,它的字節順序在所有系統中都是一樣的,沒有字節序的問題,也因此它實際上並不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。

5.config文件配置

各種配置文件都放在這個目錄下。

5.1日誌文件配置 

主要是一些日誌信息的配置。

log.config

 參考代碼
[loggers]
keys=root,infoLogger

[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler

[logger_infoLogger]
handlers=consoleHandler,fileHandler
qualname=infoLogger
propagate=0

[handlers]
keys=consoleHandler,fileHandler

[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=INFO
formatter=form01
args=('../logs/runlog.log', 'a')

[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

[formatter_form02]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

6.測試用例封裝

這裏宏哥舉例給小夥伴們演示:封裝註冊和登錄兩個測試用例。

6.1測試用例執行開始結束操作封裝

測試用例執行開始和結束的封裝,其他模塊用到直接導入,調用即可。

myunit.py

參考代碼
# coding=utf-8
# 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行

# 2.註釋:包括記錄創建時間,創建人,項目名稱。
'''
Created on 2019-11-20
@author: 北京-宏哥   QQ交流群:707699217
Project:Appium自動化測試框架綜合實踐 - 代碼實現
'''
# 3.導入模塊
import unittest
from kyb_testProject.common.desired_caps import appium_desired
import logging
from time import sleep

class StartEnd(unittest.TestCase):
    def setUp(self):
        logging.info('=====setUp====')
        self.driver=appium_desired()

    def tearDown(self):
        logging.info('====tearDown====')
        sleep(5)
        self.driver.close_app()

6.2註冊用例

開始註冊用例代碼邏輯的實現。

test_register.py

參考代碼
# coding=utf-8
# 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行

# 2.註釋:包括記錄創建時間,創建人,項目名稱。
'''
Created on 2019-11-20
@author: 北京-宏哥   QQ交流群:707699217
Project:Appium自動化測試框架綜合實踐 - 代碼實現
'''
# 3.導入模塊
from kyb_testProject.common.myunit import StartEnd
from kyb_testProject.businessView.registerView import RegisterView
import logging,random,unittest

class RegisterTest(StartEnd):
    def test_user_register(self):
        logging.info('======test_user_register======')
        r=RegisterView(self.driver)

        username = 'bjhg2019' + 'fly' + str(random.randint(1000, 9000))
        password = 'bjhg2020' + str(random.randint(1000, 9000))
        email = 'bjhg' + str(random.randint(1000, 9000)) + '@163.com'

        self.assertTrue(r.register_action(username,password,email))

if __name__ == '__main__':
    unittest.main()

6.3登錄用例

開始登錄用例代碼邏輯的實現。

test_login.py

參考代碼
# coding=utf-8
# 1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行

# 2.註釋:包括記錄創建時間,創建人,項目名稱。
'''
Created on 2019-11-13
@author: 北京-宏哥   QQ交流群:707699217
Project:Appium自動化測試框架綜合實踐 - 代碼實現
'''
# 3.導入模塊
from kyb_testProject.common.myunit import StartEnd
from kyb_testProject.businessView.loginView import LoginView
import unittest
import logging

class TestLogin(StartEnd):
    csv_file='../data/account.csv'

    @unittest.skip('test_login_zxw2018')
    def test_login_zxw2018(self):
        logging.info('======test_login_zxw2018=====')
        l=LoginView(self.driver)
        data=l.get_csv_data(self.csv_file,2)

        l.login_action(data[0],data[1])
        self.assertTrue(l.check_loginStatus())

    # @unittest.skip('skip test_login_zxw2017')
    def test_login_zxw2017(self):
        logging.info('======test_login_zxw2017=====')
        l=LoginView(self.driver)
        data = l.get_csv_data(self.csv_file, 1)

        l.login_action(data[0], data[1])
        self.assertTrue(l.check_loginStatus())

    @unittest.skip('test_login_error')
    def test_login_error(self):
        logging.info('======test_login_error=====')
        l = LoginView(self.driver)
        data = l.get_csv_data(self.csv_file, 3)

        l.login_action(data[0], data[1])
        self.assertTrue(l.check_loginStatus(),msg='login fail!')

if __name__ == '__main__':
    unittest.main()

7.小結

到此,Appium自動化測試框架就差下一篇就全部完成了,聰明的你都懂了嗎???嘿嘿!慢慢地來吧。

下節預告

下一篇,講解執行測試用例,生成測試報告,以及自動化平台,請關注宏哥,敬請期待!!!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

一文帶你深入了解 Redis 的持久化方式及其原理

Redis 提供了兩種持久化方式,一種是基於快照形式的 RDB,另一種是基於日誌形式的 AOF,每種方式都有自己的優缺點,本文將介紹 Redis 這兩種持久化方式,希望閱讀本文後你對 Redis 的這兩種方式有更加全面、清晰的認識。

RDB 快照方式持久化

先從 RDB 快照方式聊起,RDB 是 Redis 默認開啟的持久化方式,並不需要我們單獨開啟,先來看看跟 RDB 相關的配置信息:

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#   save ""
# 自動生成快照的觸發機制 中間的是時間,單位秒,後面的是變更數據 60 秒變更 10000 條數據則自動生成快照
save 900 1
save 300 10
save 60 10000

# 生成快照失敗時,主線程是否停止寫入
stop-writes-on-bgsave-error yes

# 是否採用壓縮算法存儲
rdbcompression yes

# 數據恢復時是否檢測 RDB文件有效性
rdbchecksum yes

# The filename where to dump the DB
# RDB 快照生成的文件名稱
dbfilename dump.rdb

# 快照生成的路徑 AOF 也是存放在這個路徑下面
dir .

關於 RDB 相關配置信息不多,需要我們調整的就更少了,我們只需要根據自己的業務量修改生成快照的機制和文件存放路徑即可。

RDB 有兩種持久化方式:手動觸發自動觸發手動觸發使用以下兩個命令:

  • save:會阻塞當前 Redis 服務器響應其他命令,直到 RDB 快照生成完成為止,對於內存 比較大的實例會造成長時間阻塞,所以線上環境不建議使用

  • bgsave:Redis 主進程會 fork 一個子進程,RDB 快照生成有子進程來負責,完成之後,子進程自動結束,bgsave 只會在 fork 子進程的時候短暫的阻塞,這個過程是非常短的,所以推薦使用該命令來手動觸發

除了執行命令手動觸發之外,Redis 內部還存在自動觸發 RDB 的持久化機制,在以下幾種情況下 Redis 會自動觸發 RDB 持久化

  • 在配置中配置了 save 相關配置信息,如我們上面配置文件中的 save 60 10000 ,也可以把它歸類為“save m n”格式的配置,表示 m 秒內數據集存在 n 次修改時,會自動觸發 bgsave。

  • 在主從情況下,如果從節點執行全量複製操作,主節點自動執行 bgsave 生成 RDB 文件併發送給從節點

  • 執行 debug reload 命令重新加載 Redis 時,也會自動觸發 save 操作

  • 默認情況下執行 shutdown 命令時,如果沒有開啟 AOF 持久化功能則自動執行 bgsave

上面就是 RDB 持久化的方式,可以看出 save 命令使用的比較少,大多數情況下使用的都是 bgsave 命令,所以這個 bgsave 命令還是有一些東西,那接下來我們就一起看看 bgsave 背後的原理,先從流程圖開始入手:

bgsave 命令大概有以下幾個步驟:

  • 1、執行 bgsave 命令,Redis 主進程判斷當前是否存在正在執行的 RDB/AOF 子進程,如果存在, bgsave 命令直接返回不在往下執行。
  • 2、父進程執行 fork 操作創建子進程,fork 操作過程中父進程會阻塞,fork 完成後父進程將不在阻塞可以接受其他命令。
  • 3、子進程創建新的 RDB 文件,基於父進程當前內存數據生成臨時快照文件,完成後用新的 RDB 文件替換原有的 RDB 文件,並且給父進程發送 RDB 快照生成完畢通知

上面就是 bgsave 命令背後的一些內容,RDB 的內容就差不多了,我們一起來總結 RDB 持久化的優缺點,RDB 方式的優點

  • RDB 快照是某一時刻 Redis 節點內存數據,非常適合做備份,上傳到遠程服務器或者文件系統中,用於容災備份
  • 數據恢復時 RDB 要遠遠快於 AOF

有優點同樣存在缺點,RDB 的缺點有

  • RDB 持久化方式數據沒辦法做到實時持久化/秒級持久化。我們已經知道了 bgsave 命令每次運行都要執行 fork 操作創建子進程,屬於重量級操作,頻繁執行成本過高。
  • RDB 文件使用特定二進制格式保存,Redis 版本演進過程中有多個格式 的 RDB 版本,存在老版本 Redis 服務無法兼容新版 RDB 格式的問題

如果我們對數據要求比較高,每一秒的數據都不能丟,RDB 持久化方式肯定是不能夠滿足要求的,那 Redis 有沒有辦法滿足呢,答案是有的,那就是接下來的 AOF 持久化方式

AOF 持久化方式

Redis 默認並沒有開啟 AOF 持久化方式,需要我們自行開啟,在 redis.conf 配置文件中將 appendonly no 調整為 appendonly yes,這樣就開啟了 AOF 持久化,與 RDB 不同的是 AOF 是以記錄操作命令的形式來持久化數據的,我們可以查看以下 AOF 的持久化文件 appendonly.aof

*2
$6
SELECT
$1
0
*3
$3
set
$6
mykey1
$6
你好
*3
$3
set
$4
key2
$5
hello
*1
$8

大概就是長這樣的,具體的你可以查看你 Redis 服務器上的 appendonly.aof 配置文件,這也意味着我們可以在 appendonly.aof 文件中國修改值,等 Redis 重啟時將會加載修改之後的值。看似一些簡單的操作命令,其實從命令到 appendonly.aof 這個過程中非常有學問的,下面時 AOF 持久化流程圖:

在 AOF 持久化過程中有兩個非常重要的操作:一個是將操作命令追加到 AOF_BUF 緩存區,另一個是 AOF_buf 緩存區數據同步到 AOF 文件,接下來我們詳細聊一聊這兩個操作:

1、為什麼要將命令寫入到 aof_buf 緩存區而不是直接寫入到 aof 文件?

我們知道 Redis 是單線程響應,如果每次寫入 AOF 命令都直接追加到磁盤上的 AOF 文件中,這樣頻繁的 IO 開銷,Redis 的性能就完成取決於你的機器硬件了,為了提升 Redis 的響應效率就添加了一層 aof_buf 緩存層, 利用的是操作系統的 cache 技術,這樣就提升了 Redis 的性能,雖然這樣性能是解決了,但是同時也引入了一個問題,aof_buf 緩存區數據如何同步到 AOF 文件呢?由誰同步呢?這就是我們接下來要聊的一個操作:fsync 操作

2、aof_buf 緩存區數據如何同步到 aof 文件中?

aof_buf 緩存區數據寫入到 aof 文件是有 linux 系統去完成的,由於 Linux 系統調度機制周期比較長,如果系統故障宕機了,意味着一個周期內的數據將全部丟失,這不是我們想要的,所以 Linux 提供了一個 fsync 命令,fsync 是針對單個文件操作(比如這裏的 AOF 文件),做強制硬盤同步,fsync 將阻塞直到寫入硬盤完成后返回,保證了數據持久化,正是由於有這個命令,所以 redis 提供了配置項讓我們自行決定何時進行磁盤同步,redis 在 redis.conf 中提供了appendfsync 配置項,有如下三個選項:

# appendfsync always
appendfsync everysec
# appendfsync no
  • always:每次有寫入命令都進行緩存區與磁盤數據同步,這樣保證不會有數據丟失,但是這樣會導致 redis 的吞吐量大大下降,下降到每秒只能支持幾百的 TPS ,這違背了 redis 的設計,所以不推薦使用這種方式
  • everysec:這是 redis 默認的同步機制,雖然每秒同步一次數據,看上去時間也很快的,但是它對 redis 的吞吐量沒有任何影響,每秒同步一次的話意味着最壞的情況下我們只會丟失 1 秒的數據, 推薦使用這種同步機制,兼顧性能和數據安全
  • no:不做任何處理,緩存區與 aof 文件同步交給系統去調度,操作系統同步調度的周期不固定,最長會有 30 秒的間隔,這樣出故障了就會丟失比較多的數據。

這就是三種磁盤同步策略,但是你有沒有注意到一個問題,AOF 文件都是追加的,隨着服務器的運行 AOF 文件會越來越大,體積過大的 AOF 文件對 redis 服務器甚至是主機都會有影響,而且在 Redis 重啟時加載過大的 AOF 文件需要過多的時間,這些都是不友好的,那 Redis 是如何解決這個問題的呢?Redis 引入了重寫機制來解決 AOF 文件過大的問題。

3、Redis 是如何進行 AOF 文件重寫的?

Redis AOF 文件重寫是把 Redis 進程內的數據轉化為寫命令同步到新 AOF 文件的過程,重寫之後的 AOF 文件會比舊的 AOF 文件占更小的體積,這是由以下幾個原因導致的:

  • 進程內已經超時的數據不再寫入文件
  • 舊的 AOF 文件含有無效命令,如 del key1、hdel key2、srem keys、set a111、set a222等。重寫使用進程內數據直接生成,這樣新的AOF文件只保 留最終數據的寫入命令
  • 多條寫命令可以合併為一個,如:lpush list a、lpush list b、lpush list c可以轉化為:lpush list a b c。為了防止單條命令過大造成客戶端緩衝區溢 出,對於 list、set、hash、zset 等類型操作,以 64 個元素為界拆分為多條。

重寫之後的 AOF 文件體積更小了,不但能夠節約磁盤空間,更重要的是在 Redis 數據恢復時,更小體積的 AOF 文件加載時間更短。AOF 文件重寫跟 RDB 持久化一樣分為手動觸發自動觸發,手動觸發直接調用 bgrewriteaof 命令就好了,我們後面會詳細聊一聊這個命令,自動觸發就需要我們在 redis.conf 中修改以下幾個配置

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage:代表當前 AOF文件空間 (aof_current_size)和上一次重寫后 AOF 文件空間(aof_base_size)的比值,默認是 100%,也就是一樣大的時候
  • auto-aof-rewrite-min-size:表示運行 AOF 重寫時 AOF 文件最小體積,默認為 64MB,也就是說 AOF 文件最小為 64MB 才有可能觸發重寫

滿足了這兩個條件,Redis 就會自動觸發 AOF 文件重寫,AOF 文件重寫的細節跟 RDB 持久化生成快照有點類似,下面是 AOF 文件重寫流程圖:

AOF 文件重寫也是交給子進程來完成,跟 RDB 生成快照很像,AOF 文件重寫在重寫期間建立了一個 aof_rewrite_buf 緩存區來保存重寫期間主進程響應的命令,等新的 AOF 文件重寫完成后,將這部分文件同步到新的 AOF 文件中,最後用新的 AOF 文件替換掉舊的 AOF 文件。需要注意的是在重寫期間,舊的 AOF 文件依然會進行磁盤同步,這樣做的目的是防止重寫失敗導致數據丟失,

Redis 持久化數據恢復

我們知道 Redis 是基於內存的,所有的數據都存放在內存中,由於機器宕機或者其他因素重啟了就會導致我們的數據全部丟失,這也就是要做持久化的原因,當服務器重啟時,Redis 會從持久化文件中加載數據,這樣我們的數據就恢復到了重啟前的數據,在數據恢復這一塊Redis 是如何實現的?我們先來看看數據恢復的流程圖:

Redis 的數據恢複流程比較簡單,優先恢復的是 AOF 文件,如果 AOF 文件不存在時則嘗試加載 RDB 文件,為什麼 RDB 的恢復速度比 AOF 文件快,但是還是會優先加載 AOF 文件呢?我個人認為是 AOF 文件數據更全面並且 AOF 兼容性比 RDB 強,需要注意的是當存在 RDB/AOF 時,如果數據加載不成功,Redis 服務啟動會失敗。

最後

目前互聯網上很多大佬都有 Redis 系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。

歡迎掃碼關注微信公眾號:「平頭哥的技術博文」,和平頭哥一起學習,一起進步。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包”嚨底家”

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

小三通海運與一般國際貿易有何不同?

小三通快遞通關作業有哪些?

男人的日常穿搭,展現自身氣質!

男生的日常穿搭,穿出男人魅力,展現自身氣質。看看吧。

白色加藍色易給人純凈清爽的感覺,藍色越深看上去越高冷,黑色加藍色有收斂厚重的感覺,整個的穿搭非常的沉穩,非常的時尚。

整體色調略微偏暗,軍綠、墨綠、淺綠都ok顯得人沉穩,選擇一些淺色基礎色配飾提亮整體效果,給人的感覺非常的乾淨整潔。

白加軍綠也不錯,但綠色看上去比白色重。一般建議白色在裏面,綠色在外面,內淺外深,非常的顯得人乾淨,給人的感覺非常的好。

灰色搭配藍色一般容易顯得臟,在搭配的時候建議灰藍兩色亮一點,明度越高看上去越白越亮。非常的顯人的氣質。

本站聲明:網站內容來源於http://www.shelive.net/,如有侵權,請聯繫我們,我們將及時處理

【精選推薦文章】

※聽過「電子菸」嗎?想知道與一般傳統香菸有何不同嗎?

電子煙能幫助戒菸嗎?專家學者以健康觀點帶您來了解 !

※新手該如何選擇電子菸口味及濃度呢?

※你應該要知道的電子煙懶人包!

電子煙有爭議?真相解密

※全台最大電子煙交易平台?

新政落地 北京鄉村民宿將走出“灰色地帶”

原標題:新政落地 北京鄉村民宿將走出“灰色地帶”

  北京鄉村民宿將告別野蠻生長,邁上合規之路。12月26日,北京市文旅局會同有關部門聯合印發了《關於促進鄉村民宿發展的指導意見》(以下簡稱《意見》),重點解決了鄉村民宿經營合法性問題,並彌補了審批監管短板,讓曾經因無規可依、證照難辦而遊走於灰色地帶的鄉村民宿可以拿到合法“身份證”。業內專家指出,新意見的出台,不僅給鄉村民宿的投資者吃了一顆“定心丸”,更將提升北京鄉村民宿的品質,是北京刺激京郊遊消費的又一重要舉措。

  可拿到合法身份

  新政的出台,讓鄉村民宿踏上合規之路。《意見》指出,鄉村民宿經營者需依法辦理“一照、兩證、一系統”,即營業執照、公共場所衛生許可證、食品經營許可證(如經營餐飲),安裝使用公安機關的信息採集系統,同時落實遊客住宿登記等安全管理制度,有效解決了絕大多數鄉村民宿面臨的住宿經營合法性問題。

  不僅如此,該《意見》還對鄉村民宿的經營主體、經營用房、生態環境、公共安全、從業人員、規範經營等有關事項做了明確規定。其中提到,鄉村民宿經營主體包括個體工商戶、农民專業合作社、農村集體經濟組織和企業法人,同時鼓勵有條件的農戶利用自有宅基地和农民房屋經營鄉村民宿。在經營規模方面,鄉村民宿的單體經營規模為經營用客房數不超過14間(套),建築面積不超過800平方米。對於鄉村民宿的發展規劃,該《意見》還指出,到2022年,實現北京市鄉村民宿從規模到質量的全面提升,力爭在全市推出一批鄉村精品民宿。

  “《意見》落地,對於北京鄉村民宿來說具有划時代的意義,不僅讓北京的鄉村民宿有了‘合法身份’,還對京郊住宿的品質化發展起到了推動作用。”中國旅遊協會民宿客棧與精品酒店分會會長張曉軍在接受北京商報記者採訪時表示。

  曾歷經野蠻生長

  近年來,由於京郊遊的走熱,北京鄉村民宿數量也呈現爆髮式增長,但沒有規矩難成方圓,業界對於主管部門出台指導監管政策的呼聲越來越高。

  北京市文旅局統計數據显示,僅今年“十一”當天,北京郊區民俗游就累計接待遊客50.7萬人次,營業收入達4381.4萬元。而大量的遊客也讓鄉村民宿接待爆棚。有民宿經營者表示,由於京郊遊需求不斷增加,近年來懷柔、密雲、延慶、門頭溝等區湧現大批民宿,但經營規模和水平參差不齊。

  上述經營者還表示,有些民宿僅僅是農家樂的升級版,僅有兩三間房,有些民宿則大一些,達到十幾間房。此外,在床品、衛生等方面,各家所對照的標準也不一樣。

  不僅如此,《意見》出台之前,還有鄉村民宿投資者對該行業表示出了顧慮。一位不願具名的民宿投資者就坦言,由於缺乏相應的經營資質,以及對農村土地性質能否做民宿並不了解,因此對於鄉村民宿的投資一直感到擔憂。此前,有些地方就曾出現過在民宿業發展火熱之時被一紙文件叫停的狀況。還有一些民宿剛剛開始產生盈利就被關停了,面對種種風險和隱憂,該行業急需相關法律法規作為保障。此次《意見》的出台,也算是給北京鄉村民宿投資者釋疑解惑。

  此外,房山區文旅局副局長高峰還坦言,此前一些民宿經營者對於土地、環保、消防等方面感到困惑,隨着《意見》的出台,這些困惑都有望被解決,以房山為例,接下來還將成立鄉村民宿管理小組,進一步整合資源,並出台鼓勵辦法。

  將出台配套政策

  《意見》出台之後,邁上合規之路的鄉村民宿將步入提質階段。北京旅遊學會會長安金明認為,北京現已有眾多鄉村民宿,此次《意見》除了給新涉足的民宿“立規矩”,更面向存量市場,將對提升品質方面起到積極的作用。

  公開數據显示,截至目前,北京13個涉農區共有特色旅遊業態710家,精品民宿500餘家,星級民俗旅遊戶5595戶,星級民俗旅遊村263個,農業觀光園1216個,特色旅遊村鎮100個。而《意見》實施后,未來有關部門將對鄉村民宿採取審核的方式,對審核合格的民宿將發放執照。

  不過,新《意見》出台之後也依然有問題尚待解決。業內人士指出,經營住宿行業需要落實遊客住宿登記等安全管理制度,同時對於消防安全等方面需要達到准入調整,這就需要公安、消防、工商等聯合辦公,目前還沒有具體的細則,未來這些方面都有待補齊。

  張曉軍還談到,在《意見》出台後,下一步關於北京鄉村民宿的地方標準也將出台,對民宿發展起到進一步的規範作用。據了解,目前北京已經湧現出古北水鎮、樂多港、世園人家、山楂小院、長城公社等一批新興旅遊品牌,在鄉村民宿領域,也湧現出了首旅寒舍、唐鄉等一批連鎖化發展的精品民宿品牌,可見,京郊旅遊正在向品質化發展。

  此外,張曉軍還建言,對於北京鄉村民宿的發展,有關部門應該打出一套組合拳。例如,在不同的地區有不同的發展模式,像一些鄉村民宿發展較好的區域,可以總結經驗,加以推廣,形成首都特有的民宿發展路徑。同時,未來還應該完善鄉村民宿領域的頂層制度設計。 北京商報記者 關子辰

  ・ 相關鏈接 ・

  京郊精品酒店 首次明確四大開發模式

  北京商報訊(記者 肖瑋 實習記者 楊卉)經過“摸着石頭過河”的探索階段后,郊區精品酒店終於迎來了明確的規劃。12月26日,北京市文旅局印發的《京郊精品酒店建設試點工作推進方案》提出,以既有酒店提升模式、老舊設施改造模式、土地入股聯營模式、土地試點入市模式四種開發模式為主,同時組織開展項目投融資推介,引入優質社會資本參與京郊精品酒店試點項目開發建設。預計至2022年,北京市將在部分旅遊重點區分別建設完成1-2個精品酒店試點項目。

  具體來看,《方案》規劃,郊區精品酒店主推的開發模式包括,既有酒店提升模式包含對具備良好基礎的現有酒店進行精品化提升改造;老舊設施改造模式則鼓勵各區利用廢棄工業廠房、倉儲用房等老舊設施改造精品酒店;土地入股聯營模式通過成立鎮(鄉)級土地聯營公司(股份合作社),由聯營公司統籌利用集體經營性建設用地,實現以土地使用權作價入股的方式與社會資本合作;而土地試點入市模式則是以出讓、租賃等方式進行入市交易,定向用於精品酒店項目建設。

  對此,北京皇家驛棧酒店創始人劉少軍表示,在國際市場上,精品酒店已逐漸成為未來酒店業發展的大趨勢,在國內尤其是遊客流動量較大的北京,還有很大的市場空間和發展潛力,“原創的文化設計、個性化的服務、高水平的配套設施,共同組成了一個完整的精品酒店結構,因此未來京郊精品酒店的建設,除了在數額上做增量,酒店設計、文化環境、服務質量,也都是在修建過程中要加大投入的方向。”

(責編:王子侯、孫紅麗)

【其他文章推薦】

實木地板、海島型地板、耐磨地板怎麼挑? 木地板三倍價差的秘密!!

※新屋購入,尋找台中室內設計師?是否可先免費估價丈量?

※挑好磚一點都不難!馬賽克磚挑選眉角小撇步!

※想知道北部最多平價、庫存出清的家具工廠推薦在哪裡?

※分享木質地板DIY自行施工教學影片

泰山家具工廠種類樣式多,平價優惠好選擇!

錢緊!今年6家中小房企上市謀“輸血”

原標題:錢緊!今年6家中小房企上市謀“輸血”

繼2018年之後,2019年也是中小房企的上市大年。據新京報記者統計,截至目前,年內已經有6家房企成功上市,分別為德信中國、銀城國際、中梁控股、天保集團、新力控股、景業名邦。安徽三巽、港龍地產、匯景控股、大唐地產等正排隊上市中,奧山控股、海倫堡地產的上市申請二度失效,萬創國際的第四次上市显示“被拒絕”狀態。

如同陷入資金鏈危機的房企斷臂求生一般,今年赴港上市的中小房企,普遍的認購不足、開盤遇冷、市值低估,堪稱以“割肉”求輸血。在市場下行的當下,藉助IPO打開融資閘門是中小房企求生的主要路徑,通過借新還舊,贏取時間,以期穿越周期。

頻頻遭遇破發、市值被低估

具體看來,今年成功上市或者正在上市的中小房企中,規模小、收入低、負債高、土儲少是大部分房企的特徵,而前期認購不足、募集資金少、資本市場反響一般則是普遍現象。

據新京報記者統計,上市的6家房企中,募集資金最高不過30億港元,最低不超5億港元,僅相當於上市房企資本市場的一次常規融資額度。其中,募集資金最低的是天保集團上市所得款項凈額約為4.17億港元,銀城國際全球發售的股份數目約3.54億股,募集資金凈額位7.705億港元。即便是top30房企的中梁控股,其募集資金也僅有27.73億港元。

招股階段認購不足在今年上市房企中也多有發生。德信中國計劃發售5.32億股股份,其中10%作公開發售,90%為國際配售,招股結果显示,香港部分公開認購不足,最終導致國際配售提升為總計劃的96.8%。銀城國際由於香港公開發售獲認購不足,2094萬股發售股份由香港公開發售重新分配至國際發售。天保集團、新力控股同樣遭遇香港部分認購不足的發售股份重新分配至國際發售。

上市首日股價破發或走勢一般則是資本市場對於內房企的另一種態度。3月6日,銀城國際成功於港交所上市。早間開市后,銀城國際股價破發,報每股2.36港元,較發售價跌0.02港元,跌幅0.84%。11月11日,天保集團在港交所上市,首次掛牌開報2.5港元/股,盤中一度破發,最終以2.57港元/股收盤。

事實上,近幾年,是因估值邏輯、投資者結構等多重因素,香港資本市場對內房股的投資態度甚為謹慎,這使得很多內房股的股價與市值被低估。58安居客房產研究院分院院長張波表示,在融資不利的情況下,不少中小房企將上市視為融資的“救命稻草”,殊不知這“稻草”本身也並非含金量十足,不少企業往往定價偏低,直接影響到實際融資效果。

香港資本市場對內房股估值低,中小房企為何仍義無反顧。在業內人士看來,房地產整體融資渠道收緊、成本高企的大背景下,負債高企的中小房企,通過IPO能夠打開融資通道。

融資閘門開啟

今年下半年以來,房地產融資政策多次被收緊,在銷售去化率下降的情況下,房企的生存處境愈發艱難,連華夏幸福、泰禾集團這樣的品牌房企都能遭遇資金鏈危機,ST銀億、三盛宏業、福晟地產、頤和地產、華業資本等上市中小房企相繼倒下,更何況那些未上市、融資渠道單一的中小房企呢?所承受的資金鏈壓力更大。這也正是內房股在港股資本市場遭遇“冷板凳”,仍有中小房企破釜沉舟上市的主要原因。

以德信中國為例,2015年-2017年,凈資產負債率分別為278.7%、435.2%、275.7%,截至2018年6月30日,凈負債率為192.6%。2015年-2017年,銀城國際的資本負債率分別為141.1%,238.7%,284.9%。截至2018年10月31日,銀城國際的資本負債率達到了380.1%。而銀城國際7.705億港元融資額中,約30%的款項將用於償還借款。

對於top30房企中梁控股來說,還債亦是上市的主要原因。截至2018年底,中梁還有109個信託或資產管理計劃尚未償還,總額達到147億元,占借款總額約54.5%。資金成本超過10%的有88個,其中有74個都在下半年發生,最高的年利率高達18%。中梁控股稱,約31.6%的融資額將用作償還絕大部分的若干現有信託貸款。2016年-2018年新力控股的凈資產負債比率分別為190%、270%、240%,所得款項凈額約30%將用於償還項目發展的部分現有計息借款。

更為主要的是,上市幫助中小房企打開了持續融資的閘口,已經有房企發布融資計劃。今年首個上市的德信中國,目前已經發布了兩筆美元優先票據融資計劃,合共3億美元;銀城國際擬發行1億美元的優先票據;7月份上市的中梁控股,在融資上更具效率,9月份發布兩筆境外融資計劃,共4億美元優先票據。

上市后挑戰重重

上市雖然為房企打開融資閘門,但是後續能否融到資金、融資成本的高低等更考驗房企自身的戰略布局、產品打造、品牌塑造能力。

據了解,去年上市的部分中小房企截至目前仍未發布融資計劃。與此同時,雖然德信中國、銀城國際、中梁控股開啟融資計劃,但是超高的境外融資成本也將增加未來兌付壓力。公告显示,德信中國兩筆美元債票面利率高達12.875%,銀城國際為12.5%,中梁控股兩筆美元債票面利率11.5%,均超過10%,在房企境外融資成本中排在前列。

此外,今年成功上市以及準備上市的多家房企多是偏安一隅的地方房企,其土地布局過於集中在一個區域,雞蛋放在一個籃子里,勢必增加潛在風險。

據招股書显示,截至2018年11月30日,德信中國總土儲達到693.39萬平方米,其中浙江省土儲達到589.87萬平方米,佔比高達85.07%。此外,2018年德信中國共擁有107個處於不同階段的物業項目,其中杭州、溫州、湖州三城占集團總物業項目的67.29%。截至2019年3月31日,新力控股總土地儲備約為1480萬平方米,其中約65.6%的土地儲備集中在南昌和惠州地區。

還有正在排隊上市的三巽集團,當前布局重點依然集中在安徽省,區域房企特徵顯著。據招股書,截至2019年8月31日,總土地儲備420萬平方米中的90.6%仍集中分佈在安徽本省。

在業內人士看來,土地聚焦可以集中優勢做事,但是不免會受到地方調控政策的影響,存在潛在政策風險。

成功上市只是開始,對於中小房企的挑戰仍然很大。隨着龍頭房企強者恆強的馬太效應,中小房企的生存空間不斷被擠壓,地產下行周期,被併購的機會大大增加。

恆大研究院的最新報告指出,龍頭房企槓桿水平最低、短期償債能力好且債務結構合理,發生風險可能性最小,而小房企槓桿水平最高,短期償債壓力最大且高度依賴短期債務,財務穩健性最弱。

本版采寫/新京報記者 段文平

(責編:趙爽、孫紅麗)

【其他文章推薦】

※居家隱形鐵窗安裝施作經驗分享

※分享木質地板DIY自行施工教學影片

※想要打造簡約、淡雅兼且收納空間的小資房,台中室內設計推薦哪一家?

※各項辦公家具採購清單,一次搞定!

※2020辦公家具購買網路推薦平台

※超質感設計!台中系統傢俱推薦

本市今年完成改擴建138所幼兒園

北京第二外國語學院北門外有一處自有房屋,今年,這裏變成了普惠幼兒園,9月已正式開園。“自有房”出租多好,辦普惠幼兒園,不虧嗎?二外校長計金標說:“單純經濟賬雖然不賺錢,但這是件多贏的事兒。這所幼兒園解決了本校教職員工和周邊居民適齡兒童入園難的窘況,同時標志著二外建成了從學前教育到博士后的完整的、多層次人才培養體系。”

二外辦普惠園只是今年本市持續增加學前學位供給行動中的一個縮影。今年年初,“着力緩解‘入園難’問題”被列入重要民生實事任務的頭號工程。市教委數據显示,今年,本市在保存量的基礎上,因地制宜、多措並舉,通過積極利用疏解騰退空間、創新辦園形式、支持國有企事業單位辦園、扶持新建、改建、擴建和以租代建等多種方式,公辦園民辦園並舉,內外挖潛,不斷擴增普惠性學前教育學位資源。截至目前,138所幼兒園完成改擴建,新增學前學位30326個。

新增30326個學前學位

“暖男小‘大夫’耐心地查看病情,建議輸液療效快,但是怕我暈針,開了糖漿緩解。收費窗口的小‘護士’囑咐我要留好白色的底方兒,憑粉色的小票去藥房取葯……整套醫療服務嚴謹專業,十星好評!”北京第二外國語學院幼兒園園長王邈在朋友圈裡描述着孩子們“開辦”的“醫院”,朋友們紛紛點贊。她驕傲地說:“雖然剛開園不久,但我們已經逐漸形成了高校辦園的特色核心課程!”

二外幼兒園規模為9個班,最多可招收270名幼兒。目前,幼兒園裡的小朋友有一半是二外教職工的孩子,還有一半學位惠及了附近5公里以內的居民。“我們還照顧了少量非京籍的適齡幼兒入園。”王邈說,“現在,我們每天都會接到家長諮詢明年入園的電話。”

包括二外幼兒園在內,今年本市已新建、改建和擴建138所幼兒園,124所幼兒園開班招生,新增30326個學前學位。相當於每天,教育部門和各區都要想辦法“挖”出83個新學位。

學前教育經費佔比提高

計金標心裏有本賬:二外幼兒園場地是學校無償提供的。如果按照市場每平方米5元的價格粗算,一年場地使用費接近500萬元。如果加上開園前進行的一系列抗震加固、消防噴淋設施加裝等工程,再算上人力成本等,辦普惠幼兒園絕對是件“費力又費錢”的事兒。“還要承擔‘高風險’,孩子們吃得安全嗎?在教室里會不會磕碰到?這些問題都要考慮周全。”計金標說。

“也有人提出過辦民辦園,但是作為一所市屬高校,我們堅持辦普惠園,保教費每名學生每月750元。”計金標說,“辦幼兒園不是為了盈利,我們希望將辦普惠園變成一件‘多贏’的事兒。幼兒園滿足了教職工子女入園需求。同時,附近居民也能享受到優質的學前教育。對於學校而言,辦園也為今後學校教育品牌建設和推廣提供了條件。”

政府也從政策到資金及時跟進,鼓勵普惠幼兒園建設。市教委介紹,本市普惠性幼兒園將逐漸實現公辦民辦“質量標準統一、價格標準統一、補助標準統一”。所有普惠性幼兒園,不管公辦民辦,只要提供安全的、有質量的教育,都納入生均定額補助、一次性擴學位補助及租金補助範圍,由非普惠性民辦幼兒園轉為普惠性民辦幼兒園的還會給予一次性獎勵。目前,本市學前教育經費佔財政教育經費的比例已經由3%提高到10%。相關負責人說:“給足政策,給足支持,盡全力確保園所轉成普惠性幼兒園后不僅能正常運轉,還能運轉得更好,讓園所踏踏實實地為周邊老百姓提供實實在在的普惠性學前教育服務。”

新增普惠園超百所

今年年初,本市出台《普惠性幼兒園認定與管理辦法》,明確了普惠性幼兒園的認定範圍、申報條件、認定程序、退出機制、保障支持和日常監管要求。辦法明確提出了普惠性幼兒園用於人員經費支出比例占保教費收入和財政生均定額補助收入之和的比例原則上不低於70%,這對提升普惠性幼兒園教師工資待遇,保障園所質量有重要的意義。

市教委介紹,本市還建立了普惠性幼兒園補助項目的進展台賬,督促各區落實相關補助政策。各區按月報送補助推進情況,市級建立累計滾動台賬,並根據進展情況,及時督查解決問題。

數據显示,本市普惠園的數量不斷增加,一年新增超百所。

(責編:許維娜、孫紅麗)

【其他文章推薦】

木地板哪有幾種款式?該如何選購適合的材質呢?

※屬於你的居家品味,家具訂製工廠推薦與心得分享

柚木地板是什麼,其材料規格及適合施作環境?

※想知道更多隱形防盜窗Q&A,都在生活知識王!!

※打造舒適的辦公家具,最新裝潢攻略

台中系統傢俱工廠直營,價格公道不吃虧!