分類: 3C資訊

  • .Net Core微服務入門全紀錄(三)——Consul-服務註冊與發現(下)

    .Net Core微服務入門全紀錄(三)——Consul-服務註冊與發現(下)

    前言

    上一篇【.Net Core微服務入門全紀錄(二)——Consul-服務註冊與發現(上)】已經成功將我們的服務註冊到Consul中,接下來就該客戶端通過Consul去做服務發現了。

    服務發現

    • 同樣Nuget安裝一下Consul:

    • 改造一下業務系統的代碼:

    ServiceHelper.cs:

        public class ServiceHelper : IServiceHelper
        {
            private readonly IConfiguration _configuration;
    
            public ServiceHelper(IConfiguration configuration)
            {
                _configuration = configuration;
            }
    
            public async Task<string> GetOrder()
            {
                //string[] serviceUrls = { "http://localhost:9060", "http://localhost:9061", "http://localhost:9062" };//訂單服務的地址,可以放在配置文件或者數據庫等等...
    
                var consulClient = new ConsulClient(c =>
                {
                    //consul地址
                    c.Address = new Uri(_configuration["ConsulSetting:ConsulAddress"]);
                });
    
                //consulClient.Catalog.Services().Result.Response;
                //consulClient.Agent.Services().Result.Response;
                var services = consulClient.Health.Service("OrderService", null, true, null).Result.Response;//健康的服務
    
                string[] serviceUrls = services.Select(p => $"http://{p.Service.Address + ":" + p.Service.Port}").ToArray();//訂單服務地址列表
    
                if (!serviceUrls.Any())
                {
                    return await Task.FromResult("【訂單服務】服務列表為空");
                }
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(serviceUrls[new Random().Next(0, serviceUrls.Length)]);
                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 consulClient = new ConsulClient(c =>
                {
                    //consul地址
                    c.Address = new Uri(_configuration["ConsulSetting:ConsulAddress"]);
                });
    
                //consulClient.Catalog.Services().Result.Response;
                //consulClient.Agent.Services().Result.Response;
                var services = consulClient.Health.Service("ProductService", null, true, null).Result.Response;//健康的服務
    
                string[] serviceUrls = services.Select(p => $"http://{p.Service.Address + ":" + p.Service.Port}").ToArray();//產品服務地址列表
    
                if (!serviceUrls.Any())
                {
                    return await Task.FromResult("【產品服務】服務列表為空");
                }
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(serviceUrls[new Random().Next(0, serviceUrls.Length)]);
                var request = new RestRequest("/products", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
        }
    

    appsettings.json:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "AllowedHosts": "*",
      "ConsulSetting": {
        "ConsulAddress": "http://localhost:8500"
      }
    }
    

    OK,以上代碼就完成了服務列表的獲取。

    瀏覽器測試一下:

    隨便停止2個服務:

    繼續訪問:

    這時候停止的服務地址就獲取不到了,客戶端依然正常運行。

    這時候解決了服務的發現,新的問題又來了…

    • 客戶端每次要調用服務,都先去Consul獲取一下地址,這不僅浪費資源,還增加了請求的響應時間,這顯然讓人無法接受。

    那麼怎麼保證不要每次請求都去Consul獲取地址,同時又要拿到可用的地址列表呢?
    Consul提供的解決方案:——Blocking Queries (阻塞的請求)。詳情請見官網:https://www.consul.io/api-docs/features/blocking

    Blocking Queries

    這是什麼意思呢,簡單來說就是當客戶端請求Consul獲取地址列表時,需要攜帶一個版本號信息,Consul會比較這個客戶端版本號是否和Consul服務端的版本號一致,如果一致,則Consul會阻塞這個請求,直到Consul中的服務列表發生變化,或者到達阻塞時間上限;如果版本號不一致,則立即返回。這個阻塞時間默認是5分鐘,支持自定義。
    那麼我們另外啟動一個線程去干這件事情,就不會影響每次的用戶請求了。這樣既保證了客戶端服務列表的準確性,又節約了客戶端請求服務列表的次數。

    • 繼續改造代碼:
      IServiceHelper增加一個獲取服務列表的接口方法:
        public interface IServiceHelper
        {
            /// <summary>
            /// 獲取產品數據
            /// </summary>
            /// <returns></returns>
            Task<string> GetProduct();
    
            /// <summary>
            /// 獲取訂單數據
            /// </summary>
            /// <returns></returns>
            Task<string> GetOrder();
    
            /// <summary>
            /// 獲取服務列表
            /// </summary>
            void GetServices();
        }
    

    ServiceHelper實現接口:

        public class ServiceHelper : IServiceHelper
        {
            private readonly IConfiguration _configuration;
            private readonly ConsulClient _consulClient;
            private ConcurrentBag<string> _orderServiceUrls;
            private ConcurrentBag<string> _productServiceUrls;
    
            public ServiceHelper(IConfiguration configuration)
            {
                _configuration = configuration;
                _consulClient = new ConsulClient(c =>
                {
                    //consul地址
                    c.Address = new Uri(_configuration["ConsulSetting:ConsulAddress"]);
                });
            }
    
            public async Task<string> GetOrder()
            {
                if (_productServiceUrls == null)
                    return await Task.FromResult("【訂單服務】正在初始化服務列表...");
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(_orderServiceUrls.ElementAt(new Random().Next(0, _orderServiceUrls.Count())));
                var request = new RestRequest("/orders", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
    
            public async Task<string> GetProduct()
            {
                if(_productServiceUrls == null)
                    return await Task.FromResult("【產品服務】正在初始化服務列表...");
    
                //每次隨機訪問一個服務實例
                var Client = new RestClient(_productServiceUrls.ElementAt(new Random().Next(0, _productServiceUrls.Count())));
                var request = new RestRequest("/products", Method.GET);
    
                var response = await Client.ExecuteAsync(request);
                return response.Content;
            }
    
            public void GetServices()
            {
                var serviceNames = new string[] { "OrderService", "ProductService" };
                Array.ForEach(serviceNames, p =>
                {
                    Task.Run(() =>
                    {
                        //WaitTime默認為5分鐘
                        var queryOptions = new QueryOptions { WaitTime = TimeSpan.FromMinutes(10) };
                        while (true)
                        {
                            GetServices(queryOptions, p);
                        }
                    });
                });
            }
            private void GetServices(QueryOptions queryOptions, string serviceName)
            {
                var res = _consulClient.Health.Service(serviceName, null, true, queryOptions).Result;
                
                //控制台打印一下獲取服務列表的響應時間等信息
                Console.WriteLine($"{DateTime.Now}獲取{serviceName}:queryOptions.WaitIndex:{queryOptions.WaitIndex}  LastIndex:{res.LastIndex}");
    
                //版本號不一致 說明服務列表發生了變化
                if (queryOptions.WaitIndex != res.LastIndex)
                {
                    queryOptions.WaitIndex = res.LastIndex;
    
                    //服務地址列表
                    var serviceUrls = res.Response.Select(p => $"http://{p.Service.Address + ":" + p.Service.Port}").ToArray();
    
                    if (serviceName == "OrderService")
                        _orderServiceUrls = new ConcurrentBag<string>(serviceUrls);
                    else if (serviceName == "ProductService")
                        _productServiceUrls = new ConcurrentBag<string>(serviceUrls);
                }
            }
        }
    

    Startup的Configure方法中調用一下獲取服務列表:

            public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceHelper serviceHelper)
            {
                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?}");
                });
    
                //程序啟動時 獲取服務列表
                serviceHelper.GetServices();
            }
    

    代碼完成,運行測試:

    現在不用每次先請求服務列表了,是不是流暢多了?

    看一下控制台打印:

    這時候如果服務列表沒有發生變化的話,獲取服務列表的請求會一直阻塞到我們設置的10分鐘。

    隨便停止2個服務:

    這時候可以看到,數據被立馬返回了。

    繼續訪問客戶端網站,同樣流暢。
    (gif圖傳的有點問題。。。)

    至此,我們就通過Consul完成了服務的註冊與發現。
    接下來又引發新的思考。。。

    1. 每個客戶端系統都去維護這一堆服務地址,合理嗎?
    2. 服務的ip端口直接暴露給所有客戶端,安全嗎?
    3. 這種模式下怎麼做到客戶端的統一管理呢?

    代碼放在:https://github.com/xiajingren/NetCoreMicroserviceDemo

    未完待續…

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

    【其他文章推薦】

    ※超省錢租車方案

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

    ※回頭車貨運收費標準

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

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

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

  • 雀巢號召新創尖兵 加速開發乳製品替代品

    摘錄自2020年9月29日中央社報導

    瑞士食品業巨擘雀巢集團(Nestle)今(29日)發表聲明稿說:「公司擬將旗下位於瑞士科諾爾芬根(Konolfingen)的研發中心,開放給新創公司、學生和科學家。」,加速開發以植物為主的乳製品替代品。

    雀巢表示,將會有內部、外部以及混合編組團隊在研發中心工作,為期六個月。

    除了對永續乳製品進行測試外,集團也計畫鼓勵開發以植物為基礎的乳製品替代品。雀巢發表以此程序研發出來的一種使用蔬菜為基礎乳品。

    氣候變遷
    國際新聞
    瑞士
    乳製品
    素食

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

    【其他文章推薦】

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

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

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

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

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

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

  • 為疫苗研發犧牲? 保育團體憂:25萬尾鯊魚恐間接受害

    摘錄自2020年9月29日自由時報報導

    為盡速結束武漢肺炎(COVID-19)疫情所帶來的災難,各國無不卯足全力研發疫苗,然而近期有研發廠商為了讓疫苗的效果穩定,決定在疫苗內添加高效的醫學物質「鯊烯」(Squalene),然而鯊烯這種物質相當稀少,美國有鯊魚保育團體推估,光是製造提供給美國使用的疫苗量,恐就要殺死超過2.1萬條鯊魚,若是全世界範圍,「可能要殺害25萬條鯊魚」。

    綜合外媒報導,「鯊烯」主要從鯊魚的肝油中提煉而出,在醫學與美容方面都是極為重要的高效素質,不僅可以滋潤皮膚,也可以提高、增強免疫力,加在疫苗中可使疫苗的效力提升,然而鯊魚肝油中提煉出的鯊烯十分稀少,平均一噸的鯊烯大約需要3000條鯊魚。

    英國製藥大廠葛蘭素史克(GlaxoSmithKline)專門生產用於流感疫苗中的以鯊烯製成的佐劑,而葛蘭素史克曾表示,將在2021年生產10億個以鯊烯製成的「武漢肺炎疫苗用佐劑」,引起保育團體的憂慮;位在美國加州的鯊魚保育團體鯊魚同盟(Shark Allies)表示,如果全世界的人都會接種這種加入佐劑的疫苗,「那可能要殺害25萬條鯊魚」,如果再算上二次接種,數量還會翻倍到50萬條。

    海洋
    國際新聞
    鯊魚

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

    【其他文章推薦】

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

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

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

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

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

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

  • 加州野火每5秒燒1英畝 吞噬酒莊數萬人撤離

    摘錄自2020年9月28日中央社報導

    美國加州野火在強風助長下,每5秒鐘延燒約1英畝的土地,蔓延到世界知名的葡萄酒之鄉,納帕(Napa)與索諾馬(Sonoma)山谷今天有數以萬計的民眾被迫逃離家園。

    根據美國國家海洋暨大氣總署(NOAA)衛星影像,昨天清晨約4時從納帕山谷爆發的「玻璃之火」(Glass Fire),昨晚延燒了2500英畝的土地,到了今早擴大到1萬1000英畝,相當於每5秒鐘燒掉約1英畝(約0.4公頃)。

    法新社報導,加州森林防火廳(Cal Fire)說,加州野火把天空染成橘紅色,在悶熱的熱浪侵襲之下,火勢以「危險的速度」蔓延,且沒有一處獲得控制,沿途燒毀數座葡萄園與建築物。

    官員說,當局已下令近3萬4000名居民疏散,並要求約1萬4000人準備立即撤離,因為「迅速蔓延的火勢」延燒到乾燥的植被以及難以進入的山區。

    氣候變遷
    國際新聞
    美國
    加州
    野火
    森林野火

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

    【其他文章推薦】

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

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

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

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

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

  • 保護全球最美星空 智利環團提告商業大樓「污染天空」

    摘錄自2020年9月28日奇摩新聞報導

    智利北部的阿他加馬沙漠曾獲選BBC全球十大最美暗夜星空,入夜後整片的星空美不勝收,吸引了各種追星者和天文學家,因此聚集大量觀星者的巨型望遠鏡,幾乎半數的世界天文觀測站都在這。但現在都市的擴張和發展伴隨的光污染使星星黯淡許多,甚至使一些關鍵地區的天空退化超過10%。

    智利環保機構表示,將提告用「人造冷光」污染天空的公司,當地政府也打算修法,若業者減少光污染將有特別優惠,希望利用合法的力量和新的保護措施讓天空保持黑暗。但目前收到起訴和修正的公司都還未回覆,其他公司也都還在審理中。

    污染治理
    國際新聞
    智利
    光害
    星空

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

    【其他文章推薦】

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

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

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

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

    ※回頭車貨運收費標準

  • 中國湖北化工廠大爆炸 至少5死1傷

    摘錄自2020年9月28日自由時報報導

    中國湖北省天門市岳口鎮譚湖工業園區內一化工廠,今(28)日下午發生爆炸,現場黃煙亂竄疑似硝酸外洩,當地政府部門指出,目前事故已造成5死1傷。

    綜合中媒報導,湖北省應急管理廳指出,天門市應急管理局報告,今日下午2點15分左右,天門市岳口工業園天門楚天精細化工有限公司進行設備調試期間,發生板框壓力機爆炸,初步發現事故現場5人死亡、1人受傷。有目擊者稱現場疑似是硝酸外洩,導致竄出大量黃煙。

    天門市應急管理局表示,傷者已送醫救治,現場搜救工作仍在進行中,事故原因及過程仍有待釐清。

    污染治理
    國際新聞
    中國
    化工廠
    化工廠爆炸

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

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

  • 紅毛猩猩家園上動土惹議 印尼中資水壩遇武肺將延後三年動工

    環境資訊中心綜合外電;黃鈺婷 翻譯;林大利 審校;稿源:Mongabay

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

    【其他文章推薦】

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

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

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

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

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

  • 人類壓力步步進逼 全球13年間荒野損失面積相當於墨西哥

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

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

    【其他文章推薦】

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

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

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

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

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

  • 印度8歲氣候人士 為氣候變遷法案請命

    摘錄自2020年9月29日公視報導

    印度一位年僅8歲的氣候人士「坎古嘉姆」,為氣候變遷相關法案請命:「我今年8歲,我是印度氣候人士,也是兒童運動的創辦人,今天我在議會前,要告訴我們最尊敬的總理莫迪,還有我們的議員,盡快通過氣候變遷法案。」

    坎古嘉姆舉著看板持續朝議會前進,遭警方攔阻並驅離。她出生於印度東北方的曼尼普爾邦,自小享受山上清淨的空氣,對擁有1900萬人口、世界上空污最嚴重的城市「德里」無法忍受。

    坎古嘉姆強調:「我希望每個國家及國際媒體,要寫故事就以我們的真名去寫,如果你說我是印度的童貝里,那你不是在寫故事,你是在刪故事。」

    氣候變遷
    國際新聞
    印度
    兒童

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

    【其他文章推薦】

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

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

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

    ※超省錢租車方案

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

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

  • 特斯拉為電池進軍礦業 放棄併購決定自己挖鋰礦

    摘錄自2020年9月29日聯合新聞報導

    彭博資訊引述知情人士報導,電動車大廠特斯拉(Tesla)本想以併購方式取得在美國內華達州的一處鋰礦,但是和礦商Cypress開發公司的收購談判沒能成功,現在改以自行取得採礦權的方式,準備自己開採,以確保鋰礦供應源。

    上周特斯拉舉行「電池日」時,執行長馬斯克仍宣布,已經確保了礦權,而且將要自己來挖礦。馬斯克告訴投資人,特斯拉已經確定取得1萬英畝有著鋰蘊藏豐富泥岩的區域,將以「極為永續的方法」來提取出鋰。

    特斯拉決定自己生產電池並且目標要將電池成本砍一半,進軍礦業已經成為此計畫的中心。

    能源轉型
    國際新聞
    特斯拉
    礦業

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

    【其他文章推薦】

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

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

    ※超省錢租車方案

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

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

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