Compare commits
310 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 | |
|
479c745ff3 | |
|
4e4d50916a | |
|
35280e75f6 | |
|
0c8dd5ff4b | |
|
30b864a3de | |
|
885682c23c | |
|
ea7c120c68 | |
|
44f9574a03 | |
|
de6ef4d391 | |
|
e63fae29d2 | |
|
5ddf979222 | |
|
fb6bf55f16 | |
|
92b3fd433e | |
|
011fac8a8b | |
|
e6d04e33e8 | |
|
4515a638ac | |
|
71a51f7bf9 | |
|
c3a3f240bd | |
|
49615063fd | |
|
1b17cb2199 | |
|
97ace972b4 | |
|
24c995830f | |
|
db474a5fe9 | |
|
afa9fa59bf | |
|
ce01d8de32 | |
|
48d737293f | |
|
823b545846 | |
|
52730fb1c9 | |
|
d2d4febf53 | |
|
a4711f1aa6 | |
|
745f2b5acd | |
|
4651250f94 | |
|
c5d4c234ef | |
|
0d677827fe | |
|
9b4b37d5c7 | |
|
789cac0e94 | |
|
005dab9df2 | |
|
89e51d563b | |
|
3e45767d05 | |
|
125046e38e | |
|
c810a88565 | |
|
0727b82b1e | |
|
c6c899d73c | |
|
9723f723a0 | |
|
247e288edc | |
|
ba0125db98 | |
|
6238b5ef98 | |
|
f05841993a | |
|
f3d3e9d6b7 | |
|
8ea1258eb7 | |
|
f8ffa08d19 | |
|
fdab19de7b | |
|
1a0b5198d9 | |
|
a1a9a99414 | |
|
7c46f5e455 | |
|
ab51aa6fa7 | |
|
d5da1d36c8 | |
|
e2727426eb | |
|
b84018c906 | |
|
fe6def7887 | |
|
976ddad822 | |
|
0877b7dcc7 | |
|
3796e979ca | |
|
67080488dc | |
|
42101d308e | |
|
e9d13f224a | |
|
767e879aec | |
|
c1e4c284d7 | |
|
833d78d6f1 | |
|
3b0cf8b144 | |
|
769dec41c4 | |
|
3c8337de2f | |
|
ea2f4a903f | |
|
4b14817538 | |
|
a173055e28 | |
|
1d8f543002 | |
|
14408a0e54 | |
|
475beda62e | |
|
d8d0813b99 | |
|
f55688c70c | |
|
576fd401b1 | |
|
d42fed9448 | |
|
e746010c16 | |
|
3c6a63ebe3 | |
|
06d458497c | |
|
4253b2d3a8 | |
|
0d04e5ef27 | |
|
80bdd09212 | |
|
8de447b67a | |
|
9a91cf32a8 | |
|
ead5748e3c | |
|
92101ab9f7 | |
|
343f3191cb | |
|
306f283f9a | |
|
c34b285f37 | |
|
0fd198118f | |
|
f21c576620 | |
|
7000290bd7 | |
|
9577a69db6 | |
|
eae5fe8f18 | |
|
5c741f6a25 | |
|
3db7938b8c | |
|
87b3bde801 | |
|
89dc598fd9 | |
|
2d7804bb51 | |
|
883b827817 | |
|
fd0637e2f8 | |
|
0fbd4f2943 | |
|
b179bb6779 | |
|
7bc8e494fe | |
|
322da0c477 | |
|
6f5aeac7ab | |
|
03139a89a4 | |
|
255f6c01fc | |
|
79fcba1df3 | |
|
1a024d5036 | |
|
43cb177326 | |
|
7fe688d62a | |
|
be746fec5d | |
|
d4f8937d87 | |
|
064dc34ffd | |
|
c54f39a111 | |
|
de06988f9c | |
|
dc891d2d2e | |
|
46c1a9cc0f | |
|
065f3e5008 | |
|
18038641a3 | |
|
59883ff2d2 | |
|
571a1c4751 | |
|
052ef1f983 | |
|
41aa4ebd6e | |
|
f12a803be2 | |
|
23474cd85d | |
|
f7966b8e3c | |
|
1b59329eea | |
|
a45ea2743b | |
|
a679f22ca1 | |
|
ceb7fd8fca | |
|
b84a578a4d | |
|
0d25013320 | |
|
3a01d9453f | |
|
c987e29dc1 | |
|
faffd2dfa2 | |
|
5a43d9a0ee | |
|
5229ef7420 | |
|
3f5d16fc68 | |
|
8c1ebb2106 | |
|
83b1d3cc92 | |
|
ffc8671c4e | |
|
92d77296ad | |
|
25383573d7 | |
|
20cff75deb | |
|
cd023ae268 | |
|
5fe1c7cb0b | |
|
fa90cff459 | |
|
ab33cc5027 | |
|
6ae555fd45 | |
|
76cee61f37 | |
|
a8f9a8b6b3 | |
|
c0aff448cc | |
|
4ac6ac3012 | |
|
2247c6c3d1 | |
|
a49445c590 | |
|
e503ad7339 | |
|
4de9106bd5 | |
|
a653b1f86f | |
|
f9d0bc7b91 | |
|
79a333d15d | |
|
5cb64c8b2b | |
|
381923d2bc | |
|
a8bbb06a18 | |
|
9aab8b73a1 | |
|
7878abdee6 | |
|
d3cb08bede | |
|
7114bf70e3 | |
|
e185ded3ff | |
|
1645598807 | |
|
fcaed9b3d9 | |
|
0958f5c256 | |
|
24d014636a | |
|
8403178eef | |
|
ca23dc6e24 | |
|
7d6ae0d7c0 | |
|
9fab0c0d78 | |
|
8fb626037f | |
|
720dc56a1b | |
|
aae905af88 | |
|
722939a7e4 | |
|
f916567c7b | |
|
b5b5f3add7 | |
|
08bc243f92 | |
|
edb9915e3e | |
|
36cc51df3b | |
|
0a96a30ea1 | |
|
467b22c0d8 | |
|
4914f46cfb | |
|
268bf9e4b1 | |
|
45c04c7e20 | |
|
122a33bbba | |
|
8dc451a86d | |
|
07115aa19e | |
|
ab77d78d3b | |
|
d489b77f47 | |
|
0b77b91920 | |
|
e51eb33548 | |
|
defd9b9714 | |
|
da1fab9c6a | |
|
ca7f7b847a | |
|
02c8464b83 | |
|
405ab36245 | |
|
2e455b374d | |
|
963210fef2 | |
|
45bd0d1147 | |
|
94e677878f | |
|
a07b3a4da7 | |
|
2468c63f5c | |
|
2dbd1cb507 | |
|
55d510d96e | |
|
2352591745 | |
|
5259882f52 | |
|
6f46af798e | |
|
3264415b6a | |
|
b6eb8d63a3 | |
|
87abbe7810 | |
|
e7a9a45ec0 | |
|
869b7ca098 | |
|
09dc81ae75 | |
|
daee05c366 | |
|
c1f02c2caf | |
|
d4ff4f73a9 | |
|
b60c96935d | |
|
0f97beedaf | |
|
6fde515fa3 | |
|
f2f6b029ac | |
|
6ea6e0399d | |
|
5081329e63 | |
|
2980ffe2ac | |
|
95a19809f8 | |
|
9a34d827ec | |
|
d56b544430 | |
|
b00d9b28b2 | |
|
4044d206af | |
|
ba597627a0 | |
|
e587aaaa4e | |
|
8b7eb08e88 | |
|
f16eb66cf7 |
|
@ -0,0 +1,49 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8-bom
|
||||
end_of_line = crlf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
tab_width = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[.bowerrc|*.yml]
|
||||
charset = utf-8
|
||||
|
||||
# Xml project files
|
||||
[*.*proj]
|
||||
indent_size = 2
|
||||
|
||||
# Xml build files
|
||||
[*.builds]
|
||||
indent_size = 2
|
||||
|
||||
# Xml files
|
||||
[*.{xml,stylecop,resx,ruleset,xsd}]
|
||||
indent_size = 2
|
||||
|
||||
# Xml config files
|
||||
[*.{props,targets,config,nuspec,vsixmanifest,vsct}]
|
||||
indent_size = 2
|
||||
|
||||
# JSON files
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
||||
# Shell scripts
|
||||
[*.sh]
|
||||
end_of_line = lf
|
||||
|
||||
# ReSharper properties
|
||||
resharper_csharp_wrap_lines=false
|
||||
resharper_enforce_line_ending_style=true
|
||||
resharper_js_wrap_lines=false
|
||||
resharper_protobuf_wrap_lines=false
|
||||
resharper_use_indent_from_vs=false
|
||||
resharper_vb_wrap_lines=false
|
||||
resharper_xmldoc_wrap_lines=false
|
||||
resharper_xml_wrap_lines=false
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
name: nacos-sdk-csharp template
|
||||
about: Issue Description
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Describe what happened (or what feature you want)
|
||||
|
||||
A clear and concise description of what happened or what you want.
|
||||
|
||||
## Describe what you expected to happen
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
## How to reproduce it (as minimally and precisely as possible)
|
||||
|
||||
## Related code
|
||||
|
||||
```JSON
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
services.Addxxxxx
|
||||
|
||||
builder.Addxxxx
|
||||
```
|
||||
|
||||
## Tell us your environment
|
||||
|
||||
- nacos-sdk-csharp version: [e.g. 1.1.0/...]
|
||||
- modular : [e.g. naming/config/msconfig/....]
|
||||
- nacos server version: [e.g. 2.0.0/....]
|
||||
- how to host nacos server : [e.g. docker/k8s/mse/virtual machine/...]
|
||||
|
||||
## Anything else we need to know?
|
|
@ -1,29 +0,0 @@
|
|||
name: Build
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: build on windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.x
|
||||
- name: Build with dotnet
|
||||
run: dotnet build --configuration Release
|
||||
|
||||
linux:
|
||||
name: build on linux
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.x
|
||||
- name: Build with dotnet
|
||||
run: dotnet build --configuration Release
|
|
@ -0,0 +1,83 @@
|
|||
name: Build_With_Stable_1x
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev, master ]
|
||||
pull_request:
|
||||
branches: [ dev, master ]
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: build on windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
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.Configuration\Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src\Nacos.System.Configuration\Nacos.System.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.AspNetCore.Tests\Nacos.AspNetCore.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.Microsoft.Extensions.Configuration.Tests\Nacos.Microsoft.Extensions.Configuration.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.Tests\Nacos.Tests.csproj
|
||||
|
||||
linux:
|
||||
name: build on linux
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
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.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
|
||||
nohup ./startup.sh -m standalone 2>&1 &
|
||||
sleep 30
|
||||
curl "127.0.0.1:8848/nacos/v1/ns/operator/metrics"
|
||||
- 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.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Tests/Nacos.Tests.csproj
|
||||
- name: Test with dotnet
|
||||
run: |
|
||||
dotnet test tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj --filter "Category=all|Category=1x" --no-restore
|
||||
dotnet test tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj --filter "Category=all|Category=1x" --no-restore
|
||||
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@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
|
@ -0,0 +1,83 @@
|
|||
name: Build_With_Stable_2x
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev, master ]
|
||||
pull_request:
|
||||
branches: [ dev, master ]
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
name: build on windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
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.Configuration\Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src\Nacos.System.Configuration\Nacos.System.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.AspNetCore.Tests\Nacos.AspNetCore.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.Microsoft.Extensions.Configuration.Tests\Nacos.Microsoft.Extensions.Configuration.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests\Nacos.Tests\Nacos.Tests.csproj
|
||||
|
||||
linux:
|
||||
name: build on linux
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
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.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
|
||||
nohup ./startup.sh -m standalone 2>&1 &
|
||||
sleep 30
|
||||
curl "127.0.0.1:8848/nacos/v1/ns/operator/metrics"
|
||||
- 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.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Tests/Nacos.Tests.csproj
|
||||
- name: Test with dotnet
|
||||
run: |
|
||||
dotnet test tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
dotnet test tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
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@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
|
@ -0,0 +1,65 @@
|
|||
name: Build_With_Unstable
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev, master ]
|
||||
pull_request:
|
||||
branches: [ dev, master ]
|
||||
|
||||
jobs:
|
||||
|
||||
linux:
|
||||
name: build on linux
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Setup up JDK 1.8
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
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.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
|
||||
sed -i 's/Xmx512m/Xmx1024m/g' startup.sh
|
||||
sed -i 's/Xmn256m/Xmn512m/g' startup.sh
|
||||
chmod 755 startup.sh
|
||||
nohup ./startup.sh -m standalone 2>&1 &
|
||||
sleep 30
|
||||
curl "127.0.0.1:8848/nacos/v1/ns/operator/metrics"
|
||||
- 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.Configuration/Nacos.Microsoft.Extensions.Configuration.csproj
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj
|
||||
dotnet build --configuration Release --source https://api.nuget.org/v3/index.json tests/Nacos.Tests/Nacos.Tests.csproj
|
||||
- name: Test with dotnet
|
||||
run: |
|
||||
dotnet test tests/Nacos.AspNetCore.Tests/Nacos.AspNetCore.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
dotnet test tests/Nacos.Microsoft.Extensions.Configuration.Tests/Nacos.Microsoft.Extensions.Configuration.Tests.csproj --filter "Category=all|Category=1x|Category=2x" --no-restore
|
||||
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@v3
|
||||
with:
|
||||
name: nacos-logs
|
||||
path: /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos/logs
|
|
@ -1,4 +1,4 @@
|
|||
name: Release
|
||||
name: Release_Unstable
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -11,17 +11,35 @@ 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: 5.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: dotnet build --configuration Release
|
||||
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
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
- name: Pack with dotnet
|
||||
run: dotnet pack /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos-sdk-csharp.sln --version-suffix alpha`date +%Y%m%d%H%M%S` -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
run: |
|
||||
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
|
||||
|
@ -33,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,17 +11,34 @@ 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: 5.0.x
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
7.0.x
|
||||
6.0.x
|
||||
- name: Build with dotnet
|
||||
run: dotnet build --configuration Release
|
||||
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
|
||||
dotnet msbuild -p:Configuration=Release -p:RestoreSources=https://api.nuget.org/v3/index.json -r -t:Build src/Nacos.System.Configuration/Nacos.System.Configuration.csproj
|
||||
- name: Pack with dotnet
|
||||
run: dotnet pack /home/runner/work/nacos-sdk-csharp/nacos-sdk-csharp/nacos-sdk-csharp.sln -o /home/runner/work/nugetpkgs -c Release --no-build
|
||||
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
|
||||
|
@ -33,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
|
||||
|
|
|
@ -236,7 +236,7 @@ Generated_Code/
|
|||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
# Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
|
@ -330,4 +330,9 @@ ASALocalRun/
|
|||
.mfractor/
|
||||
|
||||
# Mac OS
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
|
||||
# Read the docstates
|
||||
_build/
|
||||
_static/
|
||||
_templates/
|
|
@ -1,20 +1,22 @@
|
|||
|
||||
<Project>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn),1573,1591,1712</NoWarn>
|
||||
<CodeAnalysisRuleSet>..\..\_stylecop\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn),1573,1591,1712</NoWarn>
|
||||
<CodeAnalysisRuleSet>..\..\_stylecop\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" Version="5.*" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.*" PrivateAssets="All" Condition="'$(OS)' != 'Windows_NT'" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.*" PrivateAssets="All"/>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
|
102
README.md
102
README.md
|
@ -1,8 +1,8 @@
|
|||
# nacos-sdk-csharp [中文](./README.zh-cn.md)
|
||||
# nacos-sdk-csharp [中文](./README.zh-cn.md)
|
||||
|
||||
csharp(dotnet core) implementation of [nacos](https://nacos.io/) OpenAPI.
|
||||
|
||||
     
|
||||
     
|
||||
|
||||

|
||||
|
||||
|
@ -11,21 +11,27 @@ csharp(dotnet core) implementation of [nacos](https://nacos.io/) OpenAPI.
|
|||
Choose a package that you need.
|
||||
|
||||
```bash
|
||||
dotnet add package nacos-sdk-csharp-unofficial
|
||||
dotnet add package nacos-sdk-csharp-unofficial.AspNetCore
|
||||
dotnet add package nacos-sdk-csharp-unofficial.Extensions.Configuration
|
||||
dotnet add package nacos-sdk-csharp-unofficial.YamlParser
|
||||
dotnet add package nacos-sdk-csharp-unofficial.IniParser
|
||||
dotnet add package nacos-sdk-csharp
|
||||
dotnet add package nacos-sdk-csharp.AspNetCore
|
||||
dotnet add package nacos-sdk-csharp.Extensions.Configuration
|
||||
dotnet add package nacos-sdk-csharp.YamlParser
|
||||
dotnet add package nacos-sdk-csharp.IniParser
|
||||
```
|
||||
|
||||
> NOTE: The packages' name has remove the suffix `unofficial`.
|
||||
|
||||
## Features
|
||||
|
||||
- Basic OpenApi Usages
|
||||
- Integrate ASP.NET Core Configuration System
|
||||
- Service Registration and Discovery With ASP.NET Core
|
||||
- Integrate With Aliyun ACM
|
||||
- Integrate With Aliyun MSE/ACM
|
||||
- ...
|
||||
|
||||
Find more information on the documents pages:
|
||||
|
||||
https://nacos-sdk-csharp.readthedocs.io/en/latest/
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Simple Configuration Usage
|
||||
|
@ -33,6 +39,18 @@ dotnet add package nacos-sdk-csharp-unofficial.IniParser
|
|||
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) =>
|
||||
|
@ -41,15 +59,15 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
|
||||
// read configuration from config files
|
||||
// it will use default json parser to parse the configuration store in nacos server.
|
||||
builder.AddNacosConfiguration(c.GetSection("NacosConfig"));
|
||||
builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
// you also can specify ini or yaml parser as well.
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
2. Modify `appsettings.json`
|
||||
|
@ -57,16 +75,27 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
```JSON
|
||||
{
|
||||
"NacosConfig": {
|
||||
"Optional": false,
|
||||
"DataId": "msconfigapp",
|
||||
"Group": "",
|
||||
"Tenant": "f47e0ae1-982a-4a64-aea3-52506492a3d4",
|
||||
"Listeners": [
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "common",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
},
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
}
|
||||
],
|
||||
"Namespace": "csharp-demo", // Please set the value of Namespace ID !!!!!!!!
|
||||
"ServerAddresses": [ "http://localhost:8848/" ],
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "acm.aliyun.com:8080"
|
||||
"EndPoint": "acm.aliyun.com",
|
||||
"ConfigFilterAssemblies": ["YouPrefix.AssemblyName"],
|
||||
"ConfigFilterExtInfo": "some ext infomation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -128,7 +157,7 @@ public class Startup
|
|||
{
|
||||
// ...
|
||||
|
||||
services.AddNacosAspNetCore(Configuration);
|
||||
services.AddNacosAspNet(Configuration, "nacos");
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
|
@ -142,20 +171,29 @@ Modify `appsettings.json`
|
|||
|
||||
```JSON
|
||||
"nacos": {
|
||||
"EndPoint": "sub-domain.aliyun.com:8080",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "",
|
||||
"Namespace": "cs", // Please set the value of Namespace ID !!!!!!!!
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App1",
|
||||
"ClusterName": "",
|
||||
"GroupName": "",
|
||||
"Weight": 100,
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Ip": "",
|
||||
"PreferredNetworks": "", // select an IP that matches the prefix as the service registration IP
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"Port": 0,
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true,
|
||||
"Secure": false,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "sub-domain.aliyun.com:8080",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": "",
|
||||
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin
|
||||
"Metadata": {
|
||||
"aa": "bb",
|
||||
|
@ -171,19 +209,23 @@ Modify `appsettings.json`
|
|||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly INacosServerManager _serverManager;
|
||||
private readonly Nacos.V2.INacosNamingService _svc;
|
||||
|
||||
public ValuesController(INacosServerManager serverManager)
|
||||
public ValuesController(Nacos.V2.INacosNamingService svc)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
[HttpGet("test")]
|
||||
public async Task<IActionResult> Test()
|
||||
{
|
||||
// need to know the service name.
|
||||
// support WeightRandom and WeightRoundRobin.
|
||||
var baseUrl = await _serverManager.GetServerAsync("App2");
|
||||
var instance = await _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP");
|
||||
var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
? $"https://{host}"
|
||||
: $"http://{host}";
|
||||
|
||||
if(string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
|
|
102
README.zh-cn.md
102
README.zh-cn.md
|
@ -1,8 +1,9 @@
|
|||
# nacos-sdk-csharp [English](./README.md)
|
||||
# nacos-sdk-csharp [English](./README.md)
|
||||
|
||||
基于C#(dotnet core)实现 [nacos](https://nacos.io/) OpenAPI 的官方版本
|
||||
|
||||
     
|
||||
     
|
||||
|
||||
|
||||

|
||||
|
||||
|
@ -11,21 +12,28 @@
|
|||
选择您需要的包。
|
||||
|
||||
```bash
|
||||
dotnet add package nacos-sdk-csharp-unofficial
|
||||
dotnet add package nacos-sdk-csharp-unofficial.AspNetCore
|
||||
dotnet add package nacos-sdk-csharp-unofficial.Extensions.Configuration
|
||||
dotnet add package nacos-sdk-csharp-unofficial.YamlParser
|
||||
dotnet add package nacos-sdk-csharp-unofficial.IniParser
|
||||
dotnet add package nacos-sdk-csharp
|
||||
dotnet add package nacos-sdk-csharp.AspNetCore
|
||||
dotnet add package nacos-sdk-csharp.Extensions.Configuration
|
||||
dotnet add package nacos-sdk-csharp.YamlParser
|
||||
dotnet add package nacos-sdk-csharp.IniParser
|
||||
```
|
||||
|
||||
> 注: 包名里面的`unofficial`后缀已经被移除。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 基本的Open Api接口封装
|
||||
- 集成ASP.NET Core的配置系统
|
||||
- 简易ASP.NET Core的服务注册和发现
|
||||
- 和阿里云应用配置管理(Application Configuration Management,简称 ACM)集成使用
|
||||
- 和阿里云微服务引擎(Microservices Engine,简称 MSE)集成使用
|
||||
- ...
|
||||
|
||||
更多信息请查阅文档:
|
||||
|
||||
https://nacos-sdk-csharp.readthedocs.io/en/latest/
|
||||
|
||||
## 简易用法
|
||||
|
||||
### 配置
|
||||
|
@ -33,6 +41,18 @@ dotnet add package nacos-sdk-csharp-unofficial.IniParser
|
|||
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) =>
|
||||
|
@ -41,15 +61,15 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
|
||||
// 从配置文件读取Nacos相关配置
|
||||
// 默认会使用JSON解析器来解析存在Nacos Server的配置
|
||||
builder.AddNacosConfiguration(c.GetSection("NacosConfig"));
|
||||
builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
// 也可以按需使用ini或yaml的解析器
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
2. 修改 `appsettings.json`
|
||||
|
@ -57,16 +77,27 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
|
|||
```JSON
|
||||
{
|
||||
"NacosConfig": {
|
||||
"Optional": false,
|
||||
"DataId": "msconfigapp",
|
||||
"Group": "",
|
||||
"Tenant": "f47e0ae1-982a-4a64-aea3-52506492a3d4",
|
||||
"Listeners": [
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "common",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
},
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
}
|
||||
],
|
||||
"Namespace": "csharp-demo", // 这里请设置 Namespace ID 的值!!!!!!!!
|
||||
"ServerAddresses": [ "http://localhost:8848/" ],
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "acm.aliyun.com"
|
||||
"EndPoint": "acm.aliyun.com",
|
||||
"ConfigFilterAssemblies": ["YouPrefix.AssemblyName"],
|
||||
"ConfigFilterExtInfo": "some ext infomation"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -128,7 +159,7 @@ public class Startup
|
|||
{
|
||||
// ...
|
||||
|
||||
services.AddNacosAspNetCore(Configuration);
|
||||
services.AddNacosAspNet(Configuration, "nacos");
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
|
@ -142,20 +173,29 @@ public class Startup
|
|||
|
||||
```JSON
|
||||
"nacos": {
|
||||
"EndPoint": "sub-domain.aliyun.com:8080",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "",
|
||||
"Namespace": "cs", // 这里请设置 Namespace ID 的值!!!!!!!!
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App1",
|
||||
"ClusterName": "",
|
||||
"GroupName": "",
|
||||
"Weight": 100,
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Ip": "",
|
||||
"PreferredNetworks": "", // select an IP that matches the prefix as the service registration IP
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"Port": 0,
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true,
|
||||
"Secure": false,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "sub-domain.aliyun.com:8080",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": "",
|
||||
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin
|
||||
"Metadata": {
|
||||
"aa": "bb",
|
||||
|
@ -171,19 +211,23 @@ public class Startup
|
|||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly INacosServerManager _serverManager;
|
||||
private readonly Nacos.V2.INacosNamingService _svc;
|
||||
|
||||
public ValuesController(INacosServerManager serverManager)
|
||||
public ValuesController(Nacos.V2.INacosNamingService svc)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
[HttpGet("test")]
|
||||
public async Task<IActionResult> Test()
|
||||
{
|
||||
// 这里需要知道被调用方的服务名
|
||||
// 支持加权随机和加权轮询
|
||||
var baseUrl = await _serverManager.GetServerAsync("App2");
|
||||
var instance = await _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP")
|
||||
var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
? $"https://{host}"
|
||||
: $"http://{host}";
|
||||
|
||||
if(string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
<Rule Id="SA1503" Action="None" />
|
||||
<!-- Code should not contain multiple blank lines in a row -->
|
||||
<Rule Id="SA1507" Action="None" />
|
||||
<!-- File is required to end with a single newline character-->
|
||||
<Rule Id="SA1518" Action="None" />
|
||||
<!-- Element must be documented -->
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<!-- Parameter documentation mus be in the right order -->
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<NugetVersion>0.8.5</NugetVersion>
|
||||
<NugetVersion>1.3.10</NugetVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@ -0,0 +1,37 @@
|
|||
一些博客
|
||||
===============
|
||||
|
||||
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】
|
||||
|
||||
|
||||
2021
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- `聊一聊Yarp结合Nacos完成服务发现 <https://mp.weixin.qq.com/s/VkGSyqW0jZq4XzrEQTLbOQ>`_ 【2021-12-27】
|
||||
- `Nacos配置中心+ASP.NET Core <https://www.cnblogs.com/igeekfan/p/nacos-aspnetcore.html>`_ 【2021-12-26】
|
||||
- `聊一聊基于Nacos的metadata完成服务间的AB测试 <https://mp.weixin.qq.com/s/gm2Pt5WKMYncIWW1tb6N7g>`_ 【2021-12-13】
|
||||
- `Asp.Net5 WebAPI 使用NacOS作为配置中心的方法 <https://www.cnblogs.com/puzi0315/p/15577888.html>`_ 【2021-11-19】
|
||||
- `聊一聊声明式接口调用与Nacos的结合使用 <https://mp.weixin.qq.com/s/ySWaEVs-EETe_mvjpqdxQA>`_ 【2021-11-12】
|
||||
- `聊一聊.NET Core结合Nacos实现配置加解密 <https://mp.weixin.qq.com/s/XAWBGyHkmluC8pkJrsVW8g>`_ 【2021-06-15】
|
||||
- `聊一聊如何在.NET Core中使用Nacos 2.0 <https://mp.weixin.qq.com/s/iC6lFJJsHUFUveSJhoZxgA>`_ 【2021-03-22】
|
||||
- `聊一聊和Nacos 2.0.0对接那些事 <https://mp.weixin.qq.com/s/YOasHrZiJlT44RvD67Ayeg>`_ 【2021-03-08】
|
||||
|
||||
|
||||
2020
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- `ASP.NET Core集成Nacos配置中心之适配多格式配置 <https://mp.weixin.qq.com/s/jAr1pPNXWfdF2QO2dN5sdw>`_ 【2020-10-02】
|
||||
- `手动造轮子——为Ocelot集成Nacos注册中心 <https://www.cnblogs.com/wucy/p/13353824.html>`_ 【2020-07-21】
|
||||
- `搭建一套ASP.NET Core+Nacos+Spring Cloud Gateway项目 <https://www.cnblogs.com/wucy/p/13230453.html>`_ 【2020-07-03】
|
||||
- `ASP.NET Core使用Nacos SDK访问阿里云ACM <https://mp.weixin.qq.com/s/RHXE4WvSne4fulBzPbaH2A>`_ 【2020-06-07】
|
||||
- `在.NET Core中用最原生的方式读取Nacos的配置 <https://mp.weixin.qq.com/s/CsR1he4UsI6PSujMlwOpyg>`_ 【2020-04-26】
|
||||
|
||||
|
||||
2019
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- `ASP.NET Core使用Nacos作为配置中心的多环境问题 <https://www.cnblogs.com/catcher1994/p/11906556.html>`_ 【2019-11-21】
|
|
@ -0,0 +1,9 @@
|
|||
一些组件
|
||||
===============
|
||||
|
||||
|
||||
- `Ocelot.Provider.Nacos <https://github.com/softlgl/Ocelot.Provider.Nacos>`_ 【Ocelot集成Nacos注册中心组件】
|
||||
- `nacos-csharp-extensions <https://github.com/catcherwong/nacos-csharp-extensions>`_ 【Nacos的一些扩展(声明式接口调用集成,YARP集成等)】
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
source_suffix = ['.rst']
|
||||
|
||||
master_doc = 'index'
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'nacos-sdk-csharp'
|
||||
copyright = '2021, Catcher Wong'
|
||||
author = 'Catcher Wong'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
version = '1.0.0'
|
||||
release = '1.0.0'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'zh_CN'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
import os
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'nacos-sdk-csharp.tex', 'nacos-sdk-csharp Documentation',
|
||||
'Catcher Wong', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#
|
||||
# latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#
|
||||
# latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#
|
||||
# latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# latex_appendices = []
|
||||
|
||||
# It false, will not define \strong, \code, itleref, \crossref ... but only
|
||||
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
|
||||
# packages.
|
||||
#
|
||||
# latex_keep_old_macro_names = True
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'nacos-sdk-csharp', 'nacos-sdk-csharp Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#
|
||||
# man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'nacos-sdk-csharp', 'nacos-sdk-csharp Documentation',
|
||||
author, 'nacos-sdk-csharp', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#
|
||||
# texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#
|
||||
# texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#
|
||||
# texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#
|
||||
# texinfo_no_detailmenu = False
|
|
@ -0,0 +1,69 @@
|
|||
配置加解密
|
||||
===============
|
||||
|
||||
配置加解密这个功能是衍生功能,目前和 nacos 服务端联系还不大,是 SDK 对配置加密后再传输,解密后再使用。
|
||||
|
||||
如果需要使用这个功能,需要做下面两件事。
|
||||
|
||||
1. 自定义 ConfigFilter
|
||||
2. 配置 ConfigFilter
|
||||
|
||||
|
||||
自定义 ConfigFilter
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
把配置加解密的逻辑放到自定义的 ConfigFilter 里面。 ConfigFilter 可以有多个,不同 ConfigFilter 的执行顺序是按他们的 Order 属性来决定的。
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public class MyNacosConfigFilter : IConfigFilter
|
||||
{
|
||||
public void DoFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
|
||||
{
|
||||
if (request != null)
|
||||
{
|
||||
// 这里是请求的过滤,也就是在这里进行加密操作
|
||||
|
||||
|
||||
// 不要忘了在这里覆盖请求的内容!!!!!
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.ENCRYPTED_DATA_KEY, encryptedDataKey);
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
// 这里是响应的过滤,也就是在这里进行解密操作
|
||||
|
||||
|
||||
// 不要忘了在这里覆盖响应的内容!!!!!
|
||||
response.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFilterName() => nameof(MyNacosConfigFilter);
|
||||
|
||||
public int GetOrder() => 1;
|
||||
|
||||
public void Init(NacosSdkOptions options)
|
||||
{
|
||||
// 做一些初始化操作
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
配置 ConfigFilter
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
这一步主要是告诉 nacos-sdk-csharp 去那个程序集找 ConfigFilter 的实现,以及它的实现需要什么参数。
|
||||
|
||||
.. code-block:: JSON
|
||||
|
||||
{
|
||||
"NacosConfig": {
|
||||
"ConfigFilterAssemblies": [ "XXXX.CusLib" ],
|
||||
"ConfigFilterExtInfo": "{\"JsonPaths\":[\"ConnectionStrings.Default\"],\"Other\":\"xxxxxx\"}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
这里主要是两个配置,一个是 `ConfigFilterAssemblies` 指定实现类所在的程序集,一个是 `ConfigFilterExtInfo` 指定实现类可能需要的参数。
|
|
@ -0,0 +1,86 @@
|
|||
配置中心
|
||||
===============
|
||||
|
||||
`nacos-sdk-csharp` 操作 nacos 的配置提供了两个 nuget 包,一个是原生的 sdk 版本, 一个是集成了 ASP.NET Core 配置体系的版本,大家可以根据自己的需要选择不同的版本。
|
||||
|
||||
::
|
||||
|
||||
注: 请还在使用 nuget 包的名称里面还带有 `unofficial` 的朋友尽快升级到
|
||||
不带 `unofficial` 的版本,新版本同时支持 nacos server 1.x 和 2.x
|
||||
|
||||
|
||||
原生的 sdk 版本
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
原生 sdk 暴露出了下面几个方法
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task<string> GetConfig(string dataId, string group, long timeoutMs);
|
||||
|
||||
Task<string> GetConfigAndSignListener(string dataId, string group, long timeoutMs, IListener listener);
|
||||
|
||||
Task AddListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content, string type);
|
||||
|
||||
Task<bool> RemoveConfig(string dataId, string group);
|
||||
|
||||
Task RemoveListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
主要就是配置的 CURD 和监听。
|
||||
|
||||
监听可以让客户端实时获取 nacos 上面的最新配置,这个对实现配置的热加载/热更新是一个很重要的基石。
|
||||
|
||||
实现监听,需要自定义一个实现 `IListener` 的监听者。
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public class CusConfigListen : Nacos.V2.IListener
|
||||
{
|
||||
public void ReceiveConfigInfo(string configInfo)
|
||||
{
|
||||
// 这里会有配置变更的回调,在这里处理配置变更之后的逻辑。
|
||||
System.Console.WriteLine("config cb cb cb " + configInfo);
|
||||
}
|
||||
}
|
||||
|
||||
添加监听和移除监听,要保证是同一个监听者对象,不然会造成监听一直存在,移除不了的情况。
|
||||
|
||||
对于重要配置被修改需要通知到部门群或者其他地方时,通过监听就可以实现一个 webhook 的功能了。
|
||||
|
||||
|
||||
集成 ASP.NET Core 版本
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
推出这样一个版本很大程度是为了简化操作,只加几个配置,代码层级的用法几乎零改动,类似于 spring cloud 那样。
|
||||
|
||||
SDK 这一块通过实现了自定义的 **ConfigurationProvider** 和 **IConfigurationSource** 来达到了这个效果。
|
||||
|
||||
对于配置的热加载/热更新, SDK 则是实现了一个默认的监听者,在配置变更之后进行了 `OnReload` 的操作。
|
||||
|
||||
使用上需要在 `Program` 里面进行 **ConfigureAppConfiguration** 的设置。
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
{
|
||||
var c = builder.Build();
|
||||
builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
|
||||
::
|
||||
|
||||
注: 请注意 `IOptions<T>`、`IOptionsSnapshot<T>` 和 `IOptionsMonitor<T>` 的区别
|
||||
避免出现配置变更了,应用读取不到最新配置的情况!!!
|
|
@ -0,0 +1,59 @@
|
|||
集成微服务引擎MSE
|
||||
===================
|
||||
|
||||
前置条件
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
注册阿里云账号,并开通和购买微服务引擎。
|
||||
|
||||
|
||||
使用 SDK 操作的话,只需要将 ServerAddresses 替换成 mse 实例对应的地址即可。
|
||||
|
||||
示例如下:
|
||||
|
||||
配置模块
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"NacosConfig": {
|
||||
"Listeners": [
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "common",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
},
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
}
|
||||
],
|
||||
"Namespace": "0138xxxx-yyyy-zzzz-1111-000000000000",
|
||||
"ServerAddresses": [ "http://mse-xxxxxxxxxxx-nacos-ans.mse.aliyuncs.com:8848" ]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
服务注册发现模块
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"nacos": {
|
||||
"ServerAddresses": [ "http://mse-xxxxxxxxxxx-nacos-ans.mse.aliyuncs.com:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "0138xxxx-yyyy-zzzz-1111-000000000000",
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App1",
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
服务发现
|
||||
===============
|
||||
|
||||
`nacos-sdk-csharp` 操作 nacos 的配置提供了两个 nuget 包,一个是原生的 sdk 版本, 一个是集成了 ASP.NET Core 配置体系的版本,大家可以根据自己的需要选择不同的版本。
|
||||
|
||||
::
|
||||
|
||||
注: 请还在使用 nuget 包的名称里面还带有 `unofficial` 的朋友尽快升级到
|
||||
不带 `unofficial` 的版本,新版本同时支持 nacos server 1.x 和 2.x
|
||||
|
||||
|
||||
原生的 sdk 版本
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
原生 sdk 暴露出了下面几个方法
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task Subscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, AbstractSelector selector);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName, AbstractSelector selector);
|
||||
|
||||
Task<List<ServiceInfo>> GetSubscribeServices();
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
|
||||
可以看到有很多重载的方法,主要也是离不开服务的 CURD 和监听。
|
||||
|
||||
|
||||
集成 ASP.NET Core 版本
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
推出这样一个版本很大程度是为了简化操作,可以在应用启动的时候注册到 nacos 的注册中心,应用停止的时候可以注销。
|
||||
|
||||
SDK 内部是通过实现了一个后台服务 (IHostedService) 来达到这个效果的。
|
||||
|
||||
无论是注册还是注销,都会有重试的机制,目前最多重试 3 次。
|
||||
|
||||
查询服务实例则需要通过上面 **INacosNamingService** 提供的方法来实现。
|
|
@ -0,0 +1,41 @@
|
|||
常见问题
|
||||
===============
|
||||
|
||||
这个文档记录了一些 SDK 和 nacos server 对接使用上的常见问题。
|
||||
|
||||
1. 命名空间问题
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
命名空间可以说是第一要素,如果这个没有设置对,那么在控制台里面会看不到对应命名空间下面的数据。
|
||||
|
||||
在新建命名空间时,是可以指定命名空间Id的,不指定的话会自动生成一个UUID。
|
||||
|
||||
在SDK的配置里面,配置的一定是命名空间Id。如果是 public 命名空间,配置的是一个空字符串。
|
||||
|
||||
|
||||
2. nacos server 端口开放问题
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
SDK 在 v1.x 版本之后,就是默认用 grpc 的方式和 nacos server 对接,这个时候会出现下面几种情况。
|
||||
|
||||
- a. nacos server 是 1.x 版本,SDK 版本 >= 1.0
|
||||
- b. nacos server 是 2.x 版本,基于 docker/k8s 部署,只暴露了默认的 8848 端口,没有暴露 grpc 的端口, SDK版本 >= 1.0
|
||||
|
||||
这个时候会出现 `Client not connected,current status: STARTING` 的错误
|
||||
|
||||
针对 a 的情况,需要把 xxxUseRpc 设置为 false。
|
||||
|
||||
针对 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 版本
|
|
@ -0,0 +1,248 @@
|
|||
升级到1.0版本指引
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
背景
|
||||
---------------
|
||||
|
||||
`nacos-sdk-csharp` v1.0.0 版本之前主要是对接 nacos server 1.x。
|
||||
|
||||
随着 nacos server 2.0.0 即将发布,`nacos-sdk-csharp` 也已经进行了一次重构和适配来对接。
|
||||
|
||||
由于 nacos server 从 1.x 到 2.x 客户端对接的协议有所变更,1.x主要是HTTP, 2.x主要是gRPC。
|
||||
|
||||
之前 sdk 主要是对 Open Api 进行了封装和补充了部分内容。
|
||||
|
||||
在 1.0.0 版本,sdk 的方法会对齐 java版的 sdk, 这里的调整会比较大,但是之前用的方法还会保留几个版本。
|
||||
|
||||
升级
|
||||
---------------
|
||||
|
||||
大前提是 nacos server 版本已经是 2.0.0或更高版本。
|
||||
|
||||
修改引用的 nuget 包
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
<ItemGroup>
|
||||
- <PackageReference Include="nacos-sdk-csharp-unofficial" Version="0.8.5" />
|
||||
+ <PackageReference Include="nacos-sdk-csharp" Version="1.0.0-alphaxxxx" />
|
||||
</ItemGroup>
|
||||
|
||||
..
|
||||
|
||||
注: 包名已经移除了 `unofficial` 的后缀,1.0.0的版本目前还是prerelease,所以会有alpha的字样,
|
||||
正式发布后是没有的。如果依赖了扩展包,也需要做对应的处理。
|
||||
|
||||
核心的基础配置如下:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"EndPoint": "",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "cs",
|
||||
"ListenInterval": 1000,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": ""
|
||||
}
|
||||
|
||||
只有当 `ConfigUseRpc` 和 `NamingUseRpc` 设置为true的时候,才会用 gRPC 去和 nacos server 交互, 反之还是 HTTP。
|
||||
|
||||
另外,Namespace 字段填写的值是控制台中的 命名空间Id,不是命名空间名称!!!!
|
||||
|
||||
配置变化
|
||||
---------------
|
||||
|
||||
**SDK**
|
||||
|
||||
代码层使用的 `INacosConfigClient` 需要调整成 `INacosConfigService`, 提供了如下的方法。
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task<string> GetConfig(string dataId, string group, long timeoutMs);
|
||||
|
||||
Task<string> GetConfigAndSignListener(string dataId, string group, long timeoutMs, IListener listener);
|
||||
|
||||
Task AddListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content, string type);
|
||||
|
||||
Task<bool> RemoveConfig(string dataId, string group);
|
||||
|
||||
Task RemoveListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
**集成ASP.NET Core**
|
||||
|
||||
主要是变更 `ConfigureAppConfiguration` 里面的 AddNacosConfiguration,其余的不需要变化。
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
{
|
||||
var c = builder.Build();
|
||||
- builder.AddNacosConfiguration(c.GetSection("NacosConfig"));
|
||||
+ builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
|
||||
|
||||
服务变化
|
||||
---------------
|
||||
|
||||
**SDK**
|
||||
|
||||
代码层使用的 `INacosNamingClient` 需要调整成 `INacosNamingService`, 提供了如下的方法。
|
||||
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task Subscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, AbstractSelector selector);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName, AbstractSelector selector);
|
||||
|
||||
Task<List<ServiceInfo>> GetSubscribeServices();
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
|
||||
**集成ASP.NET Core**
|
||||
|
||||
调整 `Startup`
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
- services.AddNacosAspNetCore(Configuration);
|
||||
+ services.AddNacosAspNet(Configuration);
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
用到 `INacosServerManager` 的地方需要换成 `INacosNamingService`。
|
||||
|
||||
具体使用如下:
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
- var baseUrl = await _serverManager.GetServerAsync("App2");
|
||||
|
||||
+ var instance = await _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP");
|
||||
+ var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
+ var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
+ ? $"https://{host}"
|
||||
+ : $"http://{host}";
|
||||
|
||||
服务的配置,在原先的基础上添加了, **InstanceEnabled**, **Ephemeral**, **Secure** 三个内容。
|
||||
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
Guidelines for upgrading to version 1.0
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Background
|
||||
---------------
|
||||
|
||||
Before `nacos-sdk-csharp` v1.0.0, it was mainly connected to Nacos server 1. X.
|
||||
|
||||
With the release of Nacos server 2.0.0, `nacos-sdk-csharp` has been reconstructed and adapted to dock.
|
||||
|
||||
Because the protocol of Nacos server from 1.X to 2.X is changed, 1.X is mainly HTTP, 2.X is mainly grpc.
|
||||
|
||||
Before, the SDK mainly encapsulated and supplemented some contents of open API.
|
||||
|
||||
In version 1.0.0, the SDK method will align with the Java version of the SDK. The adjustment here will be relatively large, but several versions of the previous method will be retained.
|
||||
|
||||
Upgrade
|
||||
------------
|
||||
|
||||
|
||||
The premise is that the version of nacos server is 2.0.0 or higher.
|
||||
|
||||
Modify the referenced nuget package
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
<ItemGroup>
|
||||
- <PackageReference Include="nacos-sdk-csharp-unofficial" Version="0.8.5" />
|
||||
+ <PackageReference Include="nacos-sdk-csharp" Version="1.0.0-alphaxxxx" />
|
||||
</ItemGroup>
|
||||
|
||||
..
|
||||
|
||||
NOTE: The suffix "unofficial" has been removed from the package name. The version 1.0.0 is still prereleased,
|
||||
so there will be alpha, which will not be available after the official release.
|
||||
If you depend on the extension package, you need to do the corresponding processing.
|
||||
|
||||
|
||||
The basic configuration is as follows:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"EndPoint": "",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "cs",
|
||||
"ListenInterval": 1000,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": ""
|
||||
}
|
||||
|
||||
|
||||
Only when 'ConfigUseRpc' and 'NamingUseRpc' are set to true, gPRC will be used to interact with Nacos server, otherwise HTTP will be used.
|
||||
|
||||
And `Namespace` should be set to the Namespace Id in the nacos console, not the Namespace name!!!!!!
|
||||
|
||||
Configuration changes
|
||||
--------------------------
|
||||
|
||||
**SDK**
|
||||
|
||||
Adjust `INacosConfigClient` to `INacosConfigService`, and it providers the following methods.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task<string> GetConfig(string dataId, string group, long timeoutMs);
|
||||
|
||||
Task<string> GetConfigAndSignListener(string dataId, string group, long timeoutMs, IListener listener);
|
||||
|
||||
Task AddListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content);
|
||||
|
||||
Task<bool> PublishConfig(string dataId, string group, string content, string type);
|
||||
|
||||
Task<bool> RemoveConfig(string dataId, string group);
|
||||
|
||||
Task RemoveListener(string dataId, string group, IListener listener);
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
|
||||
**Integrate ASP.NET Core**
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
{
|
||||
var c = builder.Build();
|
||||
- builder.AddNacosConfiguration(c.GetSection("NacosConfig"));
|
||||
+ builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
|
||||
|
||||
|
||||
Service changes
|
||||
--------------------------
|
||||
|
||||
**SDK**
|
||||
|
||||
Adjust `INacosNamingClient` to `INacosNamingService`, and it providers the following methods.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task RegisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task RegisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task RegisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, string ip, int port, string clusterName);
|
||||
|
||||
Task DeregisterInstance(string serviceName, Instance instance);
|
||||
|
||||
Task DeregisterInstance(string serviceName, string groupName, Instance instance);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> GetAllInstances(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<List<Instance>> SelectInstances(string serviceName, string groupName, List<string> clusters, bool healthy, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task<Instance> SelectOneHealthyInstance(string serviceName, string groupName, List<string> clusters, bool subscribe);
|
||||
|
||||
Task Subscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Subscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task Unsubscribe(string serviceName, string groupName, List<string> clusters, IEventListener listener);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, AbstractSelector selector);
|
||||
|
||||
Task<ListView<string>> GetServicesOfServer(int pageNo, int pageSize, string groupName, AbstractSelector selector);
|
||||
|
||||
Task<List<ServiceInfo>> GetSubscribeServices();
|
||||
|
||||
Task<string> GetServerStatus();
|
||||
|
||||
Task ShutDown();
|
||||
|
||||
|
||||
**Integrate ASP.NET Core**
|
||||
|
||||
Modify `Startup`
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
- services.AddNacosAspNetCore(Configuration);
|
||||
+ services.AddNacosAspNet(Configuration);
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
|
||||
From `INacosServerManager` to `INacosNamingService`。
|
||||
|
||||
Details:
|
||||
|
||||
.. code-block:: diff
|
||||
|
||||
- var baseUrl = await _serverManager.GetServerAsync("App2");
|
||||
|
||||
+ var instance = await _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP");
|
||||
+ var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
+ var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
+ ? $"https://{host}"
|
||||
+ : $"http://{host}";
|
||||
|
||||
|
||||
On the basis of the original service configuration, three options are added: **InstanceEnabled**, **Ephemeral**, **Secure**.
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,56 @@
|
|||
.. nacos-sdk-csharp documentation master file, created by
|
||||
sphinx-quickstart on Sat Sep 4 10:44:58 2021.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
欢迎查阅 nacos-sdk-csharp 的文档!
|
||||
=================================================
|
||||
|
||||
`nacos-sdk-csharp` 是基于 C# ( dotnet core ) 实现 `nacos <https://nacos.io/>`_ 的版本
|
||||
|
||||
.. image:: ./images/prj.png
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Introduction
|
||||
|
||||
introduction/gettingstarted
|
||||
introduction/sdkenvvar
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Features
|
||||
|
||||
features/configuration
|
||||
features/cfg-encrypt
|
||||
features/servicediscovery
|
||||
features/mse
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Blogs
|
||||
|
||||
blogs/info
|
||||
blogs/lib
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Release Note
|
||||
|
||||
releasenote/v1.2.2
|
||||
releasenote/v1.3.0
|
||||
releasenote/v1.3.1
|
||||
releasenote/v1.3.2
|
||||
releasenote/v1.3.3
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:hidden:
|
||||
:caption: Guidelines
|
||||
|
||||
guide/v1.0.1/guide
|
||||
guide/v1.0.1/guide-zh
|
||||
guide/faq
|
|
@ -0,0 +1,239 @@
|
|||
快速上手
|
||||
===============
|
||||
|
||||
`nacos-sdk-csharp` 是基于 C# ( dotnet core ) 实现 `nacos <https://nacos.io/>`_ 的版本
|
||||
|
||||
安装Nuget包
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
选择您需要的包。
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
dotnet add package nacos-sdk-csharp
|
||||
dotnet add package nacos-sdk-csharp.AspNetCore
|
||||
dotnet add package nacos-sdk-csharp.Extensions.Configuration
|
||||
dotnet add package nacos-sdk-csharp.YamlParser
|
||||
dotnet add package nacos-sdk-csharp.IniParser
|
||||
|
||||
|
||||
::
|
||||
|
||||
注: 从1.0.0版本之后,包名里面的 `unofficial` 后缀已经被移除,
|
||||
带 `unofficial` 的包已经不再维护更新,请尽早更新到最新版本。
|
||||
|
||||
功能特性
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
- 基本的Open Api接口封装
|
||||
- 集成ASP.NET Core的配置系统
|
||||
- 简易ASP.NET Core的服务注册和发现
|
||||
- 和阿里云应用配置管理(Application Configuration Management,简称 ACM)集成使用
|
||||
- ...
|
||||
|
||||
简易用法
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
配置
|
||||
---------
|
||||
|
||||
1. 在 `Program.cs` 进行如下配置
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
{
|
||||
var c = builder.Build();
|
||||
|
||||
// 从配置文件读取Nacos相关配置
|
||||
// 默认会使用JSON解析器来解析存在Nacos Server的配置
|
||||
builder.AddNacosV2Configuration(c.GetSection("NacosConfig"));
|
||||
// 也可以按需使用ini或yaml的解析器
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosV2Configuration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
|
||||
|
||||
2. 修改 `appsettings.json`
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"NacosConfig": {
|
||||
"Listeners": [
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "common",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
},
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": "DEFAULT_GROUP"
|
||||
}
|
||||
],
|
||||
"Namespace": "csharp-demo",
|
||||
"ServerAddresses": [ "http://localhost:8848/" ],
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "acm.aliyun.com",
|
||||
"ConfigFilterAssemblies": ["YouPrefix.AssemblyName"],
|
||||
"ConfigFilterExtInfo": "some ext infomation"
|
||||
}
|
||||
}
|
||||
|
||||
3. 用原生的.NET Core方式来读取Nacos配置
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ConfigController : ControllerBase
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly AppSettings _settings;
|
||||
private readonly AppSettings _sSettings;
|
||||
private readonly AppSettings _mSettings;
|
||||
|
||||
public ConfigController(
|
||||
IConfiguration configuration,
|
||||
IOptions<AppSettings> options,
|
||||
IOptionsSnapshot<AppSettings> sOptions,
|
||||
IOptionsMonitor<AppSettings> _mOptions
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_settings = options.Value;
|
||||
_sSettings = sOptions.Value;
|
||||
_mSettings = _mOptions.CurrentValue;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public string Get()
|
||||
{
|
||||
// ....
|
||||
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
服务注册和发现
|
||||
------------------
|
||||
|
||||
1. 服务注册
|
||||
|
||||
在 `Program.cs` 中配置
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// ...
|
||||
|
||||
services.AddNacosAspNet(Configuration, "nacos");
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
修改 `appsettings.json`
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
"nacos": {
|
||||
"EndPoint": "sub-domain.aliyun.com:8080",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "cs",
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App1",
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Ip": "",
|
||||
"PreferredNetworks": "", // select an IP that matches the prefix as the service registration IP
|
||||
"Port": 0,
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true,
|
||||
"Secure": false,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": "",
|
||||
"LBStrategy": "WeightRandom", //WeightRandom WeightRoundRobin
|
||||
"Metadata": {
|
||||
"aa": "bb",
|
||||
"cc": "dd"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2. 服务发现
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly Nacos.V2.INacosNamingService _svc;
|
||||
|
||||
public ValuesController(Nacos.V2.INacosNamingService svc)
|
||||
{
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
[HttpGet("test")]
|
||||
public async Task<IActionResult> Test()
|
||||
{
|
||||
// 这里需要知道被调用方的服务名
|
||||
var instance = await _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP")
|
||||
var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
? $"https://{host}"
|
||||
: $"http://{host}";
|
||||
|
||||
if(string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
return "empty";
|
||||
}
|
||||
|
||||
var url = $"{baseUrl}/api/values";
|
||||
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
var result = await client.GetAsync(url);
|
||||
return await result.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
SDK环境变量说明
|
||||
===============
|
||||
|
||||
|
||||
============================================ ====================== ======================
|
||||
环境变量Key 默认值 说明
|
||||
============================================ ====================== ======================
|
||||
nacos.client.appKey 无 设定 sdk 的 AppKey
|
||||
JM.SNAPSHOT.PATH 无 Naming 模块的缓存目录
|
||||
push.receiver.udp.port 无 设定 client 的 udp 端口,针对服务端是 1.x
|
||||
com.alibaba.nacos.client.naming.local.ip 无 已经废弃,请使用com.alibaba.nacos.client.local.ip
|
||||
com.alibaba.nacos.client.local.ip 无 设置sdk的local ip
|
||||
nacos.server.grpc.port.offset 1000 nacos服务端grpc端口偏移值
|
||||
nacos.server.port 8848 nacos服务端的端口
|
||||
============================================ ====================== ======================
|
|
@ -0,0 +1,35 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
|
@ -0,0 +1,13 @@
|
|||
v1.0.1 (Mar 20th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
1. Adapt to nacos 2.0.
|
||||
#. FIxed some known bugs.
|
||||
#. Add log for SecurityProxy.
|
||||
|
||||
|
||||
------------
|
||||
|
||||
1. 适配 nacos 2.0
|
||||
#. 修复部分已知bug
|
||||
#. SecurityProxy 添加日志
|
|
@ -0,0 +1,9 @@
|
|||
v1.0.2 (Mar 21th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
|
||||
1. Fixed Grpc request bi stream,payload parse error
|
||||
|
||||
------------
|
||||
|
||||
1. 修复Grpc双向流部分payload不能解析问题
|
|
@ -0,0 +1,19 @@
|
|||
v1.0.3 (Apr 18th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
|
||||
1. Fix http with ACM
|
||||
#. Update proto file
|
||||
#. Support logging for Nacos.Microsoft.Extensions.Configuration
|
||||
#. Try to adapt SAE
|
||||
#. Publish config support type
|
||||
#. Fix some known issues.
|
||||
|
||||
------------
|
||||
|
||||
1. 修复 HTTP 协议访问 ACM 问题
|
||||
#. 更新 proto 文件
|
||||
#. Nacos.Microsoft.Extensions.Configuration 支持日志
|
||||
#. 尝试适配 SAE
|
||||
#. 发布配置支持类型
|
||||
#. 修复部分已知问题
|
|
@ -0,0 +1,29 @@
|
|||
v1.1.0 (Jun 14th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
|
||||
1. [NAMING] Fixed naming update task error
|
||||
#. [NAMING] Support naming push empty protection
|
||||
#. [NAMING] Support read UDP port from the environment variable
|
||||
#. [NAMING] Fixed services.AddNacosAspNet with action mode error
|
||||
#. [NAMING] Add/Remove cache before call server
|
||||
#. [NAMING] Support fetching server list from an endpoint with namespace
|
||||
#. [CONFIG] Fixed publish will trigger call back twice
|
||||
#. [CONFIG] Support CAS md5
|
||||
#. [CONFIG] Support config filter
|
||||
#. [CONFIG] Support .NET Framework 4.7.1
|
||||
#. Fixed and enhanced some known issues
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复服务更新任务异常
|
||||
#. [NAMING] 支持服务为空的推送保护
|
||||
#. [NAMING] 支持从环境变量读取UDP的端口
|
||||
#. [NAMING] 修复services.AddNacosAspNet用action方式的异常
|
||||
#. [NAMING] 在调用服务端之前先添加/移除缓存
|
||||
#. [NAMING] 支持根据namespace从endpoint获取服务列表
|
||||
#. [CONFIG] 修复发布配置触发两次回调问题
|
||||
#. [CONFIG] 支持 CAS md5
|
||||
#. [CONFIG] 支持 config filter
|
||||
#. [CONFIG] 支持 .NET Framework 4.7.1
|
||||
#. 修复和加强部分已知问题
|
|
@ -0,0 +1,19 @@
|
|||
v1.1.1 (Aug 9th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
|
||||
1. [NAMING] Fixed v2 ServerHttpAgent (#117 )
|
||||
#. [NAMING] Add redo feature for naming client (#122 )
|
||||
#. [NAMING] Add failover of naming (#123 )
|
||||
#. [NAMING] Improve weight round robin of v1 naming aspnetcore (#121 #124 )
|
||||
#. [NAMING] Improve create NamingGrpcClientProxy and PushReveiver (#127 )
|
||||
#. [CONFIG] Fixed key has already been added of msconfig (#119 #120 )
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复 v2 版本 ServerHttpAgent 请求问题 (#117 )
|
||||
#. [NAMING] naming client 支持 redo (#122 )
|
||||
#. [NAMING] naming client 支持 failover (#123 )
|
||||
#. [NAMING] 优化 v1 版本的加权轮询算法 (#121 #124 )
|
||||
#. [NAMING] 优化 创建 NamingGrpcClientProxy 和 PushReveiver (#127 )
|
||||
#. [CONFIG] 修复集成ASP.NET Core时出现重复配置key时的异常 (#119 #120 )
|
|
@ -0,0 +1,15 @@
|
|||
v1.2.0 (Sept 5th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
|
||||
1. [NAMING] Fixed not pass section for AddNacosV2Naming (#131)
|
||||
#. [AUTH] Fixed request login interface too frequently (#137)
|
||||
#. [CORE] improve: make rpcstatus error message readable
|
||||
#. [DOCS] improve: host documentation website on `readthedocs <https://nacos-sdk-csharp.readthedocs.io/en/latest/>`_
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复 AddNacosV2Naming 没有传递 section 的 bug (#131)
|
||||
#. [AUTH] 修复请求登录接口过于频繁的 bug (#137)
|
||||
#. [CORE] 优化 rpc 状态错误的提示语
|
||||
#. [DOCS] 托管文档网站到 `readthedocs <https://nacos-sdk-csharp.readthedocs.io/en/latest/>`_
|
|
@ -0,0 +1,16 @@
|
|||
v1.2.1 (Oct 7th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [CORE] Update ResolveServerInfo (#143 #145)
|
||||
#. [ALL] Remove old v1 version code (#146 #148)
|
||||
#. [CONFIG] Fixed overwrite configuration problem when listening multi dataid with same key (#149 #151)
|
||||
#. [NAMING] Fixed v1 naming subscribe do not trigger OnEvent (#154 #157)
|
||||
#. [TEST] Add more unit tests
|
||||
|
||||
------------
|
||||
|
||||
1. [CORE] 更新 ResolveServerInfo 方法 (#143 #145)
|
||||
#. [ALL] 移除老版本 v1 相关代码 (#146 #148)
|
||||
#. [CONFIG] 修复同时监听多个 DataId 并且包含相同配置项出现覆盖的问题 (#149 #151)
|
||||
#. [NAMING] 修复 udp 方式订阅时不触发 OnEvent 的问题 (#154 #157)
|
||||
#. [TEST] 添加更多的单元测试
|
|
@ -0,0 +1,10 @@
|
|||
v1.2.2 (Nov 7th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [NAMING] Improve server push empty pretection (#155)
|
||||
#. [NAMING] Fixed gzip compression (#161 #162)
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 优化服务端推空保护 (#155)
|
||||
#. [NAMING] 修复gzip压缩问题 (#161 #162)
|
|
@ -0,0 +1,12 @@
|
|||
v1.3.0 (Dec 9th, 2021) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [ALL] Support net6 for TargetFrameworks (#164)
|
||||
#. [NAMING] Support reading nacos server port offset from environment variable (#167)
|
||||
#. [ALL] remove RequestStream in proto file (#169)
|
||||
|
||||
------------
|
||||
|
||||
1. [ALL] TargetFrameworks添加net6支持 (#164)
|
||||
#. [NAMING] 支持从环境变量读取nacos server的端口偏移 (#167)
|
||||
#. [ALL] 从 proto 文件移除 RequestStream 方法 (#169)
|
|
@ -0,0 +1,14 @@
|
|||
v1.3.1 (Jan 20th, 2022) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [NAMING] Fix ServiceListRequest pageSize error
|
||||
#. [NAMING] Fix service push when new data lastRefTime lessthan old data lastRefTime
|
||||
#. [NAMING] Fix judgement for is subscribe services.
|
||||
#. [CONFIG] Fix thread safe issue of yaml and ini parser.
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复分页请求 pageSize 参数传递问题
|
||||
#. [NAMING] 修复服务推送时,lastRefTime 新数据比老数据的小的情况
|
||||
#. [NAMING] 修复是否订阅服务的判断
|
||||
#. [CONFIG] 修复 yaml 和 ini 解析器的线程安全问题
|
|
@ -0,0 +1,10 @@
|
|||
v1.3.2 (Mar 15th, 2022) 发布记录
|
||||
=============================================
|
||||
|
||||
1. [NAMING] Fix QueryInstancesOfService error cluster param (#180 #181)
|
||||
#. [NAMING] Fix Empty namespace issue (#187 #189)
|
||||
|
||||
------------
|
||||
|
||||
1. [NAMING] 修复 QueryInstancesOfService 请求参数错误 (#180 #181)
|
||||
#. [NAMING] 修复空命名空间默认值问题 (#187 #189)
|
|
@ -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
|
||||
|
@ -31,9 +31,23 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.AspNetCore.Tests", "t
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "parsers", "parsers", "{CFFCAA8B-3562-420B-AA8B-C525CC1ECD78}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nacos.YamlParser", "parsers\Nacos.YamlParser\Nacos.YamlParser.csproj", "{94CF8EEE-3812-47C6-998F-9105EB092036}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.YamlParser", "parsers\Nacos.YamlParser\Nacos.YamlParser.csproj", "{94CF8EEE-3812-47C6-998F-9105EB092036}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nacos.IniParser", "parsers\Nacos.IniParser\Nacos.IniParser.csproj", "{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.IniParser", "parsers\Nacos.IniParser\Nacos.IniParser.csproj", "{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nacos.System.Configuration", "src\Nacos.System.Configuration\Nacos.System.Configuration.csproj", "{7C20F5FB-33D4-460A-86F4-FC42122FA543}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigurationBuilderApp", "samples\ConfigurationBuilderApp\ConfigurationBuilderApp.csproj", "{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{81C1E3C0-6709-4726-A27D-C2346FAF39D7}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
Directory.Build.props = Directory.Build.props
|
||||
README.md = README.md
|
||||
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
|
||||
|
@ -89,6 +103,18 @@ Global
|
|||
{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CEE5E43E-F4E1-4E46-9B41-ABCBECDDEA63}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C20F5FB-33D4-460A-86F4-FC42122FA543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C20F5FB-33D4-460A-86F4-FC42122FA543}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C20F5FB-33D4-460A-86F4-FC42122FA543}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C20F5FB-33D4-460A-86F4-FC42122FA543}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{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
|
||||
|
@ -106,6 +132,9 @@ Global
|
|||
{F3DD367A-6EF5-4188-9D28-6858AA2F60F9} = {8176B7FC-151E-4EFF-A693-F60A39109595}
|
||||
{94CF8EEE-3812-47C6-998F-9105EB092036} = {CFFCAA8B-3562-420B-AA8B-C525CC1ECD78}
|
||||
{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}
|
||||
|
|
|
@ -1,19 +1,26 @@
|
|||
namespace Nacos.IniParser
|
||||
namespace Nacos.IniParser
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Nacos.Config;
|
||||
using Nacos.V2;
|
||||
|
||||
public class IniConfigurationStringParser : INacosConfigurationParser
|
||||
{
|
||||
public IniConfigurationStringParser()
|
||||
{
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public static IniConfigurationStringParser Instance = new IniConfigurationStringParser();
|
||||
|
||||
public IDictionary<string, string> Parse(string input)
|
||||
=> new IniConfigurationStringParser().ParseString(input);
|
||||
|
||||
public IDictionary<string, string> ParseString(string input)
|
||||
{
|
||||
_data.Clear();
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp-unofficial.IniParser</PackageId>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.IniParser</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
|
@ -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,10 +25,15 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<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)
|
|
@ -1,9 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp-unofficial.YamlParser</PackageId>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.YamlParser</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
|
@ -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,10 +25,15 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
|
@ -35,7 +41,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -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,7 +1,7 @@
|
|||
namespace Nacos.YamlParser
|
||||
{
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Nacos.Config;
|
||||
using Nacos.V2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -10,6 +10,10 @@
|
|||
|
||||
public class YamlConfigurationStringParser : INacosConfigurationParser
|
||||
{
|
||||
public YamlConfigurationStringParser()
|
||||
{
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Stack<string> _context = new Stack<string>();
|
||||
private string _currentPath;
|
||||
|
@ -17,6 +21,9 @@
|
|||
public static YamlConfigurationStringParser Instance = new YamlConfigurationStringParser();
|
||||
|
||||
public IDictionary<string, string> Parse(string input)
|
||||
=> new YamlConfigurationStringParser().ParseString(input);
|
||||
|
||||
private IDictionary<string, string> ParseString(string input)
|
||||
{
|
||||
_data.Clear();
|
||||
_context.Clear();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly INacosServerManager _serverManager;
|
||||
// nacos server 1.x and 2.x
|
||||
private readonly Nacos.V2.INacosNamingService _svc;
|
||||
|
||||
public ValuesController(INacosServerManager serverManager)
|
||||
public ValuesController(Nacos.V2.INacosNamingService svc)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
// GET api/values
|
||||
|
@ -27,7 +28,12 @@
|
|||
[HttpGet("test")]
|
||||
public ActionResult<string> Test()
|
||||
{
|
||||
var baseUrl = _serverManager.GetServerAsync("App2").GetAwaiter().GetResult();
|
||||
var instance = _svc.SelectOneHealthyInstance("App2", "DEFAULT_GROUP").GetAwaiter().GetResult();
|
||||
var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
? $"https://{host}"
|
||||
: $"http://{host}";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
namespace App1
|
||||
using Nacos.AspNetCore.V2;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// nacos server v1.x or v2.x
|
||||
builder.Services.AddNacosAspNet(builder.Configuration);
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseUrls("http://*:9876")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
app.Run("http://*:9876");
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
namespace App1
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddNacosAspNetCore(Configuration);
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,28 @@
|
|||
},
|
||||
"AllowedHosts": "*",
|
||||
"nacos": {
|
||||
"EndPoint": "",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "",
|
||||
"Namespace": "cs",
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App1",
|
||||
"RegisterEnabled": false
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Ip": "",
|
||||
"PreferredNetworks": "",
|
||||
"Port": 0,
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true,
|
||||
"Secure": false,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": ""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
namespace App2.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nacos.AspNetCore;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly INacosServerManager _serverManager;
|
||||
// nacos server 1.x and 2.x
|
||||
private readonly Nacos.V2.INacosNamingService _svc;
|
||||
|
||||
public ValuesController(INacosServerManager serverManager)
|
||||
public ValuesController(Nacos.V2.INacosNamingService svc)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
// GET api/values
|
||||
|
@ -27,7 +27,12 @@
|
|||
[HttpGet("test")]
|
||||
public ActionResult<string> Test()
|
||||
{
|
||||
var baseUrl = _serverManager.GetServerAsync("App1").GetAwaiter().GetResult();
|
||||
var instance = _svc.SelectOneHealthyInstance("App1", "DEFAULT_GROUP").GetAwaiter().GetResult();
|
||||
var host = $"{instance.Ip}:{instance.Port}";
|
||||
|
||||
var baseUrl = instance.Metadata.TryGetValue("secure", out _)
|
||||
? $"https://{host}"
|
||||
: $"http://{host}";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
|
|
|
@ -1,18 +1,43 @@
|
|||
namespace App2
|
||||
using Nacos.AspNetCore.V2;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// nacos server v1.x or v2.x
|
||||
builder.Services.AddNacosAspNet(x =>
|
||||
{
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
x.ServerAddresses = new List<string> { "http://localhost:8848/" };
|
||||
x.EndPoint = "";
|
||||
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;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
// swich to use http or rpc
|
||||
x.NamingUseRpc = true;
|
||||
});
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseUrls("http://*:9877")
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
builder.Services.AddControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
app.Run("http://*:9877");
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
namespace App2
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddNacosAspNetCore(Configuration);
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
/*app.UseNacosAspNetCore();*/
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,11 +6,29 @@
|
|||
},
|
||||
"AllowedHosts": "*",
|
||||
"nacos": {
|
||||
"EndPoint": "",
|
||||
"ServerAddresses": [ "http://localhost:8848" ],
|
||||
"DefaultTimeOut": 15000,
|
||||
"Namespace": "",
|
||||
"Namespace": "cs",
|
||||
"ListenInterval": 1000,
|
||||
"ServiceName": "App2",
|
||||
"GroupName": "DEFAULT_GROUP",
|
||||
"ClusterName": "DEFAULT",
|
||||
"Ip": "",
|
||||
"PreferredNetworks": "",
|
||||
"Port": 0,
|
||||
"Weight": 100,
|
||||
"RegisterEnabled": true,
|
||||
"InstanceEnabled": true,
|
||||
"Ephemeral": true,
|
||||
"Secure": false,
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"ConfigUseRpc": true,
|
||||
"NamingUseRpc": true,
|
||||
"NamingLoadCacheAtStart": "",
|
||||
"Metadata": {
|
||||
"preserved.register.source": "Test",
|
||||
"aa": "bb",
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.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>
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
namespace App3.ConfigFilters
|
||||
{
|
||||
using Nacos.V2;
|
||||
using Nacos.V2.Config.Abst;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
public class MyNacosConfigFilter : IConfigFilter
|
||||
{
|
||||
private static readonly string DefaultKey = "catcherwong00000";
|
||||
|
||||
public void DoFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
|
||||
{
|
||||
if (request != null)
|
||||
{
|
||||
var encryptedDataKey = DefaultKey;
|
||||
var raw_content = request.GetParameter(Nacos.V2.Config.ConfigConstants.CONTENT);
|
||||
var content = AESEncrypt((string)raw_content, encryptedDataKey);
|
||||
|
||||
// after encrypt the content, don't forget to update the request!!!
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.ENCRYPTED_DATA_KEY, encryptedDataKey);
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
var resp_content = response.GetParameter(Nacos.V2.Config.ConfigConstants.CONTENT);
|
||||
var resp_encryptedDataKey = response.GetParameter(Nacos.V2.Config.ConfigConstants.ENCRYPTED_DATA_KEY);
|
||||
|
||||
// nacos 2.0.2 still do not return the encryptedDataKey yet
|
||||
// but we can use a const key here.
|
||||
// after nacos server return the encryptedDataKey, we can keep one dataid with one encryptedDataKey
|
||||
var encryptedDataKey = (resp_encryptedDataKey == null || string.IsNullOrWhiteSpace((string)resp_encryptedDataKey)) ? DefaultKey : (string)resp_encryptedDataKey;
|
||||
var content = AESDecrypt((string)resp_content, encryptedDataKey);
|
||||
response.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetFilterName() => nameof(MyNacosConfigFilter);
|
||||
|
||||
public int GetOrder() => 1;
|
||||
|
||||
public void Init(NacosSdkOptions options)
|
||||
{
|
||||
Console.WriteLine("Assemblies = " + string.Join(",", options.ConfigFilterAssemblies));
|
||||
Console.WriteLine("Ext Info = " + string.Join(",", options.ConfigFilterExtInfo));
|
||||
Console.WriteLine("Init");
|
||||
}
|
||||
|
||||
public static string? AESEncrypt(string data, string key)
|
||||
{
|
||||
using (MemoryStream memory = new MemoryStream())
|
||||
{
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
byte[] plainBytes = Encoding.UTF8.GetBytes(data);
|
||||
byte[] bKey = new byte[32];
|
||||
Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);
|
||||
|
||||
aes.Mode = CipherMode.ECB;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.KeySize = 256;
|
||||
aes.Key = bKey;
|
||||
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memory, aes.CreateEncryptor(), CryptoStreamMode.Write))
|
||||
{
|
||||
try
|
||||
{
|
||||
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
|
||||
cryptoStream.FlushFinalBlock();
|
||||
return Convert.ToBase64String(memory.ToArray());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
using (MemoryStream memory = new MemoryStream(encryptedBytes))
|
||||
{
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.Mode = CipherMode.ECB;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.KeySize = 256;
|
||||
aes.Key = bKey;
|
||||
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memory, aes.CreateDecryptor(), CryptoStreamMode.Read))
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] tmp = new byte[encryptedBytes.Length];
|
||||
int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length);
|
||||
byte[] ret = new byte[len];
|
||||
Array.Copy(tmp, 0, ret, 0, len);
|
||||
|
||||
return Encoding.UTF8.GetString(ret, 0, len);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
namespace App3.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nacos.V2;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[ApiController]
|
||||
[Route("c")]
|
||||
public class ConfigController : ControllerBase
|
||||
{
|
||||
private readonly INacosConfigService _svc;
|
||||
|
||||
public ConfigController(INacosConfigService svc)
|
||||
{
|
||||
_svc = svc;
|
||||
}
|
||||
|
||||
// GET c/g?d=123
|
||||
[HttpGet("g")]
|
||||
public async Task<string> Get(string d)
|
||||
{
|
||||
var res = await _svc.GetConfig(d, "g", 3000).ConfigureAwait(false);
|
||||
|
||||
return res ?? "empty config";
|
||||
}
|
||||
|
||||
// GET c/d?d=123
|
||||
[HttpGet("d")]
|
||||
public async Task<string> Delete(string d)
|
||||
{
|
||||
var res = await _svc.RemoveConfig(d, "g").ConfigureAwait(false);
|
||||
|
||||
return "d ok" + res;
|
||||
}
|
||||
|
||||
// GET c/p?d=123
|
||||
[HttpGet("p")]
|
||||
public async Task<string> Publish(string d)
|
||||
{
|
||||
var res = await _svc.PublishConfig(d, "g", new System.Random().Next(1, 9999999).ToString()).ConfigureAwait(false);
|
||||
|
||||
return "p ok" + res;
|
||||
}
|
||||
|
||||
// GET c/al?d=123
|
||||
[HttpGet("a")]
|
||||
public async Task<string> Listen(string d)
|
||||
{
|
||||
await _svc.AddListener(d, "g", _configListen).ConfigureAwait(false);
|
||||
return "al ok";
|
||||
}
|
||||
|
||||
// GET c/rl?d=123
|
||||
[HttpGet("r")]
|
||||
public async Task<string> UnListen(string d)
|
||||
{
|
||||
await _svc.RemoveListener(d, "g", _configListen).ConfigureAwait(false);
|
||||
|
||||
return "rl ok";
|
||||
}
|
||||
|
||||
private static CusConfigListen _configListen = new CusConfigListen();
|
||||
|
||||
public class CusConfigListen : Nacos.V2.IListener
|
||||
{
|
||||
public void ReceiveConfigInfo(string configInfo)
|
||||
{
|
||||
System.Console.WriteLine("config cb cb cb " + configInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
namespace App3.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nacos.V2.Utils;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[ApiController]
|
||||
[Route("n")]
|
||||
public class NamingController : ControllerBase
|
||||
{
|
||||
private readonly Nacos.V2.INacosNamingService _client;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public NamingController(Nacos.V2.INacosNamingService client, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_client = client;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
// GET n/g
|
||||
[HttpGet("g")]
|
||||
public async Task<string> GetAllInstances()
|
||||
{
|
||||
var list = await _client.GetAllInstances("mysvc2", false).ConfigureAwait(false);
|
||||
|
||||
var res = list.ToJsonString();
|
||||
|
||||
return res ?? "GetAllInstances";
|
||||
}
|
||||
|
||||
// GET n/r
|
||||
[HttpGet("r")]
|
||||
public async Task<string> RegisterInstance()
|
||||
{
|
||||
// await _client.RegisterInstance("mysvc", "127.0.0.1", 9635);
|
||||
var instance = new Nacos.V2.Naming.Dtos.Instance
|
||||
{
|
||||
Ip = "127.0.0.1",
|
||||
Ephemeral = true,
|
||||
Port = 9562,
|
||||
ServiceName = "mysvc2"
|
||||
};
|
||||
|
||||
await _client.RegisterInstance("mysvc2", instance).ConfigureAwait(false);
|
||||
|
||||
return "RegisterInstance ok";
|
||||
}
|
||||
|
||||
// GET n/r2
|
||||
[HttpGet("r2")]
|
||||
public async Task<string> RegisterInstance2()
|
||||
{
|
||||
// await _client.RegisterInstance("mysvc", "127.0.0.1", 9635);
|
||||
var instance = new Nacos.V2.Naming.Dtos.Instance
|
||||
{
|
||||
Ip = "127.0.0.1",
|
||||
Ephemeral = true,
|
||||
Port = 9563,
|
||||
ServiceName = "mysvc2"
|
||||
};
|
||||
|
||||
await _client.RegisterInstance("mysvc2", instance).ConfigureAwait(false);
|
||||
|
||||
return "RegisterInstance ok";
|
||||
}
|
||||
|
||||
// GET n/dr
|
||||
[HttpGet("dr")]
|
||||
public async Task<string> DeregisterInstance()
|
||||
{
|
||||
// await _client.RegisterInstance("mysvc", "127.0.0.1", 9635);
|
||||
var instance = new Nacos.V2.Naming.Dtos.Instance
|
||||
{
|
||||
Ip = "127.0.0.1",
|
||||
Ephemeral = true,
|
||||
Port = 9562,
|
||||
ServiceName = "mysvc2"
|
||||
};
|
||||
|
||||
await _client.DeregisterInstance("mysvc2", instance).ConfigureAwait(false);
|
||||
|
||||
return "DeregisterInstance ok";
|
||||
}
|
||||
|
||||
// GET n/si
|
||||
[HttpGet("si")]
|
||||
public async Task<string> SelectInstances()
|
||||
{
|
||||
var list = await _client.SelectInstances("mysvc2", true, false).ConfigureAwait(false);
|
||||
|
||||
var res = list.ToJsonString();
|
||||
|
||||
return res ?? "SelectInstances ok";
|
||||
}
|
||||
|
||||
// GET n/gs
|
||||
[HttpGet("gs")]
|
||||
public async Task<string> GetServicesOfServer()
|
||||
{
|
||||
var list = await _client.GetServicesOfServer(1, 10).ConfigureAwait(false);
|
||||
|
||||
var res = list.ToJsonString();
|
||||
|
||||
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()
|
||||
{
|
||||
await _client.Subscribe("mysvc2", listener).ConfigureAwait(false);
|
||||
return "Subscribe";
|
||||
}
|
||||
|
||||
// GET n/unsub
|
||||
[HttpGet("unsub")]
|
||||
public async Task<string> Unsubscribe()
|
||||
{
|
||||
await _client.Unsubscribe("mysvc2", listener).ConfigureAwait(false);
|
||||
return "UnSubscribe";
|
||||
}
|
||||
|
||||
// NOTE: MUST keep Subscribe and Unsubscribe to use one instance of the listener!!!
|
||||
// DO NOT create new instance for each opreation!!!
|
||||
private static CusListener listener = new CusListener();
|
||||
|
||||
public class CusListener : Nacos.V2.IEventListener
|
||||
{
|
||||
public Task OnEvent(Nacos.V2.IEvent @event)
|
||||
{
|
||||
if (@event is Nacos.V2.Naming.Event.InstancesChangeEvent e)
|
||||
{
|
||||
System.Console.WriteLine("CusListener");
|
||||
System.Console.WriteLine("ServiceName" + e.ServiceName);
|
||||
System.Console.WriteLine("GroupName" + e.GroupName);
|
||||
System.Console.WriteLine("Clusters" + e.Clusters);
|
||||
System.Console.WriteLine("Hosts" + e.Hosts.ToJsonString());
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,46 +0,0 @@
|
|||
namespace App3.Controllers
|
||||
{
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nacos.AspNetCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
private readonly INacosServerManager _serverManager;
|
||||
|
||||
public ValuesController(INacosServerManager serverManager)
|
||||
{
|
||||
_serverManager = serverManager;
|
||||
}
|
||||
|
||||
// GET api/values
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<string>> Get()
|
||||
{
|
||||
return new string[] { "value1", "value2", "App3" };
|
||||
}
|
||||
|
||||
// GET api/values/test
|
||||
[HttpGet("test")]
|
||||
public ActionResult<string> Test()
|
||||
{
|
||||
var baseUrl = _serverManager.GetServerAsync("App1").GetAwaiter().GetResult();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(baseUrl))
|
||||
{
|
||||
return "empty";
|
||||
}
|
||||
|
||||
var url = $"{baseUrl}/api/values";
|
||||
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
var result = client.GetAsync(url).GetAwaiter().GetResult();
|
||||
return result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,70 @@
|
|||
namespace App3
|
||||
using Nacos.V2.DependencyInjection;
|
||||
using Nacos.OpenApi;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddNacosV2Config(x =>
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
x.ServerAddresses = new System.Collections.Generic.List<string> { "http://localhost:8848/" };
|
||||
x.EndPoint = "";
|
||||
x.Namespace = "cs";
|
||||
x.UserName = "nacos";
|
||||
x.Password = "nacos";
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
// this sample will add the filter to encrypt the config with AES.
|
||||
x.ConfigFilterAssemblies = new System.Collections.Generic.List<string> { "App3" };
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
// swich to use http or rpc
|
||||
x.ConfigUseRpc = true;
|
||||
});
|
||||
|
||||
builder.Services.AddNacosV2Naming(x =>
|
||||
{
|
||||
x.ServerAddresses = new System.Collections.Generic.List<string> { "http://localhost:8848/" };
|
||||
x.EndPoint = "";
|
||||
x.Namespace = "cs";
|
||||
|
||||
// swich to use http or rpc
|
||||
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();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run("http://*:9632");
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
namespace App3
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddNacosAspNetCore(Configuration);
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{CA0A661F-01D5-4DF7-9CD0-0399F89A8D47}</ProjectGuid>
|
||||
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>ConfigurationBuilderApp</RootNamespace>
|
||||
<AssemblyName>ConfigurationBuilderApp</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<Use64BitIISExpress />
|
||||
<IISExpressSSLPort />
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>bin\ConfigurationBuilderApp.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>bin\ConfigurationBuilderApp.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Web.DynamicData" />
|
||||
<Reference Include="System.Web.Entity" />
|
||||
<Reference Include="System.Web.ApplicationServices" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Web.Services" />
|
||||
<Reference Include="System.EnterpriseServices" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Startup.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Nacos.System.Configuration\Nacos.System.Configuration.csproj">
|
||||
<Project>{7c20f5fb-33d4-460a-86f4-fc42122fa543}</Project>
|
||||
<Name>Nacos.System.Configuration</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Owin.Host.SystemWeb">
|
||||
<Version>4.2.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>12012</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:12012/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,31 @@
|
|||
using ConfigurationBuilderApp;
|
||||
using Microsoft.Owin;
|
||||
using Owin;
|
||||
using System.Configuration;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
[assembly: OwinStartup(typeof(Startup))]
|
||||
|
||||
namespace ConfigurationBuilderApp
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void Configuration(IAppBuilder app)
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
context.Response.StatusCode = 404;
|
||||
|
||||
var key = context.Request.Query["key"];
|
||||
if (string.IsNullOrWhiteSpace(key)) return Task.CompletedTask;
|
||||
|
||||
var value = ConfigurationManager.AppSettings[key];
|
||||
if (value != null) context.Response.StatusCode = 200;
|
||||
|
||||
context.Response.Headers["Content-Type"] = "text/html; charset=utf-8";
|
||||
|
||||
return context.Response.WriteAsync(value ?? "undefined");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
|
||||
<section name="nacos" type="Nacos.System.Configuration.NacosConfigurationSection, Nacos.System.Configuration"/>
|
||||
</configSections>
|
||||
<configBuilders>
|
||||
<builders>
|
||||
<add name="nacos" type="Nacos.System.Configuration.NacosConfigurationBuilder, Nacos.System.Configuration"/>
|
||||
</builders>
|
||||
</configBuilders>
|
||||
<nacos tenant="cs" serverAddresses="http://localhost:8848/" userName="test2" password="123456" useGrpc="true">
|
||||
<listeners>
|
||||
<listener dataId="common"/>
|
||||
<listener dataId="demo"/>
|
||||
</listeners>
|
||||
</nacos>
|
||||
|
||||
<appSettings configBuilders="nacos"/>
|
||||
|
||||
<system.web>
|
||||
<compilation debug="true" targetFramework="4.7.1"/>
|
||||
<httpRuntime targetFramework="4.7.1"/>
|
||||
</system.web>
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Memory" culture="neutral" publicKeyToken="cc7b13ffcd2ddd51"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Data.Common" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.StackTrace" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Diagnostics.Tracing" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Globalization.Extensions" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.IO.Compression" culture="neutral" publicKeyToken="b77a5c561934e089"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Sockets" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.Serialization.Primitives" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Security.Cryptography.Algorithms" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.3.0.0" newVersion="4.3.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Security.SecureString" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Threading.Overlapped" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Xml.XPath.XDocument" culture="neutral" publicKeyToken="b03f5f7f11d50a3a"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
</configuration>
|
|
@ -21,14 +21,35 @@
|
|||
}
|
||||
*/
|
||||
|
||||
public string Str { get; set; }
|
||||
/*
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Default": "U2VydmVyPTEyNy4wLjAuMTtQb3J0PTMzMDY7RGF0YWJhc2U9ZGVtbztVc2VyIElkPXJvb3Q7UGFzc3dvcmQ9MTIzNDU2Ow=="
|
||||
},
|
||||
"version": "测试version",
|
||||
"AppSettings": {
|
||||
"Str": "val",
|
||||
"num": 1,
|
||||
"arr": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"subobj": {
|
||||
"a": "b"
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public string? Str { get; set; }
|
||||
|
||||
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
public int num { get; set; }
|
||||
|
||||
public List<int> arr { get; set; }
|
||||
public List<int>? arr { get; set; }
|
||||
|
||||
public SubObj subobj { get; set; }
|
||||
public SubObj? subobj { get; set; }
|
||||
#pragma warning restore SA1300 // Element should begin with upper-case letter
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
namespace MsConfigApp
|
||||
{
|
||||
using Nacos.V2;
|
||||
using Nacos.V2.Config.Abst;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
public class MyNacosConfigFilter : IConfigFilter
|
||||
{
|
||||
public void DoFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)
|
||||
{
|
||||
if (request != null)
|
||||
{
|
||||
var raw_content = request.GetParameter(Nacos.V2.Config.ConfigConstants.CONTENT);
|
||||
|
||||
// 部分配置加密后的 content
|
||||
var content = ReplaceJsonNode((string)raw_content, true);
|
||||
|
||||
// after encrypt the content, don't forget to update the request!!!
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.ENCRYPTED_DATA_KEY, "");
|
||||
request.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
var resp_content = response.GetParameter(Nacos.V2.Config.ConfigConstants.CONTENT);
|
||||
var resp_encryptedDataKey = response.GetParameter(Nacos.V2.Config.ConfigConstants.ENCRYPTED_DATA_KEY);
|
||||
|
||||
// nacos 2.0.2 still do not return the encryptedDataKey yet
|
||||
// but we can use a const key here.
|
||||
// after nacos server return the encryptedDataKey, we can keep one dataid with one encryptedDataKey
|
||||
var encryptedDataKey = (resp_encryptedDataKey == null || string.IsNullOrWhiteSpace((string)resp_encryptedDataKey)) ? string.Empty : (string)resp_encryptedDataKey;
|
||||
|
||||
var content = ReplaceJsonNode((string)resp_content, false);
|
||||
response.PutParameter(Nacos.V2.Config.ConfigConstants.CONTENT, content);
|
||||
}
|
||||
}
|
||||
|
||||
private string ReplaceJsonNode(string src, bool isEnc = true)
|
||||
{
|
||||
var jObj = JObject.Parse(src);
|
||||
|
||||
if (_jsonPaths != null)
|
||||
{
|
||||
foreach (var item in _jsonPaths)
|
||||
{
|
||||
var t = jObj.SelectToken(item);
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
var r = t.ToString();
|
||||
|
||||
// 加解密,示例用 base64
|
||||
var newToken = isEnc
|
||||
? Convert.ToBase64String(Encoding.UTF8.GetBytes(r))
|
||||
: Encoding.UTF8.GetString(Convert.FromBase64String(r));
|
||||
|
||||
t.Replace(newToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(jObj.ToString());
|
||||
|
||||
return jObj.ToString();
|
||||
}
|
||||
|
||||
public string GetFilterName() => nameof(MyNacosConfigFilter);
|
||||
|
||||
public int GetOrder() => 1;
|
||||
|
||||
private List<string>? _jsonPaths;
|
||||
|
||||
public void Init(NacosSdkOptions options)
|
||||
{
|
||||
// 从拓展信息里面获取需要加密的 json path
|
||||
// 这里只是示例,根据具体情况调整成自己合适的!!!!
|
||||
var extInfo = JObject.Parse(options.ConfigFilterExtInfo);
|
||||
|
||||
if (extInfo.ContainsKey("JsonPaths"))
|
||||
{
|
||||
_jsonPaths = extInfo?.GetValue("JsonPaths")?.ToObject<List<string>>();
|
||||
}
|
||||
|
||||
Console.WriteLine("Assemblies = " + string.Join(",", options.ConfigFilterAssemblies));
|
||||
Console.WriteLine("Ext Info = " + string.Join(",", options.ConfigFilterExtInfo));
|
||||
Console.WriteLine("Init");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +1,77 @@
|
|||
namespace MsConfigApp
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
|
||||
var outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}";
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.Enrich.FromLogContext()
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System", LogEventLevel.Warning)
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.Console(
|
||||
outputTemplate: outputTemplate)
|
||||
.CreateLogger();
|
||||
|
||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.Configure<MsConfigApp.AppSettings>(builder.Configuration.GetSection("AppSettings"));
|
||||
|
||||
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) =>
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
var config = b.Build();
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}";
|
||||
// read configuration from config files
|
||||
// default is json
|
||||
// b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"));
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.Enrich.FromLogContext()
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System", LogEventLevel.Warning)
|
||||
.MinimumLevel.Debug()
|
||||
.WriteTo.Console(
|
||||
outputTemplate: outputTemplate)
|
||||
/*.WriteTo.File(
|
||||
path: "logs/ApiTpl.log",
|
||||
outputTemplate: outputTemplate,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
retainedFileCountLimit: 5,
|
||||
encoding: System.Text.Encoding.UTF8)*/
|
||||
.CreateLogger();
|
||||
// specify ini or yaml
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
b.AddNacosV2Configuration(config.GetSection("NacosConfig"), parser: Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
});
|
||||
*/
|
||||
|
||||
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
try
|
||||
{
|
||||
Log.ForContext<Program>().Information("Application starting...");
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.ForContext<Program>().Fatal(ex, "Application start-up failed!!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
var app = builder.Build();
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureAppConfiguration((context, builder) =>
|
||||
{
|
||||
var c = builder.Build();
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
var dataId = c.GetValue<string>("NacosConfig:DataId");
|
||||
var group = c.GetValue<string>("NacosConfig:Group");
|
||||
var tenant = c.GetValue<string>("NacosConfig:Tenant");
|
||||
var optional = c.GetValue<bool>("NacosConfig:Optional");
|
||||
var serverAddresses = c.GetSection("NacosConfig:ServerAddresses").Get<List<string>>();
|
||||
app.UseRouting();
|
||||
|
||||
// read configuration from config files
|
||||
// default is json
|
||||
builder.AddNacosConfiguration(c.GetSection("NacosConfig"));
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
// specify ini or yaml
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.IniParser.IniConfigurationStringParser.Instance);
|
||||
// builder.AddNacosConfiguration(c.GetSection("NacosConfig"), Nacos.YamlParser.YamlConfigurationStringParser.Instance);
|
||||
|
||||
// hard code here
|
||||
/*builder.AddNacosConfiguration(x =>
|
||||
{
|
||||
x.DataId = dataId;
|
||||
x.Group = group;
|
||||
x.Tenant = tenant;
|
||||
x.Optional = optional;
|
||||
x.ServerAddresses = serverAddresses;
|
||||
});*/
|
||||
})
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
})
|
||||
.UseSerilog();
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
Log.ForContext<Program>().Information("Application starting...");
|
||||
app.Run("http://*:8787");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ForContext<Program>().Fatal(ex, "Application start-up failed!!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
namespace MsConfigApp
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||
services.AddControllers();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
public class SubObj
|
||||
{
|
||||
#pragma warning disable SA1300 // Element should begin with upper-case letter
|
||||
public string a { get; set; }
|
||||
public string? a { get; set; }
|
||||
#pragma warning restore SA1300 // Element should begin with upper-case letter
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
{
|
||||
{
|
||||
"NacosConfig": {
|
||||
"Listeners": [
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "common",
|
||||
"Group": ""
|
||||
"Group": "DEFAULT_GROUP"
|
||||
},
|
||||
{
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": ""
|
||||
"Group": "DEFAULT_GROUP"
|
||||
}
|
||||
],
|
||||
"Optional": false,
|
||||
"DataId": "demo",
|
||||
"Group": "group1",
|
||||
"Tenant": "9a760099-7724-4505-bb3d-e80028d53b35",
|
||||
"Namespace": "cs",
|
||||
"ServerAddresses": [ "http://localhost:8848/" ],
|
||||
"UserName": "test2",
|
||||
"Password": "123456",
|
||||
"UserName": "",
|
||||
"Password": "",
|
||||
"AccessKey": "",
|
||||
"SecretKey": "",
|
||||
"EndPoint": "acm.aliyun.com"
|
||||
"EndPoint": "acm.aliyun.com",
|
||||
"ConfigFilterAssemblies": [ "MsConfigApp" ],
|
||||
"ConfigFilterExtInfo": "{\"JsonPaths\":[\"ConnectionStrings.Default\"],\"Other\":\"xxxxxx\"}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public interface INacosServerManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the server URL with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <returns>A URL string</returns>
|
||||
Task<string> GetServerAsync(string serviceName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the server URL with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <returns>A URL string</returns>
|
||||
Task<string> GetServerAsync(string serviceName, string groupName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the server URL with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <returns>A URL string</returns>
|
||||
Task<string> GetServerAsync(string serviceName, string groupName, string clusters);
|
||||
|
||||
/// <summary>
|
||||
/// Get the server URL with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <param name="namespaceId">namespace id</param>
|
||||
/// <returns>A URL string</returns>
|
||||
Task<string> GetServerAsync(string serviceName, string groupName, string clusters, string namespaceId);
|
||||
|
||||
/// <summary>
|
||||
/// Get the HOST information with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <returns>The HOST information</returns>
|
||||
Task<Host> GetServerInfoAsync(string serviceName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the HOST information with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <returns>The HOST information</returns>
|
||||
Task<Host> GetServerInfoAsync(string serviceName, string groupName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the HOST information with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <returns>The HOST information</returns>
|
||||
Task<Host> GetServerInfoAsync(string serviceName, string groupName, string clusters);
|
||||
|
||||
/// <summary>
|
||||
/// Get the HOST information with specify load balance strategy.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <param name="namespaceId">namespace id</param>
|
||||
/// <returns>The HOST information</returns>
|
||||
Task<Host> GetServerInfoAsync(string serviceName, string groupName, string clusters, string namespaceId);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of HOST information.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <returns>A list of HOST information</returns>
|
||||
Task<List<Host>> GetServerListAsync(string serviceName);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of HOST information.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <returns>A list of HOST information</returns>
|
||||
Task<List<Host>> GetServerListAsync(string serviceName, string groupName);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of HOST information.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <returns>A list of HOST information</returns>
|
||||
Task<List<Host>> GetServerListAsync(string serviceName, string groupName, string clusters);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of HOST information.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">service name</param>
|
||||
/// <param name="groupName">group name</param>
|
||||
/// <param name="clusters">clusters</param>
|
||||
/// <param name="namespaceId">namespace id</param>
|
||||
/// <returns>A list of HOST information</returns>
|
||||
Task<List<Host>> GetServerListAsync(string serviceName, string groupName, string clusters, string namespaceId);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
public interface ILBStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// Strategy Name
|
||||
/// </summary>
|
||||
LBStrategyName Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get host
|
||||
/// </summary>
|
||||
/// <param name="list">host list</param>
|
||||
/// <returns>The Host</returns>
|
||||
Host GetHost(List<Host> list);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
public enum LBStrategyName
|
||||
{
|
||||
/// <summary>
|
||||
/// Weight Round Robin
|
||||
/// </summary>
|
||||
WeightRoundRobin,
|
||||
|
||||
/// <summary>
|
||||
/// Weight Random
|
||||
/// </summary>
|
||||
WeightRandom,
|
||||
|
||||
/// <summary>
|
||||
/// Ext1
|
||||
/// </summary>
|
||||
Ext1
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
public class LbKv
|
||||
{
|
||||
public string InstanceId { get; set; }
|
||||
|
||||
public double Weight { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using Nacos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class WeightRandomLBStrategy : ILBStrategy
|
||||
{
|
||||
public LBStrategyName Name => LBStrategyName.WeightRandom;
|
||||
|
||||
public Host GetHost(List<Host> list)
|
||||
{
|
||||
var dict = BuildScore(list);
|
||||
|
||||
Host instance = null;
|
||||
|
||||
var rd = new Random().NextDouble();
|
||||
|
||||
foreach (var item in dict)
|
||||
{
|
||||
if (item.Value >= rd)
|
||||
{
|
||||
instance = list.FirstOrDefault(x => x.InstanceId.Equals(item.Key));
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
var arr = item.Key.Split("#");
|
||||
var ip = arr[0];
|
||||
int.TryParse(arr[1], out var port);
|
||||
var cluster = arr[2];
|
||||
|
||||
instance = list.First(x => x.Ip.Equals(ip) && x.Port == port && x.ClusterName.Equals(cluster));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Dictionary<string, double> BuildScore(List<Host> list)
|
||||
{
|
||||
var dict = new Dictionary<string, double>();
|
||||
|
||||
var tmp = list.Select(x => new LbKv
|
||||
{
|
||||
// aliyun sae, the instanceid returns empty string
|
||||
// when the instanceid is empty, create a new one, but the group was missed.
|
||||
InstanceId = string.IsNullOrWhiteSpace(x.InstanceId) ? $"{x.Ip}#{x.Port}#{x.ClusterName}#{x.ServiceName}" : x.InstanceId,
|
||||
Weight = x.Weight
|
||||
}).GroupBy(x => x.InstanceId).Select(x => new LbKv
|
||||
{
|
||||
InstanceId = x.Key,
|
||||
Weight = x.Max(y => y.Weight)
|
||||
}).ToList();
|
||||
|
||||
var total = tmp.Sum(x => x.Weight);
|
||||
var cur = 0d;
|
||||
|
||||
foreach (var item in tmp)
|
||||
{
|
||||
cur += item.Weight;
|
||||
dict.TryAdd(item.InstanceId, cur / total);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using Nacos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class WeightRoundRobinLBStrategy : ILBStrategy
|
||||
{
|
||||
public LBStrategyName Name => LBStrategyName.WeightRoundRobin;
|
||||
|
||||
private int _pos;
|
||||
|
||||
private static object obj = new object();
|
||||
|
||||
public Host GetHost(List<Host> list)
|
||||
{
|
||||
var tmp = list.Select(x => new LbKv
|
||||
{
|
||||
// aliyun sae, the instanceid returns empty string
|
||||
// when the instanceid is empty, create a new one, but the group was missed.
|
||||
InstanceId = string.IsNullOrWhiteSpace(x.InstanceId) ? $"{x.Ip}#{x.Port}#{x.ClusterName}#{x.ServiceName}" : x.InstanceId,
|
||||
Weight = x.Weight
|
||||
}).GroupBy(x => x.InstanceId).Select(x => new LbKv
|
||||
{
|
||||
InstanceId = x.Key,
|
||||
Weight = x.Max(y => y.Weight)
|
||||
}).ToList();
|
||||
|
||||
// <instanceid, weight>
|
||||
var dic = tmp.ToDictionary(k => k.InstanceId, v => (int)v.Weight);
|
||||
|
||||
var srcInstanceIdList = dic.Keys.ToList();
|
||||
var tagInstanceIdList = new List<string>();
|
||||
|
||||
foreach (var item in srcInstanceIdList)
|
||||
{
|
||||
dic.TryGetValue(item, out var weight);
|
||||
|
||||
for (int i = 0; i < weight; i++)
|
||||
tagInstanceIdList.Add(item);
|
||||
}
|
||||
|
||||
var instanceId = string.Empty;
|
||||
|
||||
lock (obj)
|
||||
{
|
||||
if (_pos >= tagInstanceIdList.Count)
|
||||
_pos = 0;
|
||||
|
||||
instanceId = tagInstanceIdList[_pos];
|
||||
_pos++;
|
||||
}
|
||||
|
||||
var instance = list.FirstOrDefault(x => x.InstanceId.Equals(instanceId));
|
||||
|
||||
if (instance == null)
|
||||
{
|
||||
var arr = instanceId.Split("#");
|
||||
var ip = arr[0];
|
||||
int.TryParse(arr[1], out var port);
|
||||
var cluster = arr[2];
|
||||
|
||||
instance = list.First(x => x.Ip.Equals(ip) && x.Port == port && x.ClusterName.Equals(cluster));
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp-unofficial.AspNetCore</PackageId>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.AspNetCore</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
|
@ -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,17 +29,21 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="0.8.9" />
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.0" />
|
||||
<PackageReference Include="EasyCaching.InMemory" Version="0.8.9" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using EasyCaching.Core;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nacos;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class NacosServerManager : INacosServerManager
|
||||
{
|
||||
private readonly INacosNamingClient _client;
|
||||
private readonly IEasyCachingProvider _provider;
|
||||
private readonly ILBStrategy _strategy;
|
||||
|
||||
public NacosServerManager(
|
||||
INacosNamingClient client,
|
||||
IEasyCachingProviderFactory factory,
|
||||
IEnumerable<ILBStrategy> strategies,
|
||||
IOptions<NacosAspNetCoreOptions> optionsAccs)
|
||||
{
|
||||
_client = client;
|
||||
_provider = factory.GetCachingProvider("nacos.aspnetcore");
|
||||
_strategy = strategies.FirstOrDefault(x => x.Name.ToString().Equals(optionsAccs.Value.LBStrategy, StringComparison.OrdinalIgnoreCase))
|
||||
?? new WeightRandomLBStrategy();
|
||||
}
|
||||
|
||||
public async Task<string> GetServerAsync(string serviceName)
|
||||
{
|
||||
return await GetUrlAsync(serviceName, null, null, null);
|
||||
}
|
||||
|
||||
public async Task<string> GetServerAsync(string serviceName, string groupName)
|
||||
{
|
||||
return await GetUrlAsync(serviceName, groupName, null, null);
|
||||
}
|
||||
|
||||
public async Task<string> GetServerAsync(string serviceName, string groupName, string clusters)
|
||||
{
|
||||
return await GetUrlAsync(serviceName, groupName, clusters, null);
|
||||
}
|
||||
|
||||
public async Task<string> GetServerAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
return await GetUrlAsync(serviceName, groupName, clusters, namespaceId);
|
||||
}
|
||||
|
||||
public async Task<List<Host>> GetServerListAsync(string serviceName)
|
||||
{
|
||||
return await GetServerListInnerAsync(serviceName, null, null, null);
|
||||
}
|
||||
|
||||
public async Task<List<Host>> GetServerListAsync(string serviceName, string groupName)
|
||||
{
|
||||
return await GetServerListInnerAsync(serviceName, groupName, null, null);
|
||||
}
|
||||
|
||||
public async Task<List<Host>> GetServerListAsync(string serviceName, string groupName, string clusters)
|
||||
{
|
||||
return await GetServerListInnerAsync(serviceName, groupName, clusters, null);
|
||||
}
|
||||
|
||||
public async Task<List<Host>> GetServerListAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
return await GetServerListInnerAsync(serviceName, groupName, clusters, namespaceId);
|
||||
}
|
||||
|
||||
public async Task<Host> GetServerInfoAsync(string serviceName)
|
||||
{
|
||||
return await GetHostAsync(serviceName, null, null, null);
|
||||
}
|
||||
|
||||
public async Task<Host> GetServerInfoAsync(string serviceName, string groupName)
|
||||
{
|
||||
return await GetHostAsync(serviceName, groupName, null, null);
|
||||
}
|
||||
|
||||
public async Task<Host> GetServerInfoAsync(string serviceName, string groupName, string clusters)
|
||||
{
|
||||
return await GetHostAsync(serviceName, groupName, clusters, null);
|
||||
}
|
||||
|
||||
public async Task<Host> GetServerInfoAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
return await GetHostAsync(serviceName, groupName, clusters, namespaceId);
|
||||
}
|
||||
|
||||
private async Task<List<Host>> GetServerListInnerAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
var cachedKey = $"{serviceName}-{groupName}-{clusters}-{namespaceId}";
|
||||
|
||||
var cached = await _provider.GetAsync(cachedKey, async () =>
|
||||
{
|
||||
var serviceInstances = await _client.ListInstancesAsync(new ListInstancesRequest
|
||||
{
|
||||
ServiceName = serviceName,
|
||||
GroupName = groupName,
|
||||
Clusters = clusters,
|
||||
NamespaceId = namespaceId,
|
||||
HealthyOnly = true,
|
||||
});
|
||||
|
||||
if (serviceInstances?.Hosts == null || !serviceInstances.Hosts.Any())
|
||||
return null;
|
||||
return serviceInstances.Hosts.ToList();
|
||||
}, TimeSpan.FromSeconds(8));
|
||||
|
||||
return cached.HasValue ? cached.Value : null;
|
||||
}
|
||||
|
||||
private async Task<string> GetUrlAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
var list = await GetServerListInnerAsync(serviceName, groupName, clusters, namespaceId);
|
||||
|
||||
if (list != null && list.Any())
|
||||
{
|
||||
var host = _strategy.GetHost(list);
|
||||
|
||||
// it seems that nacos don't return the scheme
|
||||
// so here use http only.
|
||||
return $"http://{host.Ip}:{host.Port}";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<Host> GetHostAsync(string serviceName, string groupName, string clusters, string namespaceId)
|
||||
{
|
||||
var list = await GetServerListInnerAsync(serviceName, groupName, clusters, namespaceId);
|
||||
|
||||
if (list != null && list.Any())
|
||||
{
|
||||
var host = _strategy.GetHost(list);
|
||||
return host;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,88 +0,0 @@
|
|||
namespace Microsoft.AspNetCore.Builder
|
||||
{
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Nacos;
|
||||
using Nacos.AspNetCore;
|
||||
using System;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add Nacos AspNetCore.
|
||||
/// </summary>
|
||||
/// <param name="services">services.</param>
|
||||
/// <param name="configuration">configuration</param>
|
||||
/// <returns>IServiceCollection</returns>
|
||||
public static IServiceCollection AddNacosAspNetCore(
|
||||
this IServiceCollection services,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
services.Configure<NacosAspNetCoreOptions>(configuration.GetSection("nacos"));
|
||||
|
||||
// services.AddNacos(configuration);
|
||||
services.AddNacosNaming(configuration);
|
||||
|
||||
services.AddEasyCaching(options =>
|
||||
{
|
||||
options.UseInMemory(
|
||||
config =>
|
||||
{
|
||||
config.MaxRdSecond = 0;
|
||||
}, "nacos.aspnetcore");
|
||||
});
|
||||
|
||||
services.TryAddSingleton<INacosServerManager, NacosServerManager>();
|
||||
|
||||
// load balance strategies
|
||||
services.AddSingleton<ILBStrategy, WeightRandomLBStrategy>();
|
||||
services.AddSingleton<ILBStrategy, WeightRoundRobinLBStrategy>();
|
||||
|
||||
// IHostedService, report instance status
|
||||
services.AddHostedService<StatusReportBgTask>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Nacos AspNetCore.
|
||||
/// </summary>
|
||||
/// <param name="services">services.</param>
|
||||
/// <param name="nacosAspNetCoreOptions">nacosAspNetCoreOptions.</param>
|
||||
/// <param name="nacosOptions">nacosOptions</param>
|
||||
/// <returns>IServiceCollection</returns>
|
||||
public static IServiceCollection AddNacosAspNetCore(
|
||||
this IServiceCollection services,
|
||||
Action<NacosAspNetCoreOptions> nacosAspNetCoreOptions,
|
||||
Action<NacosOptions> nacosOptions)
|
||||
{
|
||||
services.Configure(nacosAspNetCoreOptions);
|
||||
services.AddNacosNaming(nacosOptions);
|
||||
|
||||
services.AddEasyCaching(options =>
|
||||
{
|
||||
options.UseInMemory(
|
||||
config =>
|
||||
{
|
||||
config.MaxRdSecond = 0;
|
||||
}, "nacos.aspnetcore");
|
||||
});
|
||||
|
||||
services.TryAddSingleton<INacosServerManager, NacosServerManager>();
|
||||
|
||||
// load balance strategies
|
||||
services.AddSingleton<ILBStrategy, WeightRandomLBStrategy>();
|
||||
services.AddSingleton<ILBStrategy, WeightRoundRobinLBStrategy>();
|
||||
|
||||
services.AddSingleton<ILocalConfigInfoProcessor, MemoryLocalConfigInfoProcessor>();
|
||||
services.TryAddSingleton<Nacos.Config.Http.IHttpAgent, Nacos.Config.Http.ServerHttpAgent>();
|
||||
services.AddSingleton<INacosConfigClient, NacosConfigClient>();
|
||||
|
||||
// IHostedService, report instance status
|
||||
services.AddHostedService<StatusReportBgTask>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
namespace Nacos.AspNetCore
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class StatusReportBgTask : IHostedService, IDisposable
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly INacosNamingClient _client;
|
||||
private readonly IFeatureCollection _features;
|
||||
private NacosAspNetCoreOptions _options;
|
||||
|
||||
private Timer _timer;
|
||||
private bool _reporting;
|
||||
private IEnumerable<Uri> uris = null;
|
||||
private List<SendHeartbeatRequest> beatRequests = new List<SendHeartbeatRequest>();
|
||||
|
||||
public StatusReportBgTask(
|
||||
ILoggerFactory loggerFactory,
|
||||
INacosNamingClient client,
|
||||
IServer server,
|
||||
IOptionsMonitor<NacosAspNetCoreOptions> optionsAccs)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<StatusReportBgTask>();
|
||||
_client = client;
|
||||
_options = optionsAccs.CurrentValue;
|
||||
_features = server.Features;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_options.RegisterEnabled)
|
||||
{
|
||||
_logger.LogInformation("setting RegisterEnabled to false, will not register to nacos");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
uris = UriTool.GetUri(_features, _options);
|
||||
|
||||
foreach (var uri in uris)
|
||||
{
|
||||
_logger.LogInformation("Report instance ({0}:{1}) status....", uri.Host, uri.Port);
|
||||
|
||||
var metadata = new Dictionary<string, string>()
|
||||
{
|
||||
{ PreservedMetadataKeys.REGISTER_SOURCE, "ASPNET_CORE" }
|
||||
};
|
||||
|
||||
foreach (var item in _options.Metadata)
|
||||
{
|
||||
if (!metadata.ContainsKey(item.Key))
|
||||
{
|
||||
metadata.TryAdd(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var beatRequest = new SendHeartbeatRequest
|
||||
{
|
||||
Ephemeral = true,
|
||||
ServiceName = _options.ServiceName,
|
||||
GroupName = _options.GroupName,
|
||||
BeatInfo = new BeatInfo
|
||||
{
|
||||
ip = uri.Host,
|
||||
port = uri.Port,
|
||||
serviceName = _options.ServiceName,
|
||||
scheduled = true,
|
||||
weight = _options.Weight,
|
||||
cluster = _options.ClusterName,
|
||||
metadata = metadata,
|
||||
},
|
||||
NameSpaceId = _options.Namespace
|
||||
};
|
||||
|
||||
beatRequests.Add(beatRequest);
|
||||
}
|
||||
|
||||
_timer = new Timer(
|
||||
async x =>
|
||||
{
|
||||
if (_reporting)
|
||||
{
|
||||
_logger.LogInformation($"Latest manipulation is still working ...");
|
||||
return;
|
||||
}
|
||||
|
||||
_reporting = true;
|
||||
await ReportAsync();
|
||||
_reporting = false;
|
||||
}, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task ReportAsync()
|
||||
{
|
||||
foreach (var beatRequest in beatRequests)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
try
|
||||
{
|
||||
// send heart beat will register instance
|
||||
flag = await _client.SendHeartbeatAsync(beatRequest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, $"{beatRequest.BeatInfo.ip}:{beatRequest.BeatInfo.port} Send heart beat to Nacos error");
|
||||
}
|
||||
|
||||
_logger.LogDebug("host = {0} report at {1}, status = {2}", $"{beatRequest.BeatInfo.ip}:{beatRequest.BeatInfo.port}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), flag);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_options.RegisterEnabled)
|
||||
{
|
||||
_logger.LogWarning("Unregistering from Nacos, serviceName={0}", _options.ServiceName);
|
||||
|
||||
foreach (var uri in uris)
|
||||
{
|
||||
var removeRequest = new RemoveInstanceRequest
|
||||
{
|
||||
ServiceName = _options.ServiceName,
|
||||
Ip = uri.Host,
|
||||
Port = uri.Port,
|
||||
GroupName = _options.GroupName,
|
||||
NamespaceId = _options.Namespace,
|
||||
ClusterName = _options.ClusterName,
|
||||
Ephemeral = true
|
||||
};
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogWarning("begin to remove instance, {0}", JsonConvert.SerializeObject(removeRequest));
|
||||
var flag = await _client.RemoveInstanceAsync(removeRequest);
|
||||
_logger.LogWarning("remove instance, status = {0}", flag);
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unregistering error, count = {0}", i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_timer?.Change(Timeout.Infinite, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_timer?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,145 +1,174 @@
|
|||
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, NacosAspNetCoreOptions config)
|
||||
{
|
||||
var splitChars = new char[] { ',', ';' };
|
||||
var port = config.Port <= 0 ? 80 : config.Port;
|
||||
|
||||
// 1. config
|
||||
if (!string.IsNullOrWhiteSpace(config.Ip))
|
||||
{
|
||||
// it seems that nacos don't return the scheme
|
||||
// so here use http only.
|
||||
return new List<Uri> { new Uri($"http://{config.Ip}:{port}") };
|
||||
}
|
||||
|
||||
// 1.1. Ip is null && Port has value
|
||||
if (string.IsNullOrWhiteSpace(config.Ip) && port != 80)
|
||||
{
|
||||
return new List<Uri> { new Uri($"http://{GetCurrentIp(config.PreferredNetworks)}:{port}") };
|
||||
}
|
||||
|
||||
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, config.PreferredNetworks);
|
||||
uris.Add(new Uri(url));
|
||||
}
|
||||
|
||||
return uris;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. ASPNETCORE_URLS
|
||||
address = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
|
||||
if (!string.IsNullOrWhiteSpace(address))
|
||||
{
|
||||
var url = ReplaceAddress(address, config.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, config.PreferredNetworks);
|
||||
|
||||
return url.Split(splitChars).Select(x => new Uri(x));
|
||||
}
|
||||
}
|
||||
|
||||
// 5. current ip address third
|
||||
address = $"http://{GetCurrentIp(config.PreferredNetworks)}:{port}";
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,25 @@
|
|||
namespace Nacos.AspNetCore
|
||||
namespace Nacos.AspNetCore.V2
|
||||
{
|
||||
using Nacos.V2;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class NacosAspNetCoreOptions
|
||||
public class NacosAspNetOptions : NacosSdkOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// nacos server addresses.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// http://10.1.12.123:8848,https://10.1.12.124:8848
|
||||
/// </example>
|
||||
public List<string> ServerAddresses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// default timeout, unit is Milliseconds.
|
||||
/// </summary>
|
||||
public int DefaultTimeOut { get; set; } = 15000;
|
||||
|
||||
/// <summary>
|
||||
/// default namespace
|
||||
/// </summary>
|
||||
public string Namespace { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// the name of the service.
|
||||
/// </summary>
|
||||
public string ServiceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the name of the group.
|
||||
/// </summary>
|
||||
public string GroupName { get; set; } = Nacos.V2.Common.Constants.DEFAULT_GROUP;
|
||||
|
||||
/// <summary>
|
||||
/// the name of the cluster.
|
||||
/// </summary>
|
||||
/// <value>The name of the cluster.</value>
|
||||
public string ClusterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the name of the group.
|
||||
/// </summary>
|
||||
public string GroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the weight of this instance.
|
||||
/// </summary>
|
||||
public double Weight { get; set; } = 100;
|
||||
public string ClusterName { get; set; } = Nacos.V2.Common.Constants.DEFAULT_CLUSTER_NAME;
|
||||
|
||||
/// <summary>
|
||||
/// the ip of this instance
|
||||
|
@ -59,6 +37,11 @@
|
|||
/// </summary>
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// the weight of this instance.
|
||||
/// </summary>
|
||||
public double Weight { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// if you just want to subscribe, but don't want to register your service, set it to false.
|
||||
/// </summary>
|
||||
|
@ -70,8 +53,38 @@
|
|||
public Dictionary<string, string> Metadata { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Load Balance Strategy
|
||||
/// If instance is enabled to accept request. The default value is true.
|
||||
/// </summary>
|
||||
public string LBStrategy { get; set; } = LBStrategyName.WeightRandom.ToString();
|
||||
public bool InstanceEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// If instance is ephemeral.The default value is true.
|
||||
/// </summary>
|
||||
public bool Ephemeral { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// whether your service is a https service.
|
||||
/// </summary>
|
||||
public bool Secure { get; set; } = false;
|
||||
|
||||
public System.Action<NacosSdkOptions> BuildSdkOptions()
|
||||
{
|
||||
return x =>
|
||||
{
|
||||
x.AccessKey = this.AccessKey;
|
||||
x.ConfigUseRpc = this.ConfigUseRpc;
|
||||
x.ContextPath = this.ContextPath;
|
||||
x.DefaultTimeOut = this.DefaultTimeOut;
|
||||
x.EndPoint = this.EndPoint;
|
||||
x.ListenInterval = this.ListenInterval;
|
||||
x.Namespace = this.Namespace;
|
||||
x.NamingLoadCacheAtStart = this.NamingLoadCacheAtStart;
|
||||
x.NamingUseRpc = this.NamingUseRpc;
|
||||
x.Password = this.Password;
|
||||
x.SecretKey = this.SecretKey;
|
||||
x.ServerAddresses = this.ServerAddresses;
|
||||
x.UserName = this.UserName;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
namespace Nacos.AspNetCore.V2
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nacos.V2;
|
||||
using Nacos.V2.Naming.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class RegSvcBgTask : IHostedService, IDisposable
|
||||
{
|
||||
private static readonly string MetadataNetVersion = "DOTNET_VERSION";
|
||||
private static readonly string MetadataHostOs = "HOST_OS";
|
||||
private static readonly string MetadataSecure = "secure";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly INacosNamingService _svc;
|
||||
private readonly IFeatureCollection _features;
|
||||
private NacosAspNetOptions _options;
|
||||
|
||||
private IEnumerable<Uri> uris = null;
|
||||
|
||||
public RegSvcBgTask(
|
||||
ILoggerFactory loggerFactory,
|
||||
INacosNamingService svc,
|
||||
IServer server,
|
||||
IOptionsMonitor<NacosAspNetOptions> optionsAccs)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<RegSvcBgTask>();
|
||||
_svc = svc;
|
||||
_options = optionsAccs.CurrentValue;
|
||||
_features = server.Features;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Console.WriteLine("Dispose");
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_options.RegisterEnabled)
|
||||
{
|
||||
_logger.LogInformation("setting RegisterEnabled to false, will not register to nacos");
|
||||
return;
|
||||
}
|
||||
|
||||
uris = UriTool.GetUri(_features, _options.Ip, _options.Port, _options.PreferredNetworks);
|
||||
|
||||
var metadata = new Dictionary<string, string>()
|
||||
{
|
||||
{ PreservedMetadataKeys.REGISTER_SOURCE, $"ASPNET_CORE" },
|
||||
{ MetadataNetVersion, Environment.Version.ToString() },
|
||||
{ MetadataHostOs, Environment.OSVersion.ToString() },
|
||||
};
|
||||
|
||||
if (_options.Secure) metadata[MetadataSecure] = "true";
|
||||
|
||||
foreach (var item in _options.Metadata)
|
||||
{
|
||||
if (!metadata.ContainsKey(item.Key))
|
||||
{
|
||||
metadata.TryAdd(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var uri in uris)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instance = new Nacos.V2.Naming.Dtos.Instance
|
||||
{
|
||||
Ephemeral = _options.Ephemeral,
|
||||
ServiceName = _options.ServiceName,
|
||||
ClusterName = _options.ClusterName,
|
||||
Enabled = _options.InstanceEnabled,
|
||||
Healthy = true,
|
||||
Ip = uri.Host,
|
||||
Port = uri.Port,
|
||||
Weight = _options.Weight,
|
||||
Metadata = metadata,
|
||||
InstanceId = ""
|
||||
};
|
||||
|
||||
_logger.LogInformation("register instance to nacos server, 【{0}】", instance);
|
||||
|
||||
await _svc.RegisterInstance(_options.ServiceName, _options.GroupName, instance).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "register instance error, count = {0}", i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_options.RegisterEnabled)
|
||||
{
|
||||
_logger.LogWarning("deregister instance from nacos server, serviceName={0}", _options.ServiceName);
|
||||
|
||||
foreach (var uri in uris)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogWarning("begin to remove instance");
|
||||
await _svc.DeregisterInstance(_options.ServiceName, _options.GroupName, uri.Host, uri.Port, _options.ClusterName).ConfigureAwait(false);
|
||||
_logger.LogWarning("removed instance");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "deregister instance error, count = {0}", i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
namespace Nacos.AspNetCore.V2
|
||||
{
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nacos.V2.DependencyInjection;
|
||||
using System;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add Nacos AspNet. This will register and de-register instance automatically.
|
||||
/// Mainly for nacos server 2.x
|
||||
/// </summary>
|
||||
/// <param name="services">services.</param>
|
||||
/// <param name="configuration">configuration</param>
|
||||
/// <param name="section">section, default is nacos</param>
|
||||
/// <returns>IServiceCollection</returns>
|
||||
public static IServiceCollection AddNacosAspNet(this IServiceCollection services, IConfiguration configuration, string section = "nacos")
|
||||
{
|
||||
services.Configure<NacosAspNetOptions>(configuration.GetSection(section));
|
||||
|
||||
services.AddNacosV2Naming(configuration, sectionName: section);
|
||||
|
||||
services.AddHostedService<RegSvcBgTask>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Nacos AspNet. This will register and de-register instance automatically.
|
||||
/// Mainly for nacos server 2.x
|
||||
/// </summary>
|
||||
/// <param name="services">services</param>
|
||||
/// <param name="optionsAccs">optionsAccs</param>
|
||||
/// <returns>IServiceCollection</returns>
|
||||
public static IServiceCollection AddNacosAspNet(this IServiceCollection services, Action<NacosAspNetOptions> optionsAccs)
|
||||
{
|
||||
services.Configure(optionsAccs);
|
||||
|
||||
var options = new NacosAspNetOptions();
|
||||
optionsAccs.Invoke(options);
|
||||
|
||||
services.AddNacosV2Naming(options.BuildSdkOptions());
|
||||
|
||||
services.AddHostedService<RegSvcBgTask>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using global::Microsoft.Extensions.Configuration;
|
||||
using Nacos.Config;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ConfigListener
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -20,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,16 +1,14 @@
|
|||
[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 Nacos.Config;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using global::System.Globalization;
|
||||
using global::System.IO;
|
||||
using global::System.Linq;
|
||||
using Nacos.V2;
|
||||
|
||||
internal class DefaultJsonConfigurationStringParser : INacosConfigurationParser
|
||||
{
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using Nacos.Config;
|
||||
using Nacos.Config.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class MsConfigServerHttpAgent : HttpAgent, IDisposable
|
||||
{
|
||||
private readonly NacosOptions _options;
|
||||
private readonly ServerListManager _serverListMgr;
|
||||
private readonly Nacos.Security.SecurityProxy _securityProxy;
|
||||
|
||||
private readonly string _namespaceId;
|
||||
private readonly Timer _timer;
|
||||
private long _securityInfoRefreshIntervalMills = 5000;
|
||||
|
||||
public MsConfigServerHttpAgent(NacosOptions options)
|
||||
{
|
||||
_options = options;
|
||||
_serverListMgr = new ServerListManager(_options);
|
||||
_namespaceId = _options.Namespace;
|
||||
|
||||
_serverListMgr = new ServerListManager(_options);
|
||||
_securityProxy = new Security.SecurityProxy(_options);
|
||||
|
||||
_securityProxy.LoginAsync(_serverListMgr.GetServerUrls()).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
_timer = new Timer(
|
||||
async x =>
|
||||
{
|
||||
await _securityProxy.LoginAsync(_serverListMgr.GetServerUrls());
|
||||
}, null, 0, _securityInfoRefreshIntervalMills);
|
||||
}
|
||||
|
||||
public override string AbstGetName() => _serverListMgr.GetName();
|
||||
|
||||
public override string AbstGetNamespace() => _serverListMgr.GetNamespace();
|
||||
|
||||
public override string AbstGetTenant() => _serverListMgr.GetTenant();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Console.WriteLine("ms config timer dispose");
|
||||
_timer?.Dispose();
|
||||
}
|
||||
|
||||
public override async Task<HttpResponseMessage> ReqApiAsync(HttpMethod httpMethod, string path, Dictionary<string, string> headers, Dictionary<string, string> paramValues, int timeout)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
client.Timeout = TimeSpan.FromSeconds(timeout);
|
||||
|
||||
var requestMessage = new HttpRequestMessage
|
||||
{
|
||||
Method = httpMethod
|
||||
};
|
||||
|
||||
var currentServerAddr = _serverListMgr.GetCurrentServerAddr();
|
||||
|
||||
var requestUrl = GetUrl(currentServerAddr, path);
|
||||
|
||||
InjectSecurityInfo(requestMessage, paramValues);
|
||||
|
||||
if (paramValues != null && paramValues.Any())
|
||||
{
|
||||
if (httpMethod == HttpMethod.Post)
|
||||
{
|
||||
requestMessage.RequestUri = new Uri(requestUrl);
|
||||
requestMessage.Content = new FormUrlEncodedContent(paramValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
var query = HttpAgentCommon.BuildQueryString(paramValues);
|
||||
requestMessage.RequestUri = new Uri($"{requestUrl}?{query}");
|
||||
}
|
||||
}
|
||||
|
||||
HttpAgentCommon.BuildHeader(requestMessage, headers);
|
||||
HttpAgentCommon.BuildSpasHeaders(requestMessage, paramValues, _options.AccessKey, _options.SecretKey);
|
||||
|
||||
var responseMessage = await client.SendAsync(requestMessage);
|
||||
|
||||
if (responseMessage.StatusCode == System.Net.HttpStatusCode.InternalServerError
|
||||
|| responseMessage.StatusCode == System.Net.HttpStatusCode.BadGateway
|
||||
|| responseMessage.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable)
|
||||
{
|
||||
System.Diagnostics.Trace.TraceError("[NACOS ConnectException] currentServerAddr: {0}, httpCode: {1}", _serverListMgr.GetCurrentServerAddr(), responseMessage.StatusCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
_serverListMgr.UpdateCurrentServerAddr(currentServerAddr);
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
throw new System.Net.Http.HttpRequestException($"no available server, currentServerAddr : {currentServerAddr}");
|
||||
}
|
||||
}
|
||||
|
||||
private void InjectSecurityInfo(HttpRequestMessage requestMessage, Dictionary<string, string> paramValues)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_securityProxy.GetAccessToken()))
|
||||
{
|
||||
if (!paramValues.ContainsKey(ConstValue.ACCESS_TOKEN))
|
||||
{
|
||||
paramValues.Add(ConstValue.ACCESS_TOKEN, _securityProxy.GetAccessToken());
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_namespaceId) && paramValues != null && !paramValues.ContainsKey("tenant"))
|
||||
{
|
||||
requestMessage.Headers.TryAddWithoutValidation("tenant", _namespaceId);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetUrl(string serverAddr, string relativePath)
|
||||
{
|
||||
return $"{serverAddr}{relativePath}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
namespace Nacos.Microsoft.Extensions.Configuration
|
||||
{
|
||||
using global::Microsoft.Extensions.Logging;
|
||||
using Nacos;
|
||||
using Nacos.Config.Http;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class NacosMsConfigClient : AbstNacosConfigClient
|
||||
{
|
||||
private readonly Nacos.Config.Http.IHttpAgent _httpAgent;
|
||||
private readonly ILocalConfigInfoProcessor _processor;
|
||||
|
||||
public NacosMsConfigClient(
|
||||
ILoggerFactory loggerFactory,
|
||||
NacosOptions options)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<NacosMsConfigClient>();
|
||||
_options = options;
|
||||
_processor = new FileLocalConfigInfoProcessor();
|
||||
|
||||
_httpAgent = new MsConfigServerHttpAgent(_options);
|
||||
|
||||
listeners = new List<Listener>();
|
||||
}
|
||||
|
||||
public override IHttpAgent GetAgent()
|
||||
{
|
||||
return _httpAgent;
|
||||
}
|
||||
|
||||
public override ILocalConfigInfoProcessor GetProcessor()
|
||||
{
|
||||
return _processor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
<Import Project="../../build/version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp-unofficial.Extensions.Configuration</PackageId>
|
||||
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
|
||||
<PackageId>nacos-sdk-csharp.Extensions.Configuration</PackageId>
|
||||
<VersionPrefix>$(NugetVersion)</VersionPrefix>
|
||||
<VersionSuffix></VersionSuffix>
|
||||
<Authors>nacos-sdk-csharp Contributors</Authors>
|
||||
|
@ -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,24 +25,42 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="README.md" Pack="true" Visible="false" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<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)' == '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" 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,19 +1,32 @@
|
|||
namespace Microsoft.Extensions.Configuration
|
||||
{
|
||||
using Nacos.Config;
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// Add Nacos Configuration
|
||||
/// Add Nacos Configuration that integrate with Microsoft.Extensions.Configuration
|
||||
/// </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 AddNacosConfiguration(
|
||||
this IConfigurationBuilder builder, Action<NacosConfigurationSource> action)
|
||||
public static IConfigurationBuilder AddNacosV2Configuration(
|
||||
this IConfigurationBuilder builder,
|
||||
Action<NacosV2ConfigurationSource> action,
|
||||
INacosConfigService client = null,
|
||||
ILoggerFactory loggerFactory = null,
|
||||
INacosConfigurationParser parser = null,
|
||||
Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
|
@ -25,26 +38,32 @@
|
|||
throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
var source = new NacosConfigurationSource();
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add Nacos Configuration
|
||||
/// Add Nacos Configuration that integrate with Microsoft.Extensions.Configuration
|
||||
/// </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 logAction.</param>
|
||||
/// <returns>IConfigurationBuilder</returns>
|
||||
public static IConfigurationBuilder AddNacosConfiguration(
|
||||
public static IConfigurationBuilder AddNacosV2Configuration(
|
||||
this IConfigurationBuilder builder,
|
||||
IConfiguration configuration,
|
||||
INacosConfigurationParser parser = null)
|
||||
INacosConfigService client = null,
|
||||
ILoggerFactory loggerFactory = null,
|
||||
INacosConfigurationParser parser = null,
|
||||
Action<ILoggingBuilder> logAction = null)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
|
@ -56,11 +75,79 @@
|
|||
throw new ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
var source = new NacosConfigurationSource();
|
||||
var source = new NacosV2ConfigurationSource(null, null);
|
||||
configuration.Bind(source);
|
||||
source.NacosConfigurationParser = parser ?? DefaultJsonConfigurationStringParser.Instance;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue