北海道天候異常沒暴風雪 罕見吹起沙塵暴

摘錄自2020年1月6日中央社東京報導

日本北海道東部的十勝地方部分地區6日突然吹起沙塵暴,造成兩條高速公路部分路段因視線不佳暫停通行。由於冬天並非當地沙塵暴季節,研判可能是因為這個冬天降雪不足所造成。

北海道往年這個時期都是大雪紛飛,十勝地方應該全部會被白雪覆蓋,但受到這個冬天降雪異常減少,讓許多未被白雪覆蓋的田地露出來,變成乾燥的沙子容易被風捲起的狀態。

上述暫停通行路段在下午2時過後就恢復車輛通行,但警方及東日本高速道路公司等還是呼籲,駕駛人行經這些路段仍要留意強風,小心駕駛。

日本放送協會(NHK)報導,十勝地方這個冬天降雪較往年來得少,強風捲起農地沙子造成視線不佳的「塵煙霧」現象,是首度在冬天出現,十勝地方帶廣市去年12月降雪量僅17公分,不到往年降雪量四成;今天積雪6公分,較往年的26公分同樣大幅減少。

 

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

【其他文章推薦】

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

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

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

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

澳洲野火災情跨年後持續擴大 下雨仍無緩解

整理:劉妙慈 (環境資訊中心實習編輯)

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

【其他文章推薦】

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

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

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

騰訊出資!中國版特斯拉 NextEV 先瞄準中國市場

騰訊和高瓴資本在內等多家中國網路巨頭和金融投資機構共同投資的新能源汽車廠商 NextEV,將成為特斯拉(Tesla)的競爭對手。據路透報導,NextEV 發言人劉吉利表示,已聘請福特前高管 Martin Leach 打造一家全球性汽車廠商,他們還招聘了有在特斯拉、寶馬(BMW)、大眾(VW)和其他主要汽車廠商工作經驗的專家。他強調,NextEV 將先瞄準中國市場,然後走向世界。   NextEV 投資方包括數家非汽車廠商的中國科技公司,且其開發電動車的努力得到中國政府的支持,中國政府最近修改相關法規,允許非汽車廠商投資電動汽車產業。目前已宣布或在考慮投資電動汽車產業的中國科技公司包括阿里巴巴、小米和樂視。   劉吉利表示,NextEV 推出的第一款產品將是一款電動超級跑車,預計該車表現將超過世界上所有採用內燃機的跑車。NextEV 並將於明年推出賽車車型,功率超過1000馬力,加速到時速 100 公里僅需 3 秒。之後 NextEV 還會推出一系列高性能車型。

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

【其他文章推薦】

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

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

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

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

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

搶佔市場份額!賓士推全新純電動車

日前,賓士稱將推出一款全新純電動車,續航里程在400-500km之間,競爭對手瞄準了特斯拉Model S。   據網通社報導,賓士2014年跟戴姆勒集團共同斥資64億美元研發低排放技術的專案,計畫未來幾年研發賓士新能源車,包括smartfortwo、A級、B級以及SLS AMG在內的多款電動車推出。   2017年起戴姆勒汽車集團斥資與福特、日產共同建設10個氫燃料補給站的舉措顯示,除了電動車外,氫燃料車也是賓士未來幾年重要產品策略。   此外,賓士還將隨主流發展插電混動版車型,據媒體消息稱截至2017年賓士將有10款插電混動版車型推出,包括S級和C級插電混動版。   除了賓士外,奧迪和寶馬均有新電動車計畫,奧迪全新Q6 e-tron Quattro概念車將於9月法蘭克福亮相,寶馬將於2018年推出一款純電動SUV競爭對手瞄準了特斯拉Model X,另外,寶馬一款基於5系打造的i5純電動也將為寶馬電動車細分市場贏得更多的份額。

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

【其他文章推薦】

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

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

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

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

保時捷推電動車,搶新市場一杯羹

  據科技日報消息,保時捷發佈了全新電動概念車Mission E。該車配有保時捷全新的800V超級充電技術,可以在15分鐘內充電80%。   Mission E全新概念車採用純電動設計,前後兩臺電動機分別驅動前後輪,形成四輪驅動系統,兩臺電動機總功率達到447kw,百公里加速僅需3.5秒,單次充電行駛里程約500公里。Mission E採用大量的空氣動力學套件,按照車身重心設計在底部安裝全新的鋰離子電池組等措施,加上130mm的最小離地間隙,都為該車的操控性起著重要作用。

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

【其他文章推薦】

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

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

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

China .NET Conf 2019-.NET技術架構下的混沌工程實踐

這個月的8號、9號,個人很榮幸參加了China.NET Conf 2019 , 中國.NET開發者峰會,同時分享了技術專題《.NET技術架構下的混沌工程實踐》,給廣大的.NET開發小夥伴介紹混沌工程和高可用性改造實踐。會後大傢伙聚餐的時候,陳計節老師建議大家將各自的議題分享到社區,分享給大家。因此,今天和大家分享我的技術專題《.NET技術架構下的混沌工程實踐》。

先放幾張大會照片:

整個專題主要分為四個部分:

  1. .NET分佈式、微服務架構下的高可用性挑戰
  2. 混沌工程簡介
  3. .NET混沌工程的實踐和成果分享
  4. 展望和規劃

一、.NET分佈式、微服務架構下的高可用性挑戰

目前,我們特來電的技術架構是分佈式、微服務化的,線上超過1000台Server,高可用保障壓力很大:

  • 系統7*24小時運行,不允許宕機,一旦宕機出問題,直接影響全國人民出行;
  • 系統SLA要求99.95% ,全年可宕機時間只有4.38小時;
  • 服務調用鏈路越來越長,依賴越來越複雜,某個環節出問題,都有肯能導致服務雪崩、大規模宕機;
  • 線上遭遇:網絡抖動、內存泄露、線程阻塞、CPU被打爆、 數據庫被打爆、中間件宕機等棘手問題;
  • 每天上百次發布更新,系統高可用性保障壓力非常大;

一張全鏈路監控圖可以反映我們系統的複雜:

 

例如主機CPU被打爆的問題,線上經常會遇到:

經歷了線上各種高可用性問題后,我們做了很多反思和總結:

系統在實現了分佈式、微服務化之後,我們到底有多少把握來保證系統的正常運行?  

如果出現問題,整個分佈式系統會變得非常“混亂”,甚至會引發系統的大規模宕機。

因此,我們有必要在線上事故出現之前,提前識別出系統有哪些弱點和問題,統一管控系統的固有混沌。

這套管控系統固有混沌的方法和體系,就是我們今天要介紹的主角:混沌工程

二、混沌工程簡介

1. 什麼是混沌工程?

通過受控的實驗,掌握系統運行行為的過程,稱為混沌工程。

    混沌工程的典型實踐:Chaos Monkey
     一隻搗亂的猴子,在你的系統裏面上蹦下竄,不停搗亂,直到搞掛你的系統。

    

2. 為什麼需要混沌工程?

   混沌工程可以提升整個系統的彈性。
   通過混沌實驗,可以發現系統脆弱的一面,主動發現這些問題,並解決這些問題

3. 混沌工程怎麼做?

   混沌工程的一般實施步驟:

1 選擇系統正常運行狀態下的可度量指標,作為基準的“穩定狀態” 2 混沌實驗分為實驗組和對照組,都能保持系統的“穩定狀態” 3 對實驗組注入混沌事件,如服務不可用、中間件宕機等混沌事件 4 比較實驗組和對照組“穩定狀態”的差異

   如果混沌實驗前後系統的“穩定狀態”一致,則可以認為系統應對這種混沌事件是彈性的、高可用的。
   相反的,如果打破了系統的穩定狀態,我們就找到了一個系統弱點,然後盡可能地解決它,提升系統的高可用性。

4. 實施混沌工程的推薦原則

  • 明確系統穩定運行的狀態(指標)
  • 混沌事件必須是現實世界可能發生的(合理的)
  • 在生產環境進行混沌實驗 :生產環境可以真實地反映系統的穩定性
  • 持續集成:線上應用每天都在更新,通過持續集成的方式可以不斷髮現問題、解決問題。
  • 最小化影響範圍:線上進行混沌實驗,必須可控,必須確定混沌實驗的最小化影響範圍。

   這裏大家會問:在生產環境上搞混沌實驗,能行嗎?

5. 現實中的混沌工程

  生產環境必須以穩定為前提,因此推薦O2O模式的混沌實驗:即線下演練、線上驗證
  在系統未經過大規模高可用性改造之前,建議首先進行全面的線下演練:

   

   那麼, .NET技術架構下的混沌工程怎麼做?

三、.NET混沌工程的實踐和成果分享

  我們線上系統主要用到了以下.NET技術棧和開源技術:

  • ASP.NET MVC
  • 基於ASP.NET Core的Web運行框架-WRF
  • 基於ASP.NET Web API的分佈式服務網關-SG
  • 基於.NET RPC通訊技術的分佈式微服務平台-HSF
  • 基於RabbitMQ和Kafka的消息應用中心-MAC
  • iBatis.NET & Entity Framework
  • RabbitMQ & RabbitMQ Client for .NET
  • Kafka & Confluent.Kafka
  • Redis
  • Nginx

    在上述.NET 技術架構下,我們梳理了大量的混沌工程事件:

    

    

    

     通過大量的混沌實驗,我們逐步建立了提升系統高可用性的方法論和體系:

     

     .NET技術架構下的高可用性改進-依賴治理、容錯降級     

      業務場景:
      隨着業務複雜度的上升,服務調用鏈路越來越長,鏈路上存在大量不可控的因素:      

    • 網絡抖動,導致服務異常
    • Redis、MQ、DB等中間件不可用,導致服務超時、異常
    • 依賴的服務不可用,直接影響服務調用方  

          

     如何應對:識彆強弱依賴,對弱依賴進行降級,對強依賴有限降級     

    • “用戶有感知” 是強依賴
    • “用戶無感知” 是弱依賴
    • 故障發生時,核心業務有損失的是強依賴,無損失的是弱依賴

           

      .NET技術架構下的高可用性改進-解耦/隔離       

      業務場景:
      核心業務的調用鏈路很長,整個鏈路上包含主流程和輔流程
      輔流程的重要性低,不能因為輔流程的不可用,影響了主流程。

      

       如何應對:

       

       .NET技術架構下的高可用性改進-超時治理        

       業務場景:
       對於服務超時,長時間等待會影響用戶體驗,併發大時還可能造成線程池被打爆。
       同時可能產生服務級聯反應,導致大範圍服務雪崩。

              

        應對方案:
        超時時間設置:服務剛上線時,可以根據壓測情況預估一個值;
        服務上線后再根據實際監控進行修改,比如設置99%的請求響應時間為超時時間。
        超時后的處理策略:
        如果不是核心服務,可直接超時返回失敗。
        如果是核心服務,可以設置相應的重試次數.         

        示例:
        配置服務超時時間
        設置Http請求超時時間
        設置數據庫連接超時、SQL執行超時
        代碼控制超時時間(例如:Polly的Timeout策略)

      .NET技術架構下的高可用性改進-重試補償         

        業務場景:
        實際線上應用中,假如遇到網絡抖動、發布重啟、數據庫阻塞超時等情況,都有可能引起服務調用失敗。         

        應對方案:
        通過失敗重試、異常后的補償,盡可能地保證業務可用。
        重試情況下:業務要保證冪等性、保證最終一致性。        

        示例:
        服務失敗重試策略
        消息發送、消費失敗重試、補償
        代碼層面失敗重試補償(例如:Polly的Retry策略)

      高可用改進還有很多技巧,這裏不一一詳細給大家贅述了。

      通過對系統進行全面的高可用性改進,提升了我們對線上系統的信心!

四、 展望和規劃

    2019年,我們啟動了混沌工程實踐,逐步建立了混沌工程的自有方法論和體系,通過近一年的混沌工程實踐,混沌工程文化逐漸被開發團隊所認可。目前,混沌工程已經逐步過渡到線上生產環境進行(這來自於足夠的信心和把握)。但這隻是一個起步,未來:

  • 正式的混沌工程團隊:通過多團隊配合、保障資源的持續投入
  • 覆蓋所有的關鍵核心應用:讓混沌工程深入到每個產品
  • 堅持O2O混沌工程實踐:線下演練、線上驗證,更可控
  • 混沌事件注入工具:ChaosBlade for .NET,工具讓混沌工程更高效
  • 持續的混沌實驗:持續進行、持續改進

    目標:通過混沌工程揭示問題、解決問題、形成閉環,不斷提升系統高可用性。

以上是本次China.NET Conf 2019的技術專題,分享給大家。

 

周國慶

2019/11/15

 

 

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

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

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

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

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

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

Unity中用Mesh畫一個圓環

Probuider

前幾天在做一個小項目的時候,用到了Unity自帶的一個包其中的Arch生成1/4圓。

挺好玩的,可以在直接Unity中根據需要用Mesh定製生成圖形,而不用建模軟件。

但是存在一個小問題,就是在使用的時候他的中心點是在生成圖形的左下角。

旋轉的時候不符合我的需求,我想要的是生成的時候旋轉中心在圓心的位置,所以準備自己定製一個。

目標

關於生成圖形的原理可以參考這篇文章,講得雖然不算很詳細,但足夠了解基本概念了。

目標是生成下面圖中的一個1/4空心圓柱體

我們切換到Wireframe模式下,可以看出它是有一個一個的頂點,並通過一條條的直線連接起來。那麼我們如何確定這些頂點和線的位置呢?

小目標-生成一個面

其實很簡單的,我們一步一步慢慢來。一次生成一整個會有點麻煩,我們可以一面一面來。只要生成了第一個面,其他的面也是類似的方法生成就好。

在前面我們提到了我們要的是生成一個圓柱體,圓柱體一個的重要性質就是可以由一個圓形疊加產生,也就是只要我們生成一個圓形,就完成了大部分的工作。

我們知道3D建模就是由一個一個的三角形組合成的,所以我們要用三角形來模擬來一個空心的圓。

在Probuilder中生成這樣一個空心圓柱體用的是Arch,它有幾個參數,分別是
\(\color{#1E90FF}{Radius}\) 半徑,圓心到最外圈的距離
\(\color{#1E90FF}{Thickness}\) 厚度,圓心到最外圈的距離-圓心到最內圈的距離
\(\color{#1E90FF}{Depth}\) 深度
\(\color{#1E90FF}{NumberOfSides}\) 由多少個面組成,面越多越平滑,性能也越差
\(\color{#1E90FF}{DrawArchDegrees}\) 總共繪製的角度

\(\color{#1E90FF}{NumberOfSides}\)中的面是指由兩個三角形一頭一尾拼成的梯形,多個頭大腳小的梯形拼在一起便成了我們需要的圓形。

原理已經知道了,那下一步只要確定三角形頂點的位置就OK了。至於如何確定三角形頂點的位置,我們可以再看下這張圖。

是不是瞬間清晰明了,紅線的交匯處就是圓心的位置,数字則是每個頂點的編號。

我們假設圓心在原點,数字0-1所在的線為180度線。\(\color{#1E90FF}{Increment}\) = \(\color{#1E90FF}{DrawArchDegrees}\)/\(\color{#1E90FF}{NumberOfSides}\)就是線與線之間的角度。每條線的角度可以由\(\color{#1E90FF}{180-Increment*i}\)得到。i為第幾條線。

線上的點可以由\(\color{#1E90FF}{y = r* sinθ, y = r* cosθ}\)得到。

        //頂點坐標
        vertexList.Clear();
        float incrementAngle = DrawArchDegrees / NumberOfSides;
        //小於等於是因為n+1條線才能組成n個面
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float innerX = (Radius - Thickness) * Mathf.Cos(angle * Mathf.Deg2Rad);
            float innerY = (Radius - Thickness) * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(innerX, innerY, 0));
            float outsideX = Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
            float outsideY = Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(outsideX, outsideY, 0));
        }

在上面的代碼中我們已經計算出了頂點的位置,下一步我們要做的是按順序插入三角形頂點的位置。從這篇文章中我們可以知道,只有是三角形是正面的情況下才會被渲染。

而正反面可以通過法線的朝向進行判斷,向外的面就是正面,相反的就是背面。

在Unity中,法線的朝向可以由左手法則得到。拿出左手,伸直,拇指與其他四個指頭垂直,然後四指彎曲,指尖朝向循環的方向,拇指就指向法線的方向。

也就是說在上圖中,我們想渲染三角形,順序應該是類似這樣的012,321, 234, 543。

        //三角形索引
        triangleList.Clear();
        int direction = 1;
        for (int i = 0; i < NumberOfSides * 2; i++)
        {
            int[] triangleIndexs = getTriangleIndexs(i, direction);
            direction *= -1;
            for (int j = 0; j < triangleIndexs.Length; j++)
            {
                triangleList.Add(triangleIndexs[j]);
            }
        }

\(\color{#F08080}{getTriangleIndexs}\)代碼如下

    int[] getTriangleIndexs(int index, int direction)
    {
        int[] triangleIndexs = new int[3] { 0,1,2};
        for (int i = 0; i < triangleIndexs.Length; i++)
        {
            triangleIndexs[i] += index;
        }
        if (direction == -1)
        {
            int temp = triangleIndexs[0];
            triangleIndexs[0] = triangleIndexs[2];
            triangleIndexs[2] = temp;
        }
        return triangleIndexs;
    }

至於uv坐標就更簡單了,把內圈頂點uv坐標中的Y固定為0,外圈頂點uv坐標中的Y固定為1,而x坐標由\(\color{#1E90FF}{1/NumberOfSides}\)得到:

    //UV索引
    uvList.Clear();
    for (int i = 0; i <= NumberOfSides; i++)
    {
        float angle = 180 - i * incrementAngle;
        float littleX = (1.0f / NumberOfSides) * i;
        uvList.Add(new Vector2(littleX, 0));
        float bigX = (1.0f / NumberOfSides) * i;
        uvList.Add(new Vector2(bigX, 1));
    }

完整代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//[RequireComponent(typeof(MeshFilter))]
//[RequireComponent(typeof(MeshRenderer))]
//[ExecuteInEditMode]
public class DrawArch : MonoBehaviour
{
    public float Radius = 20.0f;                //外圈的半徑
    public float Thickness = 10.0f;             //厚度,外圈半徑減去內圈半徑
    public float Depth = 1.0f;                  //厚度
    public float NumberOfSides = 30.0f;         //由多少個面組成
    public float DrawArchDegrees = 90.0f;       //要繪畫多長
    public Material archMaterial = null;
    
    private List<Vector3> vertexList = new List<Vector3>();
    private List<int> triangleList = new List<int>();
    private List<Vector2> uvList = new List<Vector2>();

    // Start is called before the first frame update
    void Start()
    {
        GenerateVertex();
    }

    void GenerateVertex()
    {
        //頂點坐標
        vertexList.Clear();
        float incrementAngle = DrawArchDegrees / NumberOfSides;
        //小於等於是因為n+1條線才能組成n個面
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float innerX = (Radius - Thickness) * Mathf.Cos(angle * Mathf.Deg2Rad);
            float innerY = (Radius - Thickness) * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(innerX, innerY, 0));
            float outsideX = Radius * Mathf.Cos(angle * Mathf.Deg2Rad);
            float outsideY = Radius * Mathf.Sin(angle * Mathf.Deg2Rad);
            vertexList.Add(new Vector3(outsideX, outsideY, 0));
        }

        //三角形索引
        triangleList.Clear();
        int direction = 1;
        for (int i = 0; i < NumberOfSides * 2; i++)
        {
            int[] triangleIndexs = getTriangleIndexs(i, direction);
            direction *= -1;
            for (int j = 0; j < triangleIndexs.Length; j++)
            {
                triangleList.Add(triangleIndexs[j]);
            }
        }

        //UV索引
        uvList.Clear();
        for (int i = 0; i <= NumberOfSides; i++)
        {
            float angle = 180 - i * incrementAngle;
            float littleX = (1.0f / NumberOfSides) * i;
            uvList.Add(new Vector2(littleX, 0));
            float bigX = (1.0f / NumberOfSides) * i;
            uvList.Add(new Vector2(bigX, 1));
        }
        Mesh mesh = new Mesh()
        {
            vertices = vertexList.ToArray(),
            uv = uvList.ToArray(),
            triangles = triangleList.ToArray(),
        };

        mesh.RecalculateNormals();
        gameObject.AddComponent<MeshFilter>().mesh = mesh;
        gameObject.AddComponent<MeshRenderer>().material = archMaterial;
    }

    int[] getTriangleIndexs(int index, int direction)
    {
        int[] triangleIndexs = new int[3] { 0,1,2};
        for (int i = 0; i < triangleIndexs.Length; i++)
        {
            triangleIndexs[i] += index;
        }
        if (direction == -1)
        {
            int temp = triangleIndexs[0];
            triangleIndexs[0] = triangleIndexs[2];
            triangleIndexs[2] = temp;
        }
        return triangleIndexs;
    }
}

未完待續。。。

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

【其他文章推薦】

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

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

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

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

每天3分鐘操作系統修鍊秘籍(13):兩個緩衝空間Kernel Buffer和IO Buffer

兩個緩衝空間:kernel buffer和io buffer

先看一張圖,稍後將圍繞這張圖展開描述。圖中的fd table、open file table以及兩個inode table都可以不用理解,只需要知道它們體現出來的文件描述符和磁盤文件之間的對應關係:文件描述符fd(例如圖中的fd=3)是對應磁盤上文件的。

在Linux下,我們經常會在IO操作時不可避免的涉及到文件描述符,因為Linux下的所有IO操作都是通過文件描述符來完成的。但是,文件描述符是一個非常底層的概念,通過它操作的數據,都是二進制數據,所以通過文件描述符完成IO的模式通常也稱為裸IO(Raw IO)。而且,直接通過底層的文件描述符進行編程會比較麻煩,因為是二進制數據,它缺少很多功能,比如無法指定編碼,無法指定換行符(換行符有多種:\n、\n\r、\r)等等。注意fd是用戶空間的,它僅僅是一個數值而已,並不是想象中感覺比較底層就在內核空間。

所以,現代高級語言(比如C、Python、Java、Golang)都提供了比文件描述符更高一層次的標準IO庫,比如C的標準IO庫是stdio,Python的標準IO庫是IO模塊,等等。使用這些標準IO庫中的函數進行IO操作時,都會使用比文件描述符更高一層次的對象,例如C中稱為IO流(io stream),其它面向對象的語言中一般稱為IO對象,為了方便說明,這裏統稱為IO對象。上圖中的F就是文件對象。

標準IO庫可以看作是文件描述符的更高層次的封裝,提供了比文件描述符操作IO更多的功能。例如,可以在IO對象上指定編碼、指定換行符,此外還在用戶空間提供了一個標準IO庫的緩衝空間,通常可稱為stdio bufferIO buffer,而這些功能在文件描述符上都是沒有的。另外,標準IO庫既然是高層封裝,當然也會提供用戶不使用這些功能(比如不使用IO Buffer),而是直接使用文件描述符,那麼這時候的文件對象就相當於是文件描述符了,這時候的IO操作模式也就是裸IO模式。

所有從硬件讀取或寫入到硬件的數據,默認都會經過操作系統維護的這個Kernel Buffer。正如上圖中描述的是讀數據過程。

例如,cat進程想要讀取a.log文件,cat進程是用戶空間進程,它自身沒有權限打開文件以及讀文件數據,它只能通過系統調用的方式陷入內核,請求操作系統幫助讀取數據,操作系統讀取數據後會將數據放入到page cache(剛才已說明,對於普通文件維護的Kernel buffer稱為page cache或buffer cache)。然後還要將內核空間page cache中的數據拷貝到用戶空間的IO Buffer緩衝空間(因為cat程序的源代碼中使用了標準IO庫stdio),然後cat進程從自己的IO Buffer中讀取數據。這就是整個讀數據的過程。

需要注意的是,雖然這兩段緩衝空間都在內存中,但仍然有拷貝操作,因為內核的內存空間和用戶進程的虛擬內存空間是隔離的,用戶空間進程沒有權限訪問到內核空間的內存,但是內核具有最高權限,允許訪問任何內存地址。換句話說,在將Kernel Buffer的數據拷貝到IO Buffer空間的過程中,需要陷入到內核,OS需要掌控CPU。

此外,Linux也提供了所謂的直接IO模式,只需使用一個稱為O_DIRECT的標記即可,這時會繞過Kernel Buffer,直接將硬件數據拷貝到用戶空間。雖然看上去直接IO少了一個層次的參與感覺性能會更優秀,但實際上並非如此,操作系統為內核緩衝空間做了非常多的優化,使得並不會因此而降低性能。最典型且常見的一個優化是預讀功能,它表示在讀數據時,會比所請求要讀取的數據量多讀一點放入到Kernel Buffer,這樣在下次讀取接下來的一段數據時可以直接從Kernel Buffer中取數據,而無需再和硬件IO交互。所以,使用直接IO模式的場景是非常少的,一般只會在自帶了完整緩衝模型的大型軟件(比如數據庫系統)上可能會使用直接IO模式。

上面所描述的都是讀操作,關於寫操作,這裏不再多花篇幅去描述,整體過程和讀是類似的,都會經過IO Buffer和Kernel Buffer,只是其中一些細節有所不同,如果感興趣,可以閱讀《Linux/Unix系統編程手冊》的第13章。

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

【其他文章推薦】

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

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

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

Magicodes.Pay,打造開箱即用的統一支付庫,已提供ABP模塊封裝

Magicodes.Pay,打造開箱即用的統一支付庫,已提供ABP模塊封裝

簡介

Magicodes.Pay,是心萊科技團隊提供的統一支付庫,相關庫均使用.NET標準庫編寫,支持.NET Framework以及.NET Core。目前已提供Abp模塊的封裝,支持開箱即用。

Nuget

新的包

 

 

已棄用的包,不再更新

 

 

主要功能

Magicodes.Pay,是心萊科技團隊提供的統一支付庫,相關庫均使用.NET標準庫編寫,支持.NET Framework以及.NET Core。目前已提供Abp模塊的封裝,支持開箱即用。目前支持以下支付方式和功能:

  • 支付寶支付

    • APP支付

    • Wap支付

  • 支付寶國際支付

    • 支持分賬

  • 微信支付

    • 小程序支付

    • APP支付

    • 訂單查詢

    • 企業付款(提現)

    • 退款申請

    • 普通紅包

  • 通聯支付

    • 小程序支付

  • 統一支付回調處理

  • 支持日誌函數注入(不依賴支付庫)

  • 支持支付配置函數注入,以便於支持自定義配置獲取邏輯,以應用於不同的場景(比如從配置文件、用戶設置獲取配置,或者多租戶支持)

  • 針對ABP提供模塊封裝,添加模塊依賴即可立即使用。主要包括:

    • 支付渠道註冊(IPaymentRegister)

    • 支付回調邏輯處理(IPaymentCallbackAction)

    • 統一支付服務實現(IToPayService)

    • 統一支付服務封裝(見IPayAppService)

    • 支付管理器封裝(IPaymentManager),包含:

    • 交易日誌封裝,自動記錄客戶端信息以及自動異常處理和記錄

    • 僅需編寫一次回調邏輯,即可支持多個支付渠道

    • 業務參數支持更大長度(500)

開始使用

如果使用Abp相關模塊,則使用起來比較簡單,具體您可以參考相關單元測試的編寫。主要有以下步驟:

  1. 引用對應的Abp支付的Nuget包 如果僅需某個支付,僅需引用該支付的包。下面以通聯支付為例,我們需要在工程中引用此包:

  2. 添加模塊依賴 在對應工程的Abp的模塊(AbpModule)中,添加對“AbpAllinpayModule”的依賴,如:

 [DependsOn(typeof(AbpAllinpayModule))]
  1. 在DbContext中添加名為“TransactionLogs”的DbSet 整個支付過程中(無論是支付成功還是出現異常),均會記錄交易日誌。交易日誌會記錄交易過程中的一些信息,比如客戶端信息、交易參數、自定義參數以及異常信息。因此我們需要針對EF添加對TransactionLog的支持。需要在DbContext中添加的完整代碼如下所示:

public DbSet<TransactionLog> TransactionLogs { get; set; }
  1. 註冊回調邏輯 我們需要實現“IPaymentCallbackAction”接口來編寫自定義的回調邏輯。如以下示例所示:

public class TestPaymentCallbackAction : IPaymentCallbackAction
    {
        /// <summary>
        /// 業務Key
        /// </summary>
        public string Key { get; set; } = "繳費支付";

        /// <summary>
        /// 執行回調
        /// </summary>
        /// <returns></returns>
        public async Task Process(IUnitOfWorkManager unitOfWork, TransactionLog transactionLog)
        {
            var data = transactionLog.CustomData.FromJsonString<JObject>();
            //業務處理

            await Task.FromResult(0);
        }
    }

注意Key不要重複。

  1. 向容器中註冊回調邏輯

我們可以將回調邏輯寫在一個公共的程序集,然後使用以下代碼進行註冊:

 IocManager.IocContainer.Register(
                //註冊自定義支付回調邏輯
                Classes.FromAssembly(typeof(ApplicationCoreModule).GetAssembly())
                    .BasedOn<IPaymentCallbackAction>()
                    .LifestyleTransient()
                    .Configure(component => component.Named(component.Implementation.FullName))
                    .WithServiceFromInterface()
            );

除了上面的方式,我們還可以通過注入IPaymentManager對象,通過其RegisterCallbackAction方法來註冊自定義的回調邏輯。

  1. 發起支付

通過容器獲得IPayAppService,然後調用Pay方法即可。也可以自行封裝:

public async Task<object> Payment(PaymentInput input)
        {
            return await _payAppService.Pay(new PayInputBase()
            {
                Body = $"{input.Name} {input.ChargeProjectName}",
                CustomData = input.ToJsonString(),
                Key = "繳費支付",
                OpenId = input.OpenId,
                Subject = input.ChargeProjectName,
                TotalAmount = input.Amount,
                PayChannel = input.PayChannel
            });
        }

通過IPayAppService統一支付有如下好處:

  • 統一支付(無論支付寶還是微信各種端的支付,均可統一)

  • 自動記錄交易日誌以及進行相關邏輯處理

  • 自定義數據依賴交易日誌進行存儲,而不依賴支付渠道,因此支持無業務參數的支付渠道,也支持存儲更多自定義數據

非ABP集成

請參考Abp相關模塊的封裝或者歷史代碼。

官方訂閱號

關注“麥扣聊技術”訂閱號免費獲取:

  • 最新文章、教程、文檔

  • 視頻教程

  • 基礎版免費授權

  • 模板

  • 解決方案

  • 編程心得和理念

官方博客/文檔站

其他開源庫地址

 

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

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

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

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

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

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

詳解Spring Security的formLogin登錄認證模式

一、formLogin的應用場景

在本專欄之前的文章中,已經給大家介紹過Spring Security的HttpBasic模式,該模式比較簡單,只是進行了通過攜帶Http的Header進行簡單的登錄驗證,而且沒有定製的登錄頁面,所以使用場景比較窄。
對於一個完整的應用系統,與登錄驗證相關的頁面都是高度定製化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定製登錄頁面,也就是本文給大家介紹的formLogin模式登錄認證模式。

準備工作

  • 新建一個Spring Boot 的web應用,引入Spring Security Starter。
  • 準備一個login.html登錄頁面,頁面內容非常簡單,一個from表單、用戶名和密碼輸入框,一個提交按鈕
  • 準備一個首頁index.html,在登錄成功之後需要進入index.html首頁
  • 首頁可以看到syslog(日誌管理)、sysuer(用戶管理)、biz1(業務一)、biz2(業務二)四個頁面超文本鏈接選項。通過controller控制層跳轉頁面,並在對應頁面寫一些標誌性文字即可,不需寫具體業務。

需求

  • 我們希望biz1(業務一)、biz2(業務二)普通的操作用戶user就可以訪問
  • 我們希望管理員可以訪問包括syslog(日誌管理)和sysuser(用戶管理)在內的所有資源

以上就是本文介紹formLogin模式需要進行的準備工作及需求,下面我們就來實現其中的核心的登錄驗證邏輯,準備工作非常簡單請自行實現。(新建spring boot應用,登錄頁面、首頁、四個業務頁面都寫成非常簡單的html即可,不用寫實際業務和樣式。)

二、說明

formLogin模式的三要素:

  • 登錄驗證邏輯
  • 資源訪問控制規則,如:資源權限、角色權限
  • 用戶信息

一般來說,使用權限認證框架的的業務系統登錄驗證邏輯是固定的,而資源訪問控制規則和用戶信息是從數據庫或其他存儲介質靈活加載的。但本文所有的用戶、資源、權限信息都是代碼配置寫死的,旨在為大家介紹formLogin認證模式,如何從數據庫加載權限認證相關信息我還會結合RBAC權限模型再寫文章的。

三、實現formLogin模式基礎配置

首先,我們要繼承WebSecurityConfigurerAdapter ,重寫configure(HttpSecurity http) 方法,該方法用來配置登錄驗證邏輯。請注意看下文代碼中的註釋信息。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable() //禁用跨站csrf攻擊防禦,後面的章節會專門講解
            .formLogin()
                .loginPage("/login.html")//用戶未登錄時,訪問任何資源都轉跳到該路徑,即登錄頁面
                .loginProcessingUrl("/login")//登錄表單form中action的地址,也就是處理認證請求的路徑
                .usernameParameter("uname")///登錄表單form中用戶名輸入框input的name名,不修改的話默認是username
                .passwordParameter("pword")//form中密碼輸入框input的name名,不修改的話默認是password
                .defaultSuccessUrl("/index")//登錄認證成功后默認轉跳的路徑
                .and()
            .authorizeRequests()
                .antMatchers("/login.html","/login").permitAll()//不需要通過登錄驗證就可以被訪問的資源路徑
                .antMatchers("/biz1").hasAnyAuthority("biz1")  //前面是資源的訪問路徑、後面是資源的名稱或者叫資源ID
                .antMatchers("/biz2").hasAnyAuthority("biz2")
                .antMatchers("/syslog").hasAnyAuthority("syslog")
                .antMatchers("/sysuser").hasAnyAuthority("sysuser")
                .anyRequest().authenticated();
    }
    
}

上面的代碼分為兩部分:

  • 第一部分是formLogin配置段,用於配置登錄驗證邏輯相關的信息。如:登錄頁面、登錄成功頁面、登錄請求處理路徑等。
  • 第二部分是authorizeRequests配置端,用於配置資源的訪問權限。如:開發登錄頁面的permitAll開放訪問,“/biz1”(業務一頁面資源)需要有資源ID為”biz1″的用戶才可以訪問。

這時候,我們通過瀏覽器訪問,隨便測試一個沒有訪問權限的資源,都會跳轉到login.html頁面。

四、實現資源訪問限制的需求

在上文中,我們配置了登錄驗證及資源訪問的權限規則,我們還沒有具體的用戶,下面我們就來配置具體的用戶。重寫WebSecurityConfigurerAdapter的 configure(AuthenticationManagerBuilder auth)方法

public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user").password(passwordEncoder().encode("123456")).authorities("biz1","biz2")
        .and()
        .passwordEncoder(passwordEncoder());//配置BCrypt加密
}

@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
}
  • inMemoryAuthentication指的是在內存裏面存儲用戶的身份認證和授權信息。
  • withUser("user")用戶名是user
  • password(passwordEncoder().encode("123456"))密碼是加密之後的123456
  • authorities("biz1","biz2")指的是user用戶擁有資源ID為biz1(業務一)和biz2(業務二)資源的權限

這樣,我們就實現了文首提出的普通用戶只能訪問biz1(業務一)和biz2(業務二)資源的需求。那麼管理員用戶可以訪問所有的資源的配置方式,你會不會呢?同樣的配方、同樣的方式、自己可以嘗試一下哦!

五、靜態資源訪問

在我們的實際開發中,登錄頁面login.html和控制層Controller登錄驗證’/login’都必須無條件的開放。除此之外,一些靜態資源如css、js文件通常也都不需要驗證權限,我們需要將它們的訪問權限也開放出來。下面就是實現的方法:重寫WebSecurityConfigurerAdapter類的configure(WebSecurity web) 方法


   @Override
    public void configure(WebSecurity web) {
        //將項目中靜態資源路徑開放出來
        web.ignoring().antMatchers("/config/**", "/css/**", "/fonts/**", "/img/**", "/js/**");
    }

期待您的關注

  • 博主最近新寫了一本書:
  • 本文轉載註明出處(必須帶連接,不能只轉文字):。

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

【其他文章推薦】

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

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

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

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