Compare commits
64 Commits
Author | SHA1 | Date |
---|---|---|
|
7afd0d2870 | |
|
c02eca0a22 | |
|
c26496ee89 | |
|
d2918c37e3 | |
|
86ba5d878b | |
|
ded6426c8c | |
|
237bddc703 | |
|
a3a8022361 | |
|
d65d967e85 | |
|
60de3cb573 | |
|
59b02d31a7 | |
|
4adf6d87fc | |
|
2f77ac59f2 | |
|
85719ccffc | |
|
cb9f1d16ce | |
|
686e3bfdc8 | |
|
3ea0fdef46 | |
|
5f14c1d7d4 | |
|
e6cf34bbfe | |
|
185362b2af | |
|
c7a50c7764 | |
|
42fb0b56cd | |
|
4359f77eaa | |
|
d40db4ab61 | |
|
7664d2d36a | |
|
81d54b2bbf | |
|
290cc6d784 | |
|
40afb63e45 | |
|
27e92bd2c6 | |
|
9a700ad62e | |
|
f12c66a3b2 | |
|
68df6f5351 | |
|
a29ef5086e | |
|
ce3de526e1 | |
|
76463efd14 | |
|
22537b78b8 | |
|
9597becbf4 | |
|
30d9b1c2a4 | |
|
8ebdb6b1cb | |
|
15994e4463 | |
|
4b11429f76 | |
|
cca6ba4921 | |
|
f2d57d6640 | |
|
7d67c1d8da | |
|
31d4465e16 | |
|
4e78c2d059 | |
|
8184ce58e0 | |
|
1e995cdd76 | |
|
66712bc22c | |
|
db995de99e | |
|
8c8e5879f7 | |
|
17a7dadfa1 | |
|
b8cd831e97 | |
|
e13041e8a3 | |
|
b728ca143d | |
|
d88a74a6d4 | |
|
83eae087eb | |
|
28b66a6181 | |
|
4718fba1e2 | |
|
7936de782f | |
|
99575dde9d | |
|
671246e462 | |
|
a5c22793ff | |
|
da0b20b68d |
|
@ -11,11 +11,14 @@ jobs:
|
|||
name: build on windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: |
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src\Nacos\Nacos.csproj
|
||||
|
@ -31,23 +34,27 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Show dotnet Version
|
||||
run: dotnet --version
|
||||
- name: Show java Version
|
||||
run: java -version
|
||||
- name: Setup Stable 1.x Nacos Server
|
||||
run: |
|
||||
wget https://github.com/alibaba/nacos/releases/download/1.4.2/nacos-server-1.4.2.tar.gz
|
||||
tar -xvf nacos-server-1.4.2.tar.gz
|
||||
wget https://github.com/alibaba/nacos/releases/download/1.4.4/nacos-server-1.4.4.tar.gz
|
||||
tar -xvf nacos-server-1.4.4.tar.gz
|
||||
cd nacos/bin
|
||||
# sed -i 's/nacos.core.auth.enabled=false/nacos.core.auth.enabled=true/g' ../conf/application.properties
|
||||
chmod 755 startup.sh
|
||||
|
@ -70,7 +77,7 @@ jobs:
|
|||
dotnet test tests/Nacos.Tests/Nacos.Tests.csproj --filter "Category=all|Category=1x" --no-restore
|
||||
- name: Upload Nacos logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
||||
|
|
|
@ -11,11 +11,14 @@ jobs:
|
|||
name: build on windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: |
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src\Nacos\Nacos.csproj
|
||||
|
@ -31,23 +34,27 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Show dotnet Version
|
||||
run: dotnet --version
|
||||
- name: Show java Version
|
||||
run: java -version
|
||||
- name: Setup Stable 2.x Nacos Server
|
||||
run: |
|
||||
wget https://github.com/alibaba/nacos/releases/download/2.0.2/nacos-server-2.0.2.tar.gz
|
||||
tar -xvf nacos-server-2.0.2.tar.gz
|
||||
wget https://github.com/alibaba/nacos/releases/download/2.1.0/nacos-server-2.1.0.tar.gz
|
||||
tar -xvf nacos-server-2.1.0.tar.gz
|
||||
cd nacos/bin
|
||||
# sed -i 's/nacos.core.auth.enabled=false/nacos.core.auth.enabled=true/g' ../conf/application.properties
|
||||
chmod 755 startup.sh
|
||||
|
@ -70,7 +77,7 @@ jobs:
|
|||
dotnet test tests/Nacos.Tests/Nacos.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
- name: Upload Nacos logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
||||
|
|
|
@ -13,23 +13,27 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Show dotnet Version
|
||||
run: dotnet --version
|
||||
- name: Show java Version
|
||||
run: java -version
|
||||
- name: Setup Unstable Nacos Server
|
||||
run: |
|
||||
wget https://github.com/alibaba/nacos/releases/download/2.0.3/nacos-server-2.0.3.tar.gz
|
||||
tar -xvf nacos-server-2.0.3.tar.gz
|
||||
wget https://github.com/alibaba/nacos/releases/download/2.1.1/nacos-server-2.1.1.tar.gz
|
||||
tar -xvf nacos-server-2.1.1.tar.gz
|
||||
cd nacos/bin
|
||||
# sed -i 's/nacos.core.auth.enabled=false/nacos.core.auth.enabled=true/g' ../conf/application.properties
|
||||
sed -i 's/Xms512m/Xms1024m/g' startup.sh
|
||||
|
@ -55,7 +59,7 @@ jobs:
|
|||
dotnet test tests/Nacos.Tests/Nacos.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
- name: Upload Nacos logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
||||
|
|
|
@ -11,15 +11,19 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: |
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos/Nacos.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.AspNetCore/Nacos.AspNetCore.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.Microsoft.Extensions.ServiceDiscovery/Nacos.Microsoft.Extensions.ServiceDiscovery.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.Microsoft.Extensions.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json parsers/Nacos.IniParser/Nacos.IniParser.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json parsers/Nacos.YamlParser/Nacos.YamlParser.csproj
|
||||
|
@ -29,12 +33,13 @@ jobs:
|
|||
ver=alpha`date +%Y%m%d%H%M%S`
|
||||
dotnet pack src/Nacos/Nacos.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.AspNetCore/Nacos.AspNetCore.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.Microsoft.Extensions.ServiceDiscovery/Nacos.Microsoft.Extensions.ServiceDiscovery.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.Microsoft.Extensions.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack parsers/Nacos.IniParser/Nacos.IniParser.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack parsers/Nacos.YamlParser/Nacos.YamlParser.csproj --version-suffix $ver -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet msbuild -p:Configuration=Release -t:pack -p:PackageOutputPath=/home/runner/work/nugetpkgs -p:VersionSuffix=$ver src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nugetpkgs
|
||||
path: /home/runner/work/nugetpkgs
|
||||
|
@ -46,9 +51,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nugetpkgs
|
||||
path: nugetpkgs
|
||||
- name: list nugetpkgs
|
||||
run: ls nugetpkgs
|
||||
- name: Release
|
||||
|
|
|
@ -11,15 +11,19 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: |
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos/Nacos.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.AspNetCore/Nacos.AspNetCore.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.Microsoft.Extensions.ServiceDiscovery/Nacos.Microsoft.Extensions.ServiceDiscovery.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json src/Nacos.Microsoft.Extensions.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json parsers/Nacos.IniParser/Nacos.IniParser.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json parsers/Nacos.YamlParser/Nacos.YamlParser.csproj
|
||||
|
@ -28,12 +32,13 @@ jobs:
|
|||
run: |
|
||||
dotnet pack src/Nacos/Nacos.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.AspNetCore/Nacos.AspNetCore.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.Microsoft.Extensions.ServiceDiscovery/Nacos.Microsoft.Extensions.ServiceDiscovery.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack src/Nacos.Microsoft.Extensions.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack parsers/Nacos.IniParser/Nacos.IniParser.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet pack parsers/Nacos.YamlParser/Nacos.YamlParser.csproj -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
dotnet msbuild -p:Configuration=Release -t:pack -p:PackageOutputPath=/home/runner/work/nugetpkgs src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: nugetpkgs
|
||||
path: /home/runner/work/nugetpkgs
|
||||
|
@ -45,9 +50,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nugetpkgs
|
||||
path: nugetpkgs
|
||||
- name: list nugetpkgs
|
||||
run: ls nugetpkgs
|
||||
- name: Release
|
||||
|
|
14
README.md
14
README.md
|
@ -39,6 +39,18 @@ https://nacos-sdk-csharp.readthedocs.io/en/latest/
|
|||
1. Configure in `Program.cs`
|
||||
|
||||
```cs
|
||||
// after v1.3.3, we can use UseNacosConfig to simplify
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.UseNacosConfig(section: "NacosConfig", parser: null, logAction: null)
|
||||
// .UseNacosConfig(section: "NacosConfig", parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance logAction: null)
|
||||
// .UseNacosConfig(section: "NacosConfig", parser: Nacos.IniParser.IniConfigurationStringParser.Instance logAction: null)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
|
||||
// before v1.3.3
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
|
@ -55,7 +67,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
2. Modify `appsettings.json`
|
||||
|
|
|
@ -41,6 +41,18 @@ https://nacos-sdk-csharp.readthedocs.io/en/latest/
|
|||
1. 在 `Program.cs` 进行如下配置
|
||||
|
||||
```cs
|
||||
// v1.3.3 版本之后, 可以用 UseNacosConfig 来简化
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.UseNacosConfig(section: "NacosConfig", parser: null, logAction: null)
|
||||
// .UseNacosConfig(section: "NacosConfig", parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance logAction: null)
|
||||
// .UseNacosConfig(section: "NacosConfig", parser: Nacos.IniParser.IniConfigurationStringParser.Instance logAction: null)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
|
||||
// v1.3.3 版本之前
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
|
@ -57,7 +69,7 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
2. 修改 `appsettings.json`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<NugetVersion>1.3.2</NugetVersion>
|
||||
<NugetVersion>1.3.10</NugetVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
2022
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- `微服务 配置中心 Nacos .Net 5 <https://blog.csdn.net/i2blue/article/details/124827269>`_ 【2022-05-17】
|
||||
- `待挖掘 <https://github.com/nacos-group/nacos-sdk-csharp>`_ 【2022-xx-xx】
|
||||
|
||||
|
||||
|
|
|
@ -28,3 +28,14 @@ SDK 在 v1.x 版本之后,就是默认用 grpc 的方式和 nacos server 对
|
|||
针对 b 的情况,需要把 9848 暴露出来。
|
||||
|
||||
如果修改了默认端口或者是通过环境变量设置了偏移,自行调整对应端口,参考 https://nacos.io/zh-cn/docs/2.0.0-compatibility.html
|
||||
|
||||
3. nacos-sdk-csharp 版本与 nacos server 版本关系
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
nacos server 目前主要有 1.x 版本和 2.x 版本
|
||||
|
||||
nacos-sdk-csharp 有 0.x unofficial 版本 和 1.x 版本
|
||||
|
||||
nacos-sdk-csharp 0.x unofficial 版本 只能应用于 nacos server 1.x 版本
|
||||
|
||||
nacos-sdk-csharp 1.x 版本 可以同时应用于 nacos server 1.x 版本 和 2.x 版本
|
||||
|
|
|
@ -40,11 +40,11 @@
|
|||
:hidden:
|
||||
:caption: Release Note
|
||||
|
||||
releasenote/v1.2.1
|
||||
releasenote/v1.2.2
|
||||
releasenote/v1.3.0
|
||||
releasenote/v1.3.1
|
||||
releasenote/v1.3.2
|
||||
releasenote/v1.3.3
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
v1.3.3 (May 30th, 2022) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [NAMING] Fix IsSubscribed exception when NamingUseRpc is false (#194 #196)
|
||||
#. [CONFIG] Fix ReceiveConfigInfo dict get item error in startup (#200 #201)
|
||||
#. [CONFIG] Improve Microsoft.Extensions.Configuration Integration (#203 #204)
|
||||
#. [CONFIG] Config cache path from JM.SNAPSHOT.PATH env at first (#205 #206)
|
||||
#. [CORE] Add package readme file (#207)
|
||||
#. [CI] Update version of Nacos Server
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复 NamingUseRpc 设置成 false 是 IsSubscribed 抛异常的问题 (#194 #196)
|
||||
#. [CONFIG] 修复启动时 ReceiveConfigInfo 字典操作异常问题 (#200 #201)
|
||||
#. [CONFIG] 优化 Microsoft.Extensions.Configuration 的集成 (#203 #204)
|
||||
#. [CONFIG] 优化配置缓存的路径读取方式 (#205 #206)
|
||||
#. [CORE] 添加nuget包说明文件 (#207)
|
||||
#. [CI] 更新 Nacos Server 版本
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28803.156
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.11.35303.130
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C473C3A7-1B44-4E1F-83C0-745AD0566FE9}"
|
||||
EndProject
|
||||
|
@ -47,6 +47,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
README.zh-cn.md = README.zh-cn.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.Microsoft.Extensions.ServiceDiscovery", "src\Nacos.Microsoft.Extensions.ServiceDiscovery\Nacos.Microsoft.Extensions.ServiceDiscovery.csproj", "{46FDA099-A266-4E7B-9B5B-496575A54CCD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -109,6 +111,10 @@ Global
|
|||
{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{46FDA099-A266-4E7B-9B5B-496575A54CCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46FDA099-A266-4E7B-9B5B-496575A54CCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46FDA099-A266-4E7B-9B5B-496575A54CCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{46FDA099-A266-4E7B-9B5B-496575A54CCD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -128,6 +134,7 @@ Global
|
|||
{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63} = {CFFCAA8B-3562-420B-AA8B-C525CC1ECD78}
|
||||
{7C20F5FB-33D4-460A-86F4-FC42122FA543} = {C473C3A7-1B44-4E1F-83C0-745AD0566FE9}
|
||||
{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47} = {25B1A184-1541-4F4E-A151-24A47CC08F34}
|
||||
{46FDA099-A266-4E7B-9B5B-496575A54CCD} = {C473C3A7-1B44-4E1F-83C0-745AD0566FE9}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A1C5215E-0E70-4C04-B21E-5209BCF32472}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.IniParser</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
|
@ -13,6 +13,7 @@
|
|||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
@ -24,14 +25,15 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# nacos-sdk-csharp.IniParser
|
||||
|
||||
nacos-sdk-csharp.IniParser provides ini format config parser.
|
||||
|
||||
```csharp
|
||||
builder.Host.UseNacosConfig(section: "NacosConfig", parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
|
||||
// or
|
||||
|
||||
builder.Host.ConfigureAppConfiguration((c, b) =>
|
||||
{
|
||||
var config = b.Build();
|
||||
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
});
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -2,7 +2,7 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.YamlParser</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
|
@ -13,6 +13,7 @@
|
|||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
@ -24,14 +25,15 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# nacos-sdk-csharp.YamlParser
|
||||
|
||||
nacos-sdk-csharp.YamlParser provides yaml/yml format config parser.
|
||||
|
||||
```csharp
|
||||
builder.Host.UseNacosConfig(section: "NacosConfig", parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
|
||||
// or
|
||||
|
||||
builder.Host.ConfigureAppConfiguration((c, b) =>
|
||||
{
|
||||
var config = b.Build();
|
||||
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
});
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -1,12 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Nacos.AspNetCore\Nacos.AspNetCore.csproj" />
|
||||
<ProjectReference Include="..\..\src\Nacos.Microsoft.Extensions.ServiceDiscovery\Nacos.Microsoft.Extensions.ServiceDiscovery.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -83,6 +83,9 @@
|
|||
|
||||
public static string? AESDecrypt(string data, string key)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
return null;
|
||||
|
||||
byte[] encryptedBytes = Convert.FromBase64String(data);
|
||||
byte[] bKey = new byte[32];
|
||||
Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
public class NamingController : ControllerBase
|
||||
{
|
||||
private readonly Nacos.V2.INacosNamingService _client;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public NamingController(Nacos.V2.INacosNamingService client)
|
||||
public NamingController(Nacos.V2.INacosNamingService client, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_client = client;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
// GET n/g
|
||||
|
@ -102,6 +104,17 @@
|
|||
return res ?? "GetServicesOfServer";
|
||||
}
|
||||
|
||||
// GET n/sd
|
||||
[HttpGet("sd")]
|
||||
public async Task<string> ServiceDiscovery()
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient("app1");
|
||||
var response = await client.GetAsync("/api/values").ConfigureAwait(false);
|
||||
var res = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// GET n/sub
|
||||
[HttpGet("sub")]
|
||||
public async Task<string> Subscribe()
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
namespace App3.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nacos.V2.Utils;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[ApiController]
|
||||
[Route("o")]
|
||||
public class OpenApiController : ControllerBase
|
||||
{
|
||||
private readonly Nacos.OpenApi.INacosOpenApi _api;
|
||||
|
||||
public OpenApiController(Nacos.OpenApi.INacosOpenApi api)
|
||||
{
|
||||
_api = api;
|
||||
}
|
||||
|
||||
// GET o/n-g
|
||||
[HttpGet("n-g")]
|
||||
public async Task<string> NamespaceGetAll()
|
||||
{
|
||||
var list = await _api.GetNamespacesAsync().ConfigureAwait(false);
|
||||
|
||||
var res = list.ToJsonString();
|
||||
|
||||
return res ?? "GetAllInstances";
|
||||
}
|
||||
|
||||
// GET o/n-g
|
||||
[HttpGet("n-c")]
|
||||
public async Task<string> NamespaceCreate(string i, string n)
|
||||
{
|
||||
var flag = await _api.CreateNamespaceAsync(i, n, "").ConfigureAwait(false);
|
||||
|
||||
return flag.ToString();
|
||||
}
|
||||
|
||||
// GET o/n-u
|
||||
[HttpGet("n-u")]
|
||||
public async Task<string> NamespaceUpdate(string i, string n)
|
||||
{
|
||||
var flag = await _api.UpdateNamespaceAsync(i, n, "").ConfigureAwait(false);
|
||||
|
||||
return flag.ToString();
|
||||
}
|
||||
|
||||
// GET o/n-u
|
||||
[HttpGet("n-d")]
|
||||
public async Task<string> NamespaceDelete(string i)
|
||||
{
|
||||
var flag = await _api.DeleteNamespaceAsync(i).ConfigureAwait(false);
|
||||
|
||||
return flag.ToString();
|
||||
}
|
||||
|
||||
// GET o/metrics
|
||||
[HttpGet("metrics")]
|
||||
public async Task<string> GetMetrics()
|
||||
{
|
||||
var flag = await _api.GetMetricsAsync(false).ConfigureAwait(false);
|
||||
|
||||
return flag.ToJsonString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Nacos.V2.DependencyInjection;
|
||||
using Nacos.OpenApi;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
@ -27,6 +28,32 @@ builder.Services.AddNacosV2Naming(x =>
|
|||
x.NamingUseRpc = true;
|
||||
});
|
||||
|
||||
builder.Services.AddNacosOpenApi(x =>
|
||||
{
|
||||
x.ServerAddresses = new System.Collections.Generic.List<string> { "http://localhost:8848/" };
|
||||
x.EndPoint = "";
|
||||
x.Namespace = "cs";
|
||||
});
|
||||
|
||||
// Microsoft.Extensions.ServiceDiscovery
|
||||
builder.Services.AddServiceDiscovery(o =>
|
||||
{
|
||||
o.RefreshPeriod = TimeSpan.FromSeconds(60);
|
||||
})
|
||||
.AddConfigurationServiceEndpointProvider()
|
||||
.AddNacosServiceEndpointProvider();
|
||||
|
||||
builder.Services.ConfigureHttpClientDefaults(static http =>
|
||||
{
|
||||
http.AddServiceDiscovery();
|
||||
});
|
||||
|
||||
// use IHttpClientFactory
|
||||
builder.Services.AddHttpClient("app1", cfg =>
|
||||
{
|
||||
cfg.BaseAddress = new Uri("http://app1");
|
||||
});
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
|
@ -38,9 +65,6 @@ if (app.Environment.IsDevelopment())
|
|||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
app.MapControllers();
|
||||
|
||||
app.Run("http://*:9632");
|
||||
|
|
|
@ -20,6 +20,17 @@ builder.Services.Configure<MsConfigApp.AppSettings>(builder.Configuration.GetSec
|
|||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// NOTE: after v1.3.3
|
||||
// read configuration from config files
|
||||
// default parser is json
|
||||
builder.Host.UseNacosConfig(section: "NacosConfig");
|
||||
|
||||
// specify ini or yaml parser
|
||||
// builder.Host.UseNacosConfig(section: "NacosConfig", parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.Host.UseNacosConfig(section: "NacosConfig", parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
|
||||
/*
|
||||
NOTE: before v1.3.3
|
||||
builder.Host.ConfigureAppConfiguration((c, b) =>
|
||||
{
|
||||
var config = b.Build();
|
||||
|
@ -27,13 +38,15 @@ builder.Host.ConfigureAppConfiguration((c, b) =>
|
|||
// read configuration from config files
|
||||
// default is json
|
||||
// b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), logAction: x => x.AddSerilog(Log.Logger));
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
|
||||
// specify ini or yaml
|
||||
// b.AddNacosV2Configuration(config.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// b.AddNacosV2Configuration(config.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
})
|
||||
.UseSerilog();
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
});
|
||||
*/
|
||||
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# MsConfigApp
|
||||
# MsConfigApp
|
||||
|
||||
This sample shows how to integrate ASP.NET Core Configuration System.
|
||||
|
||||
|
@ -37,7 +37,9 @@ https://nacos.io/en-us/docs/quick-start-docker.html
|
|||
"Password": "123456",
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "acm.aliyun.com"
|
||||
"EndPoint": "acm.aliyun.com",
|
||||
"ConfigFilterAssemblies": [ "MsConfigApp" ],
|
||||
"ConfigFilterExtInfo": "{\"JsonPaths\":[\"ConnectionStrings.Default\"],\"Other\":\"xxxxxx\"}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -69,10 +71,30 @@ The first one, its dataid is demo, group is DFAULT_GROUP and the value is as fol
|
|||
}
|
||||
```
|
||||
|
||||
> NOTE: If **ConfigFilterAssemblies** is not empty, using the following config value.
|
||||
|
||||
|
||||
```JSON
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Default": "U2VydmVyPTEyNy4wLjAuMTtQb3J0PTMzMDY7RGF0YWJhc2U9ZGVtbztVc2VyIElkPXJvb3Q7UGFzc3dvcmQ9MTIzNDU2Ow=="
|
||||
},
|
||||
"version": "测试version",
|
||||
"AppSettings": {
|
||||
"Str": "val",
|
||||
"num": 1,
|
||||
"arr": [1, 2, 3],
|
||||
"subobj": {
|
||||
"a": "b"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The second one, its dataid is common, group is DFAULT_GROUP and the value is as following.
|
||||
|
||||
```JSON
|
||||
{
|
||||
"all": "test"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.AspNetCore</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
|
@ -13,7 +13,8 @@
|
|||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReleaseNotes>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -28,6 +29,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
|
@ -35,8 +37,8 @@
|
|||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# nacos-sdk-csharp.AspNetCore
|
||||
|
||||
nacos-sdk-csharp.AspNetCore provides service registration and discovery With ASP.NET Core.
|
||||
|
||||
```csharp
|
||||
builder.Services.AddNacosAspNet(x =>
|
||||
{
|
||||
x.ServerAddresses = new List<string> { "http://localhost:8848/" };
|
||||
x.Namespace = "cs";
|
||||
x.ServiceName = "App2";
|
||||
x.GroupName = "DEFAULT_GROUP";
|
||||
x.ClusterName = "DEFAULT";
|
||||
x.Ip = "";
|
||||
x.PreferredNetworks = "";
|
||||
x.Port = 0;
|
||||
x.Weight = 100;
|
||||
x.RegisterEnabled = true;
|
||||
x.InstanceEnabled = true;
|
||||
x.Ephemeral = true;
|
||||
x.Secure = false;
|
||||
});
|
||||
|
||||
// or
|
||||
|
||||
builder.Services.AddNacosAspNet(builder.Configuration);
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -1,147 +1,174 @@
|
|||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Nacos.AspNetCore.Tests")]
|
||||
|
||||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
internal static class UriTool
|
||||
{
|
||||
public static IEnumerable<Uri> GetUri(IFeatureCollection features, string ip, int port, string preferredNetworks)
|
||||
{
|
||||
var splitChars = new char[] { ',', ';' };
|
||||
var appPort = port <= 0 ? 80 : port;
|
||||
|
||||
// 1. config
|
||||
if (!string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
// it seems that nacos don't return the scheme
|
||||
// so here use http only.
|
||||
return new List<Uri> { new Uri($"http://{ip}:{appPort}") };
|
||||
}
|
||||
|
||||
// 1.1. Ip is null && Port has value
|
||||
if (string.IsNullOrWhiteSpace(ip) && appPort != 80)
|
||||
{
|
||||
return new List<Uri> { new Uri($"http://{GetCurrentIp(preferredNetworks)}:{appPort}") };
|
||||
}
|
||||
|
||||
var address = string.Empty;
|
||||
|
||||
// 2. IServerAddressesFeature
|
||||
if (features != null)
|
||||
{
|
||||
var addresses = features.Get<IServerAddressesFeature>();
|
||||
var addressCollection = addresses?.Addresses;
|
||||
|
||||
if (addressCollection != null && addressCollection.Any())
|
||||
{
|
||||
var uris = new List<Uri>();
|
||||
foreach (var item in addressCollection)
|
||||
{
|
||||
var url = ReplaceAddress(item, preferredNetworks);
|
||||
uris.Add(new Uri(url));
|
||||
}
|
||||
|
||||
return uris;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. ASPNETCORE_URLS
|
||||
address = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
var url = ReplaceAddress(address, preferredNetworks);
|
||||
|
||||
return url.Split(splitChars).Select(x => new Uri(x));
|
||||
}
|
||||
|
||||
// 4. --urls
|
||||
var cmdArgs = Environment.GetCommandLineArgs();
|
||||
if (cmdArgs != null && cmdArgs.Any())
|
||||
{
|
||||
var cmd = cmdArgs.FirstOrDefault(x => x.StartsWith("--urls", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(cmd))
|
||||
{
|
||||
address = cmd.Split('=')[1];
|
||||
|
||||
var url = ReplaceAddress(address, preferredNetworks);
|
||||
|
||||
return url.Split(splitChars).Select(x => new Uri(x));
|
||||
}
|
||||
}
|
||||
|
||||
// 5. current ip address third
|
||||
address = $"http://{GetCurrentIp(preferredNetworks)}:{appPort}";
|
||||
|
||||
return new List<Uri> { new Uri(address) };
|
||||
}
|
||||
|
||||
private static string ReplaceAddress(string address, string preferredNetworks)
|
||||
{
|
||||
var ip = GetCurrentIp(preferredNetworks);
|
||||
|
||||
if (address.Contains("*"))
|
||||
{
|
||||
address = address.Replace("*", ip);
|
||||
}
|
||||
else if (address.Contains("+"))
|
||||
{
|
||||
address = address.Replace("+", ip);
|
||||
}
|
||||
else if (address.Contains("localhost", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Replace("localhost", ip, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else if (address.Contains("0.0.0.0", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Replace("0.0.0.0", ip, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
private static string GetCurrentIp(string preferredNetworks)
|
||||
{
|
||||
var instanceIp = "127.0.0.1";
|
||||
|
||||
try
|
||||
{
|
||||
// 获取可用网卡
|
||||
var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up);
|
||||
|
||||
// 获取所有可用网卡IP信息
|
||||
var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses);
|
||||
|
||||
foreach (var ipadd in ipCollection)
|
||||
{
|
||||
if (!IPAddress.IsLoopback(ipadd.Address) && ipadd.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
if (string.IsNullOrEmpty(preferredNetworks))
|
||||
{
|
||||
instanceIp = ipadd.Address.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ipadd.Address.ToString().StartsWith(preferredNetworks)) continue;
|
||||
instanceIp = ipadd.Address.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return instanceIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Nacos.AspNetCore.Tests")]
|
||||
|
||||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
internal static class UriTool
|
||||
{
|
||||
public static IEnumerable<Uri> GetUri(IFeatureCollection features, string ip, int port, string preferredNetworks)
|
||||
{
|
||||
var splitChars = new char[] { ',', ';' };
|
||||
var appPort = port <= 0 ? 80 : port;
|
||||
|
||||
// 1. config
|
||||
if (!string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
// it seems that nacos don't return the scheme
|
||||
// so here use http only.
|
||||
return new List<Uri> { new Uri($"http://{ip}:{appPort}") };
|
||||
}
|
||||
|
||||
// 1.1. Ip is null && Port has value
|
||||
if (string.IsNullOrWhiteSpace(ip) && appPort != 80)
|
||||
{
|
||||
return new List<Uri> { new Uri($"http://{GetCurrentIp(preferredNetworks)}:{appPort}") };
|
||||
}
|
||||
|
||||
var address = string.Empty;
|
||||
|
||||
// 2. IServerAddressesFeature
|
||||
if (features != null)
|
||||
{
|
||||
var addresses = features.Get<IServerAddressesFeature>();
|
||||
var addressCollection = addresses?.Addresses;
|
||||
|
||||
if (addressCollection != null && addressCollection.Any())
|
||||
{
|
||||
var uris = new List<Uri>();
|
||||
foreach (var item in addressCollection)
|
||||
{
|
||||
var url = ReplaceAddress(item, preferredNetworks);
|
||||
uris.Add(new Uri(url));
|
||||
}
|
||||
|
||||
return uris;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. ASPNETCORE_URLS
|
||||
address = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
var url = ReplaceAddress(address, preferredNetworks);
|
||||
|
||||
var uris = url.Split(splitChars).Select(x => new Uri(x));
|
||||
|
||||
foreach (var item in uris)
|
||||
{
|
||||
if (!IPAddress.TryParse(item.Host, out _))
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException("Invalid ip address from ASPNETCORE_URLS");
|
||||
}
|
||||
}
|
||||
|
||||
return uris;
|
||||
}
|
||||
|
||||
// 4. --urls
|
||||
var cmdArgs = Environment.GetCommandLineArgs();
|
||||
if (cmdArgs != null && cmdArgs.Any())
|
||||
{
|
||||
var cmd = cmdArgs.FirstOrDefault(x => x.StartsWith("--urls", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(cmd))
|
||||
{
|
||||
address = cmd.Split('=')[1];
|
||||
|
||||
var url = ReplaceAddress(address, preferredNetworks);
|
||||
|
||||
var uris = url.Split(splitChars).Select(x => new Uri(x));
|
||||
|
||||
foreach (var item in uris)
|
||||
{
|
||||
if (!IPAddress.TryParse(item.Host, out _))
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException("Invalid ip address from --urls");
|
||||
}
|
||||
}
|
||||
|
||||
return uris;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. current ip address third
|
||||
address = $"http://{GetCurrentIp(preferredNetworks)}:{appPort}";
|
||||
|
||||
return new List<Uri> { new Uri(address) };
|
||||
}
|
||||
|
||||
private static string ReplaceAddress(string address, string preferredNetworks)
|
||||
{
|
||||
var ip = GetCurrentIp(preferredNetworks);
|
||||
|
||||
if (address.Contains("*"))
|
||||
{
|
||||
address = address.Replace("*", ip);
|
||||
}
|
||||
else if (address.Contains("+"))
|
||||
{
|
||||
address = address.Replace("+", ip);
|
||||
}
|
||||
else if (address.Contains("localhost", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Replace("localhost", ip, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else if (address.Contains("0.0.0.0", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
address = address.Replace("0.0.0.0", ip, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
private static string GetCurrentIp(string preferredNetworks)
|
||||
{
|
||||
var instanceIp = "127.0.0.1";
|
||||
|
||||
try
|
||||
{
|
||||
// 获取可用网卡
|
||||
var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up);
|
||||
|
||||
// 获取所有可用网卡IP信息
|
||||
var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses);
|
||||
|
||||
var preferredNetworksArr = string.IsNullOrEmpty(preferredNetworks)
|
||||
? new string[0] : preferredNetworks.Split(",");
|
||||
foreach (var ipadd in ipCollection)
|
||||
{
|
||||
if (!IPAddress.IsLoopback(ipadd.Address) &&
|
||||
ipadd.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
if (string.IsNullOrEmpty(preferredNetworks))
|
||||
{
|
||||
instanceIp = ipadd.Address.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!preferredNetworksArr.Any(preferredNetwork =>
|
||||
ipadd.Address.ToString().StartsWith(preferredNetwork)
|
||||
|| Regex.IsMatch(ipadd.Address.ToString(), preferredNetwork))) continue;
|
||||
instanceIp = ipadd.Address.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return instanceIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,5 @@
|
|||
/// Configuration group
|
||||
/// </summary>
|
||||
public string Group { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tenant information. It corresponds to the Namespace field in Nacos.
|
||||
/// </summary>
|
||||
public string Tenant { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Nacos.Microsoft.Extensions.Configuration.Tests")]
|
||||
|
||||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using global::Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.Extensions.Configuration</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
|
@ -13,6 +13,7 @@
|
|||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
@ -24,32 +25,42 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nacos\Nacos.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Nacos.Microsoft.Extensions.Configuration.Tests" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
namespace Microsoft.Extensions.Configuration
|
||||
{
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nacos.Microsoft.Extensions.Configuration;
|
||||
using Nacos.V2;
|
||||
using Nacos.V2.DependencyInjection;
|
||||
using System;
|
||||
|
||||
public static class NacosConfigurationExtensions
|
||||
|
@ -12,9 +15,18 @@
|
|||
/// </summary>
|
||||
/// <param name="builder">IConfigurationBuilder</param>
|
||||
/// <param name="action">setup NacosConfigurationSource</param>
|
||||
/// <param name="client">The nacos config client</param>
|
||||
/// <param name="loggerFactory">The loggerFactory</param>
|
||||
/// <param name="parser">The parser.</param>
|
||||
/// <param name="logAction">The logAction.</param>
|
||||
/// <returns>IConfigurationBuilder</returns>
|
||||
public static IConfigurationBuilder AddNacosV2Configuration(
|
||||
this IConfigurationBuilder builder, Action<NacosV2ConfigurationSource> action)
|
||||
this IConfigurationBuilder builder,
|
||||
Action<NacosV2ConfigurationSource> action,
|
||||
INacosConfigService client = null,
|
||||
ILoggerFactory loggerFactory = null,
|
||||
INacosConfigurationParser parser = null,
|
||||
Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
|
@ -26,11 +38,11 @@
|
|||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
var source = new NacosV2ConfigurationSource();
|
||||
var source = new NacosV2ConfigurationSource(null, null);
|
||||
action.Invoke(source);
|
||||
source.NacosConfigurationParser ??= parser ?? DefaultJsonConfigurationStringParser.Instance;
|
||||
|
||||
action(source);
|
||||
|
||||
source.NacosConfigurationParser ??= DefaultJsonConfigurationStringParser.Instance;
|
||||
BuildDISource(source, client, loggerFactory, logAction);
|
||||
|
||||
return builder.Add(source);
|
||||
}
|
||||
|
@ -40,12 +52,16 @@
|
|||
/// </summary>
|
||||
/// <param name="builder">IConfigurationBuilder</param>
|
||||
/// <param name="configuration">Configuration binding nacos configuration source</param>
|
||||
/// <param name="client">The nacos config client</param>
|
||||
/// <param name="loggerFactory">The loggerFactory</param>
|
||||
/// <param name="parser">The parser.</param>
|
||||
/// <param name="logAction">The logging action.</param>
|
||||
/// <param name="logAction">The logAction.</param>
|
||||
/// <returns>IConfigurationBuilder</returns>
|
||||
public static IConfigurationBuilder AddNacosV2Configuration(
|
||||
this IConfigurationBuilder builder,
|
||||
IConfiguration configuration,
|
||||
INacosConfigService client = null,
|
||||
ILoggerFactory loggerFactory = null,
|
||||
INacosConfigurationParser parser = null,
|
||||
Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
|
@ -59,12 +75,79 @@
|
|||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
var source = new NacosV2ConfigurationSource();
|
||||
var source = new NacosV2ConfigurationSource(null, null);
|
||||
configuration.Bind(source);
|
||||
source.NacosConfigurationParser = parser ?? DefaultJsonConfigurationStringParser.Instance;
|
||||
source.LoggingBuilder = logAction;
|
||||
|
||||
BuildDISource(source, client, loggerFactory, logAction);
|
||||
|
||||
return builder.Add(source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use nacos config combine IHostBuilder and ConfigureAppConfiguration
|
||||
/// </summary>
|
||||
/// <param name="builder">host builder.</param>
|
||||
/// <param name="section">basic nacos configuration section.</param>
|
||||
/// <param name="parser">The parser.</param>
|
||||
/// <param name="logAction">The logAction.</param>
|
||||
/// <returns>IHostBuilder</returns>
|
||||
public static IHostBuilder UseNacosConfig(this IHostBuilder builder, string section, INacosConfigurationParser parser = null, Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
builder.ConfigureAppConfiguration((_, cfb) =>
|
||||
{
|
||||
var config = cfb.Build();
|
||||
|
||||
cfb.AddNacosV2Configuration(config.GetSection(section), parser: parser, logAction: logAction);
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
#if NET5_0_OR_GREATER
|
||||
/// <summary>
|
||||
/// Use nacos config combine IWebHostBuilder and ConfigureAppConfiguration
|
||||
/// </summary>
|
||||
/// <param name="builder">host builder.</param>
|
||||
/// <param name="section">basic nacos configuration section.</param>
|
||||
/// <param name="parser">The parser.</param>
|
||||
/// <param name="logAction">The logAction.</param>
|
||||
/// <returns>IHostBuilder</returns>
|
||||
public static AspNetCore.Hosting.IWebHostBuilder UseNacosConfig(this AspNetCore.Hosting.IWebHostBuilder builder, string section, INacosConfigurationParser parser = null, Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
builder.ConfigureAppConfiguration((_, cfb) =>
|
||||
{
|
||||
var config = cfb.Build();
|
||||
|
||||
cfb.AddNacosV2Configuration(config.GetSection(section), parser: parser, logAction: logAction);
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void BuildDISource(
|
||||
NacosV2ConfigurationSource source,
|
||||
INacosConfigService client,
|
||||
ILoggerFactory logFactory,
|
||||
Action<ILoggingBuilder> logAction)
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
IServiceCollection serviceCollection = new ServiceCollection();
|
||||
|
||||
var sdkAction = source.GetNacosSdkOptions();
|
||||
serviceCollection.AddNacosV2Config(sdkAction);
|
||||
serviceCollection.AddLogging(logAction ?? (x => x.AddConsole()));
|
||||
|
||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
|
||||
client = serviceProvider.GetService<INacosConfigService>();
|
||||
logFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||
}
|
||||
|
||||
source.Client = client ?? throw new Nacos.V2.Exceptions.NacosException("Can't get INacosConfigService instance from DI Container");
|
||||
source.LoggerFactory = logFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
namespace Nacos.Microsoft.Extensions.Configuration.NacosLog
|
||||
{
|
||||
using global::Microsoft.Extensions.DependencyInjection;
|
||||
using global::Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
|
||||
public class NacosLoggerFactory : ILoggerFactory
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return _factory.CreateLogger(name);
|
||||
}
|
||||
|
||||
public void AddProvider(ILoggerProvider provider)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_factory?.Dispose();
|
||||
}
|
||||
|
||||
public static NacosLoggerFactory GetInstance(Action<ILoggingBuilder> builder = null)
|
||||
{
|
||||
if (_loggingFactory != null) return _loggingFactory;
|
||||
|
||||
_factory = GetLoggerFactory(builder);
|
||||
var obj = new NacosLoggerFactory();
|
||||
return _loggingFactory = obj;
|
||||
}
|
||||
|
||||
private static ILoggerFactory _factory;
|
||||
private static NacosLoggerFactory _loggingFactory;
|
||||
|
||||
private static ILoggerFactory GetLoggerFactory(Action<ILoggingBuilder> builder = null)
|
||||
{
|
||||
if (_factory != null) return _factory;
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
if (builder != null)
|
||||
{
|
||||
serviceCollection.AddLogging(builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceCollection.AddLogging(x => x.AddConsole());
|
||||
}
|
||||
|
||||
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
ILoggerFactory loggerFactory = serviceProvider.GetService<ILoggerFactory>();
|
||||
return loggerFactory;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,239 +1,192 @@
|
|||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using global::Microsoft.Extensions.Configuration;
|
||||
using global::Microsoft.Extensions.Logging;
|
||||
using global::Microsoft.Extensions.Options;
|
||||
using Nacos.V2;
|
||||
using Nacos.V2.Config;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
internal class NacosV2ConfigurationProvider : ConfigurationProvider, IDisposable
|
||||
{
|
||||
private readonly NacosV2ConfigurationSource _configurationSource;
|
||||
|
||||
private readonly INacosConfigurationParser _parser;
|
||||
|
||||
private readonly INacosConfigService _client;
|
||||
|
||||
private readonly ConcurrentDictionary<string, string> _configDict;
|
||||
|
||||
private readonly Dictionary<string, MsConfigListener> _listenerDict;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public NacosV2ConfigurationProvider(NacosV2ConfigurationSource configurationSource)
|
||||
{
|
||||
_configurationSource = configurationSource;
|
||||
_parser = configurationSource.NacosConfigurationParser;
|
||||
_configDict = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
_listenerDict = new Dictionary<string, MsConfigListener>();
|
||||
|
||||
var options = Options.Create(new NacosSdkOptions()
|
||||
{
|
||||
ServerAddresses = configurationSource.ServerAddresses,
|
||||
Namespace = configurationSource.GetNamespace(),
|
||||
AccessKey = configurationSource.AccessKey,
|
||||
ContextPath = configurationSource.ContextPath,
|
||||
EndPoint = configurationSource.EndPoint,
|
||||
DefaultTimeOut = configurationSource.DefaultTimeOut,
|
||||
SecretKey = configurationSource.SecretKey,
|
||||
Password = configurationSource.Password,
|
||||
UserName = configurationSource.UserName,
|
||||
ListenInterval = 20000,
|
||||
ConfigUseRpc = configurationSource.ConfigUseRpc,
|
||||
ConfigFilterAssemblies = configurationSource.ConfigFilterAssemblies,
|
||||
ConfigFilterExtInfo = configurationSource.ConfigFilterExtInfo,
|
||||
});
|
||||
|
||||
var nacosLoggerFactory = Nacos.Microsoft.Extensions.Configuration.NacosLog.NacosLoggerFactory.GetInstance(configurationSource.LoggingBuilder);
|
||||
_logger = nacosLoggerFactory.CreateLogger<NacosV2ConfigurationProvider>();
|
||||
_client = new NacosConfigService(nacosLoggerFactory, options);
|
||||
if (configurationSource.Listeners != null && configurationSource.Listeners.Any())
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var item in configurationSource.Listeners)
|
||||
{
|
||||
var listener = new MsConfigListener(item.DataId, item.Group, item.Optional, this, _logger);
|
||||
|
||||
tasks.Add(_client.AddListener(item.DataId, item.Group, listener));
|
||||
|
||||
_listenerDict.Add($"{item.DataId}#{item.Group}", listener);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
// after remove old v1 code, Listeners must be not empty
|
||||
throw new Nacos.V2.Exceptions.NacosException("Listeners is empty!!");
|
||||
}
|
||||
}
|
||||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using global::Microsoft.Extensions.Configuration;
|
||||
using global::Microsoft.Extensions.Logging;
|
||||
using Nacos.V2;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// for test
|
||||
internal NacosV2ConfigurationProvider(NacosV2ConfigurationSource configurationSource, ILogger logger, INacosConfigService client, INacosConfigurationParser parser)
|
||||
internal class NacosV2ConfigurationProvider : ConfigurationProvider, IDisposable
|
||||
{
|
||||
private readonly NacosV2ConfigurationSource _configurationSource;
|
||||
|
||||
private readonly INacosConfigurationParser _parser;
|
||||
|
||||
private readonly INacosConfigService _client;
|
||||
|
||||
private readonly ConcurrentDictionary<string, string> _configDict;
|
||||
|
||||
private readonly Dictionary<string, MsConfigListener> _listenerDict;
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public NacosV2ConfigurationProvider(NacosV2ConfigurationSource configurationSource, INacosConfigService client, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_configurationSource = configurationSource;
|
||||
_parser = parser;
|
||||
_configDict = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
_listenerDict = new Dictionary<string, MsConfigListener>();
|
||||
_logger = logger;
|
||||
_client = client;
|
||||
if (configurationSource.Listeners != null && configurationSource.Listeners.Any())
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var item in configurationSource.Listeners)
|
||||
{
|
||||
var listener = new MsConfigListener(item.DataId, item.Group, item.Optional, this, _logger);
|
||||
|
||||
tasks.Add(_client.AddListener(item.DataId, item.Group, listener));
|
||||
|
||||
_listenerDict.Add($"{item.DataId}#{item.Group}", listener);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
// after remove old v1 code, Listeners must be not empty
|
||||
throw new Nacos.V2.Exceptions.NacosException("Listeners is empty!!");
|
||||
_configurationSource = configurationSource;
|
||||
_parser = configurationSource.NacosConfigurationParser;
|
||||
_configDict = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
_listenerDict = new Dictionary<string, MsConfigListener>();
|
||||
|
||||
_client = client;
|
||||
_logger = loggerFactory?.CreateLogger<NacosV2ConfigurationProvider>();
|
||||
|
||||
if (configurationSource.Listeners != null && configurationSource.Listeners.Any())
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var item in configurationSource.Listeners)
|
||||
{
|
||||
var listener = new MsConfigListener(item.DataId, item.Group, item.Optional, this, _logger);
|
||||
|
||||
tasks.Add(_client.AddListener(item.DataId, item.Group, listener));
|
||||
|
||||
_listenerDict.Add($"{item.DataId}#{item.Group}", listener);
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
// after remove old v1 code, Listeners must be not empty
|
||||
throw new Nacos.V2.Exceptions.NacosException("Listeners is empty!!");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var item in _listenerDict)
|
||||
{
|
||||
var arr = item.Key.Split('#');
|
||||
var dataId = arr[0];
|
||||
var group = arr[1];
|
||||
|
||||
tasks.Add(_client.RemoveListener(dataId, group, item.Value));
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
_logger?.LogInformation($"Remove All Listeners");
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_configurationSource.Listeners != null && _configurationSource.Listeners.Any())
|
||||
{
|
||||
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var listener in _configurationSource.Listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = _client.GetConfig(listener.DataId, listener.Group, 3000)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
_configDict.AddOrUpdate($"{_configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}", config, (x, y) => config);
|
||||
|
||||
var data = _parser.Parse(config);
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
dict[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, "MS Config Query config error, dataid={0}, group={1}, tenant={2}", listener.DataId, listener.Group, listener.Tenant);
|
||||
if (!listener.Optional)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Data = dict;
|
||||
}
|
||||
else
|
||||
{
|
||||
// after remove old v1 code, Listeners must be not empty
|
||||
throw new Nacos.V2.Exceptions.NacosException("Listeners is empty!!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogError(ex, "Load config error");
|
||||
}
|
||||
|
||||
internal IDictionary<string, string> GetData() => Data;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
|
||||
foreach (var item in _listenerDict)
|
||||
{
|
||||
var arr = item.Key.Split('#');
|
||||
var dataId = arr[0];
|
||||
var group = arr[1];
|
||||
|
||||
tasks.Add(_client.RemoveListener(dataId, group, item.Value));
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
_logger?.LogInformation($"Remove All Listeners");
|
||||
}
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_configurationSource.Listeners != null && _configurationSource.Listeners.Any())
|
||||
{
|
||||
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var listener in _configurationSource.Listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = _client.GetConfig(listener.DataId, listener.Group, 3000)
|
||||
.ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
_configDict.AddOrUpdate($"{_configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}", config, (x, y) => config);
|
||||
|
||||
var data = _parser.Parse(config);
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
dict[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, "MS Config Query config error, dataid={0}, group={1}, tenant={2}", listener.DataId, listener.Group, _configurationSource.GetNamespace());
|
||||
if (!listener.Optional)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Data = dict;
|
||||
}
|
||||
else
|
||||
{
|
||||
// after remove old v1 code, Listeners must be not empty
|
||||
throw new Nacos.V2.Exceptions.NacosException("Listeners is empty!!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogError(ex, "Load config error");
|
||||
}
|
||||
}
|
||||
|
||||
// for test
|
||||
internal void SetListener(string key, MsConfigListener listener)
|
||||
{
|
||||
_listenerDict[key] = listener;
|
||||
}
|
||||
|
||||
internal class MsConfigListener : IListener
|
||||
{
|
||||
private string _dataId;
|
||||
private string _group;
|
||||
private bool _optional;
|
||||
private NacosV2ConfigurationProvider _provider;
|
||||
private string _key;
|
||||
private ILogger _logger;
|
||||
|
||||
internal MsConfigListener(string dataId, string group, bool optional, NacosV2ConfigurationProvider provider, ILogger logger)
|
||||
{
|
||||
this._dataId = dataId;
|
||||
this._group = group;
|
||||
this._optional = optional;
|
||||
this._provider = provider;
|
||||
this._logger = logger;
|
||||
_key = $"{provider._configurationSource.GetNamespace()}#{_group}#{_dataId}";
|
||||
}
|
||||
|
||||
|
||||
public void ReceiveConfigInfo(string configInfo)
|
||||
{
|
||||
_logger?.LogDebug("MsConfigListener Receive ConfigInfo 【{0}】", configInfo);
|
||||
try
|
||||
{
|
||||
_provider._configDict[_key] = configInfo;
|
||||
|
||||
}
|
||||
|
||||
internal class MsConfigListener : IListener
|
||||
{
|
||||
private string _dataId;
|
||||
private string _group;
|
||||
private bool _optional;
|
||||
private NacosV2ConfigurationProvider _provider;
|
||||
private string _key;
|
||||
private ILogger _logger;
|
||||
|
||||
internal MsConfigListener(string dataId, string group, bool optional, NacosV2ConfigurationProvider provider, ILogger logger)
|
||||
{
|
||||
this._dataId = dataId;
|
||||
this._group = group;
|
||||
this._optional = optional;
|
||||
this._provider = provider;
|
||||
this._logger = logger;
|
||||
_key = $"{provider._configurationSource.GetNamespace()}#{_group}#{_dataId}";
|
||||
}
|
||||
|
||||
|
||||
public void ReceiveConfigInfo(string configInfo)
|
||||
{
|
||||
_logger?.LogDebug("MsConfigListener Receive ConfigInfo 【{0}】", configInfo);
|
||||
try
|
||||
{
|
||||
_provider._configDict.AddOrUpdate(_key, configInfo, (x, y) => configInfo);
|
||||
|
||||
var nData = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var listener in _provider._configurationSource.Listeners)
|
||||
{
|
||||
var key = $"{_provider._configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}";
|
||||
if (_provider._configDict[key] == null)
|
||||
{
|
||||
continue;
|
||||
|
||||
foreach (var listener in _provider._configurationSource.Listeners)
|
||||
{
|
||||
var key = $"{_provider._configurationSource.GetNamespace()}#{listener.Group}#{listener.DataId}";
|
||||
|
||||
if (!_provider._configDict.TryGetValue(key, out var config))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var data = _provider._parser.Parse(config);
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
nData[item.Key] = item.Value;
|
||||
}
|
||||
|
||||
var data = _provider._parser.Parse(_provider._configDict[key]);
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
nData[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
_provider.Data = nData;
|
||||
_provider.OnReload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, $"call back reload config error");
|
||||
if (!_optional)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_provider.Data = nData;
|
||||
_provider.OnReload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, $"call back reload config error");
|
||||
if (!_optional)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,26 +9,31 @@
|
|||
|
||||
public class NacosV2ConfigurationSource : Nacos.V2.NacosSdkOptions, IConfigurationSource
|
||||
{
|
||||
/// <summary>
|
||||
/// The INacosConfigService.
|
||||
/// </summary>
|
||||
internal INacosConfigService Client;
|
||||
|
||||
/// <summary>
|
||||
/// The ILoggerFactory.
|
||||
/// </summary>
|
||||
internal ILoggerFactory LoggerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The configuration listeners
|
||||
/// </summary>
|
||||
public List<ConfigListener> Listeners { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tenant information. It corresponds to the Namespace field in Nacos.
|
||||
/// </summary>
|
||||
[Obsolete("please use Namespace to configure")]
|
||||
public string Tenant { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The configuration parser, default is json
|
||||
/// </summary>
|
||||
public INacosConfigurationParser NacosConfigurationParser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The logging builder, default will use AddConsole
|
||||
/// </summary>
|
||||
public Action<ILoggingBuilder> LoggingBuilder { get; set; }
|
||||
public NacosV2ConfigurationSource(INacosConfigService client, ILoggerFactory loggerFactory)
|
||||
{
|
||||
Client = client;
|
||||
LoggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build the provider
|
||||
|
@ -37,25 +42,43 @@
|
|||
/// <returns>IConfigurationProvider</returns>
|
||||
public IConfigurationProvider Build(IConfigurationBuilder builder)
|
||||
{
|
||||
return new NacosV2ConfigurationProvider(this);
|
||||
return new NacosV2ConfigurationProvider(this, Client, LoggerFactory);
|
||||
}
|
||||
|
||||
public string GetNamespace()
|
||||
{
|
||||
// breaking change here after 1.3.3 release
|
||||
// do not use tenant any more!!!!
|
||||
if (Namespace.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return Namespace;
|
||||
}
|
||||
#pragma warning disable CS0618
|
||||
else if (Tenant.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
return Tenant;
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
internal Action<NacosSdkOptions> GetNacosSdkOptions()
|
||||
{
|
||||
Action<NacosSdkOptions> action = (x) =>
|
||||
{
|
||||
x.ServerAddresses = this.ServerAddresses;
|
||||
x.Namespace = this.Namespace;
|
||||
x.AccessKey = this.AccessKey;
|
||||
x.ContextPath = this.ContextPath;
|
||||
x.EndPoint = this.EndPoint;
|
||||
x.DefaultTimeOut = this.DefaultTimeOut;
|
||||
x.SecretKey = this.SecretKey;
|
||||
x.Password = this.Password;
|
||||
x.UserName = this.UserName;
|
||||
x.ListenInterval = this.ListenInterval;
|
||||
x.ConfigUseRpc = this.ConfigUseRpc;
|
||||
x.ConfigFilterAssemblies = this.ConfigFilterAssemblies;
|
||||
x.ConfigFilterExtInfo = this.ConfigFilterExtInfo;
|
||||
};
|
||||
|
||||
return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# nacos-sdk-csharp.Extensions.Configuration
|
||||
|
||||
nacos-sdk-csharp.Extensions.Configuration provides integration with ASP.NET Core Configuration System.
|
||||
|
||||
```csharp
|
||||
builder.Host.UseNacosConfig(section: "NacosConfig");
|
||||
|
||||
// or
|
||||
|
||||
builder.Host.ConfigureAppConfiguration((c, b) =>
|
||||
{
|
||||
var config = b.Build();
|
||||
|
||||
// read configuration from config files
|
||||
// default is json
|
||||
// b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
|
||||
// specify ini or yaml
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
});
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -0,0 +1,41 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PackageId>nacos-sdk-csharp.Extensions.ServiceDiscovery</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
<Description>nacos csharp sdk</Description>
|
||||
<PackageTags>nacos,csharp,sdk,servicediscovery</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="8.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nacos\Nacos.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,24 @@
|
|||
#pragma warning disable SA1200
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
public static class NacosServiceDiscoveryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures a service discovery endpoint provider which uses <see cref="T:Nacos.V2.INacosNamingService" /> to resolve endpoints.
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection.</param>
|
||||
/// <returns>The service collection.</returns>
|
||||
public static IServiceCollection AddNacosServiceEndpointProvider(this IServiceCollection services)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
|
||||
services.AddServiceDiscoveryCore();
|
||||
services.AddSingleton<IServiceEndpointProviderFactory, NacosServiceEndPointProviderFactory>();
|
||||
return services;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#pragma warning disable SA1200
|
||||
using Nacos.Microsoft.Extensions.ServiceDiscovery;
|
||||
using System.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
using Nacos.V2;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// NacosServiceEndpointProvider
|
||||
/// </summary>
|
||||
/// <param name="query">query</param>
|
||||
/// <param name="hostName">hostName</param>
|
||||
/// <param name="options">options</param>
|
||||
/// <param name="logger">logger</param>
|
||||
/// <param name="namingService">namingService</param>
|
||||
/// <param name="timeProvider">timeProvider</param>
|
||||
internal sealed partial class NacosServiceEndpointProvider(
|
||||
ServiceEndpointQuery query,
|
||||
string hostName,
|
||||
IOptionsMonitor<NacosServiceEndpointProviderOptions> options,
|
||||
ILogger<NacosServiceEndpointProvider> logger,
|
||||
INacosNamingService namingService,
|
||||
TimeProvider timeProvider) : NacosServiceEndpointProviderBase(query, logger, timeProvider), IHostNameFeature
|
||||
{
|
||||
protected override double RetryBackOffFactor => options.CurrentValue.RetryBackOffFactor;
|
||||
|
||||
protected override TimeSpan MinRetryPeriod => options.CurrentValue.MinRetryPeriod;
|
||||
|
||||
protected override TimeSpan MaxRetryPeriod => options.CurrentValue.MaxRetryPeriod;
|
||||
|
||||
protected override TimeSpan DefaultRefreshPeriod => options.CurrentValue.DefaultRefreshPeriod;
|
||||
|
||||
string IHostNameFeature.HostName => hostName;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => "Nacos";
|
||||
|
||||
protected override async Task ResolveAsyncCore()
|
||||
{
|
||||
var endpoints = new List<ServiceEndpoint>();
|
||||
var ttl = DefaultRefreshPeriod;
|
||||
Log.AddressQuery(logger, ServiceName, hostName);
|
||||
var selectInstances = await namingService.SelectInstances(hostName, true).ConfigureAwait(false);
|
||||
foreach (var instance in selectInstances)
|
||||
{
|
||||
var ipAddress = new IPAddress(instance.Ip.Split('.').Select(a => Convert.ToByte(a)).ToArray());
|
||||
var ipPoint = new IPEndPoint(ipAddress, instance.Port);
|
||||
var serviceEndpoint = ServiceEndpoint.Create(ipPoint);
|
||||
serviceEndpoint.Features.Set<IServiceEndpointProvider>(this);
|
||||
if (options.CurrentValue.ShouldApplyHostNameMetadata(serviceEndpoint))
|
||||
{
|
||||
serviceEndpoint.Features.Set<IHostNameFeature>(this);
|
||||
}
|
||||
|
||||
endpoints.Add(serviceEndpoint);
|
||||
}
|
||||
|
||||
if (endpoints.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"No records were found for service '{ServiceName}' ( name: '{hostName}').");
|
||||
}
|
||||
|
||||
SetResult(endpoints, ttl);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#pragma warning disable SA1200
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
using Nacos.Microsoft.Extensions.ServiceDiscovery;
|
||||
using Nacos.V2;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// NacosServiceEndPointProviderFactory
|
||||
/// </summary>
|
||||
/// <param name="options">options</param>
|
||||
/// <param name="logger">logger</param>
|
||||
/// <param name="timeProvider">timeProvider</param>
|
||||
/// <param name="namingService">nacos namingService</param>
|
||||
internal sealed partial class NacosServiceEndPointProviderFactory(
|
||||
IOptionsMonitor<NacosServiceEndpointProviderOptions> options,
|
||||
ILogger<NacosServiceEndpointProvider> logger,
|
||||
TimeProvider timeProvider,
|
||||
INacosNamingService namingService) : IServiceEndpointProviderFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to create an <see cref="T:Microsoft.Extensions.ServiceDiscovery.IServiceEndpointProvider" /> instance for the specified <paramref name="query" />.
|
||||
/// </summary>
|
||||
/// <param name="query">The service to create the provider for.</param>
|
||||
/// <param name="provider">The provider.</param>
|
||||
/// <returns><see langword="true" /> if the provider was created, <see langword="false" /> otherwise.</returns>
|
||||
public bool TryCreateProvider(ServiceEndpointQuery query, [NotNullWhen(true)] out IServiceEndpointProvider? provider)
|
||||
{
|
||||
provider = new NacosServiceEndpointProvider(query, query.ServiceName, options, logger, namingService, timeProvider);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma warning disable SA1200
|
||||
using Microsoft.Extensions.Logging;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
namespace Nacos.Microsoft.Extensions.ServiceDiscovery;
|
||||
|
||||
/// <summary>
|
||||
/// log base
|
||||
/// </summary>
|
||||
internal partial class NacosServiceEndpointProviderBase
|
||||
{
|
||||
/// <summary>
|
||||
/// log
|
||||
/// </summary>
|
||||
internal static partial class Log
|
||||
{
|
||||
[LoggerMessage(1, LogLevel.Trace, "Resolving endpoints for service '{ServiceName}' using host lookup for name '{RecordName}'.", EventName = "AddressQuery")]
|
||||
public static partial void AddressQuery(ILogger logger, string serviceName, string recordName);
|
||||
|
||||
[LoggerMessage(2, LogLevel.Debug, "Skipping endpoint resolution for service '{ServiceName}': '{Reason}'.", EventName = "SkippedResolution")]
|
||||
public static partial void SkippedResolution(ILogger logger, string serviceName, string reason);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
#pragma warning disable SA1200
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
namespace Nacos.Microsoft.Extensions.ServiceDiscovery;
|
||||
|
||||
/// <summary>
|
||||
/// A service end point provider that uses Nacos to resolve the service end points.
|
||||
/// </summary>
|
||||
internal abstract partial class NacosServiceEndpointProviderBase : IServiceEndpointProvider
|
||||
{
|
||||
private readonly object _lock = new();
|
||||
private readonly ILogger _logger;
|
||||
private readonly CancellationTokenSource _disposeCancellation = new();
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private long _lastRefreshTimeStamp;
|
||||
private Task _resolveTask = Task.CompletedTask;
|
||||
private bool _hasEndpoints;
|
||||
private CancellationChangeToken _lastChangeToken;
|
||||
private CancellationTokenSource _lastCollectionCancellation;
|
||||
private List<ServiceEndpoint>? _lastEndpointCollection;
|
||||
private TimeSpan _nextRefreshPeriod;
|
||||
|
||||
protected NacosServiceEndpointProviderBase(
|
||||
ServiceEndpointQuery query,
|
||||
ILogger logger,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
ServiceName = query.ToString()!;
|
||||
_logger = logger;
|
||||
_lastEndpointCollection = null;
|
||||
_timeProvider = timeProvider;
|
||||
_lastRefreshTimeStamp = _timeProvider.GetTimestamp();
|
||||
var cancellation = _lastCollectionCancellation = new CancellationTokenSource();
|
||||
_lastChangeToken = new CancellationChangeToken(cancellation.Token);
|
||||
}
|
||||
|
||||
private TimeSpan ElapsedSinceRefresh => _timeProvider.GetElapsedTime(_lastRefreshTimeStamp);
|
||||
|
||||
protected string ServiceName { get; }
|
||||
|
||||
protected abstract double RetryBackOffFactor { get; }
|
||||
|
||||
protected abstract TimeSpan MinRetryPeriod { get; }
|
||||
|
||||
protected abstract TimeSpan MaxRetryPeriod { get; }
|
||||
|
||||
protected abstract TimeSpan DefaultRefreshPeriod { get; }
|
||||
|
||||
protected CancellationToken ShutdownToken => _disposeCancellation.Token;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask PopulateAsync(IServiceEndpointBuilder endpoints, CancellationToken cancellationToken)
|
||||
{
|
||||
// Only add endpoints to the collection if a previous provider (eg, a configuration override) did not add them.
|
||||
if (endpoints.Endpoints.Count != 0)
|
||||
{
|
||||
Log.SkippedResolution(_logger, ServiceName, "Collection has existing endpoints");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldRefresh())
|
||||
{
|
||||
Task resolveTask;
|
||||
lock (_lock)
|
||||
{
|
||||
if (_resolveTask.IsCompleted && ShouldRefresh())
|
||||
{
|
||||
_resolveTask = ResolveAsyncCore();
|
||||
}
|
||||
|
||||
resolveTask = _resolveTask;
|
||||
}
|
||||
|
||||
await resolveTask.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_lastEndpointCollection is { Count: > 0 } eps)
|
||||
{
|
||||
foreach (var ep in eps)
|
||||
{
|
||||
endpoints.Endpoints.Add(ep);
|
||||
}
|
||||
}
|
||||
|
||||
endpoints.AddChangeToken(_lastChangeToken);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldRefresh() => _lastEndpointCollection is null || _lastChangeToken is { HasChanged: true } || ElapsedSinceRefresh >= _nextRefreshPeriod;
|
||||
|
||||
protected abstract Task ResolveAsyncCore();
|
||||
|
||||
protected void SetResult(List<ServiceEndpoint> endpoints, TimeSpan validityPeriod)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (endpoints is { Count: > 0 })
|
||||
{
|
||||
_lastRefreshTimeStamp = _timeProvider.GetTimestamp();
|
||||
_nextRefreshPeriod = DefaultRefreshPeriod;
|
||||
_hasEndpoints = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextRefreshPeriod = GetRefreshPeriod();
|
||||
validityPeriod = TimeSpan.Zero;
|
||||
_hasEndpoints = false;
|
||||
}
|
||||
|
||||
if (validityPeriod <= TimeSpan.Zero)
|
||||
{
|
||||
validityPeriod = _nextRefreshPeriod;
|
||||
}
|
||||
else if (validityPeriod > _nextRefreshPeriod)
|
||||
{
|
||||
validityPeriod = _nextRefreshPeriod;
|
||||
}
|
||||
|
||||
_lastCollectionCancellation.Cancel();
|
||||
var cancellation = _lastCollectionCancellation = new CancellationTokenSource(validityPeriod, _timeProvider);
|
||||
_lastChangeToken = new CancellationChangeToken(cancellation.Token);
|
||||
_lastEndpointCollection = endpoints;
|
||||
}
|
||||
|
||||
TimeSpan GetRefreshPeriod()
|
||||
{
|
||||
if (_hasEndpoints)
|
||||
{
|
||||
return MinRetryPeriod;
|
||||
}
|
||||
|
||||
var nextTicks = (long)(_nextRefreshPeriod.Ticks * RetryBackOffFactor);
|
||||
if (nextTicks <= 0 || nextTicks > MaxRetryPeriod.Ticks)
|
||||
{
|
||||
return MaxRetryPeriod;
|
||||
}
|
||||
|
||||
return TimeSpan.FromTicks(nextTicks);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
_disposeCancellation.Cancel();
|
||||
|
||||
if (_resolveTask is { } task)
|
||||
{
|
||||
#pragma warning disable CAC002
|
||||
await task.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
|
||||
#pragma warning restore CAC002
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#pragma warning disable SA1200
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.ServiceDiscovery;
|
||||
#pragma warning restore SA1200
|
||||
|
||||
namespace Nacos.Microsoft.Extensions.ServiceDiscovery;
|
||||
|
||||
/// <summary>
|
||||
/// Options for configuring <see cref="NacosServiceEndpointProvider"/>.
|
||||
/// </summary>
|
||||
public class NacosServiceEndpointProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the default refresh period for endpoints resolved from Nacos.
|
||||
/// </summary>
|
||||
public TimeSpan DefaultRefreshPeriod { get; set; } = TimeSpan.FromMinutes(1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the initial period between retries.
|
||||
/// </summary>
|
||||
public TimeSpan MinRetryPeriod { get; set; } = TimeSpan.FromSeconds(1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum period between retries.
|
||||
/// </summary>
|
||||
public TimeSpan MaxRetryPeriod { get; set; } = TimeSpan.FromSeconds(30);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the retry period growth factor.
|
||||
/// </summary>
|
||||
public double RetryBackOffFactor { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a delegate used to determine whether to apply host name metadata to each resolved endpoint. Defaults to <c>false</c>.
|
||||
/// </summary>
|
||||
public Func<ServiceEndpoint, bool> ShouldApplyHostNameMetadata { get; set; } = _ => false;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
# nacos-sdk-csharp.Extensions.ServiceDiscovery
|
||||
|
||||
nacos-sdk-csharp.Extensions.ServiceDiscovery provides service registration and discovery With Microsoft.Extensions.ServiceDiscovery.
|
||||
|
||||
```csharp
|
||||
builder.Services.AddServiceDiscovery(o =>
|
||||
{
|
||||
o.RefreshPeriod = TimeSpan.FromSeconds(60);
|
||||
})
|
||||
.AddConfigurationServiceEndpointProvider()
|
||||
.AddNacosServiceEndpointProvider();
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -13,17 +13,19 @@
|
|||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
<NoWarn>$(NoWarn);1591;NU5100</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="../Nacos.Microsoft.Extensions.Configuration/DefaultJsonConfigurationStringParser.cs" />
|
||||
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
|
||||
<ProjectReference Include="..\Nacos\Nacos.csproj" />
|
||||
|
||||
|
|
|
@ -1,56 +1,58 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
<Description>nacos csharp sdk</Description>
|
||||
<PackageTags>nacos,csharp,sdk</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.14.0" />
|
||||
<PackageReference Include="Grpc.Core" Version="2.34.1" />
|
||||
<!--<PackageReference Include="Grpc.Net.Client" Version="2.33.1" />-->
|
||||
<!--<Protobuf Include="V2\protos\nacos_grpc_service.proto" GrpcServices="Client" />-->
|
||||
<!--<PackageReference Include="Grpc.Tools" Version="2.36.1" PrivateAssets="All" />-->
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
<Description>nacos csharp sdk</Description>
|
||||
<PackageTags>nacos,csharp,sdk</PackageTags>
|
||||
<PackageProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/nacos-group/nacos-sdk-csharp</RepositoryUrl>
|
||||
<ProjectUrl>https://github.com/nacos-group/nacos-sdk-csharp</ProjectUrl>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.27.2" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.65.0" />
|
||||
<!--<PackageReference Include="Grpc.Net.Client" Version="2.33.1" />-->
|
||||
<!--<Protobuf Include="V2\protos\nacos_grpc_service.proto" GrpcServices="Client" />-->
|
||||
<!--<PackageReference Include="Grpc.Tools" Version="2.65.0" PrivateAssets="All" />-->
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
internal class Constants
|
||||
{
|
||||
public static readonly string HttpClientName = "OpenApi";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nacos.V2.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class DefaultNacosOpenApi : INacosOpenApi
|
||||
{
|
||||
private const string _namespacePath = "nacos/v1/console/namespaces";
|
||||
private const string _metricsPath = "nacos/v1/ns/operator/metrics";
|
||||
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly Nacos.V2.NacosSdkOptions _options;
|
||||
|
||||
public DefaultNacosOpenApi(IHttpClientFactory httpClientFactory, IOptions<Nacos.V2.NacosSdkOptions> optionsAccs)
|
||||
{
|
||||
this._httpClientFactory = httpClientFactory;
|
||||
this._options = optionsAccs.Value;
|
||||
}
|
||||
|
||||
public async Task<bool> CreateNamespaceAsync(string customNamespaceId, string namespaceName, string namespaceDesc)
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient(Constants.HttpClientName);
|
||||
|
||||
var content = new StringContent($"customNamespaceId={customNamespaceId}&namespaceName={namespaceName}&namespaceDesc={namespaceDesc}");
|
||||
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
var req = new HttpRequestMessage(HttpMethod.Post, $"{_options.ServerAddresses.First().TrimEnd('/')}/{_namespacePath}");
|
||||
req.Content = content;
|
||||
|
||||
var resp = await client.SendAsync(req).ConfigureAwait(false);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var res = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
bool.TryParse(res, out bool result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException((int)resp.StatusCode, "CreateNamespaceAsync exception");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteNamespaceAsync(string namespaceId)
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient(Constants.HttpClientName);
|
||||
|
||||
var content = new StringContent($"namespaceId={namespaceId}");
|
||||
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
var req = new HttpRequestMessage(HttpMethod.Delete, $"{_options.ServerAddresses.First().TrimEnd('/')}/{_namespacePath}");
|
||||
req.Content = content;
|
||||
|
||||
var resp = await client.SendAsync(req).ConfigureAwait(false);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var res = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
bool.TryParse(res, out bool result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException((int)resp.StatusCode, "DeleteNamespaceAsync exception");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<NacosMetrics> GetMetricsAsync(bool onlyStatus)
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient(Constants.HttpClientName);
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, $"{_options.ServerAddresses.First().TrimEnd('/')}/{_metricsPath}?onlyStatus={onlyStatus.ToString().ToLower()}");
|
||||
|
||||
var resp = await client.SendAsync(req).ConfigureAwait(false);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var res = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
return res.ToObj<NacosMetrics>();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException((int)resp.StatusCode, "GetMetricsAsync exception");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<NacosNamespace>> GetNamespacesAsync()
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient(Constants.HttpClientName);
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Get, $"{_options.ServerAddresses.First().TrimEnd('/')}/{_namespacePath}");
|
||||
|
||||
var resp = await client.SendAsync(req).ConfigureAwait(false);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var res = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var jobj = System.Text.Json.Nodes.JsonNode.Parse(res).AsObject();
|
||||
|
||||
if (jobj.TryGetPropertyValue("data", out var val))
|
||||
{
|
||||
return val.ToString().ToObj<List<NacosNamespace>>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new List<NacosNamespace>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException((int)resp.StatusCode, "GetNamespacesAsync exception");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateNamespaceAsync(string namespaceId, string namespaceName, string namespaceDesc)
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient(Constants.HttpClientName);
|
||||
|
||||
var content = new StringContent($"customNamespaceId={namespaceId}&namespaceName={namespaceName}&namespaceDesc={namespaceDesc}");
|
||||
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
var req = new HttpRequestMessage(HttpMethod.Post, $"{_options.ServerAddresses.First().TrimEnd('/')}/{_namespacePath}");
|
||||
req.Content = content;
|
||||
|
||||
var resp = await client.SendAsync(req).ConfigureAwait(false);
|
||||
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var res = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
bool.TryParse(res, out bool result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Nacos.V2.Exceptions.NacosException((int)resp.StatusCode, "UpdateNamespaceAsync exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nacos.V2;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddNacosOpenApi(this IServiceCollection services, Action<NacosSdkOptions> configure, Action<HttpClient> httpClientAction = null)
|
||||
{
|
||||
if (services == null) throw new ArgumentNullException(nameof(services));
|
||||
|
||||
services.AddOptions();
|
||||
services.Configure(configure);
|
||||
|
||||
var clientBuilder = services.AddHttpClient(Constants.HttpClientName)
|
||||
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseProxy = false, AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate });
|
||||
|
||||
if (httpClientAction != null)
|
||||
{
|
||||
clientBuilder.ConfigureHttpClient(httpClientAction);
|
||||
}
|
||||
|
||||
services.AddSingleton<INacosOpenApi, DefaultNacosOpenApi>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface INacosOpenApi
|
||||
{
|
||||
/// <summary>
|
||||
/// Get namespace list.
|
||||
/// </summary>
|
||||
/// <returns>namespace list</returns>
|
||||
Task<List<NacosNamespace>> GetNamespacesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Create namespace
|
||||
/// </summary>
|
||||
/// <param name="customNamespaceId">ID of namespace</param>
|
||||
/// <param name="namespaceName">Name of namespace</param>
|
||||
/// <param name="namespaceDesc">Description of namespace</param>
|
||||
/// <returns>Created or not</returns>
|
||||
Task<bool> CreateNamespaceAsync(string customNamespaceId, string namespaceName, string namespaceDesc);
|
||||
|
||||
/// <summary>
|
||||
/// Update namespace
|
||||
/// </summary>
|
||||
/// <param name="namespaceId">ID of namespace</param>
|
||||
/// <param name="namespaceName">Name of namespace</param>
|
||||
/// <param name="namespaceDesc">Description of namespace</param>
|
||||
/// <returns>Updated or not</returns>
|
||||
Task<bool> UpdateNamespaceAsync(string namespaceId, string namespaceName, string namespaceDesc);
|
||||
|
||||
/// <summary>
|
||||
/// Delete namespace
|
||||
/// </summary>
|
||||
/// <param name="namespaceId">ID of namespace</param>
|
||||
/// <returns>Deleted or not</returns>
|
||||
Task<bool> DeleteNamespaceAsync(string namespaceId);
|
||||
|
||||
/// <summary>
|
||||
/// Query system metrics
|
||||
/// </summary>
|
||||
/// <param name="onlyStatus">only status info or not</param>
|
||||
/// <returns>system metrics</returns>
|
||||
Task<NacosMetrics> GetMetricsAsync(bool onlyStatus);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
public class NacosMetrics
|
||||
{
|
||||
[System.Text.Json.Serialization.JsonPropertyName("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceCount")]
|
||||
public int ServiceCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("instanceCount")]
|
||||
public int InstanceCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("subscribeCount")]
|
||||
public int SubscribeCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("raftNotifyTaskCount")]
|
||||
public int RaftNotifyTaskCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("responsibleServiceCount")]
|
||||
public int ResponsibleServiceCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("responsibleInstanceCount")]
|
||||
public int ResponsibleInstanceCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clientCount")]
|
||||
public int ClientCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("connectionBasedClientCount")]
|
||||
public int ConnectionBasedClientCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("ephemeralIpPortClientCount")]
|
||||
public int EphemeralIpPortClientCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("persistentIpPortClientCount")]
|
||||
public int PersistentIpPortClientCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("responsibleClientCount")]
|
||||
public int ResponsibleClientCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("cpu")]
|
||||
public float Cpu { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("load")]
|
||||
public float Load { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("mem")]
|
||||
public float Mem { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
namespace Nacos.OpenApi
|
||||
{
|
||||
public class NacosNamespace
|
||||
{
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namespace")]
|
||||
public string Namespace { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namespaceShowName")]
|
||||
public string NamespaceShowName { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namespaceDesc")]
|
||||
public string NamespaceDesc { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("quota")]
|
||||
public int Quota { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("configCount")]
|
||||
public int ConfigCount { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public int Type { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
# nacos-sdk-csharp
|
||||
|
||||
nacos-sdk-csharp provides basic nacos operation.
|
||||
|
||||
```csharp
|
||||
// config
|
||||
builder.Services.AddNacosV2Config(x =>
|
||||
{
|
||||
x.ServerAddresses = new List<string> { "http://localhost:8848/" };
|
||||
x.Namespace = "cs";
|
||||
x.UserName = "nacos";
|
||||
x.Password = "nacos";
|
||||
});
|
||||
|
||||
// naming
|
||||
builder.Services.AddNacosV2Naming(x =>
|
||||
{
|
||||
x.ServerAddresses = new List<string> { "http://localhost:8848/" };
|
||||
x.Namespace = "cs";
|
||||
x.UserName = "nacos";
|
||||
x.Password = "nacos";
|
||||
});
|
||||
|
||||
// or
|
||||
|
||||
builder.Services.AddNacosV2Config(builder.Configuration);
|
||||
|
||||
builder.Services.AddNacosV2Naming(builder.Configuration);
|
||||
```
|
||||
|
||||
```csharp
|
||||
private readonly INacosConfigService _config;
|
||||
private readonly INacosNamingService _naming;
|
||||
|
||||
public TheCtor(INacosConfigService config, INacosNamingService naming)
|
||||
{
|
||||
_config = config;
|
||||
_naming = naming;
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
* [Documentation](https://nacos-sdk-csharp.readthedocs.io/en/latest/)
|
||||
* [nacos-sdk-csharp GitHub](https://github.com/nacos-group/nacos-sdk-csharp)
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public class Constants
|
||||
{
|
||||
public static string CLIENT_VERSION = "Nacos-CSharp-Client:v1.3.2";
|
||||
public static string CLIENT_VERSION = "Nacos-CSharp-Client:v1.3.10";
|
||||
|
||||
public const string ClientName = "NacosClient";
|
||||
|
||||
|
@ -182,5 +182,7 @@
|
|||
public static string AMORY_TAG = "Amory-Tag";
|
||||
|
||||
public static string LOCATION_TAG = "Location-Tag";
|
||||
|
||||
public static string CLUSTER_NAME_PATTERN_STRING = "^[0-9a-zA-Z-]+$";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@
|
|||
newlabels["taskId"] = taskId;
|
||||
|
||||
RpcClient rpcClient = RpcClientFactory
|
||||
.CreateClient($"{uuid}_config-{taskId}", RemoteConnectionType.GRPC, newlabels);
|
||||
.CreateClient($"{uuid}_config-{taskId}", RemoteConnectionType.GRPC, newlabels, _options.TLSConfig);
|
||||
|
||||
if (rpcClient.IsWaitInited())
|
||||
{
|
||||
|
@ -334,6 +334,7 @@
|
|||
{
|
||||
var listenCachesMap = new Dictionary<string, List<CacheData>>();
|
||||
var removeListenCachesMap = new Dictionary<string, List<CacheData>>();
|
||||
var hasChangedKeys = false;
|
||||
|
||||
// TODO: should update logic here.....
|
||||
foreach (var item in _cacheMap.Values)
|
||||
|
@ -392,6 +393,7 @@
|
|||
|
||||
if (configChangeBatchListenResponse.ChangedConfigs != null && configChangeBatchListenResponse.ChangedConfigs.Any())
|
||||
{
|
||||
hasChangedKeys = true;
|
||||
foreach (var item in configChangeBatchListenResponse.ChangedConfigs)
|
||||
{
|
||||
var changeKey = GroupKey.GetKeyTenant(item.DataId, item.Group, item.Tenant);
|
||||
|
@ -450,6 +452,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChangedKeys)
|
||||
await NotifyListenConfig().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RefreshContentAndCheck(string groupKey, bool notify)
|
||||
|
@ -496,8 +501,13 @@
|
|||
|
||||
protected override Task NotifyListenConfig()
|
||||
{
|
||||
_listenExecutebell.Add(_bellItem);
|
||||
return Task.CompletedTask;
|
||||
return Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (!_listenExecutebell.TryAdd(_bellItem))
|
||||
{
|
||||
await Task.Delay(500).ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,13 @@
|
|||
|
||||
public static class FileLocalConfigInfoProcessor
|
||||
{
|
||||
private static readonly string LOCAL_SNAPSHOT_PATH = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "nacos", "config");
|
||||
private static readonly string LOCAL_SNAPSHOT_PATH = string.Empty;
|
||||
|
||||
static FileLocalConfigInfoProcessor()
|
||||
{
|
||||
var basePath = Nacos.V2.Utils.EnvUtil.GetEnvValue("JM.SNAPSHOT.PATH", Environment.GetFolderPath(Environment.SpecialFolder.Personal));
|
||||
LOCAL_SNAPSHOT_PATH = Path.Combine(basePath, "nacos", "config");
|
||||
}
|
||||
|
||||
public static async Task<string> GetFailoverAsync(string serverName, string dataId, string group, string tenant)
|
||||
{
|
||||
|
|
|
@ -79,10 +79,11 @@
|
|||
|
||||
_isFixed = false;
|
||||
|
||||
var endpoint = _options.EndPoint.IndexOf(':') == -1 ? $"{_options.EndPoint}:{_endpointPort}" : _options.EndPoint;
|
||||
if (@namespace.IsNullOrWhiteSpace())
|
||||
{
|
||||
_name = _options.EndPoint;
|
||||
_addressServerUrl = $"http://{_options.EndPoint}:{_endpointPort}/{_contentPath}/{_defaultNodesPath}";
|
||||
_addressServerUrl = $"http://{endpoint}/{_contentPath}/{_defaultNodesPath}";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -90,7 +91,7 @@
|
|||
_tenant = $"{_options.EndPoint}-{@namespace}";
|
||||
_name = $"{FIXED_NAME}-{GetFixedNameSuffix(_serverUrls)}-{@namespace}";
|
||||
|
||||
_addressServerUrl = $"http://{_options.EndPoint}:{_endpointPort}/{_contentPath}/{_defaultNodesPath}?namespace={@namespace}";
|
||||
_addressServerUrl = $"http://{endpoint}/{_contentPath}/{_defaultNodesPath}?namespace={@namespace}";
|
||||
}
|
||||
|
||||
_refreshSvcListTimer = new Timer(
|
||||
|
|
|
@ -58,6 +58,15 @@
|
|||
/// <param name="instance">instance to register</param>
|
||||
Task RegisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
/// <summary>
|
||||
/// batch register instance to service with specified instance properties.
|
||||
/// since nacos server 2.1.1
|
||||
/// </summary>
|
||||
/// <param name="serviceName">name of service</param>
|
||||
/// <param name="groupName">group of service</param>
|
||||
/// <param name="instances">instances to register</param>
|
||||
Task BatchRegisterInstance(string serviceName, string groupName, List<Instance> instances);
|
||||
|
||||
/// <summary>
|
||||
/// deregister instance from a service.
|
||||
/// </summary>
|
||||
|
@ -438,4 +447,4 @@
|
|||
/// </summary>
|
||||
Task ShutDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,5 +72,10 @@
|
|||
/// Specify some extension info of IConfigFilter.
|
||||
/// </summary>
|
||||
public string ConfigFilterExtInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TLS config
|
||||
/// </summary>
|
||||
public TLSConfig TLSConfig { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,31 +5,31 @@
|
|||
|
||||
public class BeatInfo
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("port")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("ip")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("ip")]
|
||||
public string Ip { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("weight")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("weight")]
|
||||
public double? Weight { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("serviceName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceName")]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("cluster")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("cluster")]
|
||||
public string Cluster { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("metadata")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("metadata")]
|
||||
public Dictionary<string, string> Metadata { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("scheduled")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("scheduled")]
|
||||
public bool Scheduled { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("period")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("period")]
|
||||
public long Period { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("stopped")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("stopped")]
|
||||
public bool Stopped { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
|
|
@ -65,22 +65,22 @@
|
|||
|
||||
try
|
||||
{
|
||||
Newtonsoft.Json.Linq.JObject result = await _serverProxy.SendBeat(beatInfo, false).ConfigureAwait(false);
|
||||
System.Text.Json.Nodes.JsonObject result = await _serverProxy.SendBeat(beatInfo, false).ConfigureAwait(false);
|
||||
_logger?.LogDebug("[CLIENT-BEAT] sendbeat result = {0}", result.ToString());
|
||||
long interval = result.GetValue(CLIENT_BEAT_INTERVAL_FIELD).ToObject<long>();
|
||||
var interval = result[CLIENT_BEAT_INTERVAL_FIELD].GetValue<long>();
|
||||
|
||||
bool lightBeatEnabled = false;
|
||||
|
||||
if (result.ContainsKey(CommonParams.LIGHT_BEAT_ENABLED))
|
||||
{
|
||||
lightBeatEnabled = result.GetValue(CommonParams.LIGHT_BEAT_ENABLED).ToObject<bool>();
|
||||
lightBeatEnabled = result[CommonParams.LIGHT_BEAT_ENABLED].GetValue<bool>();
|
||||
}
|
||||
|
||||
if (interval > 0) nextTime = interval;
|
||||
|
||||
int code = OK;
|
||||
|
||||
if (result.ContainsKey(CommonParams.CODE)) code = result.GetValue(CommonParams.CODE).ToObject<int>();
|
||||
if (result.ContainsKey(CommonParams.CODE)) code = result[CommonParams.CODE].GetValue<int>();
|
||||
|
||||
if (code == RESOURCE_NOT_FOUND)
|
||||
{
|
||||
|
|
|
@ -11,61 +11,61 @@
|
|||
/// <summary>
|
||||
/// unique id of this instance.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("instanceId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("instanceId")]
|
||||
public string InstanceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// instance ip.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("ip")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("ip")]
|
||||
public string Ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// instance port.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("port")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// instance weight.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("weight")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("weight")]
|
||||
public double Weight { get; set; } = 1.0D;
|
||||
|
||||
/// <summary>
|
||||
/// instance health status.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("healthy")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("healthy")]
|
||||
public bool Healthy { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// If instance is enabled to accept request.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("enabled")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("enabled")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// If instance is ephemeral.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("ephemeral")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("ephemeral")]
|
||||
public bool Ephemeral { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// cluster information of instance.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("clusterName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clusterName")]
|
||||
public string ClusterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Service information of instance.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("serviceName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceName")]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// user extended attributes.
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("metadata")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("metadata")]
|
||||
public Dictionary<string, string> Metadata { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public void AddMetadata(string key, string value)
|
||||
|
@ -110,5 +110,16 @@
|
|||
{
|
||||
return $"Instance{{instanceId='{InstanceId}', ip='{Ip}', port={Port}, weight={Weight}, healthy={Healthy}, enabled={Enabled}, ephemeral={Ephemeral}, clusterName='{ClusterName}', serviceName='{ServiceName}', metadata={Metadata.ToJsonString()}}}";
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is not Instance) return false;
|
||||
|
||||
var host = (Instance)obj;
|
||||
|
||||
return ToString().Equals(host.ToString());
|
||||
}
|
||||
|
||||
public override int GetHashCode() => ToString().GetHashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,28 +8,28 @@
|
|||
|
||||
public class ServiceInfo
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("name")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("groupName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("cacheMillis")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("cacheMillis")]
|
||||
public long CacheMillis { get; set; } = 1000L;
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("lastRefTime")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("lastRefTime")]
|
||||
public long LastRefTime { get; set; } = 0L;
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("checksum")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("checksum")]
|
||||
public string Checksum { get; set; } = "";
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("hosts")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("hosts")]
|
||||
public List<Instance> Hosts { get; set; } = new List<Instance>();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("metallIPsadata")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("metallIPsadata")]
|
||||
public bool AllIPs { get; set; } = false;
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("clusters")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clusters")]
|
||||
public string Clusters { get; set; }
|
||||
|
||||
public ServiceInfo()
|
||||
|
@ -76,7 +76,7 @@
|
|||
=> !string.IsNullOrEmpty(clusters) ? name + Constants.SERVICE_INFO_SPLITER + clusters : name;
|
||||
|
||||
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
public string JsonFromServer { get; set; }
|
||||
|
||||
public string GetKeyEncoded() => GetKey(System.Net.WebUtility.UrlEncode(GetGroupedServiceName()), Clusters);
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
|
||||
public class InstancesChangeEvent : IEvent
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("serviceName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceName")]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("groupName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("clusters")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clusters")]
|
||||
public string Clusters { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("hosts")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("hosts")]
|
||||
public List<Instance> Hosts { get; set; }
|
||||
|
||||
public InstancesChangeEvent(string serviceName, string groupName, string clusters, List<Instance> hosts)
|
||||
|
|
|
@ -1,301 +1,308 @@
|
|||
namespace Nacos.V2.Naming
|
||||
{
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nacos.V2.Common;
|
||||
using Nacos.V2.Naming.Cache;
|
||||
using Nacos.V2.Naming.Core;
|
||||
using Nacos.V2.Naming.Dtos;
|
||||
using Nacos.V2.Naming.Event;
|
||||
using Nacos.V2.Naming.Remote;
|
||||
using Nacos.V2.Remote;
|
||||
using System.Collections.Generic;
|
||||
namespace Nacos.V2.Naming
|
||||
{
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nacos.V2.Common;
|
||||
using Nacos.V2.Naming.Cache;
|
||||
using Nacos.V2.Naming.Core;
|
||||
using Nacos.V2.Naming.Dtos;
|
||||
using Nacos.V2.Naming.Event;
|
||||
using Nacos.V2.Naming.Remote;
|
||||
using Nacos.V2.Remote;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class NacosNamingService : INacosNamingService
|
||||
{
|
||||
private static readonly string UP = "UP";
|
||||
private static readonly string DOWN = "DOWN";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly NacosSdkOptions _options;
|
||||
|
||||
private string _namespace;
|
||||
|
||||
private ServiceInfoHolder _serviceInfoHolder;
|
||||
|
||||
private InstancesChangeNotifier _changeNotifier;
|
||||
|
||||
private INamingClientProxy _clientProxy;
|
||||
|
||||
public NacosNamingService(
|
||||
ILoggerFactory loggerFactory,
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class NacosNamingService : INacosNamingService
|
||||
{
|
||||
private static readonly string UP = "UP";
|
||||
private static readonly string DOWN = "DOWN";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly NacosSdkOptions _options;
|
||||
|
||||
private string _namespace;
|
||||
|
||||
private ServiceInfoHolder _serviceInfoHolder;
|
||||
|
||||
private InstancesChangeNotifier _changeNotifier;
|
||||
|
||||
private INamingClientProxy _clientProxy;
|
||||
|
||||
public NacosNamingService(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<NacosSdkOptions> optionAccs,
|
||||
IHttpClientFactory clientFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<NacosNamingService>();
|
||||
_options = optionAccs.Value;
|
||||
_namespace = string.IsNullOrWhiteSpace(_options.Namespace) ? Utils.UtilAndComs.DEFAULT_NAMESPACE_ID : _options.Namespace;
|
||||
this._changeNotifier = new InstancesChangeNotifier();
|
||||
this._serviceInfoHolder = new ServiceInfoHolder(_logger, _namespace, _options, _changeNotifier);
|
||||
this._clientProxy = new NamingClientProxyDelegate(_logger, _namespace, _serviceInfoHolder, _options, _changeNotifier, clientFactory);
|
||||
}
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string ip, int port)
|
||||
=> await DeregisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, string ip, int port)
|
||||
=> await DeregisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string ip, int port, string clusterName)
|
||||
=> await DeregisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, string ip, int port, string clusterName)
|
||||
{
|
||||
var instance = new Instance()
|
||||
{
|
||||
Ip = ip,
|
||||
Port = port,
|
||||
ClusterName = clusterName
|
||||
};
|
||||
|
||||
await DeregisterInstance(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, Instance instance)
|
||||
=> await DeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, Instance instance)
|
||||
=> await _clientProxy.DeregisterService(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName)
|
||||
=> await GetAllInstances(serviceName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName)
|
||||
=> await GetAllInstances(serviceName, groupName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, groupName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters)
|
||||
=> await GetAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters)
|
||||
=> await GetAllInstances(serviceName, groupName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters, bool subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo;
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
if (serviceInfo == null || !await _clientProxy.IsSubscribed(serviceName, groupName, clusterString).ConfigureAwait(false))
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceInfo = await _clientProxy.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
List<Instance> list = serviceInfo.Hosts;
|
||||
if (serviceInfo == null || serviceInfo.Hosts == null || !serviceInfo.Hosts.Any())
|
||||
{
|
||||
return new List<Instance>();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public Task<string> GetServerStatus()
|
||||
=> Task.FromResult(_clientProxy.ServerHealthy() ? UP : DOWN);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, groupName, null).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP, selector).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName, AbstractSelector selector)
|
||||
=> await _clientProxy.GetServiceList(pageNo, pageSize, groupName, selector).ConfigureAwait(false);
|
||||
|
||||
public Task<List<ServiceInfo>> GetSubscribeServices()
|
||||
=> Task.FromResult(_changeNotifier.GetSubscribeServices());
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string ip, int port)
|
||||
=> await RegisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, string ip, int port)
|
||||
=> await RegisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string ip, int port, string clusterName)
|
||||
=> await RegisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, string ip, int port, string clusterName)
|
||||
{
|
||||
var instance = new Instance()
|
||||
{
|
||||
Ip = ip,
|
||||
Port = port,
|
||||
Weight = 1.0d,
|
||||
ClusterName = clusterName
|
||||
};
|
||||
|
||||
await RegisterInstance(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task RegisterInstance(string serviceName, Instance instance)
|
||||
=> await RegisterInstance(serviceName, Constants.DEFAULT_GROUP, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, Instance instance)
|
||||
=> await _clientProxy.RegisterServiceAsync(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, bool healthy)
|
||||
=> await SelectInstances(serviceName, new List<string>(), healthy).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy)
|
||||
=> await SelectInstances(serviceName, groupName, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, new List<string>(), healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, groupName, new List<string>(), healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy)
|
||||
=> await SelectInstances(serviceName, clusters, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy)
|
||||
=> await SelectInstances(serviceName, groupName, clusters, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, Constants.DEFAULT_GROUP, clusters, healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy, bool subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo;
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
if (serviceInfo == null)
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceInfo = await _clientProxy.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return SelectInstances(serviceInfo, healthy);
|
||||
}
|
||||
|
||||
private List<Instance> SelectInstances(ServiceInfo serviceInfo, bool healthy)
|
||||
{
|
||||
List<Instance> list = serviceInfo.Hosts;
|
||||
|
||||
if (serviceInfo == null || list == null || !list.Any()) return new List<Instance>();
|
||||
|
||||
return list.Where(x => x.Healthy.Equals(healthy) && x.Enabled && x.Weight > 0).ToList();
|
||||
}
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName)
|
||||
=> await SelectOneHealthyInstance(serviceName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters)
|
||||
=> await SelectOneHealthyInstance(serviceName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters, bool subscribe)
|
||||
{
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
|
||||
if (serviceInfo == null)
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return Balancer.GetHostByRandom(serviceInfo?.Hosts);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceInfo serviceInfo = await _clientProxy
|
||||
.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
|
||||
return Balancer.GetHostByRandom(serviceInfo?.Hosts);
|
||||
}
|
||||
}
|
||||
|
||||
public Task ShutDown() => Task.CompletedTask;
|
||||
|
||||
public async Task Subscribe(string serviceName, IEventListener listener)
|
||||
=> await Subscribe(serviceName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, string groupName, IEventListener listener)
|
||||
=> await Subscribe(serviceName, groupName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, List<string> clusters, IEventListener listener)
|
||||
=> await Subscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener)
|
||||
{
|
||||
if (listener == null) return;
|
||||
|
||||
string clusterString = string.Join(",", clusters);
|
||||
|
||||
_changeNotifier.RegisterListener(groupName, serviceName, clusterString, listener);
|
||||
await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task Unsubscribe(string serviceName, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, string groupName, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, groupName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, List<string> clusters, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener)
|
||||
{
|
||||
string clustersString = string.Join(",", clusters);
|
||||
|
||||
_changeNotifier.DeregisterListener(groupName, serviceName, clustersString, listener);
|
||||
if (!_changeNotifier.IsSubscribed(groupName, serviceName, clustersString))
|
||||
{
|
||||
await _clientProxy.Unsubscribe(serviceName, groupName, clustersString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
IHttpClientFactory clientFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<NacosNamingService>();
|
||||
_options = optionAccs.Value;
|
||||
_namespace = string.IsNullOrWhiteSpace(_options.Namespace) ? Utils.UtilAndComs.DEFAULT_NAMESPACE_ID : _options.Namespace;
|
||||
this._changeNotifier = new InstancesChangeNotifier();
|
||||
this._serviceInfoHolder = new ServiceInfoHolder(_logger, _namespace, _options, _changeNotifier);
|
||||
this._clientProxy = new NamingClientProxyDelegate(_logger, _namespace, _serviceInfoHolder, _options, _changeNotifier, clientFactory);
|
||||
}
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string ip, int port)
|
||||
=> await DeregisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, string ip, int port)
|
||||
=> await DeregisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string ip, int port, string clusterName)
|
||||
=> await DeregisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, string ip, int port, string clusterName)
|
||||
{
|
||||
var instance = new Instance()
|
||||
{
|
||||
Ip = ip,
|
||||
Port = port,
|
||||
ClusterName = clusterName
|
||||
};
|
||||
|
||||
await DeregisterInstance(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, Instance instance)
|
||||
=> await DeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task DeregisterInstance(string serviceName, string groupName, Instance instance)
|
||||
=> await _clientProxy.DeregisterService(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName)
|
||||
=> await GetAllInstances(serviceName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName)
|
||||
=> await GetAllInstances(serviceName, groupName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, groupName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters)
|
||||
=> await GetAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters)
|
||||
=> await GetAllInstances(serviceName, groupName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters, bool subscribe)
|
||||
=> await GetAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters, bool subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo;
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
if (serviceInfo == null || !await _clientProxy.IsSubscribed(serviceName, groupName, clusterString).ConfigureAwait(false))
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceInfo = await _clientProxy.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
List<Instance> list = serviceInfo.Hosts;
|
||||
if (serviceInfo == null || serviceInfo.Hosts == null || !serviceInfo.Hosts.Any())
|
||||
{
|
||||
return new List<Instance>();
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public Task<string> GetServerStatus()
|
||||
=> Task.FromResult(_clientProxy.ServerHealthy() ? UP : DOWN);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, groupName, null).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)
|
||||
=> await GetServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP, selector).ConfigureAwait(false);
|
||||
|
||||
public async Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName, AbstractSelector selector)
|
||||
=> await _clientProxy.GetServiceList(pageNo, pageSize, groupName, selector).ConfigureAwait(false);
|
||||
|
||||
public Task<List<ServiceInfo>> GetSubscribeServices()
|
||||
=> Task.FromResult(_changeNotifier.GetSubscribeServices());
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string ip, int port)
|
||||
=> await RegisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, string ip, int port)
|
||||
=> await RegisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string ip, int port, string clusterName)
|
||||
=> await RegisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, string ip, int port, string clusterName)
|
||||
{
|
||||
var instance = new Instance()
|
||||
{
|
||||
Ip = ip,
|
||||
Port = port,
|
||||
Weight = 1.0d,
|
||||
ClusterName = clusterName
|
||||
};
|
||||
|
||||
await RegisterInstance(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task RegisterInstance(string serviceName, Instance instance)
|
||||
=> await RegisterInstance(serviceName, Constants.DEFAULT_GROUP, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task RegisterInstance(string serviceName, string groupName, Instance instance)
|
||||
=> await _clientProxy.RegisterServiceAsync(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, bool healthy)
|
||||
=> await SelectInstances(serviceName, new List<string>(), healthy).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy)
|
||||
=> await SelectInstances(serviceName, groupName, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, new List<string>(), healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, groupName, new List<string>(), healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy)
|
||||
=> await SelectInstances(serviceName, clusters, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy)
|
||||
=> await SelectInstances(serviceName, groupName, clusters, healthy, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy, bool subscribe)
|
||||
=> await SelectInstances(serviceName, Constants.DEFAULT_GROUP, clusters, healthy, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy, bool subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo;
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
if (serviceInfo == null)
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceInfo = await _clientProxy.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return SelectInstances(serviceInfo, healthy);
|
||||
}
|
||||
|
||||
private List<Instance> SelectInstances(ServiceInfo serviceInfo, bool healthy)
|
||||
{
|
||||
List<Instance> list = serviceInfo.Hosts;
|
||||
|
||||
if (serviceInfo == null || list == null || !list.Any()) return new List<Instance>();
|
||||
|
||||
return list.Where(x => x.Healthy.Equals(healthy) && x.Enabled && x.Weight > 0).ToList();
|
||||
}
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName)
|
||||
=> await SelectOneHealthyInstance(serviceName, new List<string>()).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, new List<string>(), subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters)
|
||||
=> await SelectOneHealthyInstance(serviceName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters)
|
||||
=> await SelectOneHealthyInstance(serviceName, groupName, clusters, true).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters, bool subscribe)
|
||||
=> await SelectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe).ConfigureAwait(false);
|
||||
|
||||
public async Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters, bool subscribe)
|
||||
{
|
||||
string clusterString = string.Join(",", clusters);
|
||||
if (subscribe)
|
||||
{
|
||||
ServiceInfo serviceInfo = _serviceInfoHolder.GetServiceInfo(serviceName, groupName, clusterString);
|
||||
|
||||
if (serviceInfo == null)
|
||||
{
|
||||
serviceInfo = await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return Balancer.GetHostByRandom(serviceInfo?.Hosts);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServiceInfo serviceInfo = await _clientProxy
|
||||
.QueryInstancesOfService(serviceName, groupName, clusterString, 0, false).ConfigureAwait(false);
|
||||
|
||||
return Balancer.GetHostByRandom(serviceInfo?.Hosts);
|
||||
}
|
||||
}
|
||||
|
||||
public Task ShutDown() => Task.CompletedTask;
|
||||
|
||||
public async Task Subscribe(string serviceName, IEventListener listener)
|
||||
=> await Subscribe(serviceName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, string groupName, IEventListener listener)
|
||||
=> await Subscribe(serviceName, groupName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, List<string> clusters, IEventListener listener)
|
||||
=> await Subscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Subscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener)
|
||||
{
|
||||
if (listener == null) return;
|
||||
|
||||
string clusterString = string.Join(",", clusters);
|
||||
|
||||
_changeNotifier.RegisterListener(groupName, serviceName, clusterString, listener);
|
||||
await _clientProxy.Subscribe(serviceName, groupName, clusterString).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task Unsubscribe(string serviceName, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, string groupName, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, groupName, new List<string>(), listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, List<string> clusters, IEventListener listener)
|
||||
=> await Unsubscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener).ConfigureAwait(false);
|
||||
|
||||
public async Task Unsubscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener)
|
||||
{
|
||||
string clustersString = string.Join(",", clusters);
|
||||
|
||||
_changeNotifier.DeregisterListener(groupName, serviceName, clustersString, listener);
|
||||
if (!_changeNotifier.IsSubscribed(groupName, serviceName, clustersString))
|
||||
{
|
||||
await _clientProxy.Unsubscribe(serviceName, groupName, clustersString).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task BatchRegisterInstance(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
Naming.Utils.NamingUtils.BatchCheckInstanceIsLegal(instances);
|
||||
|
||||
await _clientProxy.BatchRegisterServiceAsync(serviceName, groupName, instances).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
{ RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_NAMING },
|
||||
};
|
||||
|
||||
this.rpcClient = RpcClientFactory.CreateClient(uuid, RemoteConnectionType.GRPC, labels);
|
||||
this.rpcClient = RpcClientFactory.CreateClient(uuid, RemoteConnectionType.GRPC, labels, _options.TLSConfig);
|
||||
this._redoService = new NamingGrpcRedoService(_logger, this);
|
||||
|
||||
Start(serverListFactory, serviceInfoHolder);
|
||||
|
@ -123,6 +123,19 @@
|
|||
await DoRegisterService(serviceName, groupName, instance).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task BatchRegisterServiceAsync(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
_redoService.CacheInstanceForRedo(serviceName, groupName, instances);
|
||||
await DoBatchRegisterService(serviceName, groupName, instances).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task DoBatchRegisterService(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
var request = new BatchInstanceRequest(namespaceId, serviceName, groupName, NamingRemoteConstants.BATCH_REGISTER_INSTANCE, instances);
|
||||
await RequestToServer<CommonResponse>(request).ConfigureAwait(false);
|
||||
_redoService.InstanceRegistered(serviceName, groupName);
|
||||
}
|
||||
|
||||
public async Task DoRegisterService(string serviceName, string groupName, Instance instance)
|
||||
{
|
||||
var request = new InstanceRequest(namespaceId, serviceName, groupName, NamingRemoteConstants.REGISTER_INSTANCE, instance);
|
||||
|
@ -235,8 +248,8 @@
|
|||
return result;
|
||||
|
||||
string signData = !string.IsNullOrWhiteSpace(serviceName)
|
||||
? DateTimeOffset.Now.ToUnixTimeSeconds().ToString() + CommonParams.SEPARATOR + serviceName
|
||||
: DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
|
||||
? DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString() + CommonParams.SEPARATOR + serviceName
|
||||
: DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString();
|
||||
|
||||
string signature = HashUtil.GetHMACSHA1(signData, _options.SecretKey);
|
||||
result[CommonParams.SIGNATURE_FILED] = signature;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
namespace Nacos.V2.Naming.Remote.Grpc
|
||||
{
|
||||
using Nacos.V2.Naming.Dtos;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class BatchInstanceRedoData : InstanceRedoData
|
||||
{
|
||||
public List<Instance> Instances { get; set; }
|
||||
|
||||
public BatchInstanceRedoData(string serviceName, string groupName)
|
||||
: base(serviceName, groupName)
|
||||
{
|
||||
}
|
||||
|
||||
public static BatchInstanceRedoData Build(string serviceName, string groupName, List<Instance> instance)
|
||||
{
|
||||
var result = new BatchInstanceRedoData(serviceName, groupName)
|
||||
{
|
||||
Instances = instance
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,6 +65,14 @@
|
|||
_registeredInstances.AddOrUpdate(key, redoData, (x, y) => redoData);
|
||||
}
|
||||
|
||||
public void CacheInstanceForRedo(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
string key = NamingUtils.GetGroupedName(serviceName, groupName);
|
||||
var redoData = BatchInstanceRedoData.Build(serviceName, groupName, instances);
|
||||
|
||||
_registeredInstances.AddOrUpdate(key, redoData, (x, y) => redoData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance register successfully, mark registered status as true
|
||||
/// </summary>
|
||||
|
@ -92,6 +100,7 @@
|
|||
if (_registeredInstances.TryGetValue(key, out var data))
|
||||
{
|
||||
data.Unregistering = true;
|
||||
data.ExpectedRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +126,10 @@
|
|||
{
|
||||
string key = NamingUtils.GetGroupedName(serviceName, groupName);
|
||||
|
||||
_registeredInstances.TryRemove(key, out _);
|
||||
if (_registeredInstances.TryGetValue(key, out var data) && data != null && !data.ExpectedRegistered)
|
||||
{
|
||||
_registeredInstances.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -182,6 +194,7 @@
|
|||
if (_subscribes.TryGetValue(key, out var data))
|
||||
{
|
||||
data.Unregistering = true;
|
||||
data.ExpectedRegistered = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +208,10 @@
|
|||
{
|
||||
string key = ServiceInfo.GetKey(NamingUtils.GetGroupedName(serviceName, groupName), cluster);
|
||||
|
||||
_subscribes.TryRemove(key, out _);
|
||||
if (_subscribes.TryGetValue(key, out var data) && data != null && !data.ExpectedRegistered)
|
||||
{
|
||||
_subscribes.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
{
|
||||
this.ServiceName = serviceName;
|
||||
this.GroupName = groupName;
|
||||
this.ExpectedRegistered = true;
|
||||
}
|
||||
|
||||
public string ServiceName { get; private set; }
|
||||
|
||||
public string GroupName { get; private set; }
|
||||
|
||||
public bool ExpectedRegistered { get; set; }
|
||||
|
||||
public T Data { get; set; }
|
||||
|
||||
public bool Registered { get; set; }
|
||||
|
|
|
@ -66,6 +66,11 @@
|
|||
case RedoType.REGISTER:
|
||||
if (IsClientDisabled()) return;
|
||||
|
||||
if (redoData is BatchInstanceRedoData batchInstanceRedoData)
|
||||
{
|
||||
await _clientProxy.BatchRegisterServiceAsync(serviceName, groupName, batchInstanceRedoData.Instances).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await _clientProxy.DoRegisterService(serviceName, groupName, redoData.Data).ConfigureAwait(false);
|
||||
break;
|
||||
case RedoType.UNREGISTER:
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
this.serviceInfoHolder = serviceInfoHolder;
|
||||
}
|
||||
|
||||
internal async Task<Newtonsoft.Json.Linq.JObject> SendBeat(BeatInfo beatInfo, bool lightBeatEnabled)
|
||||
internal async Task<System.Text.Json.Nodes.JsonObject> SendBeat(BeatInfo beatInfo, bool lightBeatEnabled)
|
||||
{
|
||||
var parameters = new Dictionary<string, string>()
|
||||
{
|
||||
|
@ -88,7 +88,7 @@
|
|||
if (!lightBeatEnabled) body["beat"] = beatInfo.ToJsonString();
|
||||
|
||||
var result = await ReqApi(UtilAndComs.NacosUrlBase + "/instance/beat", parameters, body, HttpMethod.Put).ConfigureAwait(false);
|
||||
return Newtonsoft.Json.Linq.JObject.Parse(result);
|
||||
return System.Text.Json.Nodes.JsonNode.Parse(result).AsObject();
|
||||
}
|
||||
|
||||
private void SetServerPort(int serverPort)
|
||||
|
@ -177,9 +177,9 @@
|
|||
|
||||
var result = await ReqApi(UtilAndComs.NacosUrlBase + "/service/list", paramters, HttpMethod.Get).ConfigureAwait(false);
|
||||
|
||||
var json = Newtonsoft.Json.Linq.JObject.Parse(result);
|
||||
var count = json.GetValue("count")?.ToObject<int>() ?? 0;
|
||||
var data = json.GetValue("doms")?.ToObject<List<string>>() ?? new List<string>();
|
||||
var json = System.Text.Json.Nodes.JsonNode.Parse(result).AsObject();
|
||||
var count = json["count"]?.GetValue<int>() ?? 0;
|
||||
var data = json["doms"]?.GetValue<List<string>>() ?? new List<string>();
|
||||
|
||||
ListView<string> listView = new ListView<string>(count, data);
|
||||
return listView;
|
||||
|
@ -381,9 +381,9 @@
|
|||
|| string.IsNullOrWhiteSpace(_options.SecretKey))
|
||||
return;
|
||||
|
||||
string signData = !string.IsNullOrWhiteSpace(paramters[CommonParams.SERVICE_NAME_PARAM])
|
||||
? DateTimeOffset.Now.ToUnixTimeSeconds().ToString() + CommonParams.SEPARATOR + paramters[CommonParams.SERVICE_NAME_PARAM]
|
||||
: DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
|
||||
string signData = paramters.ContainsKey(CommonParams.SERVICE_NAME_PARAM) && !string.IsNullOrWhiteSpace(paramters[CommonParams.SERVICE_NAME_PARAM])
|
||||
? DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString() + CommonParams.SEPARATOR + paramters[CommonParams.SERVICE_NAME_PARAM]
|
||||
: DateTimeOffset.Now.ToUnixTimeMilliseconds().ToString();
|
||||
|
||||
string signature = HashUtil.GetHMACSHA1(signData, _options.SecretKey);
|
||||
paramters[CommonParams.SIGNATURE_FILED] = signature;
|
||||
|
@ -411,9 +411,9 @@
|
|||
string result = ReqApi(UtilAndComs.NacosUrlBase + "/operator/metrics", new Dictionary<string, string>(),
|
||||
HttpMethod.Get).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
var json = Newtonsoft.Json.Linq.JObject.Parse(result);
|
||||
var json = System.Text.Json.Nodes.JsonNode.Parse(result).AsObject();
|
||||
|
||||
string serverStatus = json.GetValue("status")?.ToString();
|
||||
string serverStatus = json["status"]?.GetValue<string>();
|
||||
return "UP".Equals(serverStatus);
|
||||
}
|
||||
catch
|
||||
|
@ -493,7 +493,7 @@
|
|||
{
|
||||
foreach (var item in dict)
|
||||
{
|
||||
builder.Append($"{item.Key}={item.Value}&");
|
||||
builder.Append($"{item.Key}={item.Value.UrlEncode()}&");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,7 +501,7 @@
|
|||
{
|
||||
foreach (var item in body)
|
||||
{
|
||||
builder.Append($"{item.Key}={item.Value}&");
|
||||
builder.Append($"{item.Key}={item.Value.UrlEncode()}&");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,5 +509,10 @@
|
|||
}
|
||||
|
||||
public Task<bool> IsSubscribed(string serviceName, string groupName, string clusters) => Task.FromResult(true);
|
||||
|
||||
public Task BatchRegisterServiceAsync(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
throw new NotImplementedException("Do not support persistent instances to perform batch registration methods.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,15 @@
|
|||
/// <param name="instance">instance to register</param>
|
||||
Task RegisterServiceAsync(string serviceName, string groupName, Instance instance);
|
||||
|
||||
/// <summary>
|
||||
/// batch register instance to service with specified instance properties.
|
||||
/// since nacos server 2.1.1
|
||||
/// </summary>
|
||||
/// <param name="serviceName">name of service</param>
|
||||
/// <param name="groupName">group of service</param>
|
||||
/// <param name="instances">instances to register</param>
|
||||
Task BatchRegisterServiceAsync(string serviceName, string groupName, List<Instance> instances);
|
||||
|
||||
Task DeregisterService(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task UpdateInstance(string serviceName, string groupName, Instance instance);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
using Nacos.V2.Security;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -119,6 +120,13 @@
|
|||
private INamingClientProxy GetExecuteClientProxy() => _options.NamingUseRpc ? grpcClientProxy : httpClientProxy;
|
||||
|
||||
public Task<bool> IsSubscribed(string serviceName, string groupName, string clusters)
|
||||
=> grpcClientProxy.IsSubscribed(serviceName, groupName, clusters);
|
||||
=> GetExecuteClientProxy().IsSubscribed(serviceName, groupName, clusters);
|
||||
|
||||
public async Task BatchRegisterServiceAsync(string serviceName, string groupName, List<Instance> instances)
|
||||
{
|
||||
if (instances == null || !instances.Any()) await Task.Yield();
|
||||
|
||||
await GetExecuteClientProxy().BatchRegisterServiceAsync(serviceName, groupName, instances).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
{
|
||||
public static string REGISTER_INSTANCE = "registerInstance";
|
||||
|
||||
public static string BATCH_REGISTER_INSTANCE = "batchRegisterInstance";
|
||||
|
||||
public static string DE_REGISTER_INSTANCE = "deregisterInstance";
|
||||
|
||||
public static string QUERY_SERVICE = "queryService";
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
namespace Nacos.V2.Naming.Utils
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Nacos.V2.Common;
|
||||
using Nacos.V2.Exceptions;
|
||||
using Nacos.V2.Naming.Dtos;
|
||||
using Nacos.V2.Utils;
|
||||
|
||||
public class NamingUtils
|
||||
|
@ -94,5 +98,61 @@
|
|||
{
|
||||
return groupName + Constants.SERVICE_INFO_SPLITER + serviceName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Batch verify the validity of instances.
|
||||
/// </summary>
|
||||
/// <param name="instances">List of instances to be registered</param>
|
||||
public static void BatchCheckInstanceIsLegal(List<Instance> instances)
|
||||
{
|
||||
HashSet<Instance> newInstanceSet = new HashSet<Instance>(instances);
|
||||
|
||||
foreach (var instance in newInstanceSet)
|
||||
{
|
||||
CheckInstanceIsEphemeral(instance);
|
||||
CheckInstanceIsLegal(instance);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check batch register is Ephemeral.
|
||||
/// </summary>
|
||||
/// <param name="instance">instance</param>
|
||||
/// <exception cref="NacosException"></exception>
|
||||
public static void CheckInstanceIsEphemeral(Instance instance)
|
||||
{
|
||||
if (!instance.Ephemeral)
|
||||
{
|
||||
throw new NacosException(
|
||||
NacosException.INVALID_PARAM,
|
||||
$"Batch registration does not allow persistent instance registration , Instance:{instance}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check instance param about keep alive.
|
||||
/// heart beat timeout must > heart beat interval
|
||||
/// ip delete timeout must > heart beat interval
|
||||
/// </summary>
|
||||
/// <param name="instance">need checked instance</param>
|
||||
/// <exception cref="NacosException"></exception>
|
||||
public static void CheckInstanceIsLegal(Instance instance)
|
||||
{
|
||||
if (instance.GetInstanceHeartBeatTimeOut() < instance.GetInstanceHeartBeatInterval()
|
||||
|| instance.GetIpDeleteTimeout() < instance.GetInstanceHeartBeatInterval())
|
||||
{
|
||||
throw new NacosException(
|
||||
NacosException.INVALID_PARAM,
|
||||
"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.");
|
||||
}
|
||||
|
||||
if (instance.ClusterName.IsNotNullOrWhiteSpace()
|
||||
&& !Regex.IsMatch(instance.ClusterName, Common.Constants.CLUSTER_NAME_PATTERN_STRING))
|
||||
{
|
||||
throw new NacosException(
|
||||
NacosException.INVALID_PARAM,
|
||||
$"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: {instance.ClusterName})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
public abstract class CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("headers")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("headers")]
|
||||
public System.Collections.Generic.Dictionary<string, string> Headers { get; set; } = new System.Collections.Generic.Dictionary<string, string>();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("requestId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("requestId")]
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public void PutHeader(string key, string value)
|
||||
|
|
|
@ -2,22 +2,22 @@
|
|||
{
|
||||
public class CommonRequestMeta
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("connectionId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("connectionId")]
|
||||
public string ConnectionId { get; set; } = "";
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("clientIp")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clientIp")]
|
||||
public string ClientIp { get; set; } = "";
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("clientPort")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clientPort")]
|
||||
public int ClientPort { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("clientVersion")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clientVersion")]
|
||||
public string ClientVersion { get; set; } = "";
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("type")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("labels")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("labels")]
|
||||
public System.Collections.Generic.Dictionary<string, string> Labels { get; set; } = new System.Collections.Generic.Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
{
|
||||
public abstract class CommonResponse
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("resultCode")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("resultCode")]
|
||||
public int ResultCode { get; set; } = 200;
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("errorCode")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("errorCode")]
|
||||
public int ErrorCode { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("message")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("requestId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("requestId")]
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool IsSuccess() => ResultCode == 200;
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
namespace Nacos.V2.Remote.GRpc
|
||||
{
|
||||
using Grpc.Core;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nacos.V2.Common;
|
||||
using Nacos.V2.Remote.Requests;
|
||||
using Nacos.V2.Remote.Responses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
public class GrpcClient : RpcClient
|
||||
{
|
||||
private static readonly string NACOS_SERVER_GRPC_PORT_OFFSET_KEY = "nacos.server.grpc.port.offset";
|
||||
private static readonly string NACOS_SERVER_GRPC_PORT_DEFAULT_OFFSET = "1000";
|
||||
|
||||
public GrpcClient(string name)
|
||||
: base(name)
|
||||
public GrpcClient(string name, TLSConfig tlsConfig)
|
||||
: base(name, tlsConfig)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -21,16 +24,41 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
var options = new Grpc.Net.Client.GrpcChannelOptions();
|
||||
var port = serverInfo.ServerPort + RpcPortOffset();
|
||||
var address = string.Empty;
|
||||
|
||||
var channel = new Grpc.Core.Channel(
|
||||
serverInfo.ServerIp,
|
||||
port,
|
||||
Grpc.Core.ChannelCredentials.Insecure,
|
||||
/* keep config and naming using diff channel */
|
||||
new List<Grpc.Core.ChannelOption> { new Grpc.Core.ChannelOption(GetName(), 1) });
|
||||
if (_tlsConfig != null && _tlsConfig.Enabled)
|
||||
{
|
||||
var clientCertificate = new X509Certificate2(_tlsConfig.PfxFile, _tlsConfig.Password);
|
||||
|
||||
#if !NETSTANDARD2_0
|
||||
var httpClientHandler = new SocketsHttpHandler();
|
||||
httpClientHandler.UseProxy = false;
|
||||
httpClientHandler.AllowAutoRedirect = false;
|
||||
httpClientHandler.SslOptions.ClientCertificates = new X509CertificateCollection { clientCertificate };
|
||||
httpClientHandler.SslOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) => true;
|
||||
#else
|
||||
var httpClientHandler = new HttpClientHandler();
|
||||
httpClientHandler.UseProxy = false;
|
||||
httpClientHandler.AllowAutoRedirect = false;
|
||||
httpClientHandler.ClientCertificates.Add(clientCertificate);
|
||||
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
|
||||
#endif
|
||||
|
||||
options.HttpHandler = httpClientHandler;
|
||||
address = $"https://{serverInfo.ServerIp}:{port}";
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Credentials = ChannelCredentials.Insecure;
|
||||
|
||||
address = $"http://{serverInfo.ServerIp}:{port}";
|
||||
}
|
||||
|
||||
options.MaxRetryAttempts = 0;
|
||||
var channel = Grpc.Net.Client.GrpcChannel.ForAddress(address, options);
|
||||
|
||||
// after nacos alpha2 server check response was changed!!
|
||||
var response = ServerCheck(channel);
|
||||
if (response == null || response is not ServerCheckResponse scResp)
|
||||
{
|
||||
|
@ -51,7 +79,6 @@
|
|||
grpcConn.SetRequestClient(requestClient);
|
||||
grpcConn.SetChannel(channel);
|
||||
|
||||
// after nacos alpha2 setup request was changed!!
|
||||
ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest
|
||||
{
|
||||
ClientVersion = Constants.CLIENT_VERSION,
|
||||
|
@ -82,7 +109,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
private CommonResponse ServerCheck(Grpc.Core.ChannelBase channel)
|
||||
private CommonResponse ServerCheck(Grpc.Net.Client.GrpcChannel channel)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -122,6 +149,12 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
if (request is SetupAckRequest)
|
||||
{
|
||||
// there is no connection ready this time
|
||||
return;
|
||||
}
|
||||
|
||||
var response = HandleServerRequest(request);
|
||||
response.RequestId = request.RequestId;
|
||||
await call.RequestStream.WriteAsync(GrpcUtils.Convert(response)).ConfigureAwait(false);
|
||||
|
|
|
@ -1,60 +1,61 @@
|
|||
namespace Nacos.V2.Remote.GRpc
|
||||
{
|
||||
using Nacos.V2.Exceptions;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class GrpcConnection : RemoteConnection
|
||||
{
|
||||
protected Grpc.Core.ChannelBase channel;
|
||||
|
||||
protected Nacos.Request.RequestClient reqClient;
|
||||
|
||||
protected Grpc.Core.AsyncDuplexStreamingCall<Nacos.Payload, Nacos.Payload> streamCall;
|
||||
|
||||
public void SetChannel(Grpc.Core.ChannelBase channel) => this.channel = channel;
|
||||
|
||||
public void SetRequestClient(Nacos.Request.RequestClient client) => this.reqClient = client;
|
||||
|
||||
public void SetBiRequestStreamClient(Grpc.Core.AsyncDuplexStreamingCall<Nacos.Payload, Nacos.Payload> streamCall) => this.streamCall = streamCall;
|
||||
|
||||
public GrpcConnection(RemoteServerInfo serverInfo) => this.ServerInfo = serverInfo;
|
||||
|
||||
protected override async Task Close()
|
||||
{
|
||||
if (reqClient != null) reqClient = null;
|
||||
|
||||
if (channel != null) await channel.ShutdownAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override Task<CommonResponse> Request(CommonRequest req, CommonRequestMeta meta) => Request(req, meta, 3000L);
|
||||
|
||||
protected override async Task<CommonResponse> Request(CommonRequest req, CommonRequestMeta meta, long timeoutMills)
|
||||
{
|
||||
// convert normal request to grpc request
|
||||
Payload grpcRequest = GrpcUtils.Convert(req, meta);
|
||||
|
||||
Payload grpcResponse = null;
|
||||
|
||||
try
|
||||
{
|
||||
var callOptions = default(Grpc.Core.CallOptions).WithDeadline(DateTime.UtcNow.AddMilliseconds(timeoutMills));
|
||||
|
||||
grpcResponse = await reqClient.requestAsync(grpcRequest, callOptions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new NacosException(NacosException.SERVER_ERROR, ex.Message);
|
||||
}
|
||||
|
||||
var response = (CommonResponse)GrpcUtils.Parse(grpcResponse);
|
||||
return response;
|
||||
}
|
||||
|
||||
public void SendRequest(CommonRequest request, CommonRequestMeta meta)
|
||||
{
|
||||
Payload convert = GrpcUtils.Convert(request, meta);
|
||||
streamCall.RequestStream.WriteAsync(convert);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Nacos.V2.Remote.GRpc
|
||||
{
|
||||
using Nacos.V2.Exceptions;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class GrpcConnection : RemoteConnection
|
||||
{
|
||||
protected Grpc.Net.Client.GrpcChannel channel;
|
||||
|
||||
protected Nacos.Request.RequestClient reqClient;
|
||||
|
||||
protected Grpc.Core.AsyncDuplexStreamingCall<Nacos.Payload, Nacos.Payload> streamCall;
|
||||
|
||||
public void SetChannel(Grpc.Net.Client.GrpcChannel channel) => this.channel = channel;
|
||||
|
||||
public void SetRequestClient(Nacos.Request.RequestClient client) => this.reqClient = client;
|
||||
|
||||
public void SetBiRequestStreamClient(Grpc.Core.AsyncDuplexStreamingCall<Nacos.Payload, Nacos.Payload> streamCall) => this.streamCall = streamCall;
|
||||
|
||||
public GrpcConnection(RemoteServerInfo serverInfo) => this.ServerInfo = serverInfo;
|
||||
|
||||
protected override async Task Close()
|
||||
{
|
||||
if (reqClient != null) reqClient = null;
|
||||
|
||||
if (channel != null) await channel.ShutdownAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override Task<CommonResponse> Request(CommonRequest req, CommonRequestMeta meta) => Request(req, meta, 3000L);
|
||||
|
||||
protected override async Task<CommonResponse> Request(CommonRequest req, CommonRequestMeta meta, long timeoutMills)
|
||||
{
|
||||
// convert normal request to grpc request
|
||||
Payload grpcRequest = GrpcUtils.Convert(req, meta);
|
||||
|
||||
Payload grpcResponse = null;
|
||||
|
||||
try
|
||||
{
|
||||
var callOptions = default(Grpc.Core.CallOptions).WithDeadline(DateTime.UtcNow.AddMilliseconds(timeoutMills));
|
||||
|
||||
grpcResponse = await reqClient.requestAsync(grpcRequest, callOptions).ResponseAsync
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new NacosException(NacosException.SERVER_ERROR, ex.Message);
|
||||
}
|
||||
|
||||
var response = (CommonResponse)GrpcUtils.Parse(grpcResponse);
|
||||
return response;
|
||||
}
|
||||
|
||||
public void SendRequest(CommonRequest request, CommonRequestMeta meta)
|
||||
{
|
||||
Payload convert = GrpcUtils.Convert(request, meta);
|
||||
streamCall.RequestStream.WriteAsync(convert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
this.Data = data;
|
||||
}
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("count")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("count")]
|
||||
public int Count { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("data")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("data")]
|
||||
public List<T> Data { get; set; }
|
||||
|
||||
public override string ToString() => "ListView{" + "data=" + Data + ", count=" + Count + '}';
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
public static readonly string Req_ServerCheck = "ServerCheckRequest";
|
||||
|
||||
public static readonly string Req_SetupAck = "SetupAckRequest";
|
||||
|
||||
public static readonly string Req_Config_ReSync = "ConfigReSyncRequest";
|
||||
|
||||
public static readonly string Resp_Config_Pubish_Alpha2 = "ConfigPublishResponse";
|
||||
|
@ -68,6 +70,8 @@
|
|||
|
||||
public static readonly string Resp_ServerCheck = "ServerCheckResponse";
|
||||
|
||||
public static readonly string Resp_SetupAck = "SetupAckResponse";
|
||||
|
||||
public static readonly string Req_PushAck = "PushAckRequest";
|
||||
|
||||
public static readonly string Req_ConnectReset = "ConnectResetRequest";
|
||||
|
@ -84,6 +88,10 @@
|
|||
|
||||
public static readonly string Resp_Naming_NotifySubscriber = "NotifySubscriberResponse";
|
||||
|
||||
public static readonly string Req_Naming_BatchInstance = "BatchInstanceRequest";
|
||||
|
||||
public static readonly string Resp_Naming_BatchInstance = "BatchInstanceResponse";
|
||||
|
||||
public static Dictionary<string, Type> RemoteResponseTypeMapping = new Dictionary<string, Type>
|
||||
{
|
||||
{ Resp_Config_Pubish_Alpha1, typeof(ConfigPubishResponse) },
|
||||
|
@ -107,6 +115,10 @@
|
|||
{ Req_ConnectReset, typeof(ConnectResetRequest) },
|
||||
{ Resp_HealthCheck, typeof(HealthCheckResponse) },
|
||||
{ Resp_Naming_NotifySubscriber, typeof(NotifySubscriberResponse) },
|
||||
{ Req_Naming_BatchInstance, typeof(BatchInstanceRequest) },
|
||||
{ Resp_Naming_BatchInstance, typeof(BatchInstanceResponse) },
|
||||
{ Req_SetupAck, typeof(SetupAckRequest) },
|
||||
{ Resp_SetupAck, typeof(SetupAckResponse) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
{
|
||||
public abstract class AbstractNamingRequest : CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("namespace")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namespace")]
|
||||
public string Namespace { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("serviceName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceName")]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("groupName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
public AbstractNamingRequest(string @namespace, string serviceName, string groupName)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
namespace Nacos.V2.Remote.Requests
|
||||
{
|
||||
using Nacos.V2.Naming.Dtos;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class BatchInstanceRequest : AbstractNamingRequest
|
||||
{
|
||||
public BatchInstanceRequest(string @namespace, string serviceName, string groupName, string type, List<Instance> instances)
|
||||
: base(@namespace, serviceName, groupName)
|
||||
{
|
||||
this.Type = type;
|
||||
this.Instances = instances;
|
||||
}
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[System.Text.Json.Serialization.JsonPropertyName("instances")]
|
||||
public List<Instance> Instances { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Naming_SubscribeService;
|
||||
}
|
||||
}
|
|
@ -2,13 +2,13 @@
|
|||
{
|
||||
public class ClientAbilities
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("remoteAbility")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("remoteAbility")]
|
||||
public ClientRemoteAbility RemoteAbility = new ClientRemoteAbility();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("configAbility")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("configAbility")]
|
||||
public ClientConfigAbility ConfigAbility = new ClientConfigAbility();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("namingAbility")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namingAbility")]
|
||||
public ClientNamingAbility NamingAbility = new ClientNamingAbility();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public class ClientConfigAbility
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("supportRemoteMetrics")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("supportRemoteMetrics")]
|
||||
public bool SupportRemoteMetrics { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
{
|
||||
public class ClientNamingAbility
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("supportDeltaPush")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("supportDeltaPush")]
|
||||
public bool SupportDeltaPush { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("supportRemoteMetric")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("supportRemoteMetric")]
|
||||
public bool SupportRemoteMetric { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
public class ClientRemoteAbility
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("supportRemoteConnection")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("supportRemoteConnection")]
|
||||
public bool SupportRemoteConnection { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
public class ConfigBatchListenRequest : CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("configListenContexts")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("configListenContexts")]
|
||||
public List<ConfigListenContext> ConfigListenContexts { get; set; } = new List<ConfigListenContext>();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("listen")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("listen")]
|
||||
public bool Listen { get; set; } = true;
|
||||
|
||||
public void AddConfigListenContext(string tenant, string group, string dataId, string md5)
|
||||
|
|
|
@ -10,34 +10,34 @@
|
|||
/// <summary>
|
||||
/// The tenant, corresponding to the namespace field of Nacos
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration ID
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration group
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("beta")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("beta")]
|
||||
public bool Beta { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("contentPush")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("contentPush")]
|
||||
public bool ContentPush { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("lastModifiedTs")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("lastModifiedTs")]
|
||||
public long LastModifiedTs { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("content")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("content")]
|
||||
public string Content { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("type")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Resp_Config_ChangeNotify;
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
{
|
||||
public class ConfigContext
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
this.Md5 = md5;
|
||||
}
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; private set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("md5")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("md5")]
|
||||
public string Md5 { get; private set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; private set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,29 +15,29 @@
|
|||
/// <summary>
|
||||
/// The tenant, corresponding to the namespace field of Nacos
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration ID
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration group
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration content
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("content")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("content")]
|
||||
public string Content { get; private set; }
|
||||
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("additionMap")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("additionMap")]
|
||||
public Dictionary<string, string> AdditionMap { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public void PutAdditonalParam(string key, string value)
|
||||
|
|
|
@ -12,22 +12,22 @@
|
|||
/// <summary>
|
||||
/// The tenant, corresponding to the namespace field of Nacos
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration ID
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration group
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; private set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("tag")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tag")]
|
||||
public string Tag { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Config_Get;
|
||||
|
|
|
@ -12,19 +12,19 @@
|
|||
/// <summary>
|
||||
/// The tenant, corresponding to the namespace field of Nacos
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration ID
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration group
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; private set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Config_ReSync;
|
||||
|
|
|
@ -13,25 +13,25 @@
|
|||
/// <summary>
|
||||
/// The tenant, corresponding to the namespace field of Nacos
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration ID
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("dataId")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("dataId")]
|
||||
public string DataId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration group
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("group")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("group")]
|
||||
public string Group { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration content
|
||||
/// </summary>
|
||||
[Newtonsoft.Json.JsonProperty("tag")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tag")]
|
||||
public string Tag { get; private set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Config_Remove;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
{
|
||||
public class ConnectResetRequest : CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("serverIp")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serverIp")]
|
||||
public string ServerIp { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("serverPort")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serverPort")]
|
||||
public string ServerPort { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_ConnectReset;
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
public class ConnectionSetupRequest : CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("clientVersion")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("clientVersion")]
|
||||
public string ClientVersion { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("abilities")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("abilities")]
|
||||
public ClientAbilities Abilities { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("tenant")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("tenant")]
|
||||
public string Tenant { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("labels")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("labels")]
|
||||
public Dictionary<string, string> Labels = new Dictionary<string, string>();
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_ConnectionSetup;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
{
|
||||
public class InstanceRequest : AbstractNamingRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("type")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("instance")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("instance")]
|
||||
public Nacos.V2.Naming.Dtos.Instance Instance { get; set; }
|
||||
|
||||
public InstanceRequest(string @namespace, string serviceName, string groupName, string type, Nacos.V2.Naming.Dtos.Instance instance)
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
{
|
||||
public class NotifySubscriberRequest : CommonRequest
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("namespace")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("namespace")]
|
||||
public string Namespace { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("serviceName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceName")]
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("groupName")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("groupName")]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("serviceInfo")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("serviceInfo")]
|
||||
public Nacos.V2.Naming.Dtos.ServiceInfo ServiceInfo { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Naming_NotifySubscriber;
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
this.PageSize = pageSize;
|
||||
}
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("pageNo")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("pageNo")]
|
||||
public int PageNo { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("pageSize")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("pageSize")]
|
||||
public int PageSize { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("selector")]
|
||||
[System.Text.Json.Serialization.JsonPropertyName("selector")]
|
||||
public string Selector { get; set; }
|
||||
|
||||
public override string GetRemoteType() => RemoteRequestType.Req_Naming_ServiceList;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue