標籤: 網頁設計公司

  • 「譯」靜態單賦值小冊 – 1. 介紹

    「譯」靜態單賦值小冊 – 1. 介紹

    有一本小冊子Static Single Assignment Book寫的很好,內容又較少,試着翻譯一下,意譯較多(說人話),不是嚴肅的翻譯,感興趣的可以看看。頻率可能是周更。。anyway,stay tuned~

    在日常編程中,名字是一個很有用的東西。這本書想傳遞的關鍵內容是對於每個不同的東西給它一個獨一無二的名字可以消除很多不確定性以及不精確性。

    舉個例子,如果你無意中聽到一段對話中有’Homer’這個詞,沒有上下文的情況下你不知道他說的是Homer Simpson(辛普森)還是古希臘詩人荷馬還是你認識的某個叫Homer的人。但是只要你聽到對話提及Springfield (辛普森一家)而不是Smyrna(希臘詩歌),你就能知道他們說的是辛普森一家這個電視劇。不過話又說回來,如果每個人都有一個獨一無二的名字,那麼就不可能混淆電視劇角色和古希臘文學人物,這個問題都不會成立。

    這本書主要討論靜態單賦值(Static Single Assignment Form,SSA)形式,它是一種變量的命名約定。術語static說明SSA與屬性和代碼分析相關,術語single說明SSA強制變量名具有唯一性。術語assignment表示變量的定義。舉個例子,在下面的代碼中:

    x = y + 1;
    

    變量x被賦予表達式(y+1)的值。這是一個定義,或者對於x來說是賦值語句。編譯器工程師會說上面的賦值語句將值(y+1)儲存到左值x中。

    1.1 SSA定義

    關於SSA最簡單,限制最少的定義如下:

    “如果每個變量在程序中有且只有一個賦值語句,那麼該程序是SSA形式”

    但是實際上SSA還有很多變體,有更多的限制。這些變體可能使變量定義和使用與圖論的一些特性有關,或者封裝一些特定的控制流/數據流信息。每個SSA變體都有特設的性質。基本的SSA變體將會在第二章討論,本書的第三部分還會討論更多這部分的內容。

    所有SSA變體,包括上面最簡單的定義都有一個最基本屬性就是引用透明性(referential transparency),所謂引用透明性是指程序中的每個變量只有一個定義,變量的值和它所在程序的位置無關。我們可能根據分支的條件完善對於某個變量的認識。舉個例子,不用看代碼我們就知道下面if語句后緊跟着的then/else條件塊中x的值

    if (x == 0)
    

    因為x的值在這個if語句中是沒有改變的。函數式編程語言寫的程序是引用透明的,引用透明性對於形式化方法和數學推理很有用,因為表達式的值只依賴它的子表達式而不依賴求值的順序或者表達式的副作用,或者其它表達式。對於一個引用透明的程序,考慮下面的代碼片段:

    x = 1;
    y = x + 1;
    x = 2;
    z = x + 1;
    

    一個naive(而且不正確)的分析器可能認為y和z的值相等,因為他們的定義是一樣的,都是(x+1),然而x的值取決於當前代碼位置是在第二個賦值的前面還是後面,即變量的值取決於上下文。當編譯器將這個代碼段轉換為SSA形式時,它會具有引用透明性。轉換的過程會為一個變量的多次定義使用不同的名字(譯註:x1和x2)。使用SSA形式后,只有當x1和x2相等時y和z才相等。

    x1 = 1;
    y = x1 + 1;
    x2 = 2;
    z = x2 + 1;
    

    1.2 SSA的非形式化語義

    在前一節中,我們看到了如何通過簡單的重命名將代碼轉換為SSA形式。賦值語句左邊被定義的變量叫做target,在SSA中,每個target都有唯一的名字。反過來,賦值語句右邊可以多次使用target,在這裏它們叫做source。貫穿本書,SSA的target名字定義都是變量名再加一個下標這種形式。一般來說這是不重要的實現細節,雖然它對於編譯器debug來說很有用。

    φ函數是SSA最重要的一個概念,它很特別,又叫做偽賦值函數(pseudo-assignment function)。有些人也叫它notational fiction。ɸ函數的用途是合併來自不同路徑的值,一般出現在控制流的合併點。

    考慮下面的代碼示例和它對應的控制流圖(Control Flow Graph,CFG)表示:

    在if不同分支中,y有不同的定義。y的不同定義最終在print那個地方交匯。當編譯器將該代碼轉換為SSA形式時,y的不同定義被命名為y1和y2。print既可以使用y1也可以使用y2,這取決於if的條件。在這種情況下,需要用φ函數引入新的變量y3,它的參數是y1和y2。因此SSA版本的上述程序如下:

    就放置位置來說,φ函數一般是放到控制流交匯點,即CFG中有多個前驅基本塊的那個基本塊頭部。如果有n條路徑可以進入基本塊b,那麼在基本塊b頭部的φ函數有n個參數。φ函數會動態的選擇正確的參數。φ函數根據n個參數,創建新的變量名,這個名字是唯一的,因為它要保證SSA的基本性質。因此,在上面的例子中,如果控制流從基本塊A流向下面的基本塊,那麼y3使用φ函數選擇y1作為它的值,反之φ函數使用y2作為它的值。注意CFG圖φ函數的參數y1和y2前面還加了基本塊的標籤,這種形式是比較多餘的,在本書的後面部分,這個基本塊標籤能不加就不加,除非沒了它會引起歧義。

    這裏還要強調一下,如果基本塊頭部有多個φ函數,這些φ函數是并行的,即,它們是同時執行,不需要順序執行。這一點是很重要的,因為在經過一些優化,比如複寫傳播(copy propagation)后φ函數的target可能是其它φ函數的source。在SSA解構階段,φ函數會被消除(譯註:就是編譯器不需要SSA形式,想將它轉換為其它IR,這就叫SSA解構),在解構階段使用常規的複製操作序列化,這點會在17.6小結描述。這個小細節對於寄存器分配后的代碼來說是相當重要的。

    嚴格來說,φ函數不能被軟件直接執行,因為進入φ函數的控制流沒有被顯式的編碼進φ函數的參數。這是可以接受的,因為φ函數通常只用於程序的靜態分析。然而,有很多擴展使得φ函數可以執行,如 φif 或者γ函數(參見第12章),它有一個額外的參數,告訴φ函數選擇那個值。關於這個會在第12章,第16章和第18章討論。

    接下來我們再展示一個例子,它說明了一個循環控制流解構的SSA形式。下面是非SSA形式的程序和SSA形式的控制流圖:

    SSA代碼在循環頭部新增了兩個φ函數。它們合併循環前的值定義和循環中的值的定義。

    要注意不要混淆SSA和自動并行化優化中的(動態)靜態賦值這兩個概念。SSA不會阻止在程序執行的時候對一個變量的多次定義,比如,上面的SSA代碼中,變量y3和x3在循環體內,每次循環都會重定義它們。

    SSA構造的詳細描述會在第3章給出,現在只需要明白下面的內容:

    1. 如果程序的交匯點的某個變量有多個定義,那麼會在交匯點插入φ函數
    2. 整數下標用於重命名原來程序中的變量x和y

    1.3 與傳統數據流分析的比較

    在未來的第11章我們會提到,SSA主要的一個優點是它對數據流分析(data-flow analysis)很友好。數據流分析在程序編譯的時候收集信息,為未來的代碼優化做準備。在程序運行時,這些信息會在變量間流動。靜態分析通過在控制流圖中傳播這些信息,得以捕獲關於數據流的一些事實(fact)。這種方式在傳統的數據流分析中很常見。

    通常,如果程序是一種功能性的(functional)或者稀疏(sparse)的表示,如SSA形式,那麼數據流信息能程序中更高效的傳播。當程序被轉換為SSA形式時,變量在定義點被重命名。對於一個確鑿的數據流問題,比如常量傳播,它表現為一個程序點的集合,在這些程序點數據流事實可能改變。因此可以直接關聯數據流事實和變量名字,而不是在每個程序點為所有變量維護各自的數據流事實的集合,下圖展示了一個非零值分析(non-zero value analysis)

    對於程序中的每個變量,分析的目標是靜態確定哪些變量在運行時包含0值(即null)。在這裏0就表示變量為null,0打一把叉表示不為null,T表示可能為null。上圖(a)表示傳統的數據流分析,我們會在六個基本塊的入口點和出處都計算一次變量x和y信息。而在上圖(b)的基於SSA的數據流分析中,我們只需要在變量定義處計算一下,然後就能獲得六個數據流事實。

    對於其它的數據流問題,屬性也可能在變量定義之外發生改變,這些問題只要插入一些φ函數就能放入稀疏數據流分析的框架中,第11章會有一個例子討論這個。總的來說,目前這個例子說明了SSA能給分析算法帶來的關鍵好處是:

    1. 數據流信息直接從定義語句處傳播到使用它的地方,即通過def-use鏈,這個鏈條由SSA命名方式隱示給出。相反,傳統的數據流分析需要將信息傳遍整個程序,即便在很多地方這些信息都沒改變,或者不相關。
    2. 基於SSA的數據流分析更簡潔。在示例中,比起傳統方式,基於SSA的分析只有很少的數據流事實。

    這本書的第二部分給出了一個完整的基於SSA數據流分析的描述。

    1.4 此情此景此SSA

    歷史背景。在整個20世紀80年代,優化編譯器技術越來越成熟,各種中間表示被提出,它們包含了數據依賴,使得數據流分析在這些中間表示上很容易進行。在這些中間表示背後的設計理念是顯式/隱式包含變量定義和使用的關係,即def-use鏈條,使得數據流信息能有效的傳播。程序依賴圖(program dependence graph)和程序依賴網(program dependence web)均屬此類IR。第12章還會討論這些風格的IR的更多細節。

    靜態單賦值是由IBM Research開發的一種IR,並在20世紀80年代末的幾篇研究論文中公開發表。SSA由於其符合直覺的性質和直觀的構造算法得到了廣泛的應用。SSA給出了一個標準化的變量def-use鏈,簡化了很多數據流分析技術。

    當前狀況。當前主流的商業編譯器和開源編譯器,包括GCC,LLVM,HotSpot Java虛擬機,V8 JavaScript引擎都將SSA作為程序分析中的關鍵表示。由於在SSA執行優化速度快而且高效,那些即時編譯器(JIT)會在一些高級地、與平台無關的表示(如Java字節碼,CLI字節碼,LLVM bitcode)上廣泛使用SSA。
    SSA最初是為了簡化高級程序表示的變形而開發而創建的,因為其良好的特性,能夠簡化算法和減少計算複雜性。今天,SSA形式甚至被用於最後的代碼生成階段(見第四部分),即後端。好幾個工業編譯器和學術編譯器,既有靜態,也有just-in-time,都在它們的後端使用SSA,如LLVM,HotSpot,LAO,libFirm,Mono。很多使用SSA的編譯器在編譯快要結束時,即寄存器分配前才解構SSA。最近的研究甚至能在寄存器分配期間也使用SSA,SSA形式會保持到非常非常後面的機器代碼生成過程才會被解構。

    SSA與高級語言。到目前為止,我們展示了在低級代碼上使用SSA形式做分析的優勢。有趣的是,在高級代碼上如果強制遵循某些準則也可能具有SSA的性質。根據SISAL語言的定義,程序自動具備引用透明性,因為變量不允許多次賦值。其它語言也能有SSA的性質,比如Java的變量加個final或者C#的變量加個const/readonly。

    強制寫出具有SSA性質的高級語言程序主要好處是這些程序能具備不變形,這簡化了併發編程。豬肚的數據能在多個線程中自由的共享,沒有任何數據依賴問題。數據依賴對於多核處理器來說是一個大問題。

    在函數式編程語言中,引用透明是語言的基本特性。因此函數式編程隱式具有SSA性質。第6章會介紹SSA和函數式編程。

    1.5 餘下本章

    本章引入了SSA的符號表示,本書的剩下部分就SSA的各個方面詳細討論。本書的終極目標是:

    1. 清晰的描述SSA能為程序分析帶來哪些好處
    2. 消除那些阻止人們使用SSA的謬誤

    本節還剩下一些內容,它們與下一章的一些主題相關。

    1.5.1 SSA的好處

    SSA對於變量命名有嚴格要求,每個變量的名字都是獨一無二的。賦值語言和控制流交匯點會引入新的變量名。這些簡化了表達變量def-use關係的數據結構實現和變量存活範圍。本書第二部分關注基於SSA的數據流恩熙,使用SSA主要有三個好處:

    編譯時受益。如果程序是SSA形式,很多編譯器優化可以高效的進行,因為引用透明性意味着數據流信息直接與變量關聯,而不是每個程序點的變量。關於這一點我們已經在1.3的非零值分析中演示過了。

    編譯器開發受益。SSA使得程序分析和轉換能更容易表達。這意味着編譯器工程師能更高產,可以寫更多的pass,並且能debug更多的pass(譯註:smile)。舉個例子,基於SSA的GCC4.x的死代碼優化比非GCC3.x的非SSA死代碼優化實現總代碼少了40%。

    程序運行時受益。理論上,能基於SSA實現的分析和優化也能基於其它非SSA形式。前一點提到過,基於SSA的實現代碼更少,因此很多基於SSA的編譯器優化也能更高效進行,關於這一點的示例是一類控制流不敏感分析(control-flow insensitive analysis),具體參見論文Using static single assignment form to improve flowinsensitive pointer analysis

    1.5.2 SSA謬論

    一些人認為SSA很複雜很繁瑣,不能高效表達程序。這本書的目的就是讓讀者免去這些擔憂。下面的表單展示了關於SSA常見的謬論,以及破除謬論的章節。

    謬論 破除謬論
    SSA讓變量數爆炸 第二章會回顧SSA的主要變體,一些變體引入的變量數比原始SSA形式少很多
    SSA的性質難以維持 第三章和第五章討論了一些修復SSA性質的簡單技術(因為一些優化可能重寫中間表示,導致SSA性質被破壞)
    SSA的性質難以維持 第三章和第十七章展示了高效且效果顯著的SSA解構算法的複製操作

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

    【其他文章推薦】

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

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

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

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

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

  • 【譯】Introducing YARP Preview 1

    1 YARP

        YARP是一個項目,用於創建反向代理服務器。它開始於我們注意到來自微軟內部團隊的一系列問題。他們要麼為其服務構建反向代理,要麼詢問 API 和用於構建 API 的技術。因此我們決定讓他們聚在一起開發一個通用解決方案,該解決方案形成了YARP。

        YARP是一個反向代理工具包,用於使用 ASP.NET 和 .NET 中的基礎設施在 .NET 中構建代理服務器。YARP 的主要區別是,它被設計為易於自定義和調整,以滿足不同方案的特定需求。YARP 插入ASP.NET管道以處理傳入請求,然後它擁有自己的子管道,用於執行將請求代理到後端服務器的步驟。客戶可以添加其他module,或根據需要更換常備module。

        隨着其開發已基本到位,我們製作了 YARP 的第一個正式版本(Preview 1),以便更好地協作並獲得反饋。

    2 Preview 1 是什麼

      • 核心代理的基礎結構
      • 基於配置的路由定義
      • 擴展性的管道模型
      • Forwarded標頭(硬編碼)
      • 目標 .NET Core 3.1 和 .NET Core 5

    3 Preview 1 不包括

      • 會話親和性(又稱會話保持)
      • Forwarded標頭(可配置)
      • 基於代碼的路由定義和預請求路由
      • 指標和日誌
      • 性能調整
      • 連接篩選

    4 快速開始

    Step 01 下載.net framework

        YARP 適用於 .NET Core 3.1 或 .NET 5 Preview 4(或更高版本)。

    Step 02 創建一個ASP.NET Core項目

    Step 03 打開項目,添加引用,確保其包含

    <PropertyGroup>
        <TargetFramework>netcoreapp5.0</TargetFramework>
    </PropertyGroup>

      和

    <ItemGroup>
        <PackageReference Include="Microsoft.ReverseProxy" Version="1.0.0-preview.1.*" />
    </ItemGroup>

    Step 04 Startup.cs

      YARP 當前使用配置文件來定義代理的路由和終結點。在ConfigureServices方法中加載。

    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddReverseProxy()
            .LoadFromConfig(Configuration.GetSection("ReverseProxy"));
    }

      Configure方法定義ASP.NET的請求處理管道。反向代理插入到ASP.NET的終結點路由,然後具有其自己的代理子管道。在這裏,可以添加代理管道模塊(如負載均衡)來自定義請求的處理。

    /// <summary>
    /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    public void Configure(IApplicationBuilder app)
    {
        app.UseHttpsRedirection();
    
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapReverseProxy(proxyPipeline =>
            {
                proxyPipeline.UseProxyLoadBalancing();
            });
        });
    }

    Step 05 配置

      YARP 的配置定義在appsettings.json中:

    "ReverseProxy": {
        "Routes": [
          {
            "RouteId": "app1",
            "BackendId": "backend1",
            "Match": {
              "Methods": [ "GET", "POST" ],
              "Host": "localhost",
              "Path": "/app1/"
            }
          },
          {
            "RouteId": "route2",
            "BackendId": "backend2",
            "Match": {
              "Host": "localhost"
            }
          }
        ],
        "Backends": {
          "backend1": {
            "LoadBalancing": {
              "Mode": "Random"
            },
            "Destinations": {
              "backend1_destination1": {
                "Address": "https://example.com:10000/"
              },
              "backend1_destination2": {
                "Address": "http://example.com:10001/"
              }
            }
          },
          "backend2": {
            "Destinations": {
              "backend2_destination1": {
                "Address": "https://example.com:10002/"
              }
            }
          }
        }
      }
      • Backends:請求可以路由到的服務器群集。
      • Destinations:是用於指標、日誌記錄和會話保持的標識符。
      • Address:URL前綴(基地址)
      • Routes:根據請求的各個方面(如主機名、路徑、方法、請求標頭等)將傳入請求映射到後端群集。路由是有序的,因此,需要首先定義 app1 路由,因為 route2 將作為尚未匹配的所有路徑的 catchall。

      好啦,先介紹到這裏。

    原文鏈接

      https://devblogs.microsoft.com/dotnet/introducing-yarp-preview-1/?utm_source=vs_developer_news&utm_medium=referral

     

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

    【其他文章推薦】

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

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

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

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

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

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

  • Mybatis詳解(二) sqlsession的創建過程

    Mybatis詳解(二) sqlsession的創建過程

    我們處於的位置

    我們要清楚現在的情況.

    現在我們已經調用了SqlSessionFactoryBuilder的build方法生成了SqlSessionFactory 對象.

    但是如標題所說,要想生成sqlsession還要另一步SqlSessionFactory 調用openSession()方法生成sqlsession;

    這就要從上一部分代碼講起

    上文講到

    我們創建的實際上是一個叫做DefaultSqlSessionFactory的類,實際上他是一個SqlSessionFactory接口(沒錯,這玩應是接口)的實現類.

    既然sqlsession是由opensession產生的,那我們就先看這個方法.

    說一嘴題外話就是自動提交也是在這個部分設置的,下面是如果你設置了autocommit的情況.

    public SqlSession openSession(boolean autoCommit) {
      //this.configuration.getDefaultExecutorType()值為 ExecutorType.SIMPLE;
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);
    }
    

    參數中 configuration 獲取了默認的執行器 “SIMPLE”.

    DefaultSqlSessionFactory

    調用了一個同一個類中openSessionFromDataSource方法.

    在這個類中是如下執行流程

    所要知道的一部分知識.

    environments運行環境

    MyBatis 核心配置綜述之 Configuration詳解

    其實就是數據庫連接那個部分.

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
      Transaction tx = null;
      try {
        //從configuration對象中得到環境配置的對象
        final Environment environment = configuration.getEnvironment();
        //這個對象被用來創建一個事務工廠->一號分支
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      //事務工廠創建一個事務對象->二號分支
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        //而 configurationye 則會根據事務對象和執行器類型創建一個執行器。
        ->三號分支
        final Executor executor = configuration.newExecutor(tx, execType);
        //返回一個默認的DefaultSqlSession對象
        ->四號分支
        return new DefaultSqlSession(configuration, executor, autoCommit);
      } catch (Exception e) {
        closeTransaction(tx); // may have fetched a connection so lets call close()
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
      } finally {
        ErrorContext.instance().reset();
      }
    }
    

    現在我們要從一號分支開始

    一號分支

    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);

    這個代碼如下:

    我們發現有兩種可能性.

    如果傳進來的值沒有設置 標籤那麼他會執行 ManagedTransactionFactory()而反之則會執行 environment.getTransactionFactory()

    這兩者產生的對象都實現了 TransactionFactory接口.

    這裏ManagedTransactionFactory()是沒有標籤時生成的對象.其核心就是一句

    private boolean closeConnection = true;的屬性.

    我們不必過於關注這個部分.

    private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
      if (environment == null || environment.getTransactionFactory() == null) {
       //如果沒有目標標籤
        return new ManagedTransactionFactory();
      }
      //如果有目標標籤
      return environment.getTransactionFactory();
    }
    

    environment.getTransactionFactory()產生的東西才是重點.

    調用環境對象的getTransactionFactory方法,該方法和我們配置的一樣返回了一個 JdbcTransactionFactory,而實際上,TransactionFactory 只有2個實現類,一個是 ManagedTransactionFactory (沒有標籤時返回的),一個是 JdbcTransactionFactory(有標籤時返回的)。

    至此一號分支結束,從此看來,一號分支實際上是將environment對象包裝成一個工廠對象.

    請返回一號分支之前部分繼續.

    分支二

    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

    我們回到openSessionFromDataSource方法,獲取了 JdbcTransactionFactory 后,調用 JdbcTransactionFactorynewTransaction方法創建一個事務對象.

    當然因為代碼中採用TransactionFactory 接口作為聲明對象.所以無論分之一傳回來的是哪個工廠對象.在分支二中都可以執行.

    我們先講 JdbcTransactionFactory的情況.

    分支二中調用的是這個newTransaction方法.(還有一個重載的)

    public Transaction newTransaction(Connection conn) {
      return new JdbcTransaction(conn);
    }
    

    這就到了另一個類中JdbcTransaction中.

    JdbcTransaction

    我刪掉其中的實現代碼

    public class JdbcTransaction implements Transaction {
    
      private static final Log log = LogFactory.getLog(JdbcTransaction.class);
    
      protected Connection connection;
      protected DataSource dataSource;
      protected TransactionIsolationLevel level;
      protected boolean autoCommmit;
    
      public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
        dataSource = ds;
        level = desiredLevel;
        autoCommmit = desiredAutoCommit;
      }
    
      public JdbcTransaction(Connection connection) {
        this.connection = connection;
      }
    
      public Connection getConnection() throws SQLException {
      
      }
    
      public void commit() throws SQLException {
       
      }
    
      public void rollback() throws SQLException {
        
      }
    
      public void close() throws SQLException {
        
      }
    
      protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
       
      }
    
      protected void resetAutoCommit() {
        
      }
    
      protected void openConnection() throws SQLException {
       
      }
    
    }
    

    其實只要看了代碼你就會發現,這個類中的方法,和我們調用session的方法高度重合.比如commit,rollback等等.而且還能設置事務的隔離級別

    所以我們有理由認為,這個類就是對jdbc連接部分的封裝.

    總結

    至此分支二結束,我們對於 標籤在xml中的存在情況,會返回兩種截然不同對象.一種是作為jdbc連接封裝的 JdbcTransaction對象.另一個則是 ManagedTransaction對象(這個沒講….)

    分支三

    第三分支我們將回到Configuration對象.

    Configuration對象

    法此時已經創建好事務對象。接下來將事務對象執行器作為參數執行 configuration 的 newExecutor 方法來獲取一個 執行器類。我們看看該方法實現:

    首先第一句將判斷是否傳入了一個excutorType參數,如果沒有就用默認的參數.

    也就是 ExecutorType.SIMPLE(前面出現過),然後根據執行的類型來創建不同的執行器,默認是 SimpleExecutor 執行器.

    Mybatis有三種基本的Executor執行器:

    • SimpleExecutor:每執行一次update或select,就開啟一個Statement對象,用完立刻關閉Statement對象。

    • ReuseExecutor:執行update或select,以sql作為key查找Statement對象,存在就使用,不存在就創建,用完后,不關閉Statement對象,而是放置於Map<String, Statement>內,供下一次使用。簡言之,就是重複使用Statement對象。

    • BatchExecutor:執行update(沒有select,JDBC批處理不支持select),將所有sql都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個Statement對象,每個Statement對象都是addBatch()完畢后,等待逐一執行executeBatch()批處理。與JDBC批處理相同。

    作用範圍:Executor的這些特點,都嚴格限制在SqlSession生命周期範圍內。

    然後我們看下一句部分

    Executor executor;
    //看看上文.這是根據傳入的內容不同,最終結果是
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    

    我們先將 BatchExecutor執行器.

    該類包裝了事務對象,延遲加載的隊列,本地緩存,永久緩存,配置對象,還包裝了自己。

    傳入的兩個參數分別為存儲了配置信息的Configuration對象,以及封裝了jdbc中連接數據庫部分代碼的JdbcTransaction對象.

    回到 newExecutor 方法,判斷是否使用緩存,默認是true, 則將剛剛的執行器包裝到新的 CachingExecutor 緩存執行器中。最後將執行器添加到所有的攔截器中(如果配置了話),我們這裏沒有配置。

    到此分支三結束

    總結:

    我們從用從分支二得到的對象,構建了一個執行器.這個執行對象,包括事務對象(即連jdbc連接部分的控制封裝.JdbcTransaction),延遲加載的隊列,本地緩存,永久緩存,配置對象(Configuration),還包裝了自己。

    四號分支

    我們已經有了執行器,此時創建 DefaultSqlSession 對象,攜帶 configuration, executor, autoCommit 三個參數,該構造器就是簡單的賦值過程。我們有必要看看該類的結構:

    該類包含了常用的所有方法,包括事務方法,可以說,該類封裝了執行器和事務類。而執行器才是具體的執行工作人員。

    至此,我們已經完成了 SqlSession 的創建過程。

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

    【其他文章推薦】

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

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

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

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

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

  • C#9.0 終於來了,您還學的動嗎? 帶上VS一起解讀吧!(應該是全網第一篇)

    C#9.0 終於來了,您還學的動嗎? 帶上VS一起解讀吧!(應該是全網第一篇)

    一:背景

    1. 講故事

    好消息,.NET 5.0 終於在2020年6月10日發布了第五個預覽版,眼尖的同學一定看到了在這個版本中終於支持了 C# 9.0,此處有掌聲,太好了!!!

    .Net5官方鏈接

    可以看到目前的C#9還是預覽版,實現了一部分新語法供開發者提前嘗鮮,從github的roslyn倉庫上可以看到目前準備實現 17個新特性,現階段已經實現了8個,其中的 In Progress 表示正在開發中。

    新特性預覽

    2. 安裝必備

    • 下載最新的net5 sdk吧: dotnet-sdk-5.0.100-preview.5.20279.10-win-x64.exe

    • 下載最新的 visual studio 2019 preview 2

    找好你自己的vs版本類型哦。。。

    二:新特性研究

    1. Target-typed new

    這個取名一定要留給學易經的大師傅,沒見過世面的我不敢造次,取得不佳影響時運,所謂 運去金成鐵, 時來鐵似金 ,不過大概意思就是說直接new你定義的局部變量的類型,用issues中總結的話就是:

    
    Summary: Allow Point p = new (x, y);
    Shipped in preview in 16.7p1.
    
    

    接下來就是全部代碼,看看使用前使用后 的具體差別。

    
        class Program
        {
            static void Main(string[] args)
            {
                //老語法
                var person = new Person("mary", "123456");
    
                //新語法
                Person person2 = new("mary", "123456");
    
                Console.WriteLine($"person={person}person2={person2}");
            }
        }
    
        public class Person
        {
            private string username;
            private string password;
    
            public Person(string username, string password)
            {
                this.username = username;
                this.password = password;
            }
    
            public override string ToString()
            {
                return $"username={username},password={password} \n";
            }
        }
    
    

    然後用ilspy去看看下面的il代碼,是不是省略了Person,讓自己心裏踏實一點。

    總的來說這語法還行吧,能起到延長鍵盤使用壽命的功效。

    2. Lambda discard parameters

    從字面上看大概就是說可以在lambda上使用取消參數,聽起來怪怪的,那本意是什麼呢?有時候lambda上的匿名方法簽名的參數是不需要的,但在以前必須實打實的定義,這樣就會污染方法體,也就是可以在body中被訪問,如下圖:

    但有時候因為客觀原因必須使用Func<int,int,int>這樣的委託,而且還不想讓方法簽名的參數污染方法體,我猜測在函數式編程中有這樣的場景吧,可能有點類似MVC中的EmptyResult效果。

    好了,我想你大概知道啥意思了,接下來實操一把。。。

    
        Func<int, int, int> func = (_, _) =>
        {
            return 0;
        };
    
        var result = func(10, 20);
    
    

    從圖中可以看到,我在方法體中是找不到所謂的 _ 變量的,這就神奇了,怎麼做到的呢? 帶着這個好奇心看看它的IL代碼是個什麼樣子。

    
    .method private hidebysig static 
    	void Main (
    		string[] args
    	) cil managed 
    {
    	// Method begins at RVA 0x2048
    	// Code size 45 (0x2d)
    	.maxstack 3
    	.entrypoint
    	.locals init (
    		[0] class [System.Runtime]System.Func`3<int32, int32, int32> func,
    		[1] int32 result
    	)
    
    	IL_0000: nop
    	IL_0001: ldsfld class [System.Runtime]System.Func`3<int32, int32, int32> ConsoleApp1.Program/'<>c'::'<>9__0_0'
    	IL_0006: dup
    	IL_0007: brtrue.s IL_0020
    
    	IL_0009: pop
    	IL_000a: ldsfld class ConsoleApp1.Program/'<>c' ConsoleApp1.Program/'<>c'::'<>9'
    	IL_000f: ldftn instance int32 ConsoleApp1.Program/'<>c'::'<Main>b__0_0'(int32, int32)
    	IL_0015: newobj instance void class [System.Runtime]System.Func`3<int32, int32, int32>::.ctor(object, native int)
    	IL_001a: dup
    	IL_001b: stsfld class [System.Runtime]System.Func`3<int32, int32, int32> ConsoleApp1.Program/'<>c'::'<>9__0_0'
    
    	IL_0020: stloc.0
    	IL_0021: ldloc.0
    	IL_0022: ldc.i4.s 10
    	IL_0024: ldc.i4.s 20
    	IL_0026: callvirt instance !2 class [System.Runtime]System.Func`3<int32, int32, int32>::Invoke(!0, !1)
    	IL_002b: stloc.1
    	IL_002c: ret
    } // end of method Program::Main
    
    

    從上面的IL代碼來看 匿名方法 變成了<>c類的<Main>b__0_0方法,完整簽名: ConsoleApp1.Program/'<>c'::'<Main>b__0_0'(int32, int32),然後再找一下 <Main>b__0_0 方法的定義。

    
    .class nested private auto ansi sealed serializable beforefieldinit '<>c'
    	extends [System.Runtime]System.Object
    	.method assembly hidebysig 
    		instance int32 '<Main>b__0_0' (
    			int32 _,
    			int32 _
    		) cil managed 
    	{
    		// Method begins at RVA 0x2100
    		// Code size 7 (0x7)
    		.maxstack 1
    		.locals init (
    			[0] int32
    		)
    
    		IL_0000: nop
    		IL_0001: ldc.i4.0
    		IL_0002: stloc.0
    		IL_0003: br.s IL_0005
    
    		IL_0005: ldloc.0
    		IL_0006: ret
    	} // end of method '<>c'::'<Main>b__0_0'
    
    

    這說明什麼呢? 說明兩個參數是真實存在的,但編譯器搗了鬼,做了語法上的限制,不讓你訪問所謂的 _

    等等。。。有一個問題,IL中的方法簽名怎麼是這樣的: <Main>b__0_0 (int32 _,int32 _) , 大家應該知道方法簽名中不可以出現重複的參數名,比如下面這樣定義肯定是報錯的。

    這說明什麼? 說明這個語法糖不僅需要編譯器支持,更需要底層的JIT支持,那怎麼證明呢?我們用windbg去底層挖一挖。。。為了方便調試,修改如下:

    
            static void Main(string[] args)
            {
                Func<int, int, int> func = (_, _) =>
                {
                    Console.WriteLine("進入方法體了!!!");
                    Console.ReadLine();
                    return 0;
                };
    
                var result = func(10, 20);
            }
    
    0:000> !clrstack -p
    OS Thread Id: 0x52e8 (0)
    0000007035F7E5C0 00007ffaff362655 ConsoleApp1.Program+c.b__0_0(Int32, Int32) [C:\5\ConsoleApp1\ConsoleApp1\Program.cs @ 13]
        PARAMETERS:
            this (0x0000007035F7E600) = 0x000001968000cb48
            _ (0x0000007035F7E608) = 0x000000000000000a
            _ (0x0000007035F7E610) = 0x0000000000000014
    

    從圖中可以看到,雖然都是 _ ,但在線程棧上是完完全全的兩個棧地址。 0x0000007035F7E6080x0000007035F7E610

    三:總結

    總的來說,C#是越來越向函數式編程靠攏,越來越像Scala,就像Jquery的口號一樣: Write less,do more。

    好了,先就說這兩個吧,大家先安裝好工具,明天繼續解剖~~~

    如您有更多問題與我互動,掃描下方進來吧~

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

  • Elasticsearch系列—生產數據備份恢復方案

    Elasticsearch系列—生產數據備份恢復方案

    前言

    生產環境中運行的組件,只要有數據存儲,定時備份、災難恢復是必修課,mysql數據庫的備份方案已經非常成熟,Elasticsearch也同樣有成熟的數據備份、恢復方案,我們來了解一下。

    概要

    本篇介紹Elasticsearch生產集群數據的數據備份、恢復和升級的常規操作。

    curl命令

    curl是Linux操作的必備工具,Elasticsearch生產環境的搭建,不能保證都能使用kibana訪問到,而Elasticsearch Restful API都可以使用curl工具來完成訪問。

    使用curl還有一個好處:有些操作需要一連串的請求才能完成,我們可以使用shell腳本將這些關聯的操作,封裝到腳本里,後續使用起來就非常方便。

    如果有定時執行的命令,也是使用shell將一系列操作封裝好,運用Linux自帶的crontab進行觸發。

    後續的一些操作命令,將會用curl來完成,並且只需要將完整的curl請求拷貝到kibana的dev tools上,kibana能夠自動轉化成我們之前常見的請求,非常方便。

    在Linux下的請求命令:

    [esuser@elasticsearch02 ~]$ curl -XGET 'http://elasticsearch02:9200/music/children/_search?pretty' -H 'Content-Type: application/json' -d '
    {
      "query": {
        "match_all": {}
      }
    }
    '
    

    完整的命令拷貝到dev tools里時,自動會變成:

    GET /music/children/_search
    {
    
      "query": {
    
        "match_all": {}
    
      }
    
    }
    

    這工具真是強大,不過反過來操作不行的,我已經試過了。

    curl命令,有Body體的,記得加上-H 'Content-Type: application/json'?pretty參數可以讓響應結果格式化輸出

    數據備份

    我們知道Elasticsearch的索引拆分成多個shard進行存儲在磁盤裡,shard雖然分了primary shard和replica shard,可以保證集群的數據不丟失,數據訪問不間斷,但如果機房停電導致集群節點全部宕機這種重大事故時,我們就需要提前定期地對數據進行備份,以防萬一。

    既然是磁盤文件存儲,那存儲介質的選擇就有很多了:本地磁盤,NAS,文件存儲服務器(如FastDFS、HDFS等),各種雲存儲(Amazon S3, 阿里雲OSS)等

    同樣的,Elasticsearch也提供snapshot api命令來完成數據備份操作,可以把集群當前的狀態和數據全部存儲到一個其他目錄上,本地路徑或網絡路徑均可,並且支持增量備份。可以根據數據量來決定備份的執行頻率,增量備份的速度還是很快的。

    創建備份倉庫

    我們把倉庫地址暫定為本地磁盤的/home/esuser/esbackup目錄,

    首先,我們需要在elasticsearch.yml配置文件中加上

    path.repo: /home/esuser/esbackup

    並重啟Elasticsearch。

    啟動成功后,發送創建倉庫的請求:

    [esuser@elasticsearch02 ~]$ curl -XPUT 'http://elasticsearch02:9200/_snapshot/esbackup?pretty' -H 'Content-Type: application/json' -d '
    {
        "type": "fs", 
        "settings": {
            "location": "/home/esuser/esbackup",
            "max_snapshot_bytes_per_sec" : "50mb", 
            "max_restore_bytes_per_sec" : "50mb"
        }
    }
    '
    {"acknowledged":true}
    [esuser@elasticsearch02 ~]$ 
    

    參數解釋:

    • type: 倉庫的類型名稱,請求里都是fs,表示file system。
    • location: 倉庫的地址,要與elasticsearch.yml配置文件相同,否則會報錯
    • max_snapshot_bytes_per_sec: 指定數據從Elasticsearch到倉庫(數據備份)的寫入速度上限,默認是20mb/s
    • max_restore_bytes_per_sec: 指定數據從倉庫到Elasticsearch(數據恢復)的寫入速度上限,默認也是20mb/s

    用於限流的兩個參數,需要根據實際的網絡進行設置,如果備份目錄在同一局域網內,可以設置得大一些,便於加快備份和恢復的速度。

    也有查詢命令可以看倉庫的信息:

    [esuser@elasticsearch02 ~]$ curl -XGET 'http://elasticsearch02:9200/_snapshot/esbackup?pretty'
    
    {"esbackup":{"type":"fs","settings":{"location":"/home/esuser/esbackup","max_restore_bytes_per_sec":"50mb","max_snapshot_bytes_per_sec":"50mb"}}}
    
    [esuser@elasticsearch02 ~]$
    

    使用hdfs創建倉庫

    大數據這塊跟hadoop生態整合還是非常推薦的方案,數據備份這塊可以用hadoop下的hdfs分佈式文件存儲系統,關於hadoop集群的搭建方法,需要自行完成,本篇末尾有補充說明,可供參考。

    對Elasticsearch來說,需要安裝repository-hdfs的插件,我們的Elasticsearch版本是6.3.1,對應的插件則使用repository-hdfs-6.3.1.zip,hadoop則使用2.8.1版本的。

    插件下載安裝命令:

    ./elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/repository-hdfs/repository-hdfs-6.3.1.zip

    如果生產環境的服務器無法連接外網,可以先在其他機器上下載好,上傳到生產服務器,解壓到本地,再執行安裝:

    ./elasticsearch-plugin install file:///opt/elasticsearch/repository-hdfs-6.3.1

    安裝完成後記得重啟Elasticsearch節點。

    查看節點狀態:

    [esuser@elasticsearch02 ~]$ curl -XGET elasticsearch02:9200/_cat/nodes?v
    
    ip             heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
    192.168.17.137           38          95   2    0.03    0.03     0.05 mdi       *      node-1
    
    創建hdfs倉庫

    先查看節點的shard信息

    [esuser@elasticsearch02 ~]$ curl -XGET 'http://elasticsearch02:9200/_count?pretty' -H 'Content-Type: application/json' -d '
     {
         "query": {
             "match_all": {}
         }
    }'
    
    
    {
      "count" : 5392,
      "_shards" : {
        "total" : 108,
        "successful" : 108,
        "skipped" : 0,
        "failed" : 0
      }
    }
    
    

    創建一個hdfs的倉庫,名稱為hdfsbackup

    [esuser@elasticsearch02 ~]$ curl -XPUT  'http://elasticsearch02:9200/_snapshot/hdfsbackup?pretty' -H 'Content-Type: application/json' -d '
     {
       "type": "hdfs",
       "settings": {
         "uri": "hdfs://elasticsearch02:9000/",
         "path": "/home/esuser/hdfsbackup",
       "conf.dfs.client.read.shortcircuit": "false",
       "max_snapshot_bytes_per_sec" : "50mb", 
         "max_restore_bytes_per_sec" : "50mb"
       }
     }'
    
    {
      "acknowledged" : true
    }
    
    驗證倉庫

    倉庫創建好了之後,可以用verify命令驗證一下:

    [esuser@elasticsearch02 ~]$ curl -XPOST 'http://elasticsearch02:9200/_snapshot/hdfsbackup/_verify?pretty'
    {
      "nodes" : {
        "A1s1uus7TpuDSiT4xFLOoQ" : {
          "name" : "node-1"
        }
      }
    }
    
    索引備份

    倉庫創建好並驗證完成后,可以執行snapshot api對索引進行備份了,

    如果不指定索引名稱,表示備份當前所有open狀態的索引都備份,還有一個參數wait_for_completion,表示是否需要等待備份完成后才響應結果,默認是false,請求提交後會立即返回,然後備份操作在後台異步執行,如果設置為true,請求就變成同步方式,後台備份完成后,才會有響應。建議使用默認值即可,有時備份的整個過程會持續1-2小時。

    示例1:備份所有的索引,備份名稱為snapshot_20200122

    [esuser@elasticsearch02 ~]$ curl -XPUT 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122?pretty'
    {
      "accepted" : true
    }
    

    示例2:備份索引music的數據,備份名稱為snapshot_20200122_02,並指定wait_for_completion為true

    [esuser@elasticsearch02 ~]$ curl -XPUT 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122_02?wait_for_completion=true&pretty' -H 'Content-Type: application/json' -d '
    {
      "indices": "music",
      "ignore_unavailable": true,
      "include_global_state": false,
      "partial": true
    }'
    
    
    {
      "snapshot" : {
        "snapshot" : "snapshot_20200122_02",
        "uuid" : "KRXnzc6XSWagCQO92EQx6A",
        "version_id" : 6030199,
        "version" : "6.3.1",
        "indices" : [
          "music"
        ],
        "include_global_state" : false,
        "state" : "SUCCESS",
        "start_time" : "2020-01-22T07:11:06.594Z",
        "start_time_in_millis" : 1579677066594,
        "end_time" : "2020-01-22T07:11:07.313Z",
        "end_time_in_millis" : 1579677067313,
        "duration_in_millis" : 719,
        "failures" : [ ],
        "shards" : {
          "total" : 5,
          "failed" : 0,
          "successful" : 5
        }
      }
    }
    

    這條命令中幾個參數介紹:

    • indices:索引名稱,允許寫多個,用”,”分隔,支持通配符。
    • ignore_unavailable:可選值true/false,如果為true,indices里不存在的index就可以忽略掉,備份操作正常執行,默認是false,如果某個index不存在,備份操作會提示失敗。
    • include_global_state:可選值true/false,含義是要不要備份集群的全局state數據。
    • partial:可選值true/false,是否支持備份部分shard的數據。默認值為false,如果索引的部分primary shard不可用,partial為false時備份過程會提示失敗。

    使用snapshot api對數據的備份是增量進行的,執行snapshotting的時候,Elasticsearch會分析已經存在於倉庫中的snapshot對應的index file,在前一次snapshot基礎上,僅備份創建的或者發生過修改的index files。這就允許多個snapshot在倉庫中可以用一種緊湊的模式來存儲,非常節省存儲空間,並且snapshotting過程是不會阻塞所有的Elasticsearch讀寫操作的。

    同樣的,snapshot作為數據快照,在它之後寫入index中的數據,是不會反應到這次snapshot中的,snapshot數據的內容包含index的副本,也可以選擇是否保存全局的cluster元數據,元數據裡面包含了全局的cluster設置和template。

    每次只能執行一次snapshot操作,如果某個shard正在被snapshot備份,那麼這個shard此時就不能被移動到其他node上去,這會影響shard rebalance的操作。只有在snapshot結束之後,這個shard才能夠被移動到其他的node上去。

    查看snapshot備份列表
    1. 查看倉庫內所有的備份列表
    curl -XGET 'http://elasticsearch02:9200/_snapshot/hdfsbackup/_all?pretty'
    
    1. 查看單個備份數據
    [esuser@elasticsearch02 ~]$ curl -XGET 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122_02?pretty'
    {
      "snapshots" : [
        {
          "snapshot" : "snapshot_20200122_02",
          "uuid" : "KRXnzc6XSWagCQO92EQx6A",
          "version_id" : 6030199,
          "version" : "6.3.1",
          "indices" : [
            "music"
          ],
          "include_global_state" : false,
          "state" : "SUCCESS",
          "start_time" : "2020-01-22T07:11:06.594Z",
          "start_time_in_millis" : 1579677066594,
          "end_time" : "2020-01-22T07:11:07.313Z",
          "end_time_in_millis" : 1579677067313,
          "duration_in_millis" : 719,
          "failures" : [ ],
          "shards" : {
            "total" : 5,
            "failed" : 0,
            "successful" : 5
          }
        }
      ]
    }
    
    刪除snapshot備份

    如果需要刪除某個snapshot備份快照,一定要使用delete命令,造成別自個跑到服務器目錄下做rm操作,因為snapshot是增量備份的,裏面有各種依賴關係,極可能損壞backup數據,記住不要上來就自己干文件,讓人家標準的命令來執行,命令如下:

    [esuser@elasticsearch02 ~]$ curl -XDELETE 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122?pretty'
    {
      "acknowledged" : true
    }
    
    查看備份進度

    備份過程長短視數據量而定,wait_for_completion設置為true雖然可以同步得到結果,但時間太長的話也不現實,我們是希望備份操作後台自己搞,我們時不時的看看進度就行,其實還是調用的snapshot的get操作命令,加上_status參數即可,備份過程中會显示什麼時間開始的,有幾個shard在備份等等信息:

    curl -XGET 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122_02/_status?pretty'

    取消備份

    正在備份的數據可以執行取消,使用的是delete命令:

    curl -XDELETE 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122?pretty'

    這個命令有兩個作用:

    1. 如果備份正在進行中,那麼取消備份操作,並且刪除備份了一半的數據。
    2. 如果備份已經完成,直接刪除備份數據。

    數據恢復

    生產環境的備份操作,是定期執行的,執行的頻率看實際的數據量,有1天執行1次的,有4小時一次的,簡單的操作是使用shell腳本封裝備份的命令,然後使用Linux的crontab定時執行。

    既然數據有備份,那如果數據出現異常,或者需要使用到備份數據時,恢復操作就能派上用場了。

    常規恢復

    數據恢復使用restore命令,示例如下:

    [esuser@elasticsearch02 ~]$ curl -XPOST 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122_02/_restore?pretty'
    {
      "accepted" : true
    }
    

    注意一下被恢復的索引,必須全部是close狀態的,否則會報錯,關閉索引的命令:

    [esuser@elasticsearch02 ~]$ curl -XPOST  'http://elasticsearch02:9200/music/_close?pretty'
    

    恢復完成后,索引自動還原成open狀態。

    同樣有些參數可以進行選擇:

    [esuser@elasticsearch02 ~]$ curl -XPOST 'http://elasticsearch02:9200/_snapshot/hdfsbackup/snapshot_20200122_02/_restore
    {
        "indices": "music", 
    	"ignore_unavailable": true,
    	"include_global_state": true
    }
    

    默認會把備份數據里的索引全部還原,我們可以使用indices參數指定需要恢復的索引名稱。同樣可以使用wait_for_completion參數,ignore_unavailable、partial和include_global_state與備份時效果相同,不贅述。

    監控restore的進度

    與備份類似,調用的recovery的get操作命令查看恢復的進度:

    curl -XGET 'http://elasticsearch02:9200/music/_recovery?pretty'

    music為索引名稱。

    取消restore

    與備份類似,delete正在恢復的索引可以取消恢復過程:

    curl -XDELETE 'http://elasticsearch02:9200/music'

    集群升級

    我們現在使用的版本是6.3.1,目前官網最新版本已經是7.5.2了,如果沒有重大的變更或嚴重bug報告的情況下,一般是不需要做升級,畢竟升級有風險,發布要謹慎。

    這裏就簡單說一下通用的步驟,謹慎操作:

    1. 查看官網最新版本的文檔,從當前版本到目標版本的升級,有哪些變化,新加入的功能和修復的bug。
    2. 在開發環境或測試環境先執行升級,相應的插件也做一次匹配升級,穩定運行幾個項目版本周期后,再考慮生產環境的升級事宜。
    3. 升級前對數據進行全量的備份,萬一升級失敗,還有挽救的餘地。
    4. 申請生產環境升級的時間窗口,逐個node進行升級驗證。

    補充hadoop集群搭建

    Elasticsearch的數據備份,通常建議的實踐方案是結合hadoop的hdfs文件存儲,這裏我們搭建一個hadoop的集群環境用作演示,hadoop相關的基礎知識請自行了解,已經掌握的童鞋可以跳過。

    版本環境:
    hadoop 2.8.1

    虛擬機環境

    hadoop集群至少需要3個節點。我們選用elasticsearch02、elasticsearch03、elasticsearch04三台機器用於搭建。

    1. 下載解壓

    官網下載hadoop-2.8.1.tar.gz,解壓至/opt/hadoop目錄

    1. 設置環境變量

    演示環境擁有root權限,就介紹一種最簡單的設置方法,修改/etc/profile文件,添加變量後記得source一下該文件。

    
    [root@elasticsearch02 ~]# vi /etc/profile
    
    # 文件末尾添加
    export HADOOP_HOME=/opt/hadoop/hadoop-2.8.1
    export PATH=${HADOOP_HOME}/bin:$PATH
    
    [root@elasticsearch02 ~]# source /etc/profile
    
    1. 創建hadoop數據目錄,啟動hadoop時我們使用esuser賬戶,就在/home/esuser下創建目錄,如 /home/esuser/hadoopdata

    2. 修改hadoop的配置文件,在/opt/hadoop/hadoop-2.8.1/etc/hadoop目錄下,基本上是添加配置,涉及的配置文件:

    • core-site.xml
    • hdfs-site.xml
    • yarn-site.xml
    • mapred-site.xml
    • slaves(注:我們選定elasticsearch02為master,其餘兩個為slave)

    示例修改如下:

    core-site.xml
    
    <property>
      <name>fs.defaultFS</name>
      <value>hdfs://elasticsearch02:9000</value>
    </property>
    
    hdfs-site.xml
    
    <property>
      <name>dfs.namenode.name.dir</name>
      <value>/home/esuser/hadoopdata/namenode</value>
    </property>
    <property>
      <name>dfs.datanode.data.dir</name>
      <value>/home/esuser/hadoopdata/datanode</value>
    </property>
    
    yarn-site.xml
    
    <property>
      <name>yarn.resourcemanager.hostname</name>
      <value>elasticsearch02</value>
    </property>
    
    mapred-site.xml
    
    <property>
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
    </property>
    
    slaves
    
    elasticsearch03
    elasticsearch04
    
    1. 拷貝設置后的文件到另外兩台機器上
    scp -r /opt/hadoop/hadoop-2.8.1 esuser@elasticsearch03:/opt/hadoop/hadoop-2.8.1
    scp -r /opt/hadoop/hadoop-2.8.1 esuser@elasticsearch04:/opt/hadoop/hadoop-2.8.1
    

    拷貝的文件有點大,需要等一會兒,拷貝完成后,在elasticsearch03、elasticsearch04再設置一次HADOOP_HOME環境變量

    1. 啟動集群

    格式化namenode,在hadoop master節點(elasticsearch02),HADOOP_HOME/sbin目錄下執行hdfs namenode -format

    執行啟動命令:start-dfs.sh
    這個啟動過程會建立到elasticsearch03、elasticsearch04的ssh連接,輸入esuser的密碼即可,也可以提前建立好免密ssh連接。

    我們只需要用它的hdfs服務,其他的組件可以不啟動。

    驗證啟動是否成功,三台機器分別輸入jps,看下面的進程,如無意外理論上應該是這樣:
    elasticsearch02:NameNode、SecondaryNameNode
    elasticsearch03:DataNode
    elasticsearch04:DataNode

    同時在瀏覽器上輸入hadoop master的控制台地址:http://192.168.17.137:50070/dfshealth.html#tab-overview,應該能看到這兩個界面:

    datanodes看到2個結點,表示集群啟動成功,如果只能看到一個或一個都沒有,可以查看相應的日誌:/opt/hadoop/hadoop-2.8.1/logs

    Error: JAVA_HOME is not set and could not be found 錯誤解決辦法

    這個明明已經設置了JAVA_HOME,並且export命令也能看到,啟動時死活就是不行,不跟他杠了,直接在/opt/hadoop/hadoop-2.8.1/etc/hadoop/hadoop-env.sh文件加上

    export JAVA_HOME="/opt/jdk1.8.0_211"

    小結

    本篇主要以hadoop分佈式文件存儲為背景,講解了Elasticsearch數據的備份與恢復,可以了解一下。集群版本升級這類操作,實踐起來比較複雜,受項目本身影響比較大,這裏就簡單提及要注意的地方,沒有作詳細的案例操作,真要有版本升級的操作,請各位慎重操作,多驗證,確保測試環境充分測試后再上生產,記得數據要備份。

    專註Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公眾號:Java架構社區
    可以掃左邊二維碼添加好友,邀請你加入Java架構社區微信群共同探討技術

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

    【其他文章推薦】

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

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

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

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

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

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

  • Accord.NET重啟4.0 開發

    Accord.NET重啟4.0 開發

    Accord.NET Framework是在AForge.NET基礎上封裝和進一步開發來的。功能也很強大,因為AForge.NET更注重與一些底層和廣度,而Accord.NET Framework更注重與機器學習這個專業,在其基礎上提供了更多統計分析和處理函數,包括圖像處理和計算機視覺算法,所以側重點不同,但都非常有用。 官方網站:http://accord-framework.net/

    在項目中斷2年時間之後,作者cesarsouza 在2020年5月1日更新了項目狀態, 他在歐洲完成博士,雖然他的工作中主要使用Python完成他的工作,但是他喜歡C#/.NET,一直在考慮Accprd.NET的發展問題,5月15日重新設定了4.0 版本的路線圖https://github.com/accord-net/framework/issues/2123,  其中他寫道:“我看到這個項目仍然被認為對許多人有用,我不認為讓項目消亡符合任何人的利益。我最初認為這個項目將由ML.NET取代,但事實並非如此。我們可以轉換框架,轉而與它合作。”

    我們在ML.NET的最初宣布文章中有Accord.NET的影子:

    CNTK 已經死了,目前只有 Tensoflow.NET在蓬勃發展,發展的情況很不錯,隨着Accord.NET的加入,這個生態又重新激活,期待大家一起加入,推動.NET機器學習生態的發展。

    (一)框架的三大功能模塊

    Accord.NET框架主要有三個大的功能性模塊。

    • 分別為科學技術,
    • 信號與圖像處理,
    • 支持組件。

    下面將對3個模型的命名空間和功能進行簡單介紹。可以讓大家更快的接觸和了解其功能是否是自己想要的,下面是主要的命名空間介紹。

    (二) 科學計算

    Accord.Math:包括矩陣擴展程序,以及一組矩陣數值計算和分解的方法,也包括一些約束和非約束問題的數值優化算法,還有一些特殊函數以及其他一些輔助工具。

    Accord.Statistics:包含概率分佈、假設檢驗、線性和邏輯回歸等統計模型和方法,隱馬爾科夫模型,(隱藏)條件隨機域、主成分分析、偏最小二乘判別分析、內核方法和許多其他相關的技術。

    Accord.MachineLearning: 為機器學習應用程序提供包括支持向量機,決策樹,樸素貝恭弘=叶 恭弘斯模型,k-means聚類算法,高斯混合模型和通用算法如Ransac,交叉驗證和網格搜索等算法。

    Accord.Neuro:包括大量的神經網絡學習算法,如Levenberg-Marquardt,Parallel Resilient Backpropagation,Nguyen-Widrow初始化算法,深層的信念網絡和許多其他神經網絡相關的算法。具體看參考幫助文檔。

    (三)信號與圖像處理

    Accord.Imaging:包含特徵點探測器(如Harris, SURF, FAST and  FREAK),圖像過濾器、圖像匹配和圖像拼接方法,還有一些特徵提取器。

    Accord.Audio:包含一些機器學習和統計應用程序說需要的處理、轉換過濾器以及處理音頻信號的方法。

    Accord.Vision:實時人臉檢測和跟蹤,以及對人流圖像中的一般的檢測、跟蹤和轉換方法,還有動態模板匹配追蹤器。

    (四) 支持組件

    主要是為上述一些組件提供數據显示,繪圖的控件,分為以下幾個命名空間:

    Accord.Controls:包括科學計算應用程序常見的柱狀圖、散點圖和表格數據瀏覽。

    Accord.Controls.Imaging:包括用來显示和處理的圖像的WinForm控件,包含一個方便快速显示圖像的對話框。

    Accord.Controls.Audio:显示波形和音頻相關性信息的WinForm控件。

    Accord.Controls.Vision:包括跟蹤頭部,臉部和手部運動以及其他計算機視覺相關的任務WinForm控件。

    (五) 支持的算法介紹

    下面將Accord.NET框架包括的主要功能算法按照類別進行介紹。來源主要是官網介紹,進行了簡單的翻譯和整理。

    1、分類(Classification)

    SVM(支持向量機,類SupportVectorMachine、類KernelSupportVectorMachine、類SequentialMinimalOptimization—序列最小優化算法)、

    K-NN鄰近算法(類KNearestNeighbors);

    Logistic Regression(邏輯回歸)、

    Decision Trees(決策樹,類DecisionTree、ID3Learning、C45Learning)、

    Neural Networks(神經網絡)、

    Deep Learning(深度學習)

    (Deep Neural Networks深層神經網絡)、

    Levenberg-Marquardt with Bayesian Regularization、

    Restricted Boltzmann Machines(限制玻耳茲曼機)、

    Sequence classification (序列分類),

    Hidden Markov Classifiers and Hidden Conditional Random Fields(隱馬爾科夫分類器和隱藏條件隨機域)。

    2、回歸(Regression)

    Multiple linear regression(多元線性回歸-單因變量多自變量)、

    SimpleLinearRegression(線性回歸,類SimpleLinearRegression)、

    Multivariate linear regression(多元線性回歸-多因變量多自變量)、polynomial regression (多項式回歸)、logarithmic regression(對數回歸)、Logistic regression(邏輯回歸)、multinomial logistic regression(多項式邏輯回歸)(softmax) and generalized linear models(廣義線性模型)、L2-regularized L2-loss logistic regression , L2-regularized logistic regression , L1-regularized logistic regression , L2-regularized logistic regression in the dual form and regression support vector machines。

    3、聚類(Clustering)

    K-Means、K-Modes、Mean-Shift(均值漂移)、Gaussian Mixture Models(高斯混合模型)、Binary Split(二元分裂)、Deep Belief Networks(深層的信念網絡)、 Restricted Boltzmann Machines(限制玻耳茲曼機)。聚類算法可以應用於任意數據,包括圖像、數據表、視頻和音頻。

    4、概率分佈(Distributions)

    包括40多個分佈的參數和非參數估計。包括一些常見的分佈如正態分佈、柯西分佈、超幾何分佈、泊松分佈、伯努利;也包括一些特殊的分佈如Kolmogorov-Smirnov , Nakagami、Weibull、and Von-Mises distributions。也包括多元分佈如多元正態分佈、Multinomial 、Independent 、Joint and Mixture distributions。

    5、假設檢驗(Hypothesis Tests)

    超過35統計假設測試,包括單向和雙向方差分析測試、非參數測試如Kolmogorov-Smirnov測試和媒體中的信號測試。contingency table tests such as the Kappa test,with variations for multiple tables , as well as the Bhapkar and Bowker tests; and the more traditional Chi-Square , Z , F , T and Wald tests .

    6、核方法(Kernel Methods)

    內核支持向量機,多類和多標籤向量機、序列最小優化、最小二乘學習、概率學習。Including special methods for linear machines such as LIBLINEAR’s methods for Linear Coordinate Descent , Linear Newton Method , Probabilistic Coordinate Descent , Probabilistic Coordinate Descent in the Dual , Probabilistic Newton Method for L1 and L2 machines in both the dual and primal formulations .

    7、圖像(Imaging)

    興趣和特徵點探測器如Harris,FREAK,SURF,FAST。灰度共生矩陣,Border following,Bag-of-Visual-Words (BoW),RANSAC-based homography estimation , integral images , haralick textural feature extraction , and dense descriptors such as histogram of oriented gradients (HOG) and Local Binary Pattern (LBP).Several image filters for image processing applications such as difference of Gaussians , Gabor , Niblack and Sauvola thresholding。還有幾個圖像處理中經常用到的圖像過濾器。

    8、音頻信號(Audio and Signal)

    音頻信號的加載、解析、保存、過濾和轉換,如在空間域和頻域應用音頻過濾器。WAV文件、音頻捕捉、時域濾波器,高通,低通,波整流過濾器。Frequency-domain operators such as differential rectification filter and comb filter with Dirac’s delta functions . Signal generators for Cosine , Impulse , Square signals.

    9、視覺(Vision)

    實時人臉檢測和跟蹤,以及圖像流中檢測、跟蹤、轉換的一般的檢測方法。Contains cascade definitions , Camshift and Dynamic Template Matching trackers . Includes pre-created classifiers for human faces and some facial features such as noses。

    10、降維技術

    SVD奇異值分解(OctaveEnvironment.svd方法);

    PCA主成分分析(類PrincipalComponent);

    ICA獨立成份分析(類IndependentComponetAnalysis)

    11、算法精度測算

    混淆矩陣(類ConfusionMatrix);

    ROC曲線評估(類ReceiverOperatingCharacteristic);

    Bootstrap算法(自助算法;類(Bootstrap));

    CrossValidation算法(交叉檢驗;類(CrossValidation));

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

    【其他文章推薦】

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

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

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

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

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

  • .Net Core微服務入門全紀錄(一)——項目搭建

    .Net Core微服務入門全紀錄(一)——項目搭建

    前言

    寫這篇博客主要目的是記錄一下自己的學習過程,只能是簡單入門級別的,因為水平有限就寫到哪算哪吧,寫的不對之處歡迎指正。
    代碼放在:https://github.com/xiajingren/NetCoreMicroserviceDemo

    什麼是微服務?

    關於微服務的概念解釋網上有很多…
    個人理解,微服務是一種系統架構模式,它和語言無關,和框架無關,和工具無關,和服務器環境無關…
    微服務思想是將傳統的單體系統按照業務拆分成多個職責單一、且可獨立運行的接口服務。至於服務如何拆分,沒有明確的定義。
    幾乎任何後端語言都能做微服務開發。
    微服務也並不是完美無缺的,微服務架構會帶來更多的問題,增加系統的複雜度,引入更多的技術棧…

    創建項目

    一個客戶端,一個產品服務,一個訂單服務。3個項目都是asp.net core web應用程序。創建項目的時候記得啟用一下Docker支持,或者後面添加也行。

    為產品、訂單服務添加一些基礎代碼,就簡單的返回一下 服務名稱,當前時間,服務的ip、端口。

    在Docker中運行服務

    為了方便,我使用Docker來運行服務,不用Docker也行,關於docker的安裝及基本使用就不介紹了。

    • build鏡像:

    在項目根目錄打開PowerShell窗口執行:docker build -t productapi -f ./Product.API/Dockerfile .

    Successfully代表build成功了。

    • 運行容器:

    執行:docker run -d -p 9050:80 --name productservice productapi

    執行:docker ps查看運行的容器:

    沒問題,使用瀏覽器訪問一下接口:

    也沒問題,其中的ip端口是Docker容器內部的ip端口,所以端口是80,這個無所謂。

    • 產品服務部署好了,下面部署一下訂單服務,也是同樣的流程,就把指令簡單貼一下吧:

    build鏡像:docker build -t orderapi -f ./Order.API/Dockerfile .
    運行容器:docker run -d -p 9060:80 --name orderservice orderapi
    瀏覽器訪問一下:

    OK,訂單服務也部署完成了。

    客戶端調用

    客戶端我這裏只做了一個web客戶端,實際可能是各種業務系統、什麼PC端、手機端、小程序。。。這個明白就好,為了簡單就不搞那麼多了。

    • 因為客戶端需要http請求服務端接口,所以需要一個http請求客戶端,我個人比較習慣RestSharp,安利一波:https://github.com/restsharp/RestSharp

    • 添加基礎代碼:

    IServiceHelper.cs:

        public interface IServiceHelper
        {
            /// <summary>
            /// 獲取產品數據
            /// </summary>
            /// <returns></returns>
            Task<string> GetProduct();
    
            /// <summary>
            /// 獲取訂單數據
            /// </summary>
            /// <returns></returns>
            Task<string> GetOrder();
        }
    

    ServiceHelper.cs:

        public class ServiceHelper : IServiceHelper
        {
            public async Task<string> GetOrder()
            {
                string serviceUrl = "http://localhost:9060";//訂單服務的地址,可以放在配置文件或者數據庫等等...
    
                var Client = new RestClient(serviceUrl);
                var request = new RestRequest("/orders", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
    
            public async Task<string> GetProduct()
            {
                string serviceUrl = "http://localhost:9050";//產品服務的地址,可以放在配置文件或者數據庫等等...
    
                var Client = new RestClient(serviceUrl);
                var request = new RestRequest("/products", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
        }
    

    Startup.cs:

        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllersWithViews();
                
                //注入IServiceHelper
                services.AddSingleton<IServiceHelper, ServiceHelper>();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                }
                app.UseStaticFiles();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                        name: "default",
                        pattern: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    

    HomeController.cs:

        public class HomeController : Controller
        {
            private readonly ILogger<HomeController> _logger;
            private readonly IServiceHelper _serviceHelper;
    
            public HomeController(ILogger<HomeController> logger, IServiceHelper serviceHelper)
            {
                _logger = logger;
                _serviceHelper = serviceHelper;
            }
    
            public async Task<IActionResult> Index()
            {
                ViewBag.OrderData = await _serviceHelper.GetOrder();
                ViewBag.ProductData = await _serviceHelper.GetProduct();
    
                return View();
            }
    
            public IActionResult Privacy()
            {
                return View();
            }
    
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
            public IActionResult Error()
            {
                return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
            }
        }
    

    Index.cshtml:

    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div class="text-center">
        <h1 class="display-4">Welcome</h1>
        <p>
            @ViewBag.OrderData
        </p>
        <p>
            @ViewBag.ProductData
        </p>
    </div>
    

    代碼比較簡單,這裏就不用docker了,直接控制台啟動,使用瀏覽器訪問:

    • 一切正常。進行到這裏,各個服務也獨立運行了,客戶端也能正常調用了,貌似算是完成一個簡易的微服務了。但是,微服務架構最重要的原則就是——“高可用”。以上的做法明顯不能滿足高可用性,因為任何一個服務掛掉,所有依賴這個服務的業務系統都會受影響。

    停止一下訂單服務:docker stop orderservice

    訂單服務停止,導致客戶端業務系統無法獲取訂單數據。
    要解決這個問題,很容易想到:集群。

    簡單的服務集群

    既然單個服務實例有掛掉的風險,那麼部署多個服務實例就好了嘛,只要大家不同時全掛就行。

    • 使用docker運行多個服務實例:
    docker run -d -p 9061:80 --name orderservice1 orderapi
    docker run -d -p 9062:80 --name orderservice2 orderapi
    docker run -d -p 9051:80 --name productservice1 productapi
    docker run -d -p 9052:80 --name productservice2 productapi
    

    現在訂單服務和產品服務都增加到3個服務實例。

    • 那麼稍微改造一下客戶端代碼吧:
      ServiceHelper.cs:
    public class ServiceHelper : IServiceHelper
        {
            public async Task<string> GetOrder()
            {
                string[] serviceUrls = { "http://localhost:9060", "http://localhost:9061", "http://localhost:9062" };//訂單服務的地址,可以放在配置文件或者數據庫等等...
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(serviceUrls[new Random().Next(0, 3)]);
                var request = new RestRequest("/orders", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
    
            public async Task<string> GetProduct()
            {
                string[] serviceUrls = { "http://localhost:9050", "http://localhost:9051", "http://localhost:9052" };//產品服務的地址,可以放在配置文件或者數據庫等等...
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(serviceUrls[new Random().Next(0, 3)]);
                var request = new RestRequest("/products", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
        }
    

    當然拿到這些服務地址可以自己做複雜的負載均衡策略,比如輪詢,隨機,權重等等 都行,甚至在中間弄個nginx也可以。這些不是重點,所以就簡單做一個隨機吧,每次請求來了隨便訪問一個服務實例。

    • 瀏覽器測試一下:

      可以看到請求被隨機分配了。但是這種做法依然不安全,如果隨機訪問到的實例剛好掛掉,那麼業務系統依然會出問題。
      簡單處理思路是:
      1.如果某個地址請求失敗了,那麼換一個地址接着執行。
      2.如果某個地址的請求連續多次失敗了,那麼就移除這個地址,下次就不會訪問到它了。
      。。。。。。
      業務系統實現以上邏輯,基本上風險就很低了,也算是大大增加了系統可用性了。

    • 然後思考另一個問題:

    實際應用中,上層的業務系統可能非常多,為了保證可用性,每個業務系統都去考慮服務實例掛沒掛掉嗎?
    而且實際應用中服務實例的數量或者地址大多是不固定的,例如雙十一來了,流量大了,增加了一堆服務實例,這時候每個業務系統再去配置文件里配置一下這些地址嗎?雙十一過了又去把配置刪掉嗎?顯然是不現實的,服務必須要做到可靈活伸縮。

    • 這時候就引入一個名詞:服務註冊與發現

    未完待續…

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

    【其他文章推薦】

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

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

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

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

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

  • 看完這些黑科技,我覺得寶馬的真實身份其實是科技公司!

    看完這些黑科技,我覺得寶馬的真實身份其實是科技公司!

    寶馬通過一台基於全新BMW 5系的原型車展示了未來高度自動駕駛汽車極為個性化、智能化的駕駛感受。在高度自動駕駛狀態下,駕駛者的雙手和雙腳都得到了解放,無需手握方向盤和控制油門、剎車。同時,BMW實時交通信號系統還可以預測前方下一組信號燈情況,讓駕駛者更好地進行選擇。

    (拉斯維加斯/北京)2017年1月5日,一年一度的科技盛會、2017國際消費电子展在拉斯維加斯拉開帷幕。寶馬集團攜一系列前瞻理念和科技成果亮相,展現了其在智能互聯、未來汽車內部設計、控制與显示系統、自動駕駛等創新領域蓬勃的創造力。

    寶馬集團正在成為引領数字出行生活的重要力量。在其願景中,自動駕駛技術將為駕駛者帶來更多選擇和自由;豐富的智能互聯服務圍繞人的需求,將車輛與用戶的数字生活無縫對接,讓出行和生活更高效、便捷、充滿樂趣。重要的是,這些離我們的生活並不遙遠,近年在CES上亮相的手勢控制、遠程3D環視影像等,均迅速應用於量產車型,體現了寶馬在行業內的領先地位。

    這不是科幻大片,是你未來的汽車

    在CES展台,寶馬集團通過BMW i Inside Future未來內室研究項目展示出,未來配備自動駕駛技術的汽車,其座艙將根據用戶需求,在休息室、辦公室和娛樂室之間實現自由切換。

    未來,車內空間的氛圍和控制方式將取決於駕駛模式。在主動駕駛模式下,主動駕駛的功能將處於車內中心位置。在高度自動駕駛模式下,系統將显示更多的舒適、信息娛樂和通訊功能。導航系統可以推薦適合高度或完全自動駕駛的行車路線,並在到達路口時發出提醒。未來,自動駕駛將首先應用於高速或單向行駛道路。

    對人機交互模式的創新是未來車輛的重要課題。寶馬在最近的兩屆CES上都帶來了創新的人機交互系統——手勢控制和AirTouch手勢控制系統。其中手勢控制已經應用於量產的新BMW 7系和全新BMW 5系車型。今年,寶馬又帶來了BMW HoloActive觸控系統,將人機交互體驗提升至新的高度。

    BMW HoloActive觸控系統的原理與平視显示系統類似,通過反射原理在中控台位置投射出一塊“懸浮”屏幕,駕駛者通過指尖“點擊”虛擬屏幕來控制車輛,呈現出科幻大片的既視感。這套系統通過高敏感度的攝像頭捕捉駕駛者指尖的動作。在超聲波裝置的配合下,客戶的手指可以感受到輕微的壓力,模擬了傳統觸控屏的體驗,讓操作更符合人們的習慣。

    未來的車輛內,駕駛者和乘客可以各自享受音樂而不互相干擾。首次展出的音效裝置BMW Sound Curtain通過座椅頭枕發射出不同的聲音信號,為座位上的用戶提供個性化的專屬娛樂信息。一個可摺疊的大尺寸屏幕可從車內頂篷延伸出來,進一步豐富後排乘客的車內互聯生活。

    擁有一台高度互聯的自動駕駛汽車是一種怎樣的體驗?

    寶馬通過一台基於全新BMW 5系的原型車展示了未來高度自動駕駛汽車極為個性化、智能化的駕駛感受。在高度自動駕駛狀態下,駕駛者的雙手和雙腳都得到了解放,無需手握方向盤和控制油門、剎車。同時,BMW實時交通信號系統還可以預測前方下一組信號燈情況,讓駕駛者更好地進行選擇。

    在自動泊車功能展示中,抵達停車場時,車輛自動與泊車管理服務進行連接,显示屏會提示駕駛者可以使用預約的停車位。駕駛者與乘客下車后,車輛隨即啟動自動泊車功能。BMW雲端互聯將在車輛停好後向駕駛者推送提示信息。通過全新BMW 5系中首次配備的環視影像系統,用戶還可以通過BMW雲端互聯應用實時查看車輛情況。

    在自動駕駛帶來的閑暇時間里,駕駛者可以盡情享受豐富的智能互聯功能。例如,在車輛行進途中,前排乘客可以通過BMW增強手勢控制系統、獲取途經場所的信息,如娛樂場所的節目單,還可以直接訂票。

    在開放式移動雲的支持下,BMW 雲端互聯可以整合豐富的應用,讓人們在車內便捷地處理各種事務。比如已經在家用電腦上推出的個人数字助理“微軟小娜(Cortana)”也可以在BMW汽車上使用。在駕駛過程中,用戶可以通過語音控制讓小娜推薦就餐地點並預定位置。

    通過與亞馬遜prime Now速遞服務合作,未來在行車途中預約收取快遞也成為可能。設想一下,用戶正前往一個生日聚會,但忘了購買禮物,通過這一功能,用戶可以從容地在車內在線購物。prime Now與開放式移動雲將根據車輛位置、路線和實時交通信息計算出最佳交付地點;車輛到達交付點之後,prime Now的員工將把貨物送到用戶的手中。BMW 雲端互聯無疑為智能、便捷的数字生活帶來了巨大的想象空間。BMW 雲端互聯已於2016年12月在中國正式上線,未來這些功能也將逐步升級到現有版本中。

    BMW不僅在車庫,還可以在客廳——智能出行和智能生活相結合

    在2017 CES上,寶馬集團還將全新的智能互聯科技從車內延伸到用戶的家中,標志著BMW 雲端互聯與家居環境的結合。未來,通過創新的智能終端BMW Conncted Window,用戶在家也可以享受BMW雲端互聯的豐富功能。

    當用戶開始新的一天時,BMW Connected Window的界面將显示溫暖的問候,與此同時,用戶每天的出行日程會按照時間軸進行显示,出行目的地,建議出發時間、天氣情況等信息一目瞭然。BMW Connected Window的虛擬界面通過手勢來操作,與觸摸屏一樣直觀。更新信息也可以通過BMW 雲端互聯方便地添加到日程中並與其他智能設備保持同步,幫助用戶胸有成竹地開始新一天的生活。

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

    【其他文章推薦】

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

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

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

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

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

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

  • 吉利大法好!沃爾沃去年銷量創紀錄,換髮第二春!

    吉利大法好!沃爾沃去年銷量創紀錄,換髮第二春!

    2016年沃爾沃汽車進一步確立了在自動駕駛、電氣化及安全領域的領先地位,建立了新的商業聯盟,並不斷推出全新的產品,打造立足全球的生產製造基地。2016年沃爾沃汽車斥資5億美元在美國南卡羅來納州興建工廠,將生產基於SpA架構的車型,初期將聘用2,000餘名員工。

    沃爾沃汽車集團近日發布2016年銷售業績显示,2016年沃爾沃汽車全球共實現銷量534,332輛,同比增長6.2%,連續三年創銷量紀錄。2016年沃爾沃汽車在全球各大市場銷量齊頭並進,在中國和北美兩大市場均實現了兩位數增幅,西歐市場表現強勁,沃爾沃汽車全球復興第二階段持續加速。

    S90

    沃爾沃全新90系車型2016年銷量飄紅,其中XC90車型銷量較2015年激增了125%,印證了沃爾沃全新的設計語言及創新科技在全球取得成功,為未來沃爾沃全新車型的上市,打下堅實的基礎。同時,沃爾沃XC60車型年銷量達到161,092輛,自2008年投放市場以來,連續九年屢創銷量紀錄。

    XC90

    2016年沃爾沃汽車在中國市場銷量達90,930輛,同比增長11.5%。中國依然是沃爾沃汽車全球最大單一市場。其中,國產沃爾沃XC60和S60L是沃爾沃汽車在中國市場最暢銷的車型。

    沃爾沃汽車2016年在美國市場銷量增幅達18.1%,是美國增速最快的豪華汽車品牌之一,實現年銷量82,726輛。其中沃爾沃XC90和XC60最受美國消費者歡迎,市場表現出眾。得益於德國、英國、法國和意大利等主要市場強勁業績的推動,2016年沃爾沃汽車在西歐銷量增長4.1%,達到206,144輛。

    沃爾沃汽車2016年實現銷量破紀錄的同時,通過全球復興和品牌重新定位持續強化與其他豪華品牌的競爭優勢。2016年沃爾沃汽車進一步確立了在自動駕駛、電氣化及安全領域的領先地位,建立了新的商業聯盟,並不斷推出全新的產品,打造立足全球的生產製造基地。

    2016年沃爾沃汽車斥資5億美元在美國南卡羅來納州興建工廠,將生產基於SpA架構的車型,初期將聘用2,000餘名員工。2016年沃爾沃汽車發布了中國製造戰略,在提升產能的同時,將中國打造成了面向全球市場的生產和出口基地。沃爾沃大慶工廠生產旗艦級全新S90系家族,成都工廠生產現款60系及未來全新60系車型,基於CMA架構的全新40系車型正在規劃中,將在距上海以南350公里的路橋工廠投產。

    2016年9月,隨着沃爾沃全新V90 Cross Country旅行越界車的上市,沃爾沃全新90系車型已全部完成換代。其中XC90車型更是榮獲120多個國際大獎,充分展現了沃爾沃全新SpA架構在設計、技術等方面的領先優勢。

    V90 Cross Country

    未來幾年,沃爾沃汽車將以每年兩款全新車型的速度完成全部產品換代。2017年將推出基於SpA架構的全新XC60車型,以及基於CMA架構的首款40系產品——全新XC40車型;在新能源領域,2016年沃爾沃汽車發布了全方位的電氣化戰略,將在全系車型中引入插電式混合動力系統,並在2019年之前推出首款純電動車,到2025年將實現新能源車型累計銷量100萬輛。

    2016年沃爾沃汽車與優步(Uber)公司攜手合作開發自動駕駛技術,與瑞典奧托立夫公司(Autoliv)合作建立了合資公司——Zenuity,致力於設計和開發自動駕駛軟件及高級駕駛輔助系統,將為快速發展的全球市場提供自動駕駛軟件等服務。這也是豪華汽車品牌首次與一線供應商聯手開發相關技術,將為汽車行業帶來重大變革。

    2017年沃爾沃汽車將在瑞典總部哥德堡進一步推動Drive Me自動駕駛測試項目。作為目前全球最先進、最前沿的自動駕駛測試項目,沃爾沃汽車將提供100輛XC90自動駕駛汽車用於普通居民在真實的日常環境中出行使用。未來,沃爾沃汽車還將在中國與英國啟動DriveMe自動駕駛測試項目。

    隨着全球復興進度的加快及全新商業模式的拓展,沃爾沃汽車不僅是全球豪華汽車製造商,還將成為了一家全球高端移動出行公司。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

  • 20萬就能買到全新寶馬轎車?!因為它真的來了

    20萬就能買到全新寶馬轎車?!因為它真的來了

    新車基於UKL前驅平台打造,1系三廂將會是前驅車型,新車的動力系統或為1。5T 136馬力+6速自動變速箱,2。0T 192馬力/231馬力+8擋手自一體變速箱,其中官方聲稱1。5T車型的百公里油耗最低可以達到5。5L。新車將會有無鑰匙啟動、抬頭显示、倒車影像、全景天窗、LED大燈、pM2。

    寶馬1系三廂自從誕生的那一刻就備受關注,吸睛無數,小編也和大家一樣,時刻關注着寶馬1系三廂的所有信息。畢竟,哪個男人心裏沒有這一個藍天白雲夢,開寶馬也是很多人的心愿。

    但是寶馬作為豪華品牌,價格不是每個消費者都能承受的起的。寶馬進口1系的價格不是很貴,但是國人就是對兩廂車有一定的排斥心理,比較鍾愛三廂車,所以即使進口1系兩廂的價格足夠便宜,但是買單的人照樣不多。

    當然,寶馬3系是三廂車,但是3系的價格在30萬左右,還是有點小貴。所以在20萬級別這個領域,出現了一個市場空缺。如果能有一台20萬的三廂寶馬,這應該是極好的選擇。

    看看奧迪A3就知道了,作為豪華品牌的A3將價格做到了20萬元左右,在這個沒有直接競爭對手的領域,A3的銷量好的一塌糊塗,A3在11月份交出了9883輛的銷量,將近萬輛的銷量足以看出來這個細分市場有很大的潛力。

    所以寶馬義不容辭的推出了國產版的1系三廂。

    寶馬1系三廂版基於Compact Sedan概念車打造出來的,新車的設計借鑒了概念車的設計元素,同時也具有着寶馬家族化的設計風格,前大燈的造型與3系比較相似,側麵線條比較平直,從外觀看像是縮小的3系,看起來短小精悍,富有運動感。

    內飾看起來還是那麼熟悉的感覺,畢竟也是採用了寶馬家族化的設計特徵,中控台造型很有層次感,並配備了8.8英寸液晶屏,同時還有大面積的鍍鉻裝飾,可以增強內飾的精緻感。

    新車基於UKL前驅平台打造,1系三廂將會是前驅車型,新車的動力系統或為1.5T 136馬力+6速自動變速箱,2.0T 192馬力/231馬力+8擋手自一體變速箱,其中官方聲稱1.5T車型的百公里油耗最低可以達到5.5L。

    新車將會有無鑰匙啟動、抬頭显示、倒車影像、全景天窗、LED大燈、pM2.5濾清器等,這些都是國人比較看重的配置。新車的預售價為20.5萬起,這就意味着也許不到20萬的價格就可以買到帥氣的三廂寶馬,估計很多消費者都會心動吧!如果實際售價能比預售價還低一點的話,那麼A3就會瞬間感到壓力了。

    競爭對手

    奧迪A3

    指導價:18.49-28.10萬

    A3在國內的成就有目共睹,但是它真正的競爭對手預計會在2月份正式上市銷售,憑藉著“藍天白雲”在國內的號召力,A3將會面臨很大壓力,那麼它能否守住自己的陣地,就讓我們拭目以待吧!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案