orleans集群及負載均衡實現


netcore6項目,微服務框架選orleans ,國內似乎沒什么項目在用,坑多無資料。
orleans文檔可以解決幾乎,只能看官方資料。

Introduction | Microsoft Orleans 中文文檔

服務異常客戶端怎么接收,鏈接釋放,內存泄露等各種問題都迎刃而解。
早先弄了幾個服務測試,發現同一個請求或者同幾個請求,都只集中在一個服務上,而且不管服務多耗時間,都是無限等待一個請求完再下一個,除非一個掛了,下一個就頂上。這顯然不是想要的效果
(這里的服務是cpoy改文件就行)。這就是遇到無法負載均衡的問題
,網上翻遍資料,源碼test過了一遍,除了Azure提到了無關緊要的負載,已無辦法可尋。
晚上打王者突然有了靈感,既然外面獲取不到,不如自己創造條件。
很早想過用consul,但是它不是http請求那么簡單,所以以自己的能力行不通。那想做負載,為什么不弄幾個一樣的服務呢,在客戶端隨機或者循環請求幾個服務,而服務的接口應該是一模一樣的,只是看起來像不同的服務而已。
結果比想的還要簡單,只需要做配置端口,后面請求不需要自己手動去輪詢或者隨機。
這,也是最終的辦法了,雖然會多出來幾個服務。(這里是實實在在的新建服務,代碼一樣,服務名空間名不一樣。)

項目中各種配置比這復雜的多,就不多贅述

這是我提的issue:

how can orleans server response load balancing · Issue #7497 · dotnet/orleans (github.com)

后續總結,首先謝謝評論的各位。希望都能樂於分享,一個代碼demo不光能解決我的問題,有需要的大有人在。只討論是否有這個東西對那些難以理解,或者個人技術不到位的很難去解釋清楚,或者說沒有那么清晰。

orleans文檔體現是有集群負載,orleans的sample功能很多,但是都沒用到。我的project只是拿來作為前后端分離類似微服務consul,僅做請求分離,我的test里面案例寫的很清楚。
改進前的效果:
如果我同一個服務無限多開,或者改掉ip、port、gateway,效果都是一個服務端接收請求,其他服務端處於等待,直到一個掛掉后面服務再頂上。
改進后的效果:多個服務端輪詢或者隨機接收客戶端請求。
1、客戶端部署多個,服務端部署多個。
2、服務端必須輪詢或者隨機接收客戶端請求,而不是上面情況。

例子在這里:exercisebook/Orleans at main · liuzhixin405/exercisebook (github.com)

這個例子是一個服務,但是我給拷貝了三分,改了每份的配置。分別是host、hostcopy、hostcopycopy

 

 

 

三個服務代碼其實是一樣的,只是每個服務讀取的配置文件不一樣。這樣能達到目的,實現輪詢負載,但是更復雜了。因為我有多個服務,每個服務要重新建至少兩個項目,雖然項目幾乎無差別。

能力有限,能力范圍能最終解決方案來了,看代碼就知道很精簡。

exercisebook/Orleans/Orleans.MultiClient-TestTwo at main · liuzhixin405/exercisebook (github.com)

 這里只有一個host服務,只需要把host服務發布的文件拷貝一份,每份改掉下面的內容就行:

分別修改配置文件中ip、siloPort、gatewayProt分別按照這個配置文件來配置。
重點注意,1、服務端的配置節點key都是host,保持一致。而且客戶端的名字是要區分開的。2、必須先啟動服務,后啟動此客戶端(webapi)

這里不管是第一種解決方案還是第二種都不需要改動任何客戶端代碼:客戶端的配置文件和測試代碼如下:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Orleans.Grains;
using System;
using System.Threading.Tasks;

namespace Orleans.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TestMultiClientController : ControllerBase
    {
        private readonly IOrleansClient _orleansClient;
        public TestMultiClientController(IOrleansClient orleansClient)
        {
            _orleansClient = orleansClient;
        }

        [HttpGet]
        public async Task<string> GetOrleans1()
        {
            int sum = 0;
            for (int i = 10; i > 0; i--)
            {
                int temp = i;
                sum += temp;
                await Task.Delay(100);
                var cluster = _orleansClient.GetClusterClient(typeof(IHelloA).Assembly).GetGrain<IHelloA>(0);        
                await cluster.SayHello(DateTime.Now.ToString());
            }
            return sum.ToString();
        }

    }
}
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "host": {
    "ClusterId": "A",
    "ServiceId": "AAPP",
    "Password": "123",
    "Host": "*",
    "Port": 8084,
    "HostSelf": true,
    "CounterUpdateIntervalMs": 1000,
    "GatewayPort": 30004,
    "SiloPort": 11115,
    "IpAddress": "127.0.0.1"

  },
  "hostCopy": {
    "ClusterId": "A",
    "ServiceId": "AAPP",
    "Password": "123",
    "Host": "*",
    "Port": 8086,
    "HostSelf": true,
    "CounterUpdateIntervalMs": 1000,
    "GatewayPort": 30006,
    "SiloPort": 11117,
    "IpAddress": "127.0.0.1"
  },
  "hostCopyCopy": {
    "ClusterId": "A",
    "ServiceId": "AAPP",
    "Password": "123",
    "Host": "*",
    "Port": 8087,
    "HostSelf": true,
    "CounterUpdateIntervalMs": 1000,
    "GatewayPort": 30007,
    "SiloPort": 11118,
    "IpAddress": "127.0.0.1"
  } //拷貝兩份host服務,分別修改配置文件中ip、siloPort、gatewayProt分別按照這個配置文件來配置。
  //重點注意,1、服務端的配置節點key都是host,保持一致。而且客戶端的名字是要區分開的。2、必須先啟動服務,后啟動此客戶端(webapi)
}

運行結果都是這樣:

 

有疑問的請先看test代碼,再有疑問留言討論,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM