母象吃下內塞鞭炮食物致死 印度鎖定3嫌調查

摘錄自2020年6月5日中央社報導

度克勒拉省一頭懷孕母象吃下塞有鞭炮的食物重傷死亡,引起克勒拉省長維加揚關注,他今天(5日)推文表示,警方已鎖定3名嫌犯,「正義必將伸張」。

維加揚說,省政府將致力找出人類與野生動物衝突事件增加的原因,氣候變遷可能對當地社區和動物產生不利影響。克勒拉省政府公共關係官方推特也推文說,省森林廳已根據1972年「野生動物(保護)法」立案調查母象吃到鞭炮致死案;這起案件由警方和森林部門組成聯合調查小組。

印度媒體引述目擊者指稱,看到2名男子把自製鞭炮塞入鳳梨中引誘飢餓的母象靠近,母象忍不住誘惑吃下鳳梨,2名男子立即揚長而去。

物種保育
生態保育
生物多樣性
國際新聞
印度
人象衝突
大象

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

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

※推薦台中搬家公司優質服務,可到府估價

西伯利亞2萬噸柴油料外洩 普丁發布緊急狀態要徹查

摘錄自2020年6月4日自由時報報導

俄羅斯西伯利亞的北極圈內傳出嚴重漏油事件,約2萬噸柴油自諾里爾斯克(Norilsk)附近一處發電廠外洩,流入安柏那亞河(Ambarnaya River),經水路污染北極海,恐釀生態浩劫。而有關單位竟在兩天後才通報這起嚴重事故,讓總統普丁在視訊電話上怒飆負責人「難道我們必須從社群媒體上知道這起緊急事故?」同時今日下令進入緊急狀態。

綜合媒體報導,這起事件發生在5月29日,因金屬業巨擘諾里爾斯克鎳公司(Norilsk Nickel)建於永凍土上的發電廠備用油槽支撐架因氣候暖化下沉,導致大量油料外洩,克拉斯諾亞爾斯克邊疆區(Krasnoyarsk)監管單位指出,約有1萬5000噸油料流入附近的安柏那亞河,另外6000噸則滲入土中,官方媒體表示目前污染面積達350平方公里。就油量而言,這是俄國現代史上第二大漏油事件。

世界自然基金會(WWF)俄羅斯分部主管卡尼茲尼可夫(Alexey Knizhnikov)表示,因地理受限,當局很難派出大型艇除污,且安巴爾納亞河流入的湖泊又可透過水路通往生態脆弱的北極海。而俄國漁政單位評估,整條河的生態需要數十年才能恢復。

公害污染
污染治理
國際新聞
俄羅斯
漏油污染

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

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

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

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

南非「宰獅取骨」販賣給中國當藥材 專家擔憂致命病毒傳染

摘錄自2020年06月15日聯合報報導

英國保守黨前副主席邁克爾(Lord Ashcroft)近期推出新書「不公平的遊戲(Unfair Game)」,揭露了南非333個屠宰場,將大量獅子宰殺取骨,之後販賣給商人,以利中國和東南亞將其製作成傳統藥材,對此獸醫表示若獅子因病毒死亡,人類可能會因接觸其骨頭而感染。

根據「每日郵報」「太陽報」報導,中國和東南亞每年推動幾百萬英鎊(約千萬台幣)的獅子骨交易,他們將獅子骨視為傳統藥材,而獅子骨和虎骨也會被用來製作成葡萄酒和小飾品。

不過,邁克爾指出圈養的獅子在極為惡劣的環境中生長,牠們可能會將致命疾病傳播給人類,包括結核病或肉毒桿菌中毒,甚至引發一場大流行,南非普利托利亞的野生動物獸醫彼得(Peter Caldwell)表示肉毒桿菌中毒是一種會攻擊神經系統的疾病,可以通過被感染的骨頭和皮膚傳播給人類,另外布魯氏菌病也會透過獅子骨頭傳播,造成關節炎、心臟發炎、結核病、發燒等細菌感染。

物種保育
生活環境
生態保育
生物多樣性
國際新聞
中國
南非
屠宰場
人畜共通傳染病
蝙蝠與新興傳染病
獅子
公共衛生

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

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

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家公司費用怎麼算?

研究:全球大型瀕危哺乳動物消失 最終原因是人口激增

環境資訊中心外電;姜唯 翻譯;林大利 審校;稿源:ENS

西藏野氂牛(Wild Yak,學名:Bos mutus)、巴塔哥尼亞馬駝鹿(Patagonian Huemul,學名:Hippocamelus bisulcus)、不丹的羚牛(Takin,學名:Budorcas taxicolor)、越南的中南大羚(Saola,學名:Pseudoryx nghetinhensis)等世界各地特殊大型哺乳動物正在悄悄消失。過去的幾十年間,連非洲的三種斑馬和牛羚也大幅度減少。

研究人員指出,造成這些哺乳動物消失的原因不僅僅是疾病和棲息地破碎化、森林砍伐或野生動植物貿易。最終原因是人口激增。

而且,除非人類行為大幅度改變,否則科學家認為,這些哺乳動物未來的族群狀況將永遠回不去了。

西藏野氂牛、巴塔哥尼亞馬駝鹿等世界各地特殊大型哺乳動物正悄悄消失。照片來源:birdcapemay(CC BY-NC-ND 2.0)

科學家分析全球大型哺乳動物角色改變的原因 答案正是人口激增

科學家將這些發現發表在《生態與演化前線(Frontiers in Ecology and Evolution)》期刊上,題目是「破碎的食物網和混亂的未來:面對地球人口不斷成長的現代有蹄類(Disassembled food webs and messy projections: modern ungulate communities in the face of unabating human population growth)」。

研究主要作者、科羅拉多州立大學教授伯傑(Joel Berger)說,是付諸行動的時候了,吹捧過去的保育成就對改善人類的未來沒什麼幫助。

在這項研究中,科學家們分析了導致全球生態系統中哺乳動物角色改變的直接和間接原因,同時也指出生態交互作用的本質如何產生根本性的變化,甚至在未來幾十年內更大規模地發生。

他們研究了巴塔哥尼亞馬駝鹿、不丹的羚牛,北美沙漠的野馬、狼和郊狼的變化,以及大型食肉動物就地滅絕後大生態系統改變的必然性。

科學家認為,隨著人口在陸地上的分布越來越廣,這些改變是現在進行式。

「即使是在喜馬拉雅山脈的偏遠地區,人類入侵帶來流浪狗和野狗,嚴重破壞了高經濟價值和文化象徵意義的野生和圈養物種。」不丹基金會的Wangchuk說。

隨著人口激增,大型哺乳動物數量卻是在遞減。圖為巴塔哥尼亞馬駝鹿。照片來源:Vera & Jean-Christophe(CC BY-SA 2.0)

2020年世界人口已接近80億 地球上的哺乳動物有97%是牲畜和人類

人類定居喜馬拉雅山部分地區還是近年暖化融冰後的事。科學家們還指出全球人口的劇烈變化。1830年,海軍中將羅伯特.斐茲洛伊(Robert Fitzroy)乘著小獵犬號穿越南美洲麥哲倫海峽(Magellan Straits)時,地球人口不到12億。到1970年世界地球日,已超過35億。

僅50年後的今天,世界人口已接近80億,牲畜和人類占了地球哺乳動物生物量高達97%。

研究團隊指出,全世界的食物網已被人類大幅改變無法回頭了,重建過去的條件或恢復曾經由原生種創造的生態功能幾乎是不可能的。例如今日除南極洲外,在每個大陸以及美國70%的州中都有野化的家豬。這些動物影響了魚類、爬行動物、鳥類以及其他小型哺乳動物,甚至植物和土壤。

此外,氣候變遷使海洋暖化,導致海洋藻類增生,漁獲量減少。相對魚類的需求減少,陸地上盜獵野生生物的情況隨之增加。

科學家們還記錄下時尚需求如何增加從蒙古、印度和中國輸出至西方的喀什米爾羊毛,導致更多中亞沙漠牧民飼養山羊。這些山羊與原生物種競爭食物,同時也因當地狗越來越多而身處險境。

這些狗不僅是掠食者,還攜帶疾病,傳染雪豹(Snow Leopard,學名:Panthera uncia)、西藏野驢(Kiang,學名:Equus kiang)和普氏原羚(Przewalski’s gazelle,學名:​​​​​​​Procapra przewalskii)等瀕臨滅絕的物種。

棲息在亞洲中部山區的雪豹。照片來源:Antonio Marín Segovia(CC BY-NC-ND 2.0)

但作者們認為,儘管形勢嚴峻,並非沒有機會挽回。像是在極地,適應寒冷氣候的物種仍是人類重要的文化資產,我們仍然有時間保存僅存的生態。

全世界還有許多保護區,如非洲的塞倫蓋蒂和克魯格國家公園、北美黃石公園和朗格-聖伊利亞斯國家公園暨保護區、玻利維亞麥迪迪國家公園、智利和阿根廷的巴塔哥尼亞冰原、中國長塘自然保護區以及世界最大國家公園東北格陵蘭國家公園。

儘管大型哺乳動物食物網將與過去有所不同、有著不同以往的運作方式,但對於未來的走向還有許多選擇。

作者表示:「現在還不算太晚,我們沒有時間為失去哀悼。必須將生態悲痛化為行動,尊重仍然存在的特殊生物多樣性,並透過保護地球的大片原野地來實現。」

Wildife Suffers Humpty Dumpty Effect as Humans Multiply FORT COLLINS, Colorado, June 9, 2020 (ENS)

Some of the world’s largest, most spectacular and unheralded mammals are silently slipping away – species like Tibetan wild yaks and Patagonia’s huemul, Bhutan’s takin and Vietnam’s saola. Even Africa’s three species of zebras and wildebeest have suffered massive reductions over the last several decades.

The reasons for these losses are more than disease and habitat fragmentation, deforestation or wildlife trade, according to researchers. Ultimately, the cause is rampant human population growth.

And unless human behavior changes in unprecedented ways, these scientists warn that future communities of these mammals will never resemble those of the recent past or even today.

The findings are based on a new study, “Disassembled food webs and messy projections: modern ungulate communities in the face of unabating human population growth,” published June 9 in the journal “Frontiers in Ecology and Evolution.”

Joel Berger, lead author of the study and a professor at Colorado State University, said that the time for action is now, and that touting past conservation achievements does little to better humanity’s future.

In this study, the scientists analyzed direct and indirect disruptions that lead to the changing roles of mammals in global ecosystems and noted how the nature of ecological interactions has changed and will do so, on an even larger scale, in the coming decades.

They looked at what has happened with the huemul in Patagonia, takin in Bhutan, wild horses in deserts, wolves and coyotes in North America, and the inevitability of change in big ecosystems as large carnivores are extirpated.

They said this is happening as the human population increases its footprint on land.

“Even in the remote reaches of the Himalayas, stray and feral dogs, a direct result of human intrusions, wreak havoc on wild and domestic species of high economic value and cultural importance,” said Wangchuk of the Bhutan Foundation.

Humans only recently colonized parts of the Himalayas, areas where ice has receded due to warming temperatures. Yet, the authors also point to human population change at a global scale. In 1830 when Vice-Admiral Robert Fitzroy captained his ship, the Beagle, through the Magellan Straits of South America, fewer than 1.2 billion people inhabited Earth. By Earth Day in 1970, there were more than 3.5 billion.

Today, only 50 years later the world’s population approaches eight billion. Livestock and humans now constitute a staggering 97 percent of the planet’s mammal biomass.

The research team explained that worldwide food webs have become irretrievably altered by humans, with little hope to reconstitute even recent past conditions or to put back the ecological functions once created by native species.

Feral pigs, for instance, exist today on every continent except Antarctica, and in 70 percent of the states in the United States. These animals disrupt fish, reptiles, birds and other small mammals, plants and soils.

In addition, climate change warms the oceans, which in turn foments marine algal blooms, reducing fishery catches. With less demand for fish, a consequent uptick in wildlife poaching on land occurs.

The scientists also documented how an appetite for fashion like cashmere increases imports to the west from Mongolia, India and China, resulting in economic incentives for desert pastoralists to produce more domestic goats in central Asia. These goats compete for food with native species and are in danger due to increasing numbers of dogs in these areas.

The dogs are not only predators but also carry diseases, which jeopardizes endangered species like snow leopards, kiang and Przewalksi’s gazelle.

Berger and the study authors suggest that despite the grim findings, all is not yet lost.

Prospects for ecological integrity and the conservation of unheralded species improve greatly toward the world’s edges where the planet’s cold-adapted species remain important to the human spirit and we still have time to save what we have.

The world has remarkable protected areas including Serengeti and Kruger National Park in Africa, Yellowstone and Wrangell-St. Elias National Park & Preserve in North America, Madidi National Park in Bolivia, the Patagonia Ice Fields of Chile and Argentina, the Chang Tang Nature Reserve in China, and Northeast Greenland National Park, the world’s largest national park.

And although food webs with large mammals will be different from those of the past and operate differently today, there are options to shape the future.

“It is not too late and we simply do not have the luxury of time to mourn what we have lost,” said Lambert. “We need to use our ecological grief to implement action and honor the exceptional biodiversity that remains. This can be done by protecting large tracts of the planet’s wild places.”

※ 全文及圖片詳見:ENS

保育類野生動物
哺乳動物
人口
國際新聞
生態保育
生物多樣性

作者

姜唯

如果有一件事是重要的,如果能為孩子實現一個願望,那就是人類與大自然和諧共存。

林大利

於特有生物研究保育中心服務,小鳥和棲地是主要的研究對象。是龜毛的讀者,認為龜毛是探索世界的美德。

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

【其他文章推薦】

※回頭車貨運收費標準

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

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

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

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

台中搬家公司教你幾個打包小技巧,輕鬆整理裝箱!

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

「殭屍火」來襲? 破紀錄野火再臨北極圈 碳匯恐不保

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

【其他文章推薦】

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

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

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

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

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

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

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

法國擬開採莫三比克天然氣 環團批製造氣候炸彈

摘錄自2020年6月15日中央社報導

法國石油業巨擘道達爾(Total)正在莫三比克發展開採天然氣的大型計畫,環保組織「地球之友」今(15日)指控法國此舉無異是在當地放置一枚「氣候定時炸彈」。

法新社報導,「地球之友」(Friends of the Earth)一份報告名為「產業的意外之財,莫三比克的詛咒:法國把莫三比克推進氣阱」(A windfall for the industry, a curse for the country: France Thrusts Mozambique into the gas trap)。報告指出,2010年代初在莫三比克的北海岸外海水面下發現巨大的天然氣儲量,開採總投資金額將達600億美元。

「地球之友」指控,「法國這項陰謀是代表法國能源產業與銀行家的經濟利益……迫使另個非洲國家仰賴化石燃料」。

這份報告指出,法國正研擬三個天然氣計畫,「釋放出的溫室氣體可能相當於法國一年溫室氣體排放量的7倍,更是莫三比克目前年排放量的49倍」。

能源議題
能源轉型
國際新聞
法國
天然氣
油氣開採

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

※回頭車貨運收費標準

【Spring註解驅動開發】使用@Lazy註解實現懶加載

寫在前面

Spring在啟動時,默認會將單實例bean進行實例化,並加載到Spring容器中。也就是說,單實例bean默認在Spring容器啟動的時候創建對象,並將對象加載到Spring容器中。如果我們需要對某個bean進行延遲加載,我們該如何處理呢?此時,就需要使用到@Lazy註解了。

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

懶加載

懶加載就是Spring容器啟動的時候,先不創建對象,在第一次使用(獲取)bean的時候,創建並使用對象,大家是不是想到了在【設計模式】專題中的單例模式呢?對單例模式不太了解的同學可以猛戳《淺談JAVA設計模式之——單例模式(Singleton)》,也可以查看《設計模式匯總——你需要掌握的23種設計模式都在這兒了!》來系統學習每種設計模式。

非懶加載模式

此時,我們將PersonConfig2類的配置修改成單實例bean,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設置的作用域
 */
@Configuration
public class PersonConfig2 {
    @Bean("person")
    public Person person(){
        System.out.println("給容器中添加Person....");
        return new Person("binghe002", 18);
    }
}

接下來,在SpringBeanTest類中創建testAnnotationConfig5()方法,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器創建完成");
}

運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

給容器中添加Person....
IOC容器創建完成

可以看到,單實例bean在Spring容器啟動的時候就會被創建,並加載到Spring容器中。

懶加載模式

我們在PersonConfig2的person()方法上加上@Lazy註解將Person對象設置為懶加載,如下所示。

package io.mykit.spring.plugins.register.config;

import io.mykit.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試@Scope註解設置的作用域
 */
@Configuration
public class PersonConfig2 {

    @Lazy
    @Bean("person")
    public Person person(){
        System.out.println("給容器中添加Person....");
        return new Person("binghe002", 18);
    }
}

此時,我們再次運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

IOC容器創建完成

可以看到,此時,只是打印出了“IOC容器創建完成”,說明此時,只創建了IOC容器,並沒有創建bean對象。

那麼,加上@Lazy註解后,bean是何時創建的呢?我們在SpringBeanTest類中的testAnnotationConfig5()方法中獲取下person對象,如下所示。

@Test
public void testAnnotationConfig5(){
    ApplicationContext context = new AnnotationConfigApplicationContext(PersonConfig2.class);
    System.out.println("IOC容器創建完成");
    Person person = (Person) context.getBean("person");
}

此時,我們再次運行SpringBeanTest類中的testAnnotationConfig5()方法,輸出的結果信息如下所示。

IOC容器創建完成
給容器中添加Person....

說明,我們在獲取bean的時候,創建了bean對象並加載到Spring容器中。

那麼,問題又來了,只是第一次獲取bean的時候創建bean對象嗎?多次獲取會不會創建多個bean對象呢?我們再來完善下測試用例,在在SpringBeanTest類中的testAnnotationConfig5()方法中,再次獲取person對象,並比較兩次獲取的person對象是否相等,如下所示。

IOC容器創建完成
給容器中添加Person....
true

從輸出結果中,可以看出使用@Lazy註解標註后,單實例bean對象只是在第一次從Spring容器中獲取對象時創建,以後每次獲取bean對象時,直接返回創建好的對象。

總結

懶加載,也稱延時加載。僅對單例bean生效。單例bean是在Spring容器啟動的時候加載的,添加@Lazy註解后就會延遲加載,在Spring容器啟動的時候並不會加載,而是在第一次使用此bean的時候才會加載,但當你多次獲取bean的時候不會重複加載,只是在第一次獲取的時候會加載,這不是延遲加載的特性,而是單例Bean的特性。

好了,咱們今天就聊到這兒吧!別忘了給個在看和轉發,讓更多的人看到,一起學習一起進步!!

項目工程源碼已經提交到GitHub:https://github.com/sunshinelyz/spring-annotation

寫在最後

如果覺得文章對你有點幫助,請微信搜索並關注「 冰河技術 」微信公眾號,跟冰河學習Spring註解驅動開發。公眾號回復“spring註解”關鍵字,領取Spring註解驅動開發核心知識圖,讓Spring註解驅動開發不再迷茫。

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

【其他文章推薦】

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

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

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

※超省錢租車方案

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

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

※回頭車貨運收費標準

Zookeeper實現服務註冊/發現

what that?

Zookeeper在分佈式開發中使用頻繁,但許多框架都對其進行了封裝,初學者可能無法較好的理解其工作原理,該文章演示了使用Zookeeper實現服務註冊,服務發現的簡單demo,希望能達到拋磚引玉的效果;

why need RegisterCenter?

之所以需要訪問註冊和服務發現是因為分佈式系統中,服務之間需要相互調用,但若每個服務自己維護一份依賴的服務信息的話,就顯得很麻煩,且自身維護的數據無法保證其實時性,當依賴的服務信息發生變更時,無法及時獲取更新,解決方案就是引入一個註冊中心,服務提供方將自己的信息寫入到註冊中心,服務使用方從註冊中心來獲取服務信息; 如下圖:

client表示服務使用方,server表示服務提供方

實現的效果: 客戶端可自動發現服務信息,當服務狀態發生變化時(上線,下線,更換地址),客戶端可以及時響應變化,效果如下圖:

效果演示

實現

  1. 首先保證Zookeeper以安裝啟動,且可以正常訪問

  2. 創建Maven項目並添加Zookeeper的Java客戶端依賴(注意版本號需>3.6)

    				<dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.6.1</version>
            </dependency>
    
  3. 編寫服務提供方

    package com.jerry;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooDefs;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.ACL;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.*;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.Enumeration;
    
    import static java.net.InetAddress.getLocalHost;
    
    public class UserService {
    
        public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
            new UserService().serving();
        }
    
        public void serving() throws IOException, KeeperException, InterruptedException {
            //獲取本機ip地址
            String ip = null;
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) networkInterfaces.nextElement();
                Enumeration<InetAddress> nias = ni.getInetAddresses();
                while (nias.hasMoreElements()) {
                    InetAddress ia = (InetAddress) nias.nextElement();
                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
                        ip = ia.getHostAddress();
                    }
                }
            }
            int port = 8988;
    
            //啟動服務
            ServerSocket socket = new ServerSocket(port);
            System.out.println("服務器已啟動...");
            //註冊服務
            serverRegister(ip, port);
            //處理請求
            clientHandler(socket);
        }
    
        private void clientHandler(ServerSocket socket) throws IOException {
            while (true) {
                Socket accept = socket.accept();
                InputStream inputStream = accept.getInputStream();
                byte[] barr = new byte[1024];
                while (true) {
                    int size = inputStream.read(barr);
                    if (size == -1) {
                        //System.out.println("客戶端已關閉..");
                        accept.close();
                        break;
                    }
                    String s = new String(barr, 0, size);
                    //輸出客戶端消息
                    System.out.println(accept.getInetAddress().getHostAddress() + ": " + s);
                }
            }
    
        }
    
        private void serverRegister(String ip, int port) throws IOException, KeeperException, InterruptedException {
            //註冊服務
            ZooKeeper zooKeeper = new ZooKeeper("10.211.55.4: 2181",3000, null);
            try {
                ArrayList<ACL> acl = new ArrayList<>();
                acl.add(new ACL(31, ZooDefs.Ids.ANYONE_ID_UNSAFE));
                zooKeeper.create("/userServer", (ip + ":" + port).getBytes(StandardCharsets.UTF_8), acl, CreateMode.EPHEMERAL);
                System.out.println("服務發布成功!");
            } catch (KeeperException | InterruptedException e) {
                e.printStackTrace();
                throw e;
            }
        }
    }
    
  4. 編寫服務服務使用方

    package com.yyh;
    
    import org.apache.zookeeper.*;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class UserClient implements Watcher {
        String node = "/userServer"; //服務信息所在的節點 服務提供方和服務消費方一致
        private ZooKeeper zooKeeper;
        String server_ip;
        int server_port;
    
        public static void main(String[] args) throws Exception {
            //開始服務監聽
            UserClient userClient = new UserClient();
            userClient.run();
            //當訪問可用時與服務交互
            Scanner scanner = new Scanner(System.in);
            while (true){
                System.out.println("輸入要發送的信息(e:退出)");
                String text = scanner.next();
                if (text.equals("e"))System.exit(-1);
                if (userClient.server_ip == null){
                    System.err.println("沒有可用的服務...");
                }else {
                    userClient.sendToServer(text);
                }
            }
        }
        
        private void run() throws Exception {
            //連接zookeeper
            zooKeeper = new ZooKeeper("10.211.55.4:2181", 3000, null);
            //嘗試獲取服務信息
            getServerInfo();
            //添加對服務信息的永久監聽
            zooKeeper.addWatch(node,this,AddWatchMode.PERSISTENT);
        }
    
        //獲取服務信息
        private void getServerInfo()  {
            try {
                byte[] data = zooKeeper.getData(node, false, null);
                String[] infos = new String(data).split(":");
                server_ip = infos[0];
                server_port = Integer.parseInt(infos[1]);
                System.out.println("獲取服務信息成功!");
                System.out.println(server_ip+":"+ server_port);
            } catch (KeeperException e) {
                System.err.println("服務信息不存在! 等待服務上線........");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        //當節點狀態發送變化時將執行該方法(通知處理)
        @Override
        public void process(WatchedEvent event) {
            if (event.getPath().equals(node)) {
                //根據具體邏輯處理不同的事件類型,此處只關心節點的創建刪除和更新
                if (event.getType() == Event.EventType.NodeCreated) {
                    System.err.println("服務上線了");
                    getServerInfo();
                } else if (event.getType() == Event.EventType.NodeDataChanged) {
                    System.err.println("服務更新了");
                    getServerInfo();
                }else if (event.getType()== Event.EventType.NodeDeleted){
                    server_ip = null;
                    server_port = 0;
                    System.err.println("服務下線了");
                }
            }
        }
    
        public void sendToServer(String text) {
            InetSocketAddress server_address = new InetSocketAddress(server_ip, server_port);
            Socket socket = new Socket();
            try {
                socket.connect(server_address);
                //System.out.println("連接服務器成功!");
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write(text.getBytes());
                System.out.println("消息發送成功!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
  5. 打包服務端代碼,該步驟可忽略,僅為了測試客戶端正確性, 為了在打包時附帶其全部依賴,此處藉助Spring的打包插件,在pom中添加以下內容:

    		<build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>1.5.6.RELEASE</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    

    注意:Spring-boot打包插件會自動獲取項目中的主函數,必須保證主函數只有一個,所以需要暫時註釋客戶端的主函數,最後執行maven的package,得到jar包

  6. 將jar上傳至虛擬機並運行

    java -jar ZookeeperTest-1.0-SNAPSHOT.jar
    

    若沒有其他問題則客戶端依然可以正常連接服務器發送消息;

以上便是使用Zookeeper實現服務註冊和服務發現的具體步驟,在實際開發中,我們可能還會將提供的服務部署為集群,這時可將集群中的各個服務信息作為子節點註冊到指定節點下,客戶端監聽該節點變化,獲取子節點列表從而獲取到服務列表,還可以在此基礎上加上負載均衡算法實現對服務列表的合理訪問; 如圖:

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

【其他文章推薦】

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

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

※超省錢租車方案

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

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

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

台中搬家遵守搬運三大原則,讓您的家具不再被破壞!

Dubbo+Zookeeper集群案例

一.開源分佈式服務框架

1.Dubbo是阿里巴巴公司開源的一個高性能優秀的服務框架,使得應用可通過高性能的 RPC 實現服務的輸出和輸入功能,可以Spring框架無縫集成。
   Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:①面向接口的遠程方法調用;②智能容錯和負載均衡;③服務自動註冊和發現

2.結構圖

節點角色說明:

Provider: 暴露服務的服務提供方。
Consumer: 調用遠程服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的調用次數和調用時間的監控中心。
Container: 服務運行容器。
 

調用關係說明

0服務容器負責啟動,加載,運行服務提供者provider。
1服務提供者provider在啟動時,(通過連接服務器的client)向註冊中心註冊自己可以提供的服務。(其實就是註冊一些provider自己的ip:port以及對自己提供的服務的描述,比如能幹什麼!)
2服務消費者consumer在啟動時,向註冊中心訂閱自己所需的服務。並註冊自己的ip:port等信息。
3註冊中心返回服務提供者provider地址列表給消費者consumer,如果有變更,註冊中心將基於長連接推送變更數據給消費者consumer。
4服務消費者consumer,從註冊中心返回的提供者provider地址列表中,基於軟負載均衡算法,選一台提供者provider進行調用,如果調用失敗,再選另一台調用。
5服務消費者consumer和提供者provider,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心monitor。
Dubbo 架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。

二.Dubbo作用

  dubbo其實就是一个中間層管理工具,他是一個框架,裏面可以裝你想裝的服務,一般註冊中心大多用zookeeper,當然除了zookeeper,還要Redis等也可以做註冊中心。  
 

三.Dubbo+Zookeeper(註冊中心使用Zookeeper),Zookeeper其實是樹狀結構。

1.可以把register理解成房產中介,provider是賣房的人,張三想賣掉自己在秦淮區的學區房,李四想賣掉自己在棲霞區的學區房,consumer王五是想在棲霞區買學區房給自己孩子上學,王五去中介諮詢后,中介返回給王五的需求 滿足者是李四,王五從中介那得到李四的電話,自己打電話找李四買房。

比如Provider註冊的是  192.168.1.(描述121是吃飯,122睡覺,123打遊戲,124健身四種不同的服務)
2-0、 、dubbo–這是dubbo在ZooKeeper上創建的根節點  /dubbo
2-1 、 Dubbo在Zookeeper上註冊的節點目錄:假設接口名稱是:com.bob.dubbo.service.CityDubboService。
這是服務節點,代表了Dubbo的一個服務  /dubbo/com.bob.dubbo.service.CityDubboService
2-2 、 Dubbo啟動時,Consumer和Provider都會把自身的URL格式化為字符串,然後註冊到zookeeper相應節點下,作為一個臨時節點,當連斷開時,節點被刪除。
這是服務提供者的根節點,其子節點代表了每一個服務真正的提供者/dubbo/com.bob.dubbo.service.CityDubboService/providers
這是服務消費者的根節點,其子節點代表每一個服務真正的消費者;/dubbo/com.bob.dubbo.service.CityDubboService/consumers
2-3、 Consumer在啟動時,不僅僅會註冊自身到 …/consumers/目錄下,同時還會訂閱…/providers目錄下所有子節點,具體的看你訂閱具體是哪一個節點(比如訂閱健身這些服務),實時獲取其上Provider的URL字符串信息。register返回給Consumer這個ip–192.168.1.124,Consumer拿着這個iP直接去找Provider調用這項服務–健身。
2-4 、監控中心啟動時訂閱com.bob.dubbo.service.CityDubboService目錄下的所有提供者和消費者URL。

 

四.Dubbo——Zookeeper補充:

支持以下功能:

 
當提供者出現斷電等異常停機時,註冊中心能自動刪除提供者信息
當註冊中心重啟時,能自動恢復註冊數據,以及訂閱請求
當會話過期時,能自動恢復註冊數據,以及訂閱請求
當設置<dubbo:registry check=”false” />時,記錄失敗註冊和訂閱請求,後台定時重試
可通過設置<dubbo:registry username=”admin” password=”124″ />設置zookeeper 登錄信息
可通過<dubbo:registry group=”dubbo” />設置 zookeeper 的根節點,不設置將使用無 根樹
支持 * 號通配符 <dubbo:redistry group=”*” version=”*” />,可訂閱服務的所有分組 和所有版本的提供者
 
補充:
  消費者從ZK獲取provider地址列表后,會在本地緩存一份。當ZK註冊中心所有節點全部宕掉之後,消費者可以使用本地緩存的服務列表和provider進行通信。
ZK的意義在於為consumer和provider提供服務地址的發布/訂閱服務,讓消費者及時感知最新的服務列表,consumer真正調用provider是通過某種通信協議直接調用,並不依賴ZK。
 
所以當zookeeper宕機之後,不會影響消費者調用服務提供者,影響的是zookeeper宕機之後如果提供者有變動,增加或者減少,zk無法把變更通知推送給consumer,consumer會因為感知不到變更時間,不去拉取最新的服務列表,導致本地緩存的服務列表有可能過時的。

完結,個人理解,如有偏差,請大家指正,謝謝!

2020-06-09 10:58:28

 

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

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

※推薦台中搬家公司優質服務,可到府估價

Kubernetes內部域名解析的那些事兒

前言

    在kubernets環境中,服務發現大都是基於內部域名的方式。那麼就涉及到內部域名的解析。從1.11版本開始,kubeadm已經使用第三方的CoreDNS替換官方的kubedns作為集群內部域名的解析組件。

kubernets中的4種DNS策略

None

表示空的DNS設置,這種方式一般用於想要自定義 DNS 配置的場景,往往需要和 dnsConfig 配合一起使用達到自定義 DNS 的目的。

Default

此種方式是讓kubelet來決定使用何種DNS策略。而kubelet默認的方式,就是使用宿主機的/etc/resolv.conf文件。

同時,kubelet也可以配置指定的DNS策略文件,使用kubelet參數即可,如:–resolv-conf=/etc/resolv.conf

ClusterFirst

此種方式是使用kubernets集群內部中的kubedns或coredns服務進行域名解析。若解析不成功,才會使用宿主機的DNS配置來進行解析。

ClusterFistWithHostNet

在某些場景下,我們的 POD 是用 HOST 模式啟動的(HOST模式,是共享宿主機網絡的),一旦用 HOST 模式,表示這個 POD 中的所有容器,都要使用宿主機的 /etc/resolv.conf 配置進行DNS查詢,但如果你想使用了 HOST 模式,還繼續使用 Kubernetes 的DNS服務,那就將 dnsPolicy 設置為 ClusterFirstWithHostNet。

策略配置示例

DNS策略,需要在Pod,或者Deployment、RC等資源中,設置 dnsPolicy 即可,以 Pod 為例:

apiVersion: v1
kind: Pod
metadata:
   labels:
    name: cadvisor-nodexxxx
    hostip: 192.168.x.x
  name: cadvisor-nodexxxx
  namespace: monitoring
spec:
  containers:
  - args:
    - --profiling
    - --housekeeping_interval=10s
    - --storage_duration=1m0s
    image: google/cadvisor:latest
    name: cadvisor-nodexxxx
    ports:
    - containerPort: 8080
      name: http
      protocol: TCP
    resources: {}
    securityContext:
      privileged: true
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
  dnsPolicy: ClusterFirst
  nodeName: nodexxxx

kubernets中域名解析流程

# Pod中的resolv.conf的解析配置

[root@l-k8s01 ~]# kubectl exec -it nginx-deploy-5754944d6c-dtzpj cat /etc/resolv.conf

nameserver 10.96.0.2
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

[root@l-k8s01 ~]# kubectl get svc -n kube-system |grep dns

kube-dns   ClusterIP  10.96.0.2   <none>   53/UDP,53/TCP,9153/TCP   158d

a)文件中配置的 nameserver 一般是k8s集群內部的dns服務的ClusterIP,無法ping,但是可以訪問。

b)意味着集群Pod內部的所有域名的解析,都要經過kubedns的虛擬ip 10.96.0.2 進行解析。

c)resolv.conf中search域分別是default.svc.cluster.local svc.cluster.local cluster.local,在kubernets中,域名的全稱必須是 service-name.namespace.svc.cluster.local 。

d)假如集群中有一個svc(Service)名為a,在某個Pod中執行命令 curl a 時,在此Pod中會根據/etc/resolv.conf進行解析流程。選擇nameserver 10.96.0.2進行解析,將字符串’a’帶入到/etc/resolv.conf文件中不同的search域,依次進行查找,如下:

a.default.svc.cluster.local -> a.svc.cluster.local -> a.cluster.local

先查找 a.default.svc.cluster.local ,若找不到,則再查找 a.svc.cluster.local ,依次往下進行,直到找到為止。

curl效率分析

在集群中若存在一個名為a的svc,在Pod中curl a和curl a.default都能實現請求,那麼兩種方式哪個的效率高呢?

那肯定是curl a啦,因為發起此請求時,通過/etc/resolv.conf中第一列的search域就能直接找到 a.default.svc.cluster.local ,直接避免了下一級的查找。

容器中訪問外部域名講述

下文將通過示例說明Pod訪問外部域名時發起的相應的請求信息。

以請求baidu.com為例,因為DNS容器一般不具備bash,所以無法通過docker exec的方式進入容器抓包,所以此處採用 進入到DNS容器的網絡中(不是發起DNS請求的容器)的姿勢去抓包,抓包姿勢準備好后,同時在某容器中訪問baidu.com,即可看到在進行的DNS查找的過程中都產生了什麼樣的數據包。

 

### 實操

# 進入dns容器網絡,準備好抓包姿勢

# 查看Pod所在具體的node節點

[root@master1 ~]# kubectl get pods -n kube-system -o wide|grep dns

coredns-5c48579f88-8wprg  1/1   Running  16    30d   10.244.4.120   node1
coredns-5c48579f88-rsnpr   1/1   Running   0     30d   10.244.5.142   node2

# 這裏以node1上的容器為操作對象,所以到node1節點上進行操作

# 找到容器並打印對應的NS ID

[root@node1 ~]# docker ps |grep dns

a964bbb43534 c0f6e815079e "/coredns -conf /etc…" 2 days ago Up 2 days k8s_coredns_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-4843-b156-1d203f98bd74_16
fbd12d2f9c7c k8s.gcr.io/pause:3.1 "/pause" 5 days ago Up 5 days k8s_POD_coredns-5c48579f88-8wprg_kube-system_b1e7f3c3-98eb-4843-b156-1d203f98bd74_3

[root@node1 ~]# docker inspect –format “{{.State.Pid}}”  a964bbb43534

21617

# 進入此容器的網絡Namespace

[root@node1 ~]# nsenter -n -t 21617

# 抓包姿勢就緒

[root@node1 ~]# tcpdump -i eth0 udp dst port 53|grep ‘baidu.com’

 

# 在另外的某容器中,進行域名查找操作

說明:一般pod中沒有nslookup命令,故需要手動安裝,根據不同環境自選以下操作。

### Centos

]# cat /etc/redhat-release

CentOS Linux release 7.5.1804 (Core)

]# yum -y install bind-utils

### Debian

# cat /etc/issue

Debian GNU/Linux 9

# apt-get install dnsutils -y

root@jenkins-7d66bf7977-cm4x4:~# nslookup baidu.com 10.244.4.120

 

注意:10.244.4.120是node1上的dns pod在kubernets集群中的內部通信ip地址。因為環境中有兩個dns pod,將其指定要單個具體的容器,能夠使抓包數據完整。

 

# 隨後,在前面就緒的抓包姿勢窗口就能看到數據包的出現

[root@node1 ~]# tcpdump -i eth0 udp dst port 53|grep ‘baidu.com’

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:57:50.791154 IP 10.244.4.127.51794 > node1.domain: 55406+ A? baidu.com.infra.svc.cluster.local. (51)
16:57:50.792540 IP 10.244.4.127.56306 > node1.domain: 27958+ A? baidu.com.svc.cluster.local. (45)
16:57:50.793439 IP 10.244.4.127.59799 > node1.domain: 27048+ A? baidu.com.cluster.local. (41)
16:57:50.799463 IP 10.244.4.127.39116 > node1.domain: 2303+ A? baidu.com. (27)

說明:

a)數據包中显示的 infra 是執行nslookup的pod的NameSpace;

b)根據數據显示,在真正解析到 baidu.com 之前,經歷了baidu.com.infra.svc.cluster.local. > baidu.com.svc.cluster.local. > baidu.com.cluster.local. 三次DNS請求。

