Tesla正式進軍中國 官網接受Model S/Model X預定

特斯拉(Tesla)正式進軍中國市場,Tesla中國官網12月13日已經正式上線,並開放Model S與Model X等兩種車款接受預訂,訂金均為人民幣25 萬元,實際官方售價則尚未公佈。顯示Tesla電動車已獲中國監管部門許可,即將在當地上市。

市場推測,以Model S在美國市場訂價7萬至10萬美元,加上進口車各項稅費,Model S的零售價可能在人民幣60萬至85萬元間,交貨期最早在2014年初。

早在2012年,特斯拉就計劃在北京設立展示中心,並承租約800平方公尺的店面,但目前為止尚未看到正式營運跡象。但由於Tesla在中國當地尚未取得商標使用權,目前中文官方網站是採用tuosule.cn為域名,Tesla與商標所有者的爭奪已進入法律程序。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

三星將進軍電動車市場?已申請多項相關專利

據「華爾街日報」(WSJ)報導,雖然三星集團對WSJ稱,沒有進軍電動車市場的計畫。但三星電子(Samsung Electronics)今年在美國和韓國申請的專利,涵蓋了可用在電動車的零件和技術,這些文件透露出這個財團可能在動擴大營收來源的腦筋。

根據美國專利商標局(U.S. Patent & Trademark Office)和韓國智慧財產權局訊息服務局(Korea Intellectual Property Rights Information Service)公布的專利申請文件,三星遞交的申請文件是電動車會使用的汽車零件製作新技術。三星申請的技術專利包含輪胎、引擎及分享資訊給汽車和駕駛者的車上電子產品。

電動車目前在全球市場的人氣還不高,但這為三星提供了將技術實力發揮在智慧型手機、電視和記憶體以外產品的機會,三星在競爭激烈的電視和行動裝置市場動能已經放慢。

大和證券分析指出,一旦世界進入電動車時代,車廠和電子企業的界線將日益模糊;等到電動車日益普及,三星可輕鬆加入獲利。8月公佈的專利案顯示,三星有意結合汽車和醫療科技,依照駕駛的身體情況,讓車輛接手控制。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

EV(電動車)

電動車(Electric vehicle, EV),指使用電動機或牽引電動機推動而在路面上行駛的車輛。存在三種主要類型的電動車輛:第一種是直接從外部電站供電;第二種是最初是從一個外部電源所存儲的電力供電;第三種是採用了車載的發電機,如內燃機(混合動力電動汽車)或氫燃料電池。電動車包括電動汽車,電動火車,電動貨車,電動飛機,電動船,電動摩托車,摩托車和電動飛船。

如果電力來源是電池,而電池的能量來自外部電源,這就是純電動車或電池電動車(BEV);如果電力來自內燃機帶動的發電機,那就是混合動力車(HEV);如果來自太陽能板,那就是太陽能車;如果來自燃料電池,那就是燃料電池車(FCEV)。除內部電源外,也可來自外部電源,例如無軌電車。

豐田普銳斯(Toyota Prius),首款量產的油電混合動力車,於2001年在全球範圍內被引入。截至2013年3月,一共有三個世代的293萬豐田普銳斯汽車已銷往世界各地,它是世界上最暢銷的油電混合動力車。

截止2013年5月,日產聆風(Nissan Leaf)通過在全球範圍內銷售超過了65,000台,它是在歷史上和在世界上最暢銷的具有高速公路功能的純電動車。

截至2013年6月,一些純電動車已經在一些國家大量生產,包括REVAi, Buddy, Mitsubishi i MiEV, 奇瑞QQ3 EV, JAC J3 EV, Nissan Leaf, Smart ED, Wheego Whip LiFe, Mia electric, 比亞迪e6, Bolloré Bluecar, Renault Fluence Z.E., Ford Focus Electric, BMW ActiveE, Tesla Model S, Honda Fit EV, RAV4 EV second generation, Renault Zoe, Roewe E50, Mahindra e2o, 和Chevrolet Spark EV。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

HEV(混合動力車輛)

混合動力車輛(Hybrid electric vehicle, HEV)),是使用兩種或以上能源的車輛,所使用的動力來源有:內燃機、電動機、電池、氫氣、燃料電池等的技術。

多數油電混合動力車使用汽油,雖然消耗汽油較少,但是加速表現卻較佳,被視為比普通由內燃引擎發動車輛較為環保的選擇。近年有的可以從輸電網絡上向內部電池充電,叫插電式混合動力汽車(Plug-in hybrid, PHEV)。

原理

絕大多數的混合動力車的推動裝置不外乎內燃機或電動機,若當中有使用電力推動電動機作為其中一種推動裝置者即可以用電池進行再生制動,把能量回收,以節省能源,現在較普遍使用的油電混合動力車就屬於這一類。油電混合動力車或柴電動力車的推動裝置可以是同時擁有電動機及內燃機引擎,也有只使用電動機的設計。

分類方式

以動力來源劃分:
1 油電混合動力 及柴電混合動力
2 燃料電池和電池混合車
3 液壓動力混合系統
4 多重燃料混合動力系統
5 人力混合動力系統

依程度分類(degree of hybridization):
1 輕度混合動力
2 中度混合動力
3 重度混合動力
4 插電式混合動力(PHEV)

依傳動配置分類(drive train structure/power train configurations):
1 並聯式油電混合系統
2 串聯混合動力系統
3 混聯式混合動力系統(動力整合/分配式混合動力系統)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

PHEV(插電式混合動力汽車)

插電式混合動力汽車(Plug-in hybrid electric vehicle, PHEV)的是一種混合動力車輛。其充電電池可以使用外部電源充電,而電池容量比電動車小、但大多大於普通油電混合動力車。

插電式混合動力車輛是針對通勤族設計的,多數通勤族通勤距離在十幾公里內,插電式混合動力車輛的電池續航力只要有二三十公里即可以滿足多數通勤需求(通勤時不需啟動內燃機)。

在長途駕駛的情況下,既使是續航力數百公里的電動車也可能沒電,此時插電式混合動力車輛則使用內燃機提供能量,方便性與傳統汽柴油車輛相近;引擎運轉模式更接近最高效率的定速運轉,因此也很省油,甚至可以讓轉子引擎、渦輪引擎達到低油耗低污染的目標;有些車輛使用小型引擎、且不使用複雜的傳動系統,可以抵銷電池所增加的重量跟成本。

但混合動力車的缺點,插電式混合動力車輛可能更嚴重,例如鋰礦問題、電池成本、製造電池的環境成本。

發售中的插電式混合動力車輛有:比亞迪F3DM(比亞迪汽車)、雪佛蘭伏特(通用汽車)、普銳斯III PHEV(豐田汽車)等。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

BEV(純電動車)

純電動車(Battery Electric Vehicle, BEV),是指以事前已充滿電的蓄電池供電給電動機,由電動機推動的車輛,而電池的電量由外部電源補充。由於不會在路面排放廢氣,因此不會污染路面的空氣。

原理

純電動車以蓄電池把能量存于車上,相等於一般汽車的油箱,為車輛提供電力給電動機,電動機把電能轉化為動能,推動車輛,結構上非常簡單。

純電動車所使用的電池是蓄電池,在電力用盡後經由車外輸入電源給電池充電。電動機推動車輪的方式可以是像傳統車輛般經差速器傳動到車輪,較新的作法是每個推動輪各自有一個電動機,電動機則直接推動車輪,省減了差速器。

電動機通常除用作推動車輛外,在刹車時也充作再生制動系統的能量轉換器,把車輛的動能回收轉化為電能蓄存放電池中。不同於一般汽車,純電動在停下來時電動機是完全停下,完全不消耗能量。

電池性能決定了純電動車的最大行程、充電時間。電池成本占了整體成本相當大的比重,製造電池的排碳量也占了整個使用週期排碳量相當大部份(43%)。所以電池是純電動車發展的最重要的技術關鍵,重要的電池性能參數有:電池容量、充電時間、電池壽命。

現今純電動車所使用的電池有鎳氫電池(Ni-MH)或鋰離子電池(Li-ion battery),兩種電池都可以回收再用。現在適合並已用於純電動車的鋰電池有磷酸鋰鐵電池及鈦酸鋰電池。

性能

現今的純電動車性能在多方面都相當不錯。跑車方面,Tesla Roadster,加速由0至97公里/小時只需3.9秒,一般房車例如Smart ED0至50km/h是6.5秒,這主要歸功於電動機的性能,但當用在負重較大的用途上時,使用純電動車的還不多,這可能是由於電池的性能及成本所至。在扭力方面是電動機的強項,因此在一般用途扭力不會的是問題。

至於極速,很多純電動車都能達至100km/h以上,像Tesla Roadster一類跑車更達到200km/h以上,而且只需轉一次檔。

由於電動機的扭力輸出穩定,控制也比內燃機容易,純電動車的行駛較暢順,震動及雜訊也較小;也不需如一般汽車那樣需要經常換檔才能確保有足夠動力。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

FB行銷專家,教你從零開始的技巧

Spring如何解決循環依賴?

介紹

先說一下什麼是循環依賴,Spring在初始化A的時候需要注入B,而初始化B的時候需要注入A,在Spring啟動后這2個Bean都要被初始化完成

Spring的循環依賴有兩種場景

  1. 構造器的循環依賴
  2. 屬性的循環依賴

構造器的循環依賴,可以在構造函數中使用@Lazy註解延遲加載。在注入依賴時,先注入代理對象,當首次使用時再創建對象完成注入

屬性的循環依賴主要是通過3個map來解決的

構造器的循環依賴

@Component
public class ConstructorA {

	private ConstructorB constructorB;

	@Autowired
	public ConstructorA(ConstructorB constructorB) {
		this.constructorB = constructorB;
	}
}
@Component
public class ConstructorB {

	private ConstructorA constructorA;

	@Autowired
	public ConstructorB(ConstructorA constructorA) {
		this.constructorA = constructorA;
	}
}
@Configuration
@ComponentScan("com.javashitang.dependency.constructor")
public class ConstructorConfig {
}
public class ConstructorMain {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(ConstructorConfig.class);
		System.out.println(context.getBean(ConstructorA.class));
		System.out.println(context.getBean(ConstructorB.class));
	}
}

運行ConstructorMain的main方法的時候會在第一行就報異常,說明Spring沒辦法初始化所有的Bean,即上面這種形式的循環依賴Spring無法解決。

我們可以在ConstructorA或者ConstructorB構造函數的參數上加上@Lazy註解就可以解決

@Autowired
public ConstructorB(@Lazy ConstructorA constructorA) {
	this.constructorA = constructorA;
}

因為我們主要關注屬性的循環依賴,構造器的循環依賴就不做過多分析了

屬性的循環依賴

先演示一下什麼是屬性的循環依賴

@Component
public class FieldA {

	@Autowired
	private FieldB fieldB;
}
@Component
public class FieldB {

	@Autowired
	private FieldA fieldA;
}
@Configuration
@ComponentScan("com.javashitang.dependency.field")
public class FieldConfig {
}
public class FieldMain {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context =
				new AnnotationConfigApplicationContext(FieldConfig.class);
		// com.javashitang.dependency.field.FieldA@3aa9e816
		System.out.println(context.getBean(FieldA.class));
		// com.javashitang.dependency.field.FieldB@17d99928
		System.out.println(context.getBean(FieldB.class));
	}
}

Spring容器正常啟動,能獲取到FieldA和FieldB這2個Bean

屬性的循環依賴在面試中還是經常被問到的。總體來說也不複雜,但是涉及到Spring Bean的初始化過程,所以感覺比較複雜,我寫個demo演示一下整個過程

Spring的Bean的初始化過程其實比較複雜,為了方便理解Demo,我就把Spring Bean的初始化過程分為2部分

  1. bean的實例化過程,即調用構造函數將對象創建出來
  2. bean的初始化過程,即填充bean的各種屬性

bean初始化過程完畢,則bean就能被正常創建出來了

下面開始寫Demo,ObjectFactory接口用來生產Bean,和Spring中定義的接口一樣

public interface ObjectFactory<T> {
	T getObject();
}
public class DependencyDemo {

	// 初始化完畢的Bean
	private final Map<String, Object> singletonObjects =
			new ConcurrentHashMap<>(256);

	// 正在初始化的Bean對應的工廠,此時對象已經被實例化
	private final Map<String, ObjectFactory<?>> singletonFactories =
			new HashMap<>(16);

	// 存放正在初始化的Bean,對象還沒有被實例化之前就放進來了
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	public  <T> T getBean(Class<T> beanClass) throws Exception {
		// 類名為Bean的名字
		String beanName = beanClass.getSimpleName();
		// 已經初始化好了,或者正在初始化
		Object initObj = getSingleton(beanName, true);
		if (initObj != null) {
			return (T) initObj;
		}
		// bean正在被初始化
		singletonsCurrentlyInCreation.add(beanName);
		// 實例化bean
		Object object = beanClass.getDeclaredConstructor().newInstance();
		singletonFactories.put(beanName, () -> {
			return object;
		});
		// 開始初始化bean,即填充屬性
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			// 獲取需要注入字段的class
			Class<?> fieldClass = field.getType();
			field.set(object, getBean(fieldClass));
		}
		// 初始化完畢
		singletonObjects.put(beanName, object);
		singletonsCurrentlyInCreation.remove(beanName);
		return (T) object;
	}

	/**
	 * allowEarlyReference參數的含義是Spring是否允許循環依賴,默認為true
	 * 所以當allowEarlyReference設置為false的時候,當項目存在循環依賴,會啟動失敗
	 */
	public Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null 
				&& isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory =
							this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
					}
				}
			}
		}
		return singletonObject;
	}

	/**
	 * 判斷bean是否正在被初始化
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

}

測試一波

public static void main(String[] args) throws Exception {
	DependencyDemo dependencyDemo = new DependencyDemo();
	// 假裝掃描出來的對象
	Class[] classes = {A.class, B.class};
	// 假裝項目初始化所有bean
	for (Class aClass : classes) {
		dependencyDemo.getBean(aClass);
	}
	// true
	System.out.println(
			dependencyDemo.getBean(B.class).getA() == dependencyDemo.getBean(A.class));
	// true
	System.out.println(
			dependencyDemo.getBean(A.class).getB() == dependencyDemo.getBean(B.class));
}

是不是很簡單?我們只用了2個map就搞定了Spring的循環依賴

2個Map就能搞定循環依賴,那為什麼Spring要用3個Map呢?

原因其實也很簡單,當我們從singletonFactories中根據BeanName獲取相應的ObjectFactory,然後調用getObject()這個方法返回對應的Bean。在我們的例子中
ObjectFactory的實現很簡單哈,就是將實例化好的對象直接返回,但是在Spring中就沒有這麼簡單了,執行過程比較複雜,為了避免每次拿到ObjectFactory然後調用getObject(),我們直接把ObjectFactory創建的對象緩存起來不就行了,這樣就能提高效率了

比如A依賴B和C,B和C又依賴A,如果不做緩存那麼初始化B和C都會調用A對應的ObjectFactory的getObject()方法。如果做緩存只需要B或者C調用一次即可。

知道了思路,我們把上面的代碼改一波,加個緩存。

public class DependencyDemo {

	// 初始化完畢的Bean
	private final Map<String, Object> singletonObjects =
			new ConcurrentHashMap<>(256);

	// 正在初始化的Bean對應的工廠,此時對象已經被實例化
	private final Map<String, ObjectFactory<?>> singletonFactories =
			new HashMap<>(16);

	// 緩存Bean對應的工廠生產好的Bean
	private final Map<String, Object> earlySingletonObjects =
			new HashMap<>(16);

	// 存放正在初始化的Bean,對象還沒有被實例化之前就放進來了
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	public  <T> T getBean(Class<T> beanClass) throws Exception {
		// 類名為Bean的名字
		String beanName = beanClass.getSimpleName();
		// 已經初始化好了,或者正在初始化
		Object initObj = getSingleton(beanName, true);
		if (initObj != null) {
			return (T) initObj;
		}
		// bean正在被初始化
		singletonsCurrentlyInCreation.add(beanName);
		// 實例化bean
		Object object = beanClass.getDeclaredConstructor().newInstance();
		singletonFactories.put(beanName, () -> {
			return object;
		});
		// 開始初始化bean,即填充屬性
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			// 獲取需要注入字段的class
			Class<?> fieldClass = field.getType();
			field.set(object, getBean(fieldClass));
		}
		singletonObjects.put(beanName, object);
		singletonsCurrentlyInCreation.remove(beanName);
		earlySingletonObjects.remove(beanName);
		return (T) object;
	}

	/**
	 * allowEarlyReference參數的含義是Spring是否允許循環依賴,默認為true
	 */
	public Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null
				&& isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory<?> singletonFactory =
							this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
}

我們寫的getSingleton的實現和org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)的實現一模一樣,這個方法幾乎所有分析Spring循環依賴的文章都會提到,這次你明白工作原理是什麼了把

總結一波

  1. 拿bean的時候先從singletonObjects(一級緩存)中獲取
  2. 如果獲取不到,並且對象正在創建中,就從earlySingletonObjects(二級緩存)中獲取
  3. 如果還是獲取不到就從singletonFactories(三級緩存)中獲取,然後將獲取到的對象放到earlySingletonObjects(二級緩存)中,並且將bean對應的singletonFactories(三級緩存)清除
  4. bean初始化完畢,放到singletonObjects(一級緩存)中,將bean對應的earlySingletonObjects(二級緩存)清除

歡迎關注

參考博客

[1]https://mp.weixin.qq.com/s/gBr3UfC1HRcw4U-ZMmtRaQ
[2]https://mp.weixin.qq.com/s/5mwkgJB7GyLdKDgzijyvXw
比較詳細
[1]https://zhuanlan.zhihu.com/p/84267654
[2]https://juejin.im/post/5c98a7b4f265da60ee12e9b2

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

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

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

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

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

※教你寫出一流的銷售文案?

一起玩轉微服務(10)——spring boot介紹

對於Spring,相信大家都非常熟悉,從出現開始,一直是企業級開發的主流。但是隨着軟件的發展和應用開發的不斷演化,它的一些缺點也逐漸胡暴露了出來,下面,我們就一起看一下Spring的發展歷程並且認識一下Spring Boot。

由來

在Spring 1.x的時候,所有的配置都通過XML,隨着項目的擴大,需要頻繁的在java和XML之間切換。 在Spring 2.x的時候,已經開始逐步替換掉XML配置。在Spring 3.x的時候,已經開始提供java的配置方式,在4.x的時候,已經全部推薦使用java配置的方式。隨着動態語言的流行,java的開發顯得格外的繁瑣,體現在配置的複雜、開發效率低下、部署以及與第三方的集成繁雜,這個時候Spring Boot應運而生。

 

 

 Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化新 Spring 應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。簡化了基於 Spring 的應用開發,通過少量的代碼就能創建一個獨立的、產品級別的 Spring 應用。Spring Boot 為 Spring 平台及第三方庫提供開箱即用的設置,減少與第三方庫集成的複雜度。 Spring Boot 的核心思想就是約定大於配置,多數 Spring Boot 應用只需要很少的 Spring 配置。採用 Spring Boot 可以大大的簡化你的開發模式,所有你想集成的常用框架,它都有對應的組件支持。

 

特性

1.方便地創建獨立的Spring應用,為基於Spring的開發提供更快的入門體驗。2.內置嵌入tomcat,無需生成war文件。3.簡化maven配置。4.自動配置Spring,更快、更方便的與第三方應用整合,比如消息隊列、緩存等在企業級開發中常用的組件。5.提供大型項目中的非功能特性。如:指標、安全、健康檢查及外部配置。6.開箱即用,無需代碼生成,也無需XML配置,同時也能夠通過修改默認值來滿足待定的需求。

四大神器

自動配置

Spring Boot 的自動配置功能可基於類路徑檢測自動為運行中的應用配置依賴關係,不需要提供額外的XML配置。

Starters

Spring Boot 可提供一系列稱為 POM Starters 的精細依賴關係。Spring Boot 熟知如何配置這些依賴關係,同時讓組織能夠擴展 Spring Boot 來配置自定義的依賴關係。

Actuator

Actuator 可提供運行狀況檢查和指標等生產就緒型功能。這些功能通過 Spring Boot 應用內的 REST 終端提供。只需要簡單的配置就可以實現強大的監控和檢查。

開發工具

這些工具旨在縮短開發和測試周期,其中包括一個可在資源變更時觸發瀏覽器刷新的嵌入式 LiveReload 服務器。這些工具還提供了應用自動重啟功能,只要類路徑上的文件發生更改,該功能更即可啟動。重啟技術使用兩種類加載器。未更改的分類(例如來自第三方 JAR 的類)被加載到基礎類加載器,而開發中的分類則被加載到重啟類加載器。當應用重啟時,重啟類加載器會被丟棄,同時創建一個新的類加載器。這種方法意味着應用重啟的速度通常要比“冷啟動”的速度快得多,因為基礎類加載器已準備就緒且已填充完畢。從而快速實現應用的熱部署,對於簡單的修改這種場景能夠非常有效的提高效率。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

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

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

009.OpenShift管理及監控

一 資源限制

1.1 pod資源限制

pod可以包括資源請求和資源限制:

  • 資源請求

用於調度,並控制pod不能在計算資源少於指定數量的情況下運行。調度程序試圖找到一個具有足夠計算資源的節點來滿足pod請求。

  • 資源限制

用於防止pod耗盡節點的所有計算資源,基於pod的節點配置Linux內核cgroups特性,以執行pod的資源限制。

儘管資源請求和資源限制是pod定義的一部分,但通常建議在dc中設置。OpenShift推薦的實踐規定,不應該單獨創建pod,而應該由dc創建。

1.2 應用配額

OCP可以執行跟蹤和限制兩種資源使用的配額:

對象的數量:Kubernetes資源的數量,如pod、service和route。

計算資源:物理或虛擬硬件資源的數量,如CPU、內存和存儲容量。

通過避免master的Etcd數據庫的無限制增長,對Kubernetes資源的數量設置配額有助於OpenShift master服務器的穩定性。對Kubernetes資源設置配額還可以避免耗盡其他有限的軟件資源,比如服務的IP地址。

同樣,對計算資源的數量施加配額可以避免耗盡OpenShift集群中單個節點的計算能力。還避免了一個應用程序使用所有集群容量,從而影響共享集群的其他應用程序。

OpenShift通過使用ResourceQuota對象或簡單的quota來管理對象使用的配額及計算資源。

ResourceQuota對象指定項目的硬資源使用限制。配額的所有屬性都是可選的,這意味着任何不受配額限制的資源都可以無限制地使用。

注意:一個項目可以包含多個ResourceQuota對象,其效果是累積的,但是對於同一個項目,兩個不同的 ResourceQuota 不會試圖限制相同類型的對象或計算資源。

1.3 ResourceQuota限制資源

下錶显示 ResourceQuota 可以限制的主要對象和計算資源:

對象名 描述
pods 總計的pod數量
replicationcontrollers 總計的rc數量
services 總計的service數量
secrets 總計的secret數量
persistentvolumeclaims 總計的pvc數量
cpu 所有容器的CPU使用總量
memory 所有容器的總內存使用
storage 所有容器的磁盤總使用量

Quota屬性可以跟蹤項目中所有pod的資源請求或資源限制。默認情況下,配額屬性跟蹤資源請求。要跟蹤資源限制,可以在計算資源名稱前面加上限制,例如limit.cpu。

示例一:使用YAML語法定義的ResourceQuota資源,它為對象計數和計算資源指定了配額:

  1 $ cat
  2 apiVersion: v1
  3 kind: ResourceQuota
  4 metadata:
  5   name: dev-quota
  6 spec:
  7   hard:
  8     services: "10"
  9     cpu: "1300m"
 10     memory: "1.5Gi"
 11 $ oc create -f dev-quota.yml

示例二:使用oc create quota命令創建:

  1 $ oc create quota dev-quota \
  2 --hard=services=10 \
  3 --hard=cpu=1300m \
  4 --hard=memory=1.5Gi
  5 $ oc get resourcequota				#列出可用的配額
  6 $ oc describe resourcequota NAME		#查看與配額中定義的任何與限制相關的統計信息
  7 $ oc delete resourcequota compute-quota		#按名稱刪除活動配額

提示:若oc describe resourcequota命令不帶參數,只显示項目中所有resourcequota對象的累積限制集,而不显示哪個對象定義了哪個限制。

當在項目中首次創建配額時,項目將限制創建任何可能超出配額約束的新資源的能力,然後重新計算資源使用情況。在創建配額和使用數據統計更新之後,項目接受新內容的創建。當創建新資源時,配額使用量立即增加。當一個資源被刪除時,在下一次對項目的 quota 統計數據進行全面重新計算時,配額使用將減少。

ResourceQuota 應用於整個項目,但許多 OpenShift 過程,例如 build 和 deployment,在項目中創建 pod,可能會失敗,因為啟動它們將超過項目 quota。

如果對項目的修改超過了對象數量的 quota,則服務器將拒絕操作,並向用戶返回錯誤消息。但如果修改超出了計算資源的quota,則操作不會立即失敗。OpenShift 將重試該操作幾次,使管理員有機會增加配額或執行糾正操作,比如上線新節點,擴容節點資源。

注意:如果設置了計算資源的 quota,OpenShift 拒絕創建不指定該計算資源的資源請求或資源限制的pod。

1.3 應用限制範圍

LimitRange資源,也稱為limit,定義了計算資源請求的默認值、最小值和最大值,以及項目中定義的單個pod或單個容器的限制,pod的資源請求或限制是其容器的總和。

要理解limit rang和resource quota之間的區別,limit rang為單個pod定義了有效範圍和默認值,而resource quota僅為項目中所有pod的和定義了最高值。

通常可同時定義項目的限制和配額。

LimitRange資源還可以為image、is或pvc的存儲容量定義默認值、最小值和最大值。如果添加到項目中的資源不提供計算資源請求,那麼它將接受項目的limit ranges提供的默認值。如果新資源提供的計算資源請求或限制小於項目的limit range指定的最小值,則不創建該資源。同樣,如果新資源提供的計算資源請求或限制高於項目的limit range所指定的最大值,則不會創建該資源。

OpenShift 提供的大多數標準 S2I builder image 和 templabe 都沒有指定。要使用受配額限制的 template 和 builder,項目需要包含一個 limit range 對象,該對象為容器資源請求指定默認值。

如下為描述了一些可以由LimitRange對象指定的計算資源。


類型 資源名稱 描述
Container cpu 每個容器允許的最小和最大CPU。
Container memory 每個容器允許的最小和最大內存
Pod cpu 一個pod中所有容器允許的最小和最大CPU
Pod memory 一個pod中所有容器允許的最小和最大內存
Image storage 可以推送到內部倉庫的圖像的最大大小
PVC storage 一個pvc的容量的最小和最大容量

示例一:limit rang的yaml示例:

  1 $ cat dev-limits.yml
  2 apiVersion: "v1"
  3 kind: "LimitRange"
  4 metadata:
  5   name: "dev-limits"
  6 spec:
  7   limits:
  8     - type: "Pod"
  9       max:
 10         cpu: "2"
 11         memory: "1Gi"
 12       min:
 13         cpu: "200m"
 14         memory: "6Mi"
 15     - type: "Container"
 16       default:
 17         cpu: "1"
 18         memory: "512Mi"
 19 $ oc create -f dev-limits.yml
 20 $ oc describe limitranges NAME		#查看項目中強制執行的限制約束
 21 $ oc get limits				#查看項目中強制執行的限制約束
 22 $ oc delete limitranges name		#按名稱刪除活動的限制範圍

提示:OCP 3.9不支持使用oc create命令參數形式創建limit rang。

在項目中創建limit rang之後,將根據項目中的每個limit rang資源評估所有資源創建請求。如果新資源違反由任何limit rang設置的最小或最大約束,則拒絕該資源。如果新資源沒有聲明配置值,且約束支持默認值,則將默認值作為其使用值應用於新資源。

所有資源更新請求也將根據項目中的每個limit rang資源進行評估,如果更新后的資源違反了任何約束,則拒絕更新。

注意:避免將LimitRange設的過高,或ResourceQuota設的過低。違反LimitRange將阻止pod創建,並清晰保存。違反ResourceQuota將阻止pod被調度,狀態轉為pending。

1.4 多項目quota配額

ClusterResourceQuota資源是在集群級別創建的,創建方式類似持久卷,並指定應用於多個項目的資源約束。

可以通過以下兩種方式指定哪些項目受集群資源配額限制:

  • 使用openshift.io/requester標記,定義項目所有者,該所有者的所有項目均應用quota;
  • 使用selector,匹配該selector的項目將應用quota。

示例1:

  1 $ oc create clusterquota user-qa \
  2 --project-annotation-selector openshift.io/requester=qa \
  3 --hard pods=12 \
  4 --hard secrets=20			#為qa用戶擁有的所有項目創建集群資源配額
  5 $ oc create clusterquota env-qa \
  6 --project-label-selector environment=qa \
  7 --hard pods=10 \
  8 --hard services=5			#為所有具有environment=qa標籤的項目創建集群資源配額
  9 $ oc describe QUOTA NAME		#查看應用於當前項目的集群資源配額
 10 $ oc delete clusterquota NAME		#刪除集群資源配額

提示:不建議使用一個集群資源配額來匹配超過100個項目。這是為了避免較大的locking開銷。當創建或更新項目中的資源時,在搜索所有適用的資源配額時鎖定項目需要較大的資源消耗。

二 限制資源使用

2.1 前置準備

準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

2.2 本練習準備

  1 [student@workstation ~]$ lab monitor-limit setup

2.3 查看當前資源

  1 [student@workstation ~]$ oc login -u admin -p redhat https://master.lab.example.com
  2 [student@workstation ~]$ oc describe node node1.lab.example.com | grep -A 4 Allocated
  3 [student@workstation ~]$ oc describe node node2.lab.example.com | grep -A 4 Allocated

2.4 創建應用

  1 [student@workstation ~]$ oc new-project resources
  2 [student@workstation ~]$ oc new-app --name=hello \
  3 --docker-image=registry.lab.example.com/openshift/hello-openshift
  4 [student@workstation ~]$ oc get pod -o wide
  5 NAME            READY     STATUS    RESTARTS   AGE       IP            NODE
  6 hello-1-znk56   1/1       Running   0          24s       10.128.0.16   node1.lab.example.com

2.5 刪除應用

  1 [student@workstation ~]$ oc delete all -l app=hello

2.6 添加資源限制

作為集群管理員,向項目quota和limit range,以便為項目中的pod提供默認資源請求。

  1 [student@workstation ~]$ cd /home/student/DO280/labs/monitor-limit/
  2 [student@workstation monitor-limit]$ cat limits.yml		#創建limit range
  3 apiVersion: "v1"
  4 kind: "LimitRange"
  5 metadata:
  6   name: "project-limits"
  7 spec:
  8   limits:
  9     - type: "Container"
 10       default:
 11         cpu: "250m
 12 [student@workstation monitor-limit]$ oc create -f limits.yml	#創建limit range
 13 [student@workstation monitor-limit]$ oc describe limitrange	#查看limit range

  1 [student@workstation monitor-limit]$ cat quota.yml		#創建配額
  2 apiVersion: v1
  3 kind: ResourceQuota
  4 metadata:
  5   name: project-quota
  6 spec:
  7   hard:
  8     cpu: "900m"
  9 [student@workstation monitor-limit]$ oc create -f quota.yml
 10 [student@workstation monitor-limit]$ oc describe quota		#確保創建了resource限制

2.7 授權項目

  1 [student@workstation monitor-limit]$ oc adm policy add-role-to-user edit developer

2.8 驗證資源限制

  1 [student@workstation ~]$ oc login -u developer -p redhat https://master.lab.example.com
  2 [student@workstation ~]$ oc project resources			#選擇項目
  3 Already on project "resources" on server "https://master.lab.example.com:443".
  4 [student@workstation ~]$ oc get limits				#查看limit
  5 NAME             AGE
  6 project-limits   14m
  7 [student@workstation ~]$ oc delete limits project-limits	#驗證限制是否有效,但developer用戶不能刪除該限制
  8 Error from server (Forbidden): limitranges "project-limits" is forbidden: User "developer" cannot delete limitranges in the namespace "resources": User "developer" cannot delete limitranges in project "resources"
  9 [student@workstation ~]$ oc get quota
 10 NAME            AGE
 11 project-quota   15m

2.9 創建應用

  1 [student@workstation ~]$ oc new-app --name=hello \
  2 --docker-image=registry.lab.example.com/openshift/hello-openshift
  3 [student@workstation ~]$ oc get pod
  4 NAME            READY     STATUS    RESTARTS   AGE
  5 hello-1-t7tfn   1/1       Running   0          35s

2.10 查看quota

  1 [student@workstation ~]$ oc describe quota
  2 Name:       project-quota
  3 Namespace:  resources
  4 Resource    Used  Hard
  5 --------    ----  ----
  6 cpu         250m  900m

2.11 查看節點可用資源

  1 [student@workstation ~]$ oc login -u admin -p redhat \
  2 https://master.lab.example.com
  3 [student@workstation ~]$ oc get pod -o wide -n resources
  4 [student@workstation ~]$ oc describe node node1.lab.example.com | grep -A 4 Allocated
  5 [student@workstation ~]$ oc describe pod hello-1-t7tfn | grep -A2 Requests

2.12 擴容應用

  1 [student@workstation ~]$ oc scale dc hello --replicas=2		#擴容應用
  2 [student@workstation ~]$ oc get pod				#查看擴容后的pod
  3 [student@workstation ~]$ oc describe quota			#查看擴容后的quota情況
  4 [student@workstation ~]$ oc scale dc hello --replicas=4		#繼續擴容至4個
  5 [student@workstation ~]$ oc get pod				#查看擴容的pod
  6 [student@workstation ~]$ oc describe dc hello | grep Replicas	#查看replaces情況

結論:由於超過了配額規定,會提示控制器無法創建第四個pod。

2.13 添加配額請求

  1 [student@workstation ~]$ oc scale dc hello --replicas=1
  2 [student@workstation ~]$ oc get pod
  3 [student@workstation ~]$ oc set resources dc hello --requests=memory=256Mi	#設置資源請求
  4 [student@workstation ~]$ oc get pod
  5 [student@workstation ~]$ oc describe pod hello-2-4jvpw | grep -A 3 Requests
  6 [student@workstation ~]$ oc describe quota					#查看quota

結論:由上可知從項目的配額角度來看,沒有什麼變化。

2.14 增大配額請求

  1 [student@workstation ~]$ oc set resources dc hello --requests=memory=8Gi	#將內存請求增大到超過node最大值
  2 [student@workstation ~]$ oc get pod						#查看pod
  3 [student@workstation ~]$ oc logs hello-3-deploy					#查看log
  4 [student@workstation ~]$ oc status

結論:由於資源請求超過node最大值,最終显示一個警告,說明由於內存不足,無法將pod調度到任何節點。

三 OCP升級

3.1 升級OPENSHIFT

當OCP的新版本發布時,可以升級現有集群,以應用最新的增強功能和bug修復。這包括從以前的次要版本(如從3.7升級到3.9)升級,以及對次要版本(3.7)應用更新。

提示:OCP 3.9包含了Kubernetes 1.8和1.9的特性和補丁的合併。由於主要版本之間的核心架構變化,OpenShift Enterprise 2環境無法升級為OpenShift容器平台3,必須需要重新安裝。

通常,主版本中不同子版本的node是向前和向後兼容的。但是,運行不匹配的版本的時間不應超過升級整個集群所需的時間。此外,不支持使用quick installer將版本3.7升級到3.9。

3.2 升級方式

有兩種方法可以執行OpenShift容器平台集群升級,一種為in-place升級(可以自動升級或手動升級),也可以使用blue-green部署方法進行升級。

in-place升級:使用此方式,集群升級將在單個運行的集群中的所有主機上執行。首先升級master,然後升級node。在node升級開始之前,Pods被遷移到集群中的其他節點。這有助於減少用戶應用程序的停機時間。

注意:對於使用quick和高級安裝方法安裝的集群,可以使用自動in-place方式升級。

當使用高級安裝方法安裝集群時,您可以通過重用它們的庫存文件執行自動化或手動就地升級。

blue-green部署:blue-green部署是一種旨在減少停機時間同時升級環境的方法。在blue-green部署中,相同的環境與一個活動環境一起運行,而另一個環境則被更新。OpenShift升級方法標記了不可調度節點,並將pod調度到可用節點。升級成功后,節點將恢復到可調度狀態。

3.3 執行自動化集群升級

使用高級安裝方法,可以使用Ansible playbook自動化執行OpenShift集群升級過程。用於升級的劇本位於/usr/share/ansible/openshift-ansible/Playbooks/common/openshift-cluster/updates/中。該目錄包含一組用於升級集群的子目錄,例如v3_9。

注意:將集群升級到 OCP 3.9 前,集群必須已經升級到 3.7。集群升級一次不能跨越一個以上的次要版本,因此,如果集群的版本早於3.6,則必須先漸進地升級,例如從3.5升級到3.6,然後從3.6升級到3.7

要執行升級,可以使用ansible-playbook命令運行升級劇本,如使用v3_9 playbook將運行3.7版本的現有OpenShift集群升級到3.9版本。

自動升級主要執行以下任務:

  • 應用最新的配置更改;
  • 保存Etcd數據;
  • 將api從3.7更新到3.8,然後從3.8更新到3.9;
  • 如果存在,將默認路由器從3.7更新到3.9;
  • 如果存在,則將默認倉庫從3.7更新到3.9;
  • 更新默認is和Templates。

注意:在繼續升級之前,確保已經滿足了所有先決條件,否則可能導致升級失敗。

如果使用容器化的GlusterFS,節點將不會從pod中撤離,因為GlusterFS pod作為daemonset的一部分運行。要正確地升級運行容器化GlusterFS的集群,需要:

1:升級master服務器、Etcd和基礎設施服務(route、內部倉庫、日誌記錄和metric)。

2:升級運行應用程序容器的節點。

3:一次升級一個運行GlusterFS的節點。

注意:在升級之前,使用oc adm diagnostics命令驗證集群的健康狀況。這確認節點處於ready狀態,運行預期的啟動版本,並且沒有診斷錯誤或警告。對於離線安裝,使用–network-pod-image=’REGISTRY URL/ IMAGE參數指定要使用的image。

3.4 準備自動升級

下面的過程展示了如何為自動升級準備環境,在執行升級之前,Red Hat建議檢查配置Inventory文件,以確保對Inventory文件進行了手動更新。如果配置沒有修改,則使用默認值覆蓋更改。

  1. 如果這是從OCP 3.7升級到3.9,手動禁用3.7存儲庫,並在每個master節點和node節點上啟用3.8和3.9存儲庫:
  1 [root@demo ~]# subscription-manager repos \
  2 --disable="rhel-7-server-ose-3.7-rpms" \
  3 --enable="rhel-7-server-ose-3.9-rpms" \
  4 --enable="rhel-7-server-ose-3.8-rpms" \
  5 --enable="rhel-7-server-rpms" \
  6 --enable="rhel-7-server-extras-rpms" \
  7 --enable="rhel-7-server-ansible-2.4-rpms" \
  8 --enable="rhel-7-fast-datapath-rpms"
  9 [root@demo ~]# yum clean all

  1. 確保在每個RHEL 7系統上都有最新版本的atom-openshift-utils包,它還更新openshift-ansible-*包。
  1 [root@demo ~]# yum update atomic-openshift-utils
  1. 在OpenShift容器平台的以前版本中,安裝程序默認將master節點標記為不可調度,但是,從OCP 3.9開始,master節點必須標記為可調度的,這是在升級過程中自動完成的。

如果沒有設置默認的節點選擇器(如下配置),它們將在升級過程中添加。則master節點也將被標記為master節點角色。所有其他節點都將標記為compute node角色。

  1 openshift_node_labels="{'region':'infra', 'node-role.kubernetes.io/compute':'true'}
  1. 如果將openshift_disable_swap=false變量添加到的Ansible目錄中,或者在node上手動配置swap,那麼在運行升級之前禁用swap內存。

3.5 升級master節點和node節點

在滿足了先決條件(如準備工作)之後,則可以按照如下步驟進行升級:

  1. 在清單文件中設置openshift_deployment_type=openshift-enterprise變量。
  2. 如果使用自定義Docker倉庫,則必須顯式地將倉庫的地址指定為openshift_web_console_prefix和template_service_broker_prefix變量。這些值由Ansible在升級過程中使用。
  1 openshift_web_console_prefix=registry.demo.example.com/openshift3/ose-
  2 template_service_broker_prefix=registry.demo.example.com/openshift3/ose-

  1. 如果希望重啟service或重啟node,請在Inventory文件中設置openshift_rolling_restart_mode=system選項。如果未設置該選項,則默認值表明升級過程在master節點上執行service重啟,但不重啟系統。
  2. 可以通過運行一個Ansible Playbook (upgrade.yml)來更新環境中的所有節點,也可以通過使用單獨的Playbook分多個階段進行升級。
  3. 重新啟動所有主機,重啟之後,如果沒有部署任何額外的功能,可以驗證升級。

3.6 分階段升級集群

如果決定分多個階段升級環境,根據Ansible Playbook (upgrade_control_plan .yml)確定的第一個階段,升級以下組件:

  1. master節點;
  2. 運行master節點的節點services;
  3. Docker服務位於master節點和任何獨立Etcd主機上。

第二階段由upgrade_nodes.yml playbook,升級了以下組件。在運行此第二階段之前,必須已經升級了master節點。

  1. node節點的服務;
  2. 運行在獨立節點上的Docker服務。

兩個階段的升級過程允許通過指定自定義變量自定義升級的運行方式。例如,要升級總節點的50%,可以運行以下命令:

  1 [root@demo ~]# ansible-playbook \
  2 /usr/share/ansible/openshift-ansible/playbooks/common/openshift-cluster/upgrades/
  3 v3_9/upgrade_nodes.yml \
  4 -e openshift_upgrade_nodes_serial="50%"

若要在HA region一次升級兩個節點,請運行以下命令:

  1 [root@demo ~]# ansible-playbook \
  2 /usr/share/ansible/openshift-ansible/playbooks/common/openshift-cluster/upgrades/
  3 v3_9/upgrade_nodes.yml \
  4 -e openshift_upgrade_nodes_serial="2"
  5 -e openshift_upgrade_nodes_label="region=HA"

要指定每個更新批處理中允許有多少節點失敗,可使用openshift_upgrade_nodes_max_fail_percent選項。當故障百分比超過定義的值時,Ansible將中止升級。

使用openshift_upgrade_nodes_drain_timeout選項指定中止play前等待的時間。

示例:如下所示一次升級10個節點,以及如果20%以上的節點(兩個節點)失敗,以及終止play執行的等待時間。

  1 [root@demo ~]# ansible-playbook \
  2 /usr/share/ansible/openshift-ansible/playbooks/common/openshift-cluster/upgrades/
  3 v3_9/upgrade_nodes.yml \
  4 -e openshift_upgrade_nodes_serial=10 \
  5 -e openshift_upgrade_nodes_max_fail_percentage=20 \
  6 -e openshift_upgrade_nodes_drain_timeout=600

3.7 使用Ansible Hooks

可以通過hook為特定的操作執行定製的任務。hook允許通過定義在升級過程中特定點之前或之後執行的任務來擴展升級過程的默認行為。例如,可以在升級集群時驗證或更新自定義基礎設施組件。

提示:hook沒有任何錯誤處理機制,因此,hook中的任何錯誤都會中斷升級過程。需要修復hook並重新運行升級過程。

使用Inventory文件的[OSEv3:vars]部分來定義hook。每個hook必須指向一個.yaml文件,該文件定義了可能的任務。該文件是作為include語句的一部分集成的,該語句要求定義一組任務,而不是一個劇本。Red Hat建議使用絕對路徑來避免任何歧義。

以下hook可用於定製升級過程:

1. openshift_master_upgrade_pre_hook:hook在更新每個master節點之前運行。

2. openshift_master_upgrade_hook:hook在每個master節點升級之後、主服務或節點重新啟動之前運行。

3.openshift_master_upgrade_post_hook:hook在每個master節點升級並重啟服務或系統之後運行。

示例:在庫存文件中集成一個鈎子。

  1 [OSEv3:vars]
  2 openshift_master_upgrade_pre_hook=/usr/share/custom/pre_master.yml
  3 openshift_master_upgrade_hook=/usr/share/custom/master.yml
  4 openshift_master_upgrade_post_hook=/usr/share/custom/post_master.yml

如上示例,引入了一個pre_master.yml,包括了以下任務:

  1 ---
  2 - name: note the start of a master upgrade
  3 debug:
  4 msg: "Master upgrade of {{ inventory_hostname }} is about to start"
  5 - name: require an operator agree to start an upgrade pause:
  6 prompt: "Hit enter to start the master upgrade"

