├── .gitignore
├── LICENSE
├── Orleans.MultiClient.sln
├── README.md
├── README.zh-cn.md
├── example
├── Orleans.Example
│ ├── Orleans.Example.csproj
│ └── Program.cs
├── Orleans.Grain
│ ├── HelloGrain.cs
│ ├── IHelloA.cs
│ └── Orleans.Grain.csproj
├── Orleans.Grain2
│ ├── HelloGrain2.cs
│ ├── IHelloB.cs
│ └── Orleans.Grain2.csproj
├── Orleans.Host
│ ├── Orleans.Host.csproj
│ └── Program.cs
└── Orleans.Host2
│ ├── Orleans.Host2.csproj
│ └── Program.cs
└── src
└── Orleans.MultiClient
├── ClusterClientBuilder.cs
├── DependencyInjection
├── GenericHostExtensions.cs
├── IMultiClientBuilder.cs
├── MultiClientBuilder.cs
├── MultiClientBuilderExtensions.cs
└── ServiceCollectionExtensions.cs
├── IClusterClientBuilder.cs
├── IClusterClientFactory.cs
├── IOrleansClient.cs
├── MultiClusterClientFactory.cs
├── Orleans.MultiClient.csproj
├── OrleansClient.cs
└── OrleansClientOptions.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *.log
81 | *.vspscc
82 | *.vssscc
83 | .builds
84 | *.pidb
85 | *.svclog
86 | *.scc
87 |
88 | # Chutzpah Test files
89 | _Chutzpah*
90 |
91 | # Visual C++ cache files
92 | ipch/
93 | *.aps
94 | *.ncb
95 | *.opendb
96 | *.opensdf
97 | *.sdf
98 | *.cachefile
99 | *.VC.db
100 | *.VC.VC.opendb
101 |
102 | # Visual Studio profiler
103 | *.psess
104 | *.vsp
105 | *.vspx
106 | *.sap
107 |
108 | # Visual Studio Trace Files
109 | *.e2e
110 |
111 | # TFS 2012 Local Workspace
112 | $tf/
113 |
114 | # Guidance Automation Toolkit
115 | *.gpState
116 |
117 | # ReSharper is a .NET coding add-in
118 | _ReSharper*/
119 | *.[Rr]e[Ss]harper
120 | *.DotSettings.user
121 |
122 | # JustCode is a .NET coding add-in
123 | .JustCode
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # The packages folder can be ignored because of Package Restore
183 | **/[Pp]ackages/*
184 | # except build/, which is used as an MSBuild target.
185 | !**/[Pp]ackages/build/
186 | # Uncomment if necessary however generally it will be regenerated when needed
187 | #!**/[Pp]ackages/repositories.config
188 | # NuGet v3's project.json files produces more ignorable files
189 | *.nuget.props
190 | *.nuget.targets
191 |
192 | # Microsoft Azure Build Output
193 | csx/
194 | *.build.csdef
195 |
196 | # Microsoft Azure Emulator
197 | ecf/
198 | rcf/
199 |
200 | # Windows Store app package directories and files
201 | AppPackages/
202 | BundleArtifacts/
203 | Package.StoreAssociation.xml
204 | _pkginfo.txt
205 | *.appx
206 |
207 | # Visual Studio cache files
208 | # files ending in .cache can be ignored
209 | *.[Cc]ache
210 | # but keep track of directories ending in .cache
211 | !*.[Cc]ache/
212 |
213 | # Others
214 | ClientBin/
215 | ~$*
216 | *~
217 | *.dbmdl
218 | *.dbproj.schemaview
219 | *.jfm
220 | *.pfx
221 | *.publishsettings
222 | orleans.codegen.cs
223 |
224 | # Including strong name files can present a security risk
225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
226 | #*.snk
227 |
228 | # Since there are multiple workflows, uncomment next line to ignore bower_components
229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
230 | #bower_components/
231 |
232 | # RIA/Silverlight projects
233 | Generated_Code/
234 |
235 | # Backup & report files from converting an old project file
236 | # to a newer Visual Studio version. Backup files are not needed,
237 | # because we have git ;-)
238 | _UpgradeReport_Files/
239 | Backup*/
240 | UpgradeLog*.XML
241 | UpgradeLog*.htm
242 | ServiceFabricBackup/
243 | *.rptproj.bak
244 |
245 | # SQL Server files
246 | *.mdf
247 | *.ldf
248 | *.ndf
249 |
250 | # Business Intelligence projects
251 | *.rdl.data
252 | *.bim.layout
253 | *.bim_*.settings
254 | *.rptproj.rsuser
255 |
256 | # Microsoft Fakes
257 | FakesAssemblies/
258 |
259 | # GhostDoc plugin setting file
260 | *.GhostDoc.xml
261 |
262 | # Node.js Tools for Visual Studio
263 | .ntvs_analysis.dat
264 | node_modules/
265 |
266 | # Visual Studio 6 build log
267 | *.plg
268 |
269 | # Visual Studio 6 workspace options file
270 | *.opt
271 |
272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
273 | *.vbw
274 |
275 | # Visual Studio LightSwitch build output
276 | **/*.HTMLClient/GeneratedArtifacts
277 | **/*.DesktopClient/GeneratedArtifacts
278 | **/*.DesktopClient/ModelManifest.xml
279 | **/*.Server/GeneratedArtifacts
280 | **/*.Server/ModelManifest.xml
281 | _Pvt_Extensions
282 |
283 | # Paket dependency manager
284 | .paket/paket.exe
285 | paket-files/
286 |
287 | # FAKE - F# Make
288 | .fake/
289 |
290 | # JetBrains Rider
291 | .idea/
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/**
303 | # !tools/packages.config
304 |
305 | # Tabs Studio
306 | *.tss
307 |
308 | # Telerik's JustMock configuration file
309 | *.jmconfig
310 |
311 | # BizTalk build output
312 | *.btp.cs
313 | *.btm.cs
314 | *.odx.cs
315 | *.xsd.cs
316 |
317 | # OpenCover UI analysis results
318 | OpenCover/
319 |
320 | # Azure Stream Analytics local run output
321 | ASALocalRun/
322 |
323 | # MSBuild Binary and Structured Log
324 | *.binlog
325 |
326 | # NVidia Nsight GPU debugger configuration file
327 | *.nvuser
328 |
329 | # MFractors (Xamarin productivity tool) working folder
330 | .mfractor/
331 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 阿凌
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Orleans.MultiClient.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29111.141
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.MultiClient", "src\Orleans.MultiClient\Orleans.MultiClient.csproj", "{04493B45-81E5-49F8-9CD5-914D52864704}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{92788A18-295E-4D97-9716-7F6EA6AC8BE4}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "example", "example", "{A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Example", "example\Orleans.Example\Orleans.Example.csproj", "{C7571F58-0AD4-41C5-8072-4CA07FB5EB32}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Host", "example\Orleans.Host\Orleans.Host.csproj", "{27E47CD2-6AD7-442D-B94E-B33B196C48A1}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Grain", "example\Orleans.Grain\Orleans.Grain.csproj", "{B540D7B0-3565-4F18-AA2B-290367EC571A}"
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Grain2", "example\Orleans.Grain2\Orleans.Grain2.csproj", "{D7D98B51-5B86-4C45-BF31-27A48B4D99E9}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orleans.Host2", "example\Orleans.Host2\Orleans.Host2.csproj", "{2CBDD05F-C056-4EED-9167-5110EABB893D}"
21 | EndProject
22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7CB5FF92-9B8A-4F55-934F-32A87680731D}"
23 | ProjectSection(SolutionItems) = preProject
24 | .gitignore = .gitignore
25 | LICENSE = LICENSE
26 | README.md = README.md
27 | EndProjectSection
28 | EndProject
29 | Global
30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
31 | Debug|Any CPU = Debug|Any CPU
32 | Release|Any CPU = Release|Any CPU
33 | EndGlobalSection
34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
35 | {04493B45-81E5-49F8-9CD5-914D52864704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {04493B45-81E5-49F8-9CD5-914D52864704}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {04493B45-81E5-49F8-9CD5-914D52864704}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {04493B45-81E5-49F8-9CD5-914D52864704}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {C7571F58-0AD4-41C5-8072-4CA07FB5EB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {C7571F58-0AD4-41C5-8072-4CA07FB5EB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {C7571F58-0AD4-41C5-8072-4CA07FB5EB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {C7571F58-0AD4-41C5-8072-4CA07FB5EB32}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {27E47CD2-6AD7-442D-B94E-B33B196C48A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {27E47CD2-6AD7-442D-B94E-B33B196C48A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {27E47CD2-6AD7-442D-B94E-B33B196C48A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {27E47CD2-6AD7-442D-B94E-B33B196C48A1}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {B540D7B0-3565-4F18-AA2B-290367EC571A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {B540D7B0-3565-4F18-AA2B-290367EC571A}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {B540D7B0-3565-4F18-AA2B-290367EC571A}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {B540D7B0-3565-4F18-AA2B-290367EC571A}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {D7D98B51-5B86-4C45-BF31-27A48B4D99E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {D7D98B51-5B86-4C45-BF31-27A48B4D99E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {D7D98B51-5B86-4C45-BF31-27A48B4D99E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {D7D98B51-5B86-4C45-BF31-27A48B4D99E9}.Release|Any CPU.Build.0 = Release|Any CPU
55 | {2CBDD05F-C056-4EED-9167-5110EABB893D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {2CBDD05F-C056-4EED-9167-5110EABB893D}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {2CBDD05F-C056-4EED-9167-5110EABB893D}.Release|Any CPU.ActiveCfg = Release|Any CPU
58 | {2CBDD05F-C056-4EED-9167-5110EABB893D}.Release|Any CPU.Build.0 = Release|Any CPU
59 | EndGlobalSection
60 | GlobalSection(SolutionProperties) = preSolution
61 | HideSolutionNode = FALSE
62 | EndGlobalSection
63 | GlobalSection(NestedProjects) = preSolution
64 | {04493B45-81E5-49F8-9CD5-914D52864704} = {92788A18-295E-4D97-9716-7F6EA6AC8BE4}
65 | {C7571F58-0AD4-41C5-8072-4CA07FB5EB32} = {A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}
66 | {27E47CD2-6AD7-442D-B94E-B33B196C48A1} = {A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}
67 | {B540D7B0-3565-4F18-AA2B-290367EC571A} = {A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}
68 | {D7D98B51-5B86-4C45-BF31-27A48B4D99E9} = {A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}
69 | {2CBDD05F-C056-4EED-9167-5110EABB893D} = {A9738E2A-0CAD-4ABA-A368-4ABDB56A6E0C}
70 | EndGlobalSection
71 | GlobalSection(ExtensibilityGlobals) = postSolution
72 | SolutionGuid = {A5C5EA71-8A8F-4295-ABA5-C990415CE4E1}
73 | EndGlobalSection
74 | EndGlobal
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Orleans MultiClient [中文](https://github.com/lfzm/Orleans.MultiClient/blob/master/README.zh-cn.md)
2 |
3 |
4 | [](http://www.nuget.org/packages/Orleans.MultiClient)
5 | [](https://raw.githubusercontent.com/dotnetcore/CAP/master/LICENSE.txt)
6 |
7 |
8 | `Orleans.MultiClient` is an Orleans multi-client, with simple configuration you can easily connect to Orleans Slio.
9 | `Orleans.MultiClient` can connect to many different Orleans Slio, Orleans.MultiClient Orleans Grain automatically finds Orleans clients upon request.
10 |
11 | *Note:Orleans.MultiClient only supports .NET Core platform.*
12 |
13 | ## Getting Started
14 |
15 | ### NuGet
16 |
17 | ```
18 | PM> dotnet add package Orleans.MultiClient
19 | ```
20 |
21 | ### Simple example
22 |
23 | A simple example demonstrates how Orleans.MultiClient connects to two different services (A, B).
24 |
25 | *Note:The source code for the [simple example](https://github.com/lfzm/Orleans.MultiClient/tree/master/example) is in the example folder in the Github repository*
26 |
27 |
28 | 1、Add the Grain interface package of A and B to the project of Orleans Client
29 |
30 | ```
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | 2、Configure Orleans.MultiClient and inject Orleans.MultiClient into `IServiceCollection`。
42 |
43 |
44 | ```CSharp
45 | services.AddOrleansMultiClient(build =>
46 | {
47 | build.AddClient(opt =>
48 | {
49 | opt.ServiceId = "A";
50 | opt.ClusterId = "AApp";
51 | opt.SetServiceAssembly(typeof(IHelloA).Assembly);
52 | opt.Configure = (b =>
53 | {
54 | b.UseLocalhostClustering(gatewayPort: 30000);
55 | });
56 | });
57 | build.AddClient(opt =>
58 | {
59 | opt.ServiceId = "B";
60 | opt.ClusterId = "BApp";
61 | opt.SetServiceAssembly(typeof(IHelloB).Assembly);
62 | opt.Configure = (b =>
63 | {
64 | b.UseLocalhostClustering(gatewayPort: 30001);
65 | });
66 | });
67 | });
68 | ```
69 |
70 | 3、Request A Slio and B Slio separately
71 |
72 | *Note: Before requesting, A Slio and B Slio need to be started, otherwise the request will fail.*
73 |
74 | ```CSharp
75 | // Request A Slio.
76 | var serviceA = _serviceProvider.GetRequiredService().GetGrain(1);
77 | var resultA = serviceA.SayHello("Hello World Success GrainA").GetAwaiter().GetResult();
78 |
79 | // Request B Slio.
80 | var serviceB = _serviceProvider.GetRequiredService().GetGrain(1);
81 | var resultB = serviceB.SayHello("Hello World Success GrainB").GetAwaiter().GetResult();
82 |
83 | ```
84 |
85 |
86 | ## Configuration
87 |
88 | `AddOrleansMultiClient` method supports IServiceCollection and GenericHost configuration.
89 |
90 |
91 | ### Configure Orleans Slio connection
92 |
93 |
94 | Configure connectivity for a single Orleans Slio.
95 |
96 | ``` CSharp
97 | services.AddOrleansMultiClient(build =>
98 | {
99 | build.AddClient(opt =>
100 | {
101 | opt.ServiceId = "A";
102 | opt.ClusterId = "AApp";
103 | opt.SetServiceAssembly(typeof(IHelloA).Assembly);
104 | opt.Configure = (b =>
105 | {
106 | b.UseLocalhostClustering(gatewayPort: 30000);
107 | // b.UseStaticClustering(...);
108 | // b.UseConsulClustering(...); // Configure Consul
109 | // b.UseKubeGatewayListProvider(); // Configure Kubernetes
110 | // b.UseAdoNetClustering(...); // Configure MySql and SQLServer
111 | });
112 | });
113 | }
114 | ```
115 |
116 | Global configuration, common to all clients
117 |
118 | ```CSharp
119 | services.AddOrleansMultiClient(build =>{
120 | build.Configure(b =>{
121 | b.UseConsulClustering(...);
122 | // b.UseKubeGatewayListProvider(); // Configure Kubernetes
123 | // b.UseAdoNetClustering(...); // Configure MySql and SQLServer
124 | });
125 | build.AddClient(opt =>
126 | {
127 | opt.ServiceId = "A";
128 | opt.ClusterId = "AApp";
129 | opt.SetServiceAssembly(typeof(IHelloA).Assembly);
130 | }
131 | }
132 | ```
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/README.zh-cn.md:
--------------------------------------------------------------------------------
1 | # Orleans MultiClient [English](https://github.com/lfzm/Orleans.MultiClient/blob/master/README.md)
2 |
3 |
4 |
5 | [](http://www.nuget.org/packages/Orleans.MultiClient)
6 | [](https://raw.githubusercontent.com/dotnetcore/CAP/master/LICENSE.txt)
7 |
8 | ## 介绍
9 | `Orleans.MultiClient` 是一个 Orleans 复合客户端,只需要简单配置就可以简单高效连接和请求 Orleans 服务。
10 |
11 | `Orleans.MultiClient` 可以轻松连接多个不同服务的 Orleans 服务,在请求 Orleans 时会根据请求的接口自动寻找 Orleans 客户端,使用者无需关心底层的实现。
12 |
13 | `Orleans.MultiClient` 的开源地址和 `Demo` 可以在 `GitHub` 源代码下载查看。
14 | > https://github.com/AClumsy/Orleans.MultiClient/
15 |
16 | ## 使用
17 |
18 | 从 `NuGet` 下载 `Orleans.MultiClient` 包。
19 |
20 | ```
21 | dotnet add package Orleans.MultiClient
22 | ```
23 |
24 | ### 简单例子
25 | 如果有一个服务需要同时调用 `A` 和 `B` 两个 `Orleans` 服务,看一看 `Orleans.MultiClient` 是怎么更简单的调用 Orleans 服务的。
26 |
27 | 第一步:先引用 `Orleans.MultiClient` 包和 `A`、`B` 的接口,分别为 `IHelloA`、 `IHelloB`
28 |
29 | 第二步:需要把 `Orleans.MultiClient` 注入到 `DI 容器` 中,并且配置添加两个 Orleans Client。
30 |
31 | *提示:`Orleans.MultiClient` 暂时只支持 `.NET Core` 平台上面使用。*
32 | ```CSharp
33 | services.AddOrleansMultiClient(build =>
34 | {
35 | build.AddClient(opt =>
36 | {
37 | opt.ServiceId = "A";
38 | opt.ClusterId = "AApp";
39 | opt.SetServiceAssembly(typeof(IHelloA).Assembly);
40 | opt.Configure = (b =>
41 | {
42 | b.UseLocalhostClustering();
43 | });
44 | });
45 | build.AddClient(opt =>
46 | {
47 | opt.ServiceId = "B";
48 | opt.ClusterId = "BApp";
49 | opt.SetServiceAssembly(typeof(IHelloB).Assembly);
50 | opt.Configure = (b =>
51 | {
52 | b.UseLocalhostClustering(gatewayPort: 30001);
53 | });
54 | });
55 | });
56 | ```
57 | 第二步:开始调用对应的 Orleans 服务。
58 | `IOrleansClient` 是 `Orleans.MultiClient` 的复合客户端,通过 `IOrleansClient` 调用 Orleans 服务。
59 | ```CSharp
60 | // 调用 A 服务。
61 | var serviceA = _serviceProvider.GetRequiredService().GetGrain(1);
62 | var resultA = serviceA.SayHello("Hello World Success GrainA").GetAwaiter().GetResult();
63 |
64 | // 调用 B 服务。
65 | var serviceB = _serviceProvider.GetRequiredService().GetGrain(1);
66 | var resultB = serviceB.SayHello("Hello World Success GrainB").GetAwaiter().GetResult();
67 | ```
68 | 简单吧,只要配置好客户端之后,在使用的过程中,无需管怎么连接 `Orleans` ,只要通过依赖注入得到 `IOrleansClient` 就可以轻松的请求 Orleans 服务。
69 |
70 | ## 配置
71 | ### **注入到 DI 容器**
72 |
73 | **`AddOrleansMultiClient`** :把 `Orleans.MultiClient` 注入到 `DI 容器` 中,使用时需要通过依赖注入得到 `IOrleansClient` 。
74 |
75 | ### **添加多个 Client**
76 | **`AddClient`**: 添加多个 Orleans 客户客户端,添加客户端时需要配置 Orleans 相关选项。 `Orleans.MultiClient` 提供了函数和 `IConfiguration` 两种方式进行配置。
77 | 使用 `IConfiguration` 进行配置时需要注意配置文件的内容必须是 `IList` 类型的。
78 |
79 | ```CSharp
80 | services.AddOrleansMultiClient(build =>
81 | {
82 | build.AddClient((OrleansClientOptions opt) =>{
83 | ...// OrleansClientOptions 配置
84 | }
85 | });
86 | ```
87 | ### **全局 Orleans 服务配置**
88 | **`Configure`**:如果所有的 Orleans 的连接配置是一样的情况下,可以配置全局的 Orleans 服务配置。
89 | 比如:如果所有的 Orleans Silo 都是通过 `Consul` 进行服务发现的,就可以配置一个全局配置。
90 | ```CSharp
91 | services.AddOrleansMultiClient(build =>{
92 | build.Configure(b =>{
93 | b.UseConsulClustering(o =>{
94 | o.Address = new Uri("https://127.0.0.1:8500");
95 | });
96 | });
97 | }
98 | ```
99 |
100 | #### **OrleansClientOptions 配置**
101 | * **`ServiceList`**:用于在 `IOrleansClient` 调用接口时和 Orleans 连接配置建立关联。ServiceList 的值时 Orleans Silo 接口的 `Assembly.FullName`, 由于 Orleans Silo 可能有多个接口,所以 ServiceList 是一个数组集合。可以通过 `SetServiceAssembly` 方法来配置 ServiceList。
102 |
103 | * **`ServiceId`**:Orleans Silo 的 ServiceId,在连接 Orleans 时需要。
104 |
105 | * **`ClusterId`**:Orleans Silo 的 ClusterId,在连接 Orleans 时需要。
106 |
107 | * **`Configure`**:Orleans 服务配置,如连接组件(`Consul`、`Zookeeperr`、等)。如果配置了 `全局 Orleans 服务配置` 这个选项可以不配置,但是这选项配置之后会覆盖上面的 `全局 Orleans 服务配置`。
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/example/Orleans.Example/Orleans.Example.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/Orleans.Example/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Orleans.Grains;
3 | using Orleans.Grains2;
4 | using Orleans.Hosting;
5 | using System;
6 |
7 | namespace Orleans.Example
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | Console.WriteLine("Enter btn start");
14 | Console.ReadKey();
15 | IServiceCollection services = new ServiceCollection();
16 | services.AddLogging();
17 | services.AddOrleansMultiClient(build =>
18 | {
19 | build.AddClient(opt =>
20 | {
21 | opt.ServiceId = "A";
22 | opt.ClusterId = "AApp";
23 | opt.SetServiceAssembly(typeof(IHelloA).Assembly);
24 | opt.Configure = (b =>
25 | {
26 | b.UseLocalhostClustering();
27 | });
28 | });
29 | build.AddClient(opt =>
30 | {
31 | opt.ServiceId = "B";
32 | opt.ClusterId = "BApp";
33 | opt.SetServiceAssembly(typeof(IHelloB).Assembly);
34 | opt.Configure = (b =>
35 | {
36 | b.UseLocalhostClustering(gatewayPort: 30001);
37 | });
38 | });
39 | });
40 |
41 | var sp = services.BuildServiceProvider();
42 |
43 | var service = sp.GetRequiredService().GetGrain(1);
44 | var result1 = service.SayHello("Hello World Success Grain1").GetAwaiter().GetResult();
45 |
46 |
47 | var serviceA = sp.GetRequiredService().GetClusterClient(typeof(IHelloA).Assembly) .GetGrain(1);
48 | var resultA1 = serviceA.SayHello("Hello World Success GrainA").GetAwaiter().GetResult();
49 |
50 |
51 | var service2 = sp.GetRequiredService().GetGrain(1);
52 | var result2 = service2.SayHello("Hello World Success Grain2").GetAwaiter().GetResult();
53 | Console.WriteLine("dev1:" + result1);
54 | Console.WriteLine("dev2:" + result2);
55 |
56 | Console.ReadKey();
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/example/Orleans.Grain/HelloGrain.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Orleans.Grains
8 | {
9 | ///
10 | /// Orleans grain implementation class HelloGrain.
11 | ///
12 | public class HelloGrain : Grain, IHelloA
13 | {
14 | private readonly ILogger logger;
15 |
16 | public HelloGrain(ILogger logger)
17 | {
18 | this.logger = logger;
19 | }
20 |
21 | public Task SayHello(string greeting)
22 | {
23 | logger.LogInformation($"SayHello message received: greeting = '{greeting}'");
24 | return Task.FromResult($"You said: '{greeting}', I say: Hello!");
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/Orleans.Grain/IHelloA.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 |
6 | namespace Orleans.Grains
7 | {
8 | ///
9 | /// Orleans grain communication interface IHello
10 | ///
11 | public interface IHelloA : Orleans.IGrainWithIntegerKey
12 | {
13 | Task SayHello(string greeting);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/Orleans.Grain/Orleans.Grain.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/example/Orleans.Grain2/HelloGrain2.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Orleans.Grains2
8 | {
9 | ///
10 | /// Orleans grain implementation class HelloGrain.
11 | ///
12 | public class HelloGrain2 : Grain, IHelloB
13 | {
14 | private readonly ILogger logger;
15 |
16 | public HelloGrain2(ILogger logger)
17 | {
18 | this.logger = logger;
19 | }
20 |
21 | public Task SayHello(string greeting)
22 | {
23 | logger.LogInformation($"SayHello message received: greeting = '{greeting}'");
24 | return Task.FromResult($"You said: '{greeting}', I say: Hello!");
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/Orleans.Grain2/IHelloB.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.Threading.Tasks;
5 |
6 | namespace Orleans.Grains2
7 | {
8 | ///
9 | /// Orleans grain communication interface IHello
10 | ///
11 | public interface IHelloB : Orleans.IGrainWithIntegerKey
12 | {
13 | Task SayHello(string greeting);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/Orleans.Grain2/Orleans.Grain2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/example/Orleans.Host/Orleans.Host.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/example/Orleans.Host/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Orleans.Configuration;
3 | using Orleans.Grains;
4 | using Orleans.Hosting;
5 | using System;
6 | using System.Net;
7 | using System.Threading.Tasks;
8 |
9 | namespace Orleans.Host
10 | {
11 | public class Program
12 | {
13 | public static int Main(string[] args)
14 | {
15 | return RunMainAsync().Result;
16 | }
17 |
18 | private static async Task RunMainAsync()
19 | {
20 | try
21 | {
22 | var host = await StartSilo();
23 | Console.WriteLine("Press Enter to terminate...");
24 | Console.ReadLine();
25 |
26 | await host.StopAsync();
27 |
28 | return 0;
29 | }
30 | catch (Exception ex)
31 | {
32 | Console.WriteLine(ex);
33 | return 1;
34 | }
35 | }
36 |
37 | private static async Task StartSilo()
38 | {
39 | // define the cluster configuration
40 | var builder = new SiloHostBuilder()
41 | .UseLocalhostClustering()
42 | .Configure(options =>
43 | {
44 | options.ClusterId = "A";
45 | options.ServiceId = "AApp";
46 | })
47 | .Configure(options => options.AdvertisedIPAddress = IPAddress.Loopback)
48 | .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(HelloGrain).Assembly).WithReferences())
49 | .ConfigureLogging(logging => logging.AddConsole());
50 |
51 | var host = builder.Build();
52 | await host.StartAsync();
53 | return host;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/example/Orleans.Host2/Orleans.Host2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/example/Orleans.Host2/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Orleans.Configuration;
3 | using Orleans.Grains2;
4 | using Orleans.Hosting;
5 | using System;
6 | using System.Net;
7 | using System.Threading.Tasks;
8 | namespace Orleans.Host2
9 | {
10 | public class Program
11 | {
12 | public static int Main(string[] args)
13 | {
14 | return RunMainAsync().Result;
15 | }
16 |
17 | private static async Task RunMainAsync()
18 | {
19 | try
20 | {
21 | var host = await StartSilo();
22 | Console.WriteLine("Press Enter to terminate...");
23 | Console.ReadLine();
24 |
25 | await host.StopAsync();
26 |
27 | return 0;
28 | }
29 | catch (Exception ex)
30 | {
31 | Console.WriteLine(ex);
32 | return 1;
33 | }
34 | }
35 |
36 | private static async Task StartSilo()
37 | {
38 | // define the cluster configuration
39 | var builder = new SiloHostBuilder()
40 | .UseLocalhostClustering(siloPort:11112,gatewayPort:30001)
41 | .Configure(options =>
42 | {
43 | options.ClusterId = "B";
44 | options.ServiceId = "BApp";
45 | })
46 | .Configure(options => options.AdvertisedIPAddress = IPAddress.Loopback)
47 | .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(HelloGrain2).Assembly).WithReferences())
48 | .ConfigureLogging(logging => logging.AddConsole());
49 |
50 | var host = builder.Build();
51 | await host.StartAsync();
52 | return host;
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/ClusterClientBuilder.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Logging;
3 | using Orleans.Configuration;
4 | using Orleans.Runtime;
5 | using System;
6 | using System.Threading.Tasks;
7 |
8 | namespace Orleans.MultiClient
9 | {
10 | public class ClusterClientBuilder : IClusterClientBuilder
11 | {
12 | private readonly OrleansClientOptions _options;
13 | private readonly ILogger _logger;
14 | private readonly string _serviceName;
15 |
16 | public ClusterClientBuilder(IServiceProvider serviceProvider, OrleansClientOptions options,string serviceName)
17 | {
18 | this._logger = serviceProvider.GetRequiredService>();
19 | this._options = options;
20 | this._serviceName = serviceName;
21 | }
22 | public IClusterClient Build()
23 | {
24 | IClientBuilder build = new ClientBuilder();
25 | if (_options.Configure == null)
26 | {
27 | _logger.LogError($"{_serviceName} There is no way to connect to Orleans, please configure it in OrleansClientOptions.Configure");
28 | }
29 | _options.Configure(build);
30 | build.Configure(opt =>
31 | {
32 | if (!string.IsNullOrEmpty(_options.ClusterId))
33 | opt.ClusterId = _options.ClusterId;
34 | if (!string.IsNullOrEmpty(_options.ServiceId))
35 | opt.ServiceId = _options.ServiceId;
36 | });
37 |
38 | var client = build.Build();
39 | return this.ConnectClient(_serviceName, client);
40 | }
41 |
42 | private IClusterClient ConnectClient(string serviceName, IClusterClient client)
43 | {
44 | try
45 | {
46 | var res = client.Connect(RetryFilter).Wait(TimeSpan.FromSeconds(10));
47 | if (!res)
48 | {
49 | throw new Exception($"Connection {serviceName} timeout...");
50 | }
51 | _logger.LogDebug($"Connection {serviceName} Sucess...");
52 | return client;
53 | }
54 | catch (Exception ex)
55 | {
56 | throw new Exception($"Connection {serviceName} Faile...", ex);
57 | }
58 | }
59 |
60 | private int attempt = 0;
61 | private async Task RetryFilter(Exception exception)
62 | {
63 | if (exception.GetType() != typeof(SiloUnavailableException))
64 | {
65 | _logger.LogError(exception,$"Cluster client failed to connect to cluster with unexpected error. ");
66 | return false;
67 | }
68 | attempt++;
69 | _logger.LogError(exception,$"Cluster client attempt {attempt} of {10} failed to connect to cluster.");
70 | if (attempt > 10)
71 | {
72 | return false;
73 | }
74 | await Task.Delay(TimeSpan.FromSeconds(4));
75 | return true;
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/DependencyInjection/GenericHostExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Orleans.MultiClient.DependencyInjection;
3 | using System;
4 |
5 | namespace Microsoft.Extensions.Hosting
6 | {
7 | public static class GenericHostExtensions
8 | {
9 | public static IHostBuilder UseOrleansMultiClient(this IHostBuilder hostBuilder, Action startup)
10 | {
11 | hostBuilder.ConfigureServices((context, service) => service.AddOrleansMultiClient(startup));
12 | return hostBuilder;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/DependencyInjection/IMultiClientBuilder.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | namespace Orleans.MultiClient.DependencyInjection
6 | {
7 | public interface IMultiClientBuilder
8 | {
9 | IServiceCollection Services { get; }
10 |
11 | Action OrleansConfigure { get; set; }
12 | IList ClientOptions { get; set; }
13 | void Build();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/DependencyInjection/MultiClientBuilder.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Orleans.Runtime;
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace Orleans.MultiClient.DependencyInjection
7 | {
8 | public class MultiClientBuilder : IMultiClientBuilder
9 | {
10 | public IServiceCollection Services { get; private set; }
11 | public Action OrleansConfigure { get; set; }
12 | public IList ClientOptions { get; set; } = new List();
13 | public MultiClientBuilder(IServiceCollection services)
14 | {
15 | this.Services = services;
16 | }
17 | public void Build()
18 | {
19 | if (this.ClientOptions.Count <= 0)
20 | {
21 | throw new ArgumentNullException($"Please add silo via MultiClientBuilderExtensions.AddClient");
22 | }
23 | foreach (var client in this.ClientOptions)
24 | {
25 | if (client.Configure == null)
26 | client.Configure = this.OrleansConfigure;
27 | if (client.ServiceList.Count == 0)
28 | throw new ArgumentNullException($"Request to go to the configuration OrleansClientOptions.SetServiceAssembly Orleans interface");
29 | foreach (var serviceName in client.ServiceList)
30 | {
31 | //if (!client.ExistAssembly(serviceName))
32 | // throw new ArgumentNullException($"{serviceName} service does not exist in the assembly");
33 |
34 | Services.AddSingletonNamedService(serviceName, (sp, key) =>
35 | {
36 | return new ClusterClientBuilder(sp, client, key);
37 | });
38 | }
39 | }
40 |
41 | this.Services.AddSingleton(typeof(IKeyedServiceCollection<,>), typeof(KeyedServiceCollection<,>));
42 | this.Services.AddSingleton();
43 | this.Services.AddSingleton();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/DependencyInjection/MultiClientBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Orleans;
3 | using Orleans.MultiClient;
4 | using Orleans.MultiClient.DependencyInjection;
5 | using Orleans.Runtime;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Reflection;
9 |
10 | namespace Microsoft.Extensions.DependencyInjection
11 | {
12 | public static class MultiClientBuilderExtensions
13 | {
14 | public static IMultiClientBuilder AddClient(this IMultiClientBuilder builder, Action startup)
15 | {
16 | OrleansClientOptions options = new OrleansClientOptions();
17 | startup.Invoke(options);
18 | return builder.AddClient(options);
19 | }
20 | public static IMultiClientBuilder AddClient(this IMultiClientBuilder builder, OrleansClientOptions options)
21 | {
22 |
23 | builder.ClientOptions.Add(options);
24 |
25 |
26 | return builder;
27 | }
28 | public static IMultiClientBuilder AddClient(this IMultiClientBuilder builder, IConfiguration config)
29 | {
30 | var optionList = config.Get>();
31 | foreach (var options in optionList)
32 | {
33 | builder.AddClient(options);
34 | }
35 | return builder;
36 | }
37 | public static IMultiClientBuilder Configure(this IMultiClientBuilder builder, Action OrleansConfigure)
38 | {
39 | builder.OrleansConfigure = OrleansConfigure;
40 | return builder;
41 | }
42 |
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/DependencyInjection/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Orleans.MultiClient.DependencyInjection;
2 | using System;
3 |
4 | namespace Microsoft.Extensions.DependencyInjection
5 | {
6 | public static class ServiceCollectionExtensions
7 | {
8 | public static IServiceCollection AddOrleansMultiClient(this IServiceCollection services, Action startup)
9 | {
10 | var build = new MultiClientBuilder(services);
11 | startup.Invoke(build);
12 | build.Build();
13 | return services;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/IClusterClientBuilder.cs:
--------------------------------------------------------------------------------
1 | namespace Orleans.MultiClient
2 | {
3 | public interface IClusterClientBuilder
4 | {
5 | IClusterClient Build();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/IClusterClientFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 |
4 | namespace Orleans.MultiClient
5 | {
6 | public interface IClusterClientFactory
7 | {
8 | IGrainFactory Create();
9 |
10 | IGrainFactory Create(Type type);
11 |
12 | IGrainFactory Create(Assembly assembly);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/IOrleansClient.cs:
--------------------------------------------------------------------------------
1 | using Orleans.Runtime;
2 | using Orleans.Streams;
3 | using System;
4 | using System.Reflection;
5 | using System.Threading.Tasks;
6 |
7 | namespace Orleans
8 | {
9 | ///
10 | /// Orleans Client
11 | ///
12 | public interface IOrleansClient
13 | {
14 | ///
15 | /// get stream provider
16 | ///
17 | /// Assembly of silo interface
18 | /// stream provider name
19 | ///
20 | IStreamProvider GetStreamProvider(Assembly assembly, string name);
21 | ///
22 | /// get
23 | ///
24 | /// Assembly of silo interface
25 | ///
26 | IClusterClient GetClusterClient(Assembly assembly);
27 | void BindGrainReference(Assembly assembly, IAddressable grain);
28 | Task CreateObjectReference(IGrainObserver obj) where TGrainObserverInterface : IGrainObserver;
29 | Task DeleteObjectReference(IGrainObserver obj) where TGrainObserverInterface : IGrainObserver;
30 | TGrainInterface GetGrain(Guid primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithGuidKey;
31 | TGrainInterface GetGrain(long primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithIntegerKey;
32 | TGrainInterface GetGrain(string primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithStringKey;
33 | TGrainInterface GetGrain(Guid primaryKey, string keyExtension, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithGuidCompoundKey;
34 | TGrainInterface GetGrain(long primaryKey, string keyExtension, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithIntegerCompoundKey;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/MultiClusterClientFactory.cs:
--------------------------------------------------------------------------------
1 | using Orleans.Runtime;
2 | using System;
3 | using System.Collections.Concurrent;
4 | using System.Reflection;
5 |
6 | namespace Orleans.MultiClient
7 | {
8 | public class MultiClusterClientFactory : IClusterClientFactory
9 | {
10 | private readonly ConcurrentDictionary clusterClientCache = new ConcurrentDictionary();
11 | private readonly IServiceProvider _serviceProvider;
12 | public MultiClusterClientFactory(IServiceProvider serviceProvider)
13 | {
14 | _serviceProvider = serviceProvider;
15 | }
16 |
17 | public IGrainFactory Create()
18 | {
19 | return this.Create(typeof(TGrainInterface).Assembly);
20 | }
21 |
22 | public IGrainFactory Create(Type type)
23 | {
24 | return this.Create(type.Assembly);
25 | }
26 |
27 | public IGrainFactory Create(Assembly assembly)
28 | {
29 | var name = assembly.FullName;
30 | return clusterClientCache.GetOrAdd(name, (key) =>
31 | {
32 | IClusterClient client = this._serviceProvider.GetRequiredServiceByName(key).Build();
33 | if (client.IsInitialized)
34 | {
35 | return client;
36 | }
37 | else
38 | {
39 | throw new Exception("Can not initialized clusterClient");
40 | }
41 | });
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/Orleans.MultiClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | true
6 | 阿凌
7 | 阿凌
8 | Orleans' Multi Client
9 |
10 | https://github.com/OrleansContrib/Orleans.MultiClient
11 | https://raw.githubusercontent.com/dotnet/orleans/gh-pages/assets/logo_128.png
12 | https://github.com/OrleansContrib/Orleans.MultiClient
13 |
14 | Orleans MultiClient Client
15 | 3.3.0
16 | false
17 |
18 |
19 |
20 | bin\Orleans.MultiClient.xml
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/OrleansClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Reflection;
3 | using System.Threading.Tasks;
4 | using Orleans.Runtime;
5 | using Orleans.Streams;
6 |
7 | namespace Orleans.MultiClient
8 | {
9 | public class OrleansClient : IOrleansClient
10 | {
11 | private readonly IServiceProvider _serviceProvider;
12 | private readonly IClusterClientFactory _clusterClientFactory;
13 |
14 |
15 | public OrleansClient(IServiceProvider serviceProvider, IClusterClientFactory clusterClientFactory)
16 | {
17 | _serviceProvider = serviceProvider;
18 | _clusterClientFactory = clusterClientFactory;
19 | }
20 |
21 | public void BindGrainReference(Assembly assembly, IAddressable grain)
22 | {
23 | _clusterClientFactory.Create(assembly).BindGrainReference(grain);
24 | }
25 | public IStreamProvider GetStreamProvider(Assembly assembly, string name)
26 | {
27 | return this.GetClusterClient(assembly).GetStreamProvider(name);
28 | }
29 | public IClusterClient GetClusterClient(Assembly assembly)
30 | {
31 | return (IClusterClient)_clusterClientFactory.Create(assembly);
32 | }
33 | public Task CreateObjectReference(IGrainObserver obj) where TGrainObserverInterface : IGrainObserver
34 | {
35 | return _clusterClientFactory.Create().CreateObjectReference(obj);
36 | }
37 |
38 | public Task DeleteObjectReference(IGrainObserver obj) where TGrainObserverInterface : IGrainObserver
39 | {
40 | return _clusterClientFactory.Create().DeleteObjectReference(obj);
41 | }
42 |
43 | public TGrainInterface GetGrain(Guid primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithGuidKey
44 | {
45 | return _clusterClientFactory.Create().GetGrain(primaryKey, grainClassNamePrefix);
46 | }
47 | public TGrainInterface GetGrain(long primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithIntegerKey
48 | {
49 | return _clusterClientFactory.Create().GetGrain(primaryKey, grainClassNamePrefix);
50 | }
51 | public TGrainInterface GetGrain(string primaryKey, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithStringKey
52 | {
53 | return _clusterClientFactory.Create().GetGrain(primaryKey, grainClassNamePrefix);
54 | }
55 |
56 | public TGrainInterface GetGrain(Guid primaryKey, string keyExtension, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithGuidCompoundKey
57 | {
58 | return _clusterClientFactory.Create().GetGrain(primaryKey, keyExtension, grainClassNamePrefix);
59 | }
60 | public TGrainInterface GetGrain(long primaryKey, string keyExtension, string grainClassNamePrefix = null) where TGrainInterface : IGrainWithIntegerCompoundKey
61 | {
62 | return _clusterClientFactory.Create().GetGrain(primaryKey, keyExtension, grainClassNamePrefix);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/Orleans.MultiClient/OrleansClientOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Reflection;
4 | using System;
5 |
6 | namespace Orleans.MultiClient
7 | {
8 | public class OrleansClientOptions
9 | {
10 | public OrleansClientOptions()
11 | {
12 | ServiceList = new List();
13 | }
14 | public IList ServiceList { get; set; }
15 | public string ServiceId { get; set; }
16 | public string ClusterId { get; set; }
17 | public Action Configure { get; set; }
18 |
19 | public void SetServiceAssembly(params Assembly[] assemblys)
20 | {
21 | foreach (var assembly in assemblys)
22 | {
23 | var name = assembly.FullName;
24 | if (!this.ServiceList.Contains(name))
25 | {
26 | this.ServiceList.Add(name);
27 | }
28 | }
29 | }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------