請求浪費的原因

上文在正確請求到baidu.com之前,有過三次無效請求,即意味着請求浪費,那為什麼會出現那種情況呢,請繼續往下看。

 

# Pod中的resolv.conf的解析配置

root@jenkins-7d66bf7977-cm4x4:/# cat /etc/resolv.conf
nameserver 10.96.0.2
search infra.svc.cluster.local svc.cluster.local cluster.local host.com
options ndots:5

 

# options ndots:5 解釋

如果查詢的域名包含的點”.”,不到5個,那麼進行DNS查找,將使用非完全限定名稱(或者叫絕對域名),如果你查詢的域名包含點數大於等於5,那麼DNS查詢,默認會使用絕對域名進行查詢。

如果我們請求的域名是,a.b.c.d.e,這個域名中有4個點,那麼容器中進行DNS請求時,會使用非絕對域名進行查找,使用非絕對域名,會按照 /etc/resolv.conf 中的 search 域,走一遍追加匹配:

a.b.c.d.e.cicd.svc.cluster.local. ->

a.b.c.d.e.svc.cluster.local. ->

a.b.c.d.e.cluster.local.

直到找到為止。如果走完了search域還找不到,則使用 a.b.c.d.e. ,作為絕對域名進行DNS查找。

 

說明:

a)請求域名中點數少於5個時,先走search域,最後將其視為絕對域名進行查詢;

b)請求域名中點數大於等於5個時,直接視為絕對域名進行查找,只有當查詢不到的時候,才繼續走 search 域。

優化請求浪費

使用全限定域名

當訪問某域名時,以 ‘.’ 為後綴,即使用 完全限定域名(絕對域名),這樣發起的域名請求時將不會走search域進行匹配,而是直接使用整個原始域名字符串為個體進行解析。

 

如:

nslookup baidu.com.

配置特定ndots

在kubernets中,ndots值默認是5。是因為,Kubernetes 認為,內部域名,最長為5,要保證內部域名的請求,優先走集群內部的DNS,而不是將內部域名的DNS解析請求,有打到外網的機會,Kubernetes 設置 ndots 為5是一個比較合理的行為。

如果有特定業務需求,也可配置ndots,如下:

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsConfig:
    options:
      - name: ndots
        value: "1"

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

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

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

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