挖角鋰電池廠 A123 傳蘋果電動車將於 2020 年量產

過去幾個月來,蘋果打算進軍終極行動裝置──汽車的傳言甚囂塵上。最新消息更顯示,蘋果正在加緊鞭策研發團隊,希望能在 2020 年產出旗下第一輛電動車。無獨有偶,數小時前才剛洩漏的法院文件顯示,美國汽車鋰離子電池與電池系統廠商 A123 Systems Inc. 控訴蘋果挖角多名重要的工程師,或許蘋果開發電動車是真有其事。   彭博社 20 日引述未具名消息人士報導,蘋果最快 2020 年就會開始量產電動車。一般來說,有經驗的汽車業者想要研發一款全新汽車、通常得花上 5 至 7 年的時間,假如要從零開始、時間更得費上 10 年之久。蘋果設定了如此緊迫的量產時程,凸顯了該公司對汽車領域的強大企圖心。   相較之下,特斯拉(Tesla Motors Inc.)、通用汽車(General Motors Co.)這兩家汽車大廠,則都預定要在 2017 年發表一輛單次充電後可行駛超過 200 英里、售價低於 4 萬美元的電動車。   蘋果的汽車團隊過去幾個月加緊聘人、目前已有 200 人之譜,而最新延攬的員工大多是電池、機器人專才。不過,根據消息人士的說法,倘若汽車的進展不如預期,蘋果仍可能推延開發案、或甚至直接抽手退出。

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

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

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

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

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

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

※回頭車貨運收費標準

三星收購電池部門 傳將研發電動車

蘋果(Apple)研發電動車的傳聞滿天飛,三星(Samsung)不甘示弱跟進,打算在電動車界跟蘋果再次一決雌雄?   韓聯社和 Tomˋs Hardware 報導,南韓電池製造龍頭 Samsung SDI 23 日宣布收購汽車零件商 Magna Steyr 的電池部門,購併金額未對外透露。   Tomˋs Hardware 網站認為,Samsung SDI 是 BMW i3 電動車的電池供應商,購併固然可能只是要強化電池部門實力,但也有可能代表三星打算跨足電動車。三星集團旗下業務橫跨電機、化學、造船、工具機等,如果真的要生產電動車,三星握有的技術資源更勝蘋果。

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

【其他文章推薦】

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

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

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

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

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

※超省錢租車方案

蟬聯兩年!Tesla Models S 再登美國年度最佳汽車

美國消費者報告(Consumer Reports)的調查顯示,電動車製造商 Tesla 的 Model S 已連續 2 年榮登年度最佳汽車。   消費者報告是根據道路表現、可靠度和防撞測試結果來評比車輛,除了選出整體表現最佳的汽車外,也會按照車種來評比。Model S 今年之所以蟬聯年度最佳汽車,原因除了充滿電後能跑 426 公里外,能夠透過網路升級軟體、及 Tesla 已克服初期面臨的技術問題,也是這輛車獲得青睞的原因。   在消費者報告劃分的十大分類中,只有 6 類是由日本車贏得最佳汽車頭銜,為消費者報告 19 年前開始評比以來最少,贏得最佳汽車頭銜的美國汽車品牌則有 3 個。除了 Tesla,另外 2 個品牌是 Buick 及雪佛蘭(Chevrolet)。

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

【其他文章推薦】

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

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

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

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

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

日本充電樁達4萬個 超傳統加油站

日產汽車(Nissan)日前宣佈,目前日本全國有4萬個充電設施,其中包括家用充電站,而加油站只有3.4萬個,充電樁數量已超過傳統加油站。   去年5月,豐田、日產、本田、三菱這四大日本汽車製造商與日本政策投資銀行共同成立了“日本充電服務”公司,承擔起在商業設施等地設置充電樁的成本及8年內充電樁的維護費用。   日本便利店巨頭也表示將加快完善電動車充電設施,期待以此增加客流量。全家便利店在今年3月底之前將可為電動車及插電式混合動力車快速充電的店鋪增加至650家,期待達到同行業數量之最,並成為首個能源補給設施遍佈日本全境的便利店企業。羅森便利店也計畫在今年5月前將電動車充電樁由目前的12個增至200個左右。

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

【其他文章推薦】

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

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

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

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

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

比亞迪電動巴士入日本市場 遭日本人吐槽「跑跑就散架」

近日,比亞迪電動巴士K9亮相日本京都地區,成為首個進入日本市場的中國汽車品牌。據日本當地媒體報導,本次引入京都的比亞迪電動巴士共計5輛,每輛車核定乘員人數69人,將由京都急行巴士株式會社運營。   環球網掌握的公開資料顯示,該款單層電動巴士完成單次充電後,可行駛約250公里。比亞迪在美國亦有生產電動巴士K9,售價約80萬美元。而從 2011年3月比亞迪與丹麥最大的公交公司Movia達成純電動公交合作開始,K9已經駛入了全球五大洲的多個城市,從德國的法蘭克福、到美國的華盛頓、再到英國的倫敦,多個新能源公交領域的訂單花落比亞迪。   而對於比亞迪電動巴士的亮相,日本各界表現出了截然相反的態度。一方面,日本國土交通省對於中國自主品牌積極「點贊」。在京都國立博物館內舉行的K9運營啟動儀式上,日本國土交通省官員阪部光雄表示:「非常高興能在京都迎來比亞迪的純電動巴士,這是京都公交系統首次採用零排放的純電動巴士,運營純電動巴士對於地區的環境治理意義非常深遠。」

但也有一些日本線民並不是表現那麼「淡定」,他們反應強烈。有網友在網上留言表示,「還不知道一年後是啥樣兒••••估計跑著跑著就散架了,這都能想像到!反正我堅決不坐。」有的網友則質疑純電動公車的續航里程,「到底一次能跑幾個小時啊?不說滿電能跑幾天,也不說充滿電能運行多久••••總感覺這車的事故處理費用和乘客賠償費用會跟高啊!」

有的甚至表示,「買這廉價玩意兒,還不如讓有軌電車重新上路呢!」還有人則對日本媒體對此事的報導不滿,「看到這條新聞,總感覺很不爽,報導最後竟然還來了一句「今後訪問京都的中國遊客多數人都會看到BYD在日本街頭的雄姿」。」

不少人則開始擔憂中國產品大量湧入日本,其驚呼,「(中國製造開始不斷湧入日本市場了!)從電視到電腦,再到智慧手機,現在居然輪到汽車了啊!」

也有一些上了年紀的日本網友感歎中國製造的迅速崛起,「日本的車企也在做HV巴士,但純電動巴士好像還沒有在做呢。估計(比亞迪K9)比較便宜吧,但還是希望安全第一。1985年的時候,日本贈送給了北京兩輛公車,30年後,中國巴士開始進入日本了!好神奇!不過首先讓我們來一起見證這輛車的性能吧!」   文章來源:環球網

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

【其他文章推薦】

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

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

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

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

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

台達電電動車驅動馬達 打入福斯供應鏈

電源供應器廠積極跨入車用市場,台達電耕耘 3 年的電動車驅動馬達打入福斯集團供應鏈,今年開始出貨;新巨微動開關則陸續取得德國雙 B、奧迪與福斯,美系福特和日系車廠訂單;康舒電源轉換器也與多家國際電動車大廠談合作。   台達電董事長海英俊表示,目前各國積極發展電動車,基礎設施也開始動起來,因此台達電最近在電動車零組件有不錯的進展,包括出貨給美國知名電動車廠充電樁、轉換器,台達電在歐、美、日、中國等各地的電動車標準都通過認證。   海英俊透露,台達電研發電動車驅動馬達,經過 3 年努力,已獲歐洲車廠認證。

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

【其他文章推薦】

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

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

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

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

※超省錢租車方案

雷軍:小米3至5年內不做電動車

今日,雷軍出席亞布力中國企業家論壇第十五屆年會,並發表了演講。對於進入電動車領域的傳聞,雷軍稱小米三到五年內不會涉及,主要目標是把現有產品做好。   他明確表示,小米佈局已經完成,包括三類、五種產品,包括手機、平板、電視、電視盒、路由器等,主要是為了智慧家居。他稱,「(不涉及電動車)跟市場好壞沒關係,我們專注的把現在幾個產品做好,就已經很不容易了。不是不看好,是精力有限。」

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

【其他文章推薦】

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

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

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

※超省錢租車方案

使用 nuget server 的 API 來實現搜索安裝 nuget 包

使用 nuget server 的 API 來實現搜索安裝 nuget 包

Intro

nuget 現在幾乎是 dotnet 開發不可缺少的一部分了,還沒有用過 nuget 的就有點落後時代了,還不快用起來

nuget 是 dotnet 里的包管理機制,類似於前端的 npm ,php 的 composer,java 里的 maven …

nuget 定義了一套關於 nuget server 的規範,使得用戶可以自己實現一個 nuget server

也正是這些規範,使得我們可以根據這些規範來實現 nuget server 的包管理的功能,今天主要介紹一下,根據 nuget server 的 api 規範使用原始的 HTTP 請求來實現 nuget 包的搜索和使用 nuget 提供的客戶端 SDK 來實現 nuget 包的搜索和下載

Nuget Server Api

Nuget 協議介紹

nuget 的協議有好幾個版本,目前主要用的是 v3,開源的 nuget server Baget 也實現了基於 nuget protocal v3 的規範

我們添加 nuget 源的時候會指定一個 source url,類似 https://api.nuget.org/v3/index.json 這樣的,着通常被稱為 Service Index,是一個 nuget 源的入口,有點類似於 Identity Server 里的發現文檔,通過這個地址可以獲取到一系列的資源的地址

有一些資源是協議規範里定義的必須要實現的,有一些是可選的,具體參考官方文檔,以後隨着版本變化,可能會有差異,目前 nuget.org 提供的資源如下:

Nuget.org 提供了兩種搜索的方式,

一個是 SearchQuery,會根據包名稱、 tag、description 等信息去匹配關鍵詞,

一個是 SearchAutocomplete 根據包名稱的前綴去匹配包的名稱

獲取某個 nuget 包的版本信息,可以使用 PackageBaseAddress 來獲取

ServiceIndex 返回的信息示例如下:

返回的信息會有一個 resources 的數組,會包含各種不同類型的資源,對應的 @id 就是調用這種類型的API要用到的地址,下面來看一個搜索的示例

在每個 API 的文檔頁面可以看到會使用的 @type,調用這個 API 的時候應該使用這些 @type 對應的資源

這裏的 @id 就是上面的 resource 對應的 @id

參數說明:

q 搜索時所用的關鍵詞,

skip/take 用來分頁显示查詢結果,

prelease 用來指定是否限制預覽版的 package,true 包含預覽版的 nuget 包,false 只包含已經正式發布的 nuget 包

semVerLevel 是用來指定包的語義版本

The semVerLevel query parameter is used to opt-in to SemVer 2.0.0 packages. If this query parameter is excluded, only packages with SemVer 1.0.0 compatible versions will be returned (with the standard NuGet versioning caveats, such as version strings with 4 integer pieces). If semVerLevel=2.0.0 is provided, both SemVer 1.0.0 and SemVer 2.0.0 compatible packages will be returned. See the SemVer 2.0.0 support for nuget.org for more information

packageType 用來指定 nuget 包的類型,目前支持的類型包括 Dependency(默認)項目依賴項,DotnetTool(dotnetcore 2.1 引入的 dotnet cli tool),Template (dotnet new 用) 自定義的項目模板

其他的 API 可以自行參考官方文檔:https://docs.microsoft.com/en-us/nuget/api/service-index

Packages

SearchQuery 返回的信息比較多而且可能並不準確,適用於不清楚包的名稱的時候使用,如果知道 nuget 包的名稱(PackageId) ,可以使用 SearchAutocomplete 來搜索,這樣更精準,返回的信息也更簡單,只有匹配的 package 名稱

通過原始 api 調用的方式實現 nuget 包的搜索

using var httpClient = new HttpClient(new NoProxyHttpClientHandler());
// loadServiceIndex
var serviceIndexResponse = await httpClient.GetStringAsync(NugetServiceIndex);
var serviceIndexObject = JObject.Parse(serviceIndexResponse);

var keyword = "weihanli";

//https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource
var queryEndpoint = serviceIndexObject["resources"]
    .First(x => x["@type"].Value<string>() == "SearchQueryService")["@id"]
    .Value<string>();
var queryUrl = $"{queryEndpoint}?q={keyword}&skip=0&take=5&prerelease=false&semVerLevel=2.0.0";
var queryResponse = await httpClient.GetStringAsync(queryUrl);
Console.WriteLine($"formatted queryResponse:");
Console.WriteLine($"{JObject.Parse(queryResponse).ToString(Formatting.Indented)}");

// https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource
var autoCompleteQueryEndpoint = serviceIndexObject["resources"]
    .First(x => x["@type"].Value<string>() == "SearchAutocompleteService")["@id"]
    .Value<string>();
var autoCompleteQueryUrl = $"{autoCompleteQueryEndpoint}?q={keyword}&skip=0&take=5&prerelease=false&semVerLevel=2.0.0";
var autoCompleteQueryResponse = await httpClient.GetStringAsync(autoCompleteQueryUrl);
Console.WriteLine($"formatted autoCompleteQueryResponse:");
Console.WriteLine($"{JObject.Parse(autoCompleteQueryResponse).ToString(Formatting.Indented)}");

output 示例:

Query 返回示例

Autocomplete 返回結果

從上面我們可以看到 Query 接口返回了很多的信息,Autocomplete 接口只返回了 package 的名稱,返回的信息更為簡潔,所以如果可以使用 Autocomplete 的方式就盡可能使用 Autocomplete 的方式

Package Versions

前面我們提到了可以使用 PackageBaseAddress 來查詢某個 nuget 包的版本信息,文檔地址:https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource,來看一下示例:

using (var httpClient = new HttpClient(new NoProxyHttpClientHandler()))
{
    // loadServiceIndex
    var serviceIndexResponse = await httpClient.GetStringAsync(NugetServiceIndex);
    var serviceIndexObject = JObject.Parse(serviceIndexResponse);

    // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource
    var packageVersionsEndpoint = serviceIndexObject["resources"]
        .First(x => x["@type"].Value<string>() == "PackageBaseAddress/3.0.0")["@id"]
        .Value<string>();

    var packageVersionsQueryUrl = $"{packageVersionsEndpoint}/dbtool.core/index.json";
    var packageVersionsQueryResponse = await httpClient.GetStringAsync(packageVersionsQueryUrl);
    Console.WriteLine("DbTool.Core versions:");
    Console.WriteLine(JObject.Parse(packageVersionsQueryResponse)
                      .ToString(Formatting.Indented));
}

output 示例:

注:api 地址中的 packageId 要轉小寫

Nuget Client SDK

除了上面的根據 api 自己調用,我們還可以使用 nuget 提供的客戶端 sdk 實現上述功能,這裏就不詳細介紹了,有需要可能查閱官方文檔:https://docs.microsoft.com/en-us/nuget/reference/nuget-client-sdk

下面給出一個使用示例:

var packageId = "WeihanLi.Common";
var packageVersion = new NuGetVersion("1.0.38");

var logger = NullLogger.Instance;
var cache = new SourceCacheContext();
// 在 SDK 的概念里,每一個 nuget 源是一個 repository
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");

// SearchQuery
{
    var resource = await repository.GetResourceAsync<PackageSearchResource>();
    var searchFilter = new SearchFilter(includePrerelease: false);

    var results = await resource.SearchAsync(
        "weihanli",
        searchFilter,
        skip: 0,
        take: 20,
        logger,
        CancellationToken.None);
    foreach (var result in results)
    {
        Console.WriteLine($"Found package {result.Identity.Id} {result.Identity.Version}");
    }
}
// SearchAutoComplete
{
    var autoCompleteResource = await repository.GetResourceAsync<AutoCompleteResource>();
    var packages =
        await autoCompleteResource.IdStartsWith("WeihanLi", false, logger, CancellationToken.None);
    foreach (var package in packages)
    {
        Console.WriteLine($"Found Package {package}");
    }
}
//
{
    // get package versions
    var findPackageByIdResource = await repository.GetResourceAsync<FindPackageByIdResource>();
    var versions = await findPackageByIdResource.GetAllVersionsAsync(
        packageId,
        cache,
        logger,
        CancellationToken.None);

    foreach (var version in versions)
    {
        Console.WriteLine($"Found version {version}");
    }
}

More

你可以使用 nuget sdk 方便的實現 nuget 包的下載安裝,內部實現了簽名校驗等,這樣就可以把本地不存在的 nuget 包下載到本地了,

實現示例:

{
    var pkgDownloadContext = new PackageDownloadContext(cache);
    var downloadRes = await repository.GetResourceAsync<DownloadResource>();

    var downloadResult = await RetryHelper.TryInvokeAsync(async () =>
        await downloadRes.GetDownloadResourceResultAsync(
            new PackageIdentity(packageId, packageVersion),
            pkgDownloadContext,
            @"C:\Users\liweihan\.nuget\packages", // nuget globalPackagesFolder
            logger,
            CancellationToken.None), r => true);
    Console.WriteLine(downloadResult.Status.ToString());
}

最後提供一個解析 nuget globalPackagesFolder 的兩種思路:

一個是前面有篇文章介紹的,有個默認的配置文件,然後就是默認的配置,寫了一個解析的方法示例,支持 Windows/Linux/Mac:

{
    var packagesFolder = Environment.GetEnvironmentVariable("NUGET_PACKAGES");

    if (string.IsNullOrEmpty(packagesFolder))
    {
        // Nuget globalPackagesFolder resolve
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            var defaultConfigFilePath =
                $@"{Environment.GetEnvironmentVariable("APPDATA")}\NuGet\NuGet.Config";
            if (File.Exists(defaultConfigFilePath))
            {
                var doc = new XmlDocument();
                doc.Load(defaultConfigFilePath);
                var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                if (node != null)
                {
                    packagesFolder = node.Attributes["value"]?.Value;
                }
            }

            if (string.IsNullOrEmpty(packagesFolder))
            {
                packagesFolder = $@"{Environment.GetEnvironmentVariable("USERPROFILE")}\.nuget\packages";
            }
        }
        else
        {
            var defaultConfigFilePath =
                $@"{Environment.GetEnvironmentVariable("HOME")}/.config/NuGet/NuGet.Config";
            if (File.Exists(defaultConfigFilePath))
            {
                var doc = new XmlDocument();
                doc.Load(defaultConfigFilePath);
                var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                if (node != null)
                {
                    packagesFolder = node.Attributes["value"]?.Value;
                }
            }

            if (string.IsNullOrEmpty(packagesFolder))
            {
                defaultConfigFilePath = $@"{Environment.GetEnvironmentVariable("HOME")}/.nuget/NuGet/NuGet.Config";
                if (File.Exists(defaultConfigFilePath))
                {
                    var doc = new XmlDocument();
                    doc.Load(defaultConfigFilePath);
                    var node = doc.SelectSingleNode("/configuration/config/add[@key='globalPackagesFolder']");
                    if (node != null)
                    {
                        packagesFolder = node.Value;
                    }
                }
            }

            if (string.IsNullOrEmpty(packagesFolder))
            {
                packagesFolder = $@"{Environment.GetEnvironmentVariable("HOME")}/.nuget/packages";
            }
        }
    }

    Console.WriteLine($"globalPackagesFolder: {packagesFolder}");
}

另一個是可以根據 nuget 提供的一個命令查詢 nuget locals global-packages -l,通過命令輸出獲取

Reference

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/NugetSample/RawApiSample.cs
  • https://github.com/WeihanLi/SamplesInPractice/blob/master/NugetSample/NugetClientSdkSample.cs
  • https://docs.microsoft.com/en-us/nuget/reference/nuget-client-sdk
  • https://docs.microsoft.com/en-us/nuget/create-packages/set-package-type
  • https://docs.microsoft.com/en-us/nuget/api/overview
  • https://docs.microsoft.com/en-us/nuget/api/search-autocomplete-service-resource

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

【【其他文章推薦】

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

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

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

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

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

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

Zookeeper分佈式過程協同技術 – 群首選舉

Zookeeper分佈式過程協同技術 – 群首選舉

群首概念

群首為集群中服務器選擇出來的一個服務器,並被集群認可。設置群首目的在與對客戶端所發起的狀態變更請求進行排序,包括:create、setData、delete操作。群首將每一個請求轉換為一個事務並將事務發送給追隨者,確保集群按照群首確定的順序接受並處理這些事務。

Zookeeper事務

Zookeeper服務器會在本地處理只讀請求(例如:exists、getData、getChildren)。如果一台服務器接收到客戶端的getData請求,服務器讀取該狀態信息,並將這些信息返回客戶端。由於服務器在本地處理讀請求,所以在處理以只讀請求為主要負載時,性能會比較高。

那些會改變狀態的客戶端請求(create、delete、setData)將會被轉發給群首,由群首執行相應的請求,完成狀態的更新,這就是Zookeeper的事務。

選舉過程

每個服務器啟動後進入LOOKING狀態,服務器之間進行通信來選舉一個群首,通過信息交換對群首選舉達成共識。在本次選舉中勝出的服務器將進入LEADING狀態,而集群中其他服務器將進入FOLLOWING狀態。

群首選舉消息(leader election notifications)或簡單的稱為通知。當一個服務器進入LOOKING狀態就會向集群中的每一個服務器發送一個通知消息。消息中包含該服務器的投票信息。

投票信息包含服務器標識符(sid)和最近執行的事務的zxid信息,例如投票信息(1,5)代表機器ID為1,最近執行的事務zxid為5。

zxid為一個long型(64位)整數,分為2部分:時間戳部分和計數器部分,每個部分為32位。

 當一個服務器收到一個投票信息,該服務器將會根據以下規則修改自己的投票信息:

  1. 將接受的voteId和voteZxid作為一個標識符,並獲取接收方當前的投票中的zxid,用myZxid和mySid表示接收方服務器自己的值。
  2. 如果(voteZxid > myZxid)或者(voteZxid = myZxid 且 voteId > mySid),保留當前的投票信息。
  3. 否則,修改自己的投票信息,將voteZxid賦值給myZxid,將voteId賦值給mySid。

當一個服務器收到的仲裁數量的服務器發來的投票信息都一樣時,就表示群首選舉成功,如果被選舉的群首為某個服務器自己,該服務器將會開始行使群首角色,否則就會成為一個追隨者並嘗試連接被選舉的群首服務器。一旦連接成功,追隨者和群首之間將會進行狀態同步,在同步完成后,追隨者才可以處理新的請求。 

 

 

通過例子來演示選舉過程,三台服務器在分別發送出不同的選舉投票信息,其投票值包含服務器的標識符和最新的zxid。每個服務器都會收到另外兩個服務器發送的投票信息,在第一輪之後,服務器S2和S3將會改變其投票信息為(1,6),之後服務器S2和S3在改變投票信息之後會發送新的通知消息,S1服務器在接收到仲裁數量的通知消息擁有一樣的投票信息,最後S1被選舉出為集群的群首。

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

【其他文章推薦】

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

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

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

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

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

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

C# 9.0 終於來了, Top-level programs 和 Partial Methods 兩大新特性探究

一:背景

1. 講故事

.NET 5 終於在 6月25日 發布了第六個預覽版,隨之而來的是更多的新特性加入到了 C# 9 Preview 中,這個系列也可以繼續往下寫了,廢話不多說,今天來看一下 Top-level programsExtending Partial Methods 兩大新特性。

2. 安裝必備

下載最新的 .net 5 preview 6

下載最新的 Visual Studio 2019 version 16.7 Preview 3.1

二:新特性研究

1. Top-level programs

如果大家玩過 python,應該知道在 xxx.py 中寫一句 print,這程序就能跑起來了,簡單高效又粗暴,很開心的是這特性被帶到了C# 9.0 中。

  • 修改前

using System;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }

  • 修改后

System.Console.WriteLine("Hello World!");

這就有意思了,Main入口函數去哪了? 沒它的話,JIT還怎麼編譯代碼呢? 想知道答案的話用 ILSpy 反編譯看一下就好啦!


.class private auto ansi abstract sealed beforefieldinit $Program
	extends [System.Runtime]System.Object
{
	.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
		01 00 00 00
	)
	// Methods
	.method private hidebysig static 
		void $Main (
			string[] args
		) cil managed 
	{
		// Method begins at RVA 0x2050
		// Code size 18 (0x12)
		.maxstack 8
		.entrypoint

		IL_0000: ldstr "Hello World!"
		IL_0005: call void [System.Console]System.Console::WriteLine(string)
		IL_000a: nop
		IL_000b: call string [System.Console]System.Console::ReadLine()
		IL_0010: pop
		IL_0011: ret
	} // end of method $Program::$Main

} // end of class $Program


從 IL 上看,類變成了 $Program, 入口方法變成了 $Main, 這就好玩了,在我們的印象中入口函數必須是 Main,否則編譯器會給你一個大大的錯誤,你加了一個 $ 符號,那CLR還能認識嗎? 能不能認識我們用 windbg 看一些託管和非託管堆棧,看看有什麼新發現。


0:010> ~0s
ntdll!NtReadFile+0x14:
00007ffe`f8f8aa64 c3              ret
0:000> !dumpstack
OS Thread Id: 0x7278 (0)
Current frame: ntdll!NtReadFile + 0x14
Child-SP         RetAddr          Caller, Callee
0000008551F7E810 00007ffed1e841dc (MethodDesc 00007ffe4020d500 + 0x1c System.Console.ReadLine()), calling 00007ffe400ab090
0000008551F7E840 00007ffe4014244a (MethodDesc 00007ffe401e58f0 + 0x3a $Program.$Main(System.String[])), calling 00007ffe40240f58
0000008551F7E880 00007ffe9fcc8b43 coreclr!CallDescrWorkerInternal + 0x83 [F:\workspace\_work\1\s\src\coreclr\src\vm\amd64\CallDescrWorkerAMD64.asm:101]
0000008551F7E8C0 00007ffe9fbd1e03 coreclr!MethodDescCallSite::CallTargetWorker + 0x263 [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:554], calling coreclr!CallDescrWorkerWithHandler [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:56]
0000008551F7E950 00007ffe9fb8c4e5 coreclr!MethodDesc::IsVoid + 0x21 [F:\workspace\_work\1\s\src\coreclr\src\vm\method.cpp:1098], calling coreclr!MetaSig::IsReturnTypeVoid [F:\workspace\_work\1\s\src\coreclr\src\vm\siginfo.cpp:5189]
0000008551F7EA00 00007ffe9fb8c4bf coreclr!RunMainInternal + 0x11f [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1488], calling coreclr!MethodDescCallSite::CallTargetWorker [F:\workspace\_work\1\s\src\coreclr\src\vm\callhelpers.cpp:266]
0000008551F7EB30 00007ffe9fb8c30a coreclr!RunMain + 0xd2 [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1559], calling coreclr!RunMainInternal [F:\workspace\_work\1\s\src\coreclr\src\vm\assembly.cpp:1459]

從上面堆棧的流程圖看: coreclr!RunMain -> coreclr!MethodDesc -> coreclr!CallDescrWorkerInternal -> $Program.$Main, 確實被調用了,不過有一個重大發現,在 $Program.$Main 調用之前底層的 CLR 讀取了 方法描述符,這就是一個重大突破點,方法描述符在哪裡呢? 可以用 ildasm 去看一下元數據列表。

可以看到,入口函數那裡打上了一個 ENTRYPOINT 標記,這就說明入口函數名其實是可以隨便更改的,只要被 ENTRYPOINT打上標記即可,CoreCLR就能認的出來~~~

2. Partial Methods

我們知道 部分方法 是一個很好的樁函數,而且在 C# 3.0 中就已經實現了,那時候給我們增加了很多限制,如下圖:

翻譯過來就是:

  • 部分方法的簽名必須一致

  • 方法必須返回void

  • 不允許使用訪問修飾符,而且還是隱式私有的。

在 C# 9.0 中放開了對 方法簽名 的所有限制,正如 issue 總結:

這是一個非常好的消息,現在你的部分方法上可以加上各種類型的返回值啦,這裏我舉一個例子:


    class Program
    {
        static void Main(string[] args)
        {
            var person = new Person();

            Console.WriteLine(person.Run("jack"));
        }
    }

    public partial class Person
    {
        public partial string Run(string name);
    }

    public partial class Person
    {
        public partial string Run(string name) => $"{name}:開溜了~";
    }

然後我們用 ILSpy 簡單看看底層怎麼玩的,如下圖可以看到其實就是一個簡單的合成,對吧。

現在我有想法了,如果我不給 Run 方法實現會怎麼樣? 把下面的 partial 類註釋掉看一下。

從報錯信息看,可訪問的修飾符必須要有方法實現,還以為直接編譯的時候抹掉呢。 這就起不到樁函數的作用:-D,不過這個特性還是給了我們更多的可能用的到的應用場景吧。

三:總結

本篇兩個特性還是非常實用的,Top-level programs 讓我們可以寫更少的代碼,甚至拿起 記事本 都可以快捷的編寫類似一次性使用的測試代碼, Partial Methods 特性留給大家補充吧,我基本上算是沒用過 (┬_┬)。

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

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

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

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

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

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

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

※回頭車貨運收費標準