3.8 驗證升級

升級完成后,應該執行以下步驟以確保升級成功。

  1 [root@demo ~]# oc get nodes		#驗證node處於ready
  2 [root@demo ~]# oc get -n default dc/docker-registry -o json | grep \"image\"
  3 #驗證倉庫版本
  4 [root@demo ~]# oc get -n default dc/router -o json | grep \"image\
  5 #驗證image版本
  6 [root@demo ~]# oc adm diagnostics	#使用診斷工具

3.9 升級步驟匯總

  1. 確保在每個RHEL 7系統上都有atom-openshift-utils包的最新版本。
  2. 如果使用自定義Docker倉庫,可以選擇將倉庫的地址指定為openshift_web_console_prefix和template_service_broker_prefix變量。
  3. 禁用所有節點上的swap。
  4. 重新啟動所有主機,重啟之後,檢查升級。
  5. 可選地:檢查Inventory文件中的節點選擇器。
  6. 禁用3.7存儲庫,並在每個master主機和node節點主機上啟用3.8和3.9存儲庫。
  7. 通過使用合適的Ansible劇本集,使用單個或多個階段策略進行更新。
  8. 在清單文件中設置openshift_deployment_type=openshift-enterprise變量。

四 使用probes監視應用

4.1 OPENSHIFT探針介紹

OpenShift應用程序可能會因為臨時連接丟失、配置錯誤或應用程序錯誤等問題而異常。開發人員可以使用探針來監視他們的應用程序。探針是一種Kubernetes操作,它定期對正在運行的容器執行診斷。可以使用oc客戶端命令或OpenShift web控制台配置探針。

目前,可以使用兩種類型的探測:

  • Liveness探針

Liveness探針確定在容器中運行的應用程序是否處於健康狀態。如果Liveness探針返回檢測到一個不健康的狀態,OpenShift將殺死pod並試圖重新部署它。開發人員可以通過配置template.spec.container.livenessprobe來設置Liveness探針。

  • Readiness探針

Readiness探針確定容器是否準備好為請求服務,如果Readiness探針返回失敗狀態,OpenShift將從所有服務的端點刪除容器的IP地址。開發人員可以使用Readiness探針向OpenShift發出信號,即使容器正在運行,它也不應該從代理接收任何流量。開發人員可以通過配置template.spec.containers.readinessprobe來設置Readiness探針。

OpenShift為探測提供了許多超時選項,有五個選項控制支持如上兩個探針:

initialDelaySeconds:強制性的。確定容器啟動后,在開始探測之前要等待多長時間。

timeoutSeconds:強制性的確定等待探測完成所需的時間。如果超過這個時間,OpenShift容器平台會認為探測失敗。

periodSeconds:可選的,指定檢查的頻率。

successThreshold:可選的,指定探測失敗后被認為成功的最小連續成功數。

failureThreshold:可選的,指定探測器成功后被認為失敗的最小連續故障。

4.2 檢查應用程序健康

Readiness和liveness probes可以通過三種方式檢查應用程序的健康狀況:

HTTP檢查:當使用HTTP檢查時,OpenShift使用一個webhook來確定容器的健康狀況。如果HTTP響應代碼在200到399之間,則認為檢查成功。

示例:演示如何使用HTTP檢查方法實現readiness probe 。

  1 ...
  2 readinessProbe:
  3   httpGet:
  4     path: /health			#檢測的URL
  5     port: 8080				#端口
  6   initialDelaySeconds: 15		#在容器啟動后多久才能檢查其健康狀況
  7   timeoutSeconds: 1			#要等多久探測器才能完成
  8 ...

4.3 容器執行檢查

當使用容器執行檢查時,kubelet agent在容器內執行命令。退出狀態為0的檢查被認為是成功的。

示例:實現容器檢查。

  1 ...
  2 livenessProbe:
  3   exec:
  4     command:
  5     - cat
  6     - /tmp/health
  7   initialDelaySeconds: 15
  8   timeoutSeconds: 1
  9 ...

4.4 TCP Socket檢查

當使用TCP Socket檢查時,kubelet agent嘗試打開容器的socket。如果檢查能夠建立連接,則認為容器是健康的。

示例:使用TCP套接字檢查方法實現活動探測。

  1 ...
  2 livenessProbe:
  3   tcpSocket:
  4     port: 8080
  5   initialDelaySeconds: 15
  6   timeoutSeconds: 1
  7 ...

4.5 使用Web管理probes

開發人員可以使用OpenShift web控制台管理readiness和liveness探針。對於每個部署,探針管理都可以從Actions下拉列表中獲得。

對於每種探針類型,開發人員可以選擇該類型,例如HTTP GET、TCP套接字或命令,併為每種類型指定參數。web控制台還提供了刪除探針的選項。

web控制台還可以用於編輯定義部署配置的YAML文件。在創建探針之後,將一個新條目添加到DC的配置文件中。使用DC編輯器來檢查或編輯探針。實時編輯器允許編輯周期秒、成功閾值和失敗閾值選項。

五 使用探針監視應用程序實驗

5.1 前置準備

準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

5.2 本練習準備

  1 [student@workstation ~]$ lab probes setup

5.3 創建應用

  1 [student@workstation ~]$ oc login -u developer -p redhat \
  2 https://master.lab.example.com
  3 [student@workstation ~]$ oc new-project probes
  4 [student@workstation ~]$ oc new-app --name=probes \
  5 http://services.lab.example.com/node-hello
  6 [student@workstation ~]$ oc status

  1 [student@workstation ~]$ oc get pods -w
  2 NAME             READY     STATUS      RESTARTS   AGE
  3 probes-1-build   0/1       Completed   0          1m
  4 probes-1-nqpwh   1/1       Running     0          12s

5.4 暴露服務

  1 [student@workstation ~]$ oc expose svc probes --hostname=probe.apps.lab.example.com
  2 [student@workstation ~]$ curl http://probe.apps.lab.example.com
  3 Hi! I am running on host -> probes-1-nqpwh

5.5 檢查服務

  1 [student@workstation ~]$ curl http://probe.apps.lab.example.com/health
  2 OK
  3 [student@workstation ~]$ curl http://probe.apps.lab.example.com/ready
  4 READY

5.6 創建readiness探針

使用Web控制台登錄。並創建readiness探針。

Add readiness probe

參考5.5存在的用於檢查健康的鏈接添加probe。

5.7 創建Liveness探針

使用Web控制台登錄。並創建Liveness探針。

參考5.5存在的用於檢查健康,特意使用healtz錯誤的值而不是health創建,從而測試相關報錯。這個錯誤將導致OpenShift認為pod不健康,這將觸發pod的重新部署。

提示:由於探針更新了部署配置,因此更改將觸發一個新的部署。

5.8 確認探測

通過單擊側欄上的Monitoring查看探測的實現。觀察事件面板的實時更新。此時將標記為不健康的條目,這表明liveness探針無法訪問/healtz資源。

view details查看詳情。

[student@workstation ~]$ oc get events –sort-by=’.metadata.creationTimestamp’ | grep ‘probe failed’ #查看probe失敗事件

5.9 修正probe

修正healtz為health。

5.10 再次確認

  1 [student@workstation ~]$ oc get events \
  2 --sort-by='.metadata.creationTimestamp'

#從終端重新運行oc get events命令,此時OpenShift在重新部署DC新版本,以及殺死舊pod。同時將不會有任何關於pod不健康的信息。

六 Web控制台使用

6.1 WEB控制台簡介

OpenShift web控制台是一個可以從web瀏覽器訪問的用戶界面。它是管理和監視應用程序的一種方便的方法。儘管命令行界面可以用於管理應用程序的生命周期,但是web控制台提供了額外的優勢,比如部署、pod、服務和其他資源的狀態,以及

關於系統範圍內事件的信息。

可使用Web查看基礎設施內的重要信息,包括:

  • pod各種狀態;
  • volume的可用性;
  • 通過使用probes獲得應用程序的健康行;

登錄並選擇項目之後,web控制台將提供項目項目的概述。

  1. 項目允許在授權訪問的項目之間切換。
  2. Search Catalog:瀏覽image目錄。
  3. Add to project:向項目添加新的資源和應用程序。可以從文件或現有項目導入資源。
  4. Overview:提供當前項目的高級視圖。它显示service的名稱及其在項目中運行的相關pod。
  5. Applications:提供對部署、pod、服務和路由的訪問。它還提供了對Stateful set的訪問,Kubernetes hat特性為pod提供了一個惟一的標識,用於管理部署的順序。
  6. build:提供對構建和IS的訪問。
  7. Resources:提供對配額管理和各種資源(如角色和端點)的訪問。
  8. Storage:提供對持久卷和存儲請求的訪問。
  9. Monitoring選項卡提供對構建、部署和pod日誌的訪問。它還提供了對項目中各種對象的事件通知的訪問。
  10. Catalog選項卡提供對可用於部署應用程序包的模板的訪問。

6.2 使用HAWKULAR管理指標

Hawkular是一組用於監控環境的開源項目。它由各種組件組成,如Hawkular services、Hawkular Application Performance Management (APM)和Hawkular metrics。Hawkular可以通過Hawkular OpenShift代理在OpenShift集群中收集應用程序指標。通過在OpenShift集群中部署Hawkular,可以訪問各種指標,比如pod使用的內存、cpu數量和網絡使用情況。

在部署了Hawkular代理之後,web控制台可以查看各種pod的圖表了。

6.3 管理Deployments和Pods

·Actions按鈕可用於pod和部署,允許管理各種設置。例如,可以向部署添加存儲或健康檢查(包括準備就緒和活動探測)。該按鈕還允許訪問YAML編輯器,以便通過web控制台實時更新配置。

6.4 管理存儲

web控制台允許訪問存儲管理,可以使用該接口創建卷聲明,以使用向項目公開的卷。注意,該接口不能用於創建持久卷,因為只有管理員才能執行此任務。管理員創建持久性卷之後,可以使用web控制台創建請求。該接口支持使用選擇器和標籤屬性。

定義卷聲明之後,控制台將显示它所使用的持久性卷,這是由管理員定義的。、

七 Web控制台監控指標

7.1 前置準備

準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

同時安裝OpenShift Metrics,參考《008.OpenShift Metric應用》3.1

7.2 本練習準備

  1 [student@workstation ~]$ lab web-console setup

7.3 創建項目

  1 [student@workstation ~]$ oc login -u developer -p redhat \
  2 https://master.lab.example.com
  3 [student@workstation ~]$ oc new-project load
  4 [student@workstation ~]$ oc new-app --name=load http://services.lab.example.com/node-hello

7.4 ·暴露服務

  1 [student@workstation ~]$ oc expose svc load
  2 [student@workstation ~]$ oc get pod
  3 NAME           READY     STATUS    RESTARTS   AGE
  4 load-1-build   1/1       Running   0          48s

7.5 壓力測試

  1 [student@workstation ~]$ sudo yum install httpd-tools
  2 [student@workstation ~]$ ab -n 3000000 -c 20 \
  3 http://load-load.apps.lab.example.com/

7.6 控制台擴容pod

workstation節點上登錄控制填,並擴展應用。

查看概覽頁面,確保有一個pod在運行。單擊部署配置load #1,所显示的第一個圖,它對應於pod使用的內存。並指示pod使用了多少內存,突出显示第二張圖,該圖表示pods使用的cpu數量。突出显示第三個圖,它表示pod的網絡流量。

單擊pod視圖圈旁的向上指向的箭頭,將此應用程序的pod數量增加到兩個。

導航到應用程序→部署以訪問項目的部署

注意右側的Actions按鈕,單擊它並選擇Edit YAML來編輯部署配置。

檢查部署的YAML文件,確保replicas條目的值為2,該值與為該部署運行的pod的數量相匹配。

7.7 查看metric

單擊Metrics選項卡訪問項目的度量,可以看到應用程序的四個圖:使用的內存數量、使用的cpu數量、接收的網絡數據包數量和發送的網絡數據包數量。對於每個圖,有兩個圖,每個圖被分配到一個pod。

7.8 查看web控制監視

在側窗格中,單擊Monitoring以訪問Monitoring頁面。Pods部分下應該有兩個條目,deployment部分下應該有一個條目。

向下滾動以訪問部署,並單擊部署名稱旁邊的箭頭以打開框架。日誌下面應該有三個圖表:一個表示pod使用的內存數量,一個表示pod使用的cpu數量,一個表示pod發送和接收的網絡數據包。

7.9 創建PV

為應用程序創建PVC,此練習環境已經提供了聲明將綁定到的持久卷。

單擊Storage創建持久卷聲明,單擊Create Storage來定義聲明。輸入web-storage作為名稱。選擇Shared Access (RWX)作為訪問模式。輸入1作為大小,並將單元保留為GiB

單擊Create創建持久卷聲明。

7.10 嚮應用程序添加存儲

導航到應用程序——>部署來管理部署,單擊load條目以訪問部署。單擊部署的Actions,然後選擇Add Storage選項。此選項允許將現有的持久卷聲明添加到部署配置的模板中。選擇web-storage作為存儲聲明,輸入/web-storage作為掛載路徑,web-storage作為卷名。

7.11 檢查存儲

從deployment頁面中,單擊由(latest)指示的最新部署。等待兩個副本被標記為活動的。確保卷部分將卷web存儲作為持久卷。從底部的Pods部分中,選擇一個正在運行的Pods。單擊Terminal選項卡打開pod的外殼。

也可在任何一個pod中運行如下命令查看:

八 管理和監控OpenShift

8.1 前置準備

準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

8.2 本練習準備

  1 [student@workstation ~]$ lab review-monitor setup

8.3 創建項目

  1 [student@workstation ~]$ oc login -u developer -p redhat https://master.lab.example.com、
  2 [student@workstation ~]$ oc new-project load-review

8.4 創建limit range

  1 [student@workstation ~]$ oc login -u admin -p redhat
  2 [student@workstation ~]$ oc project load-review
  3 [student@workstation ~]$ cat /home/student/DO280/labs/monitor-review/limits.yml
  4 apiVersion: "v1"
  5 kind: "LimitRange"
  6 metadata:
  7   name: "review-limits"
  8 spec:
  9   limits:
 10     - type: "Container"
 11       max:
 12         memory: "300Mi"
 13       default:
 14         memory: "200Mi"
 15 [student@workstation ~]$ oc create -f /home/student/DO280/labs/monitor-review/limits.yml
 16 [student@workstation ~]$ oc describe limitrange
 17 Name:       review-limits
 18 Namespace:  load-review
 19 Type        Resource  Min  Max    Default Request  Default Limit  Max Limit/Request Ratio
 20 ----        --------  ---  ---    ---------------  -------------  -----------------------
 21 Container   memory    -    300Mi  200Mi            200Mi          -

8.5 創建應用

  1 [student@workstation ~]$ oc login -u developer -p redhat
  2 [student@workstation ~]$ oc new-app --name=load http://services.lab.example.com/node-hello
  3 [student@workstation ~]$ oc get pods
  4 NAME           READY     STATUS      RESTARTS   AGE
  5 load-1-6szhm   1/1       Running     0          6s
  6 load-1-build   0/1       Completed   0          43s
  7 [student@workstation ~]$ oc describe pod load-1-6szhm

8.6 擴大資源請求

  1 [student@workstation ~]$ oc set resources dc load --requests=memory=350M
  2 [student@workstation ~]$ oc get events | grep Warning

結論:請求資源超過limit限制,則會出現如上告警。

  1 [student@workstation ~]$ oc set resources dc load --requests=memory=200Mi

8.7 創建ResourceQuota

  1 [student@workstation ~]$ oc status ; oc get pod

  1 [student@workstation ~]$ oc login -u admin -p redhat
  2 [student@workstation ~]$ cat /home/student/DO280/labs/monitor-review/quotas.yml
  3 apiVersion: "v1"
  4 kind: "LimitRange"
  5 metadata:
  6   name: "review-limits"
  7 spec:
  8   limits:
  9     - type: "Container"
 10       max:
 11         memory: "300Mi"
 12       default:
 13         memory: "200Mi"
 14 [student@workstation ~]$ oc create -f /home/student/DO280/labs/monitor-review/quotas.yml
 15 [student@workstation ~]$ oc describe quota
 16 Name:            review-quotas
 17 Namespace:       load-review
 18 Resource         Used  Hard
 19 --------         ----  ----
 20 requests.memory  200M  600Mi   -

8.8 創建應用

  1 [student@workstation ~]$ oc login -u developer -p redhat
  2 [student@workstation ~]$ oc scale --replicas=4 dc load
  3 [student@workstation ~]$ oc get pods
  4 NAME           READY     STATUS      RESTARTS   AGE
  5 load-1-build   0/1       Completed   0          7m
  6 load-3-577fc   1/1       Running     0          5s
  7 load-3-nnncf   1/1       Running     0          4m
  8 load-3-nps4w   1/1       Running     0          5s
  9 [student@workstation ~]$  oc get events | grep Warning

結論:當前已應用配額規定會阻止創建第四個pod。

  1 [student@workstation ~]$ oc scale --replicas=1 dc load

8.9 暴露服務

  1 [student@workstation ~]$ oc expose svc load --hostname=load-review.apps.lab.example.com

8.10 創建探針

Web控制台創建。

Applications ——> Deployments ——> Actions ——> Edit Health Checks。

9.11 確認驗證

導航到Applications ——> Deployments,選擇應用程序的最新部署。

在Template部分中,找到以下條目:

  1 [student@workstation ~]$ lab review-monitor grade #腳本判斷結果
  2 

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

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

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

架構設計 | 高併發流量削峰,共享資源加鎖機制

本文源碼:GitHub·點這裏 || GitEE·點這裏

一、高併發簡介

在互聯網的業務架構中,高併發是最難處理的業務之一,常見的使用場景:秒殺,搶購,訂票系統;高併發的流程中需要處理的複雜問題非常多,主要涉及下面幾個方面:

  • 流量管理,逐級承接削峰;
  • 網關控制,路由請求,接口熔斷;
  • 併發控制機制,資源加鎖;
  • 分佈式架構,隔離服務和數據庫;

高併發業務核心還是流量控制,控制流量下沉速度,或者控制承接流量的容器大小,多餘的直接溢出,這是相對複雜的流程。其次就是多線程併發下訪問共享資源,該流程需要加鎖機制,避免數據寫出現錯亂情況。

二、秒殺場景

1、預搶購業務

活動未正式開始,先進行活動預約,先把一部分流量收集和控制起來,在真正秒殺的時間點,很多數據可能都已經預處理好了,可以很大程度上削減系統的壓力。有了一定預約流量還可以提前對庫存系統做好準備,一舉兩得。

場景:活動預約,定金預約,高鐵搶票預購。

2、分批搶購

分批搶購和搶購的場景實現的機制是一致的,只是在流量上緩解了很多壓力,秒殺10W件庫存和秒殺100件庫存系統的抗壓不是一個級別。如果秒殺10W件庫存,系統至少承擔多於10W幾倍的流量衝擊,秒殺100件庫存,體系可能承擔幾百或者上千的流量就結束了。下面流量削峰會詳解這裏的策略機制。

場景:分時段多場次搶購,高鐵票分批放出。

3、實時秒殺

最有難度的場景就是準點實時的秒殺活動,假如10點整準時搶1W件商品,在這個時間點前後會湧入高併發的流量,刷新頁面,或者請求搶購的接口,這樣的場景處理起來是最複雜的。

  • 首先系統要承接住流量的湧入;
  • 頁面的不斷刷新要實時加載;
  • 高併發請求的流量控制加鎖等;
  • 服務隔離和數據庫設計的系統保護;

場景:618準點搶購,雙11準點秒殺,電商促銷秒殺。

三、流量削峰

1、Nginx代理

Nginx是一個高性能的HTTP和反向代理web服務器,經常用在集群服務中做統一代理層和負載均衡策略,也可以作為一層流量控制層,提供兩種限流方式,一是控制速率,二是控制併發連接數。

基於漏桶算法,提供限制請求處理速率能力;限制IP的訪問頻率,流量突然增大時,超出的請求將被拒絕;還可以限制併發連接數。

高併發的秒殺場景下,經過Nginx層的各種限制策略,可以控制流量在一個相對穩定的狀態。

2、CDN節點

CDN靜態文件的代理節點,秒殺場景的服務有這樣一個操作特點,活動倒計時開始之前,大量的用戶會不斷的刷新頁面,這時候靜態頁面可以交給CDN層面代理,分擔數據服務接口的壓力。

CDN層面也可以做一層限流,在頁面內置一層策略,假設有10W用戶點擊搶購,可以只放行1W的流量,其他的直接提示活動結束即可,這也是常用的手段之一。

話外之意:平時參与的搶購活動,可能你的請求根本沒有到達數據接口層面,就極速響應商品已搶完,自行意會吧。

3、網關控制

網關層面處理服務接口路由,一些校驗之外,最主要的是可以集成一些策略進入網關,比如經過上述層層的流量控制之後,請求已經接近核心的數據接口,這時在網關層面內置一些策略控制:如果活動是想激活老用戶,網關層面快速判斷用戶屬性,老用戶會放行請求;如果活動的目的是拉新,則放行更多的新用戶。

經過這些層面的控制,剩下的流量已經不多了,後續才真正開始執行搶購的數據操作。

話外之意:如果有10W人參加搶購活動,真正下沉到底層的搶購流量可能就1W,甚至更少,在分散到集群服務中處理。

4、併發熔斷

在分佈式服務的接口中,還有最精細的一層控制,對於一個接口在單位之間內控制請求處理的數量,這個基於接口的響應時間綜合考慮,響應越快,單位時間內的併發量就越高,這裏邏輯不難理解。

言外之意:流量經過層層控制,數據接口層面分擔的壓力已經不大,這時候就是面對秒殺業務中的加鎖問題了。

四、分佈式加鎖

1、悲觀鎖

機制描述

所有請求的線程必須在獲取鎖之後,才能執行數據庫操作,並且基於序列化的模式,沒有獲取鎖的線程處於等待狀態,並且設定重試機制,在單位時間后再次嘗試獲取鎖,或者直接返回。

過程圖解

Redis基礎命令

SETNX:加鎖的思路是,如果key不存在,將key設置為value如果key已存在,則 SETNX 不做任何動作。並且可以給key設置過期時間,過期后其他線程可以繼續嘗試鎖獲取機制。

藉助Redis的該命令模擬鎖的獲取動作。

代碼實現

這裏基於Redis實現的鎖獲取和釋放機制。

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import javax.annotation.Resource;
@Component
public class RedisLock {

    @Resource
    private Jedis jedis ;

    /**
     * 獲取鎖
     */
    public boolean getLock (String key,String value,long expire){
        try {
            String result = jedis.set( key, value, "nx", "ex", expire);
            return result != null;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }

    /**
     * 釋放鎖
     */
    public boolean unLock (String key){
        try {
            Long result = jedis.del(key);
            return result > 0 ;
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null) jedis.close();
        }
        return false ;
    }
}

這裏基於Jedis的API實現,這裏提供一份配置文件。

@Configuration
public class RedisConfig {

    @Bean
    public JedisPoolConfig jedisPoolConfig (){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig() ;
        jedisPoolConfig.setMaxIdle(8);
        jedisPoolConfig.setMaxTotal(20);
        return jedisPoolConfig ;
    }

    @Bean
    public JedisPool jedisPool (@Autowired JedisPoolConfig jedisPoolConfig){
        return new JedisPool(jedisPoolConfig,"127.0.0.1",6379) ;
    }

    @Bean
    public Jedis jedis (@Autowired JedisPool jedisPool){
        return jedisPool.getResource() ;
    }
}

問題描述

在實際的系統運行期間可能出現如下情況:線程01獲取鎖之後,進程被掛起,後續該執行的沒有執行,鎖失效后,線程02又獲取鎖,在數據庫更新后,線程01恢復,此時在持有鎖之後的狀態,繼續執行后就會容易導致數據錯亂問題。

這時候就需要引入鎖版本概念的,假設線程01獲取鎖版本1,如果沒有執行,線程02獲取鎖版本2,執行之後,通過鎖版本的比較,線程01的鎖版本過低,數據更新就會失敗。

CREATE TABLE `dl_data_lock` (
	`id` INT (11) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	`inventory` INT (11) DEFAULT '0' COMMENT '庫存量',
	`lock_value` INT (11) NOT NULL DEFAULT '0' COMMENT '鎖版本',
	PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '鎖機製表';

說明:lock_value就是記錄鎖版本,作為控制數據更新的條件。

<update id="updateByLock">
    UPDATE dl_data_lock SET inventory=inventory-1,lock_value=#{lockVersion}
    WHERE id=#{id} AND lock_value &lt;#{lockVersion}
</update>

說明:這裏的更新操作,不但要求線程獲取鎖,還會判斷線程鎖的版本不能低於當前更新記錄中的最新鎖版本。

2、樂觀鎖

機制描述

樂觀鎖大多是基於數據記錄來控制,在更新數據庫的時候,基於前置的查詢條件判斷,如果查詢出來的數據沒有被修改,則更新操作成功,如果前置的查詢結果作為更新的條件不成立,則數據寫失敗。

過程圖解

代碼實現

業務流程,先查詢要更新的記錄,然後把讀取的列,作為更新條件。

@Override
public Boolean updateByInventory(Integer id) {
    DataLockEntity dataLockEntity = dataLockMapper.getById(id);
    if (dataLockEntity != null){
        return dataLockMapper.updateByInventory(id,dataLockEntity.getInventory())>0 ;
    }
    return false ;
}

例如如果要把庫存更新,就把讀取的庫存數據作為更新條件,如果讀取庫存是100,在更新的時候庫存變了,則更新條件自然不能成立。

<update id="updateByInventory">
    UPDATE dl_data_lock SET inventory=inventory-1 WHERE id=#{id} AND inventory=#{inventory}
</update>

五、分佈式服務

1、服務保護

在處理高併發的秒殺場景時,經常出現服務掛掉場景,常見某些APP的營銷頁面,出現活動火爆頁面丟失的提示情況,但是不影響整體應用的運行,這就是服務的隔離和保護機制。

基於分佈式的服務結構可以把高併發的業務服務獨立出來,不會因為秒殺服務掛掉影響整體的服務,導致服務雪崩的場景。

2、數據庫保護

數據庫保護和服務保護是相輔相成的,分佈式服務架構下,服務和數據庫是對應的,理論上秒殺服務對應的就是秒殺數據庫,不會因為秒殺庫掛掉,導致整個數據庫宕機。

六、源代碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

推薦閱讀:《架構設計系列》,蘿蔔青菜,各有所需

序號 標題
00 架構設計:單服務.集群.分佈式,基本區別和聯繫
01 架構設計:分佈式業務系統中,全局ID生成策略
02 架構設計:分佈式系統調度,Zookeeper集群化管理
03 架構設計:接口冪等性原則,防重複提交Token管理
04 架構設計:緩存管理模式,監控和內存回收策略
05 架構設計:異步處理流程,多種實現模式詳解

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

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

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

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案