Skip to content

Commit 2b968ff

Browse files
committed
Merge branch 'dev'
2 parents 01e77f8 + 17170dd commit 2b968ff

File tree

49 files changed

+645
-270
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+645
-270
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Uragano
22
A simple, high performance RPC library.
33

4+
Support load balancing, circuit breaker, fallback, caching, intercepting.
5+
46
## Package & Status
57
Package | NuGet
68
--------|------

Uragano.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uragano.Core", "src\Uragano
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uragano.DynamicProxy", "src\Uragano.DynamicProxy\Uragano.DynamicProxy.csproj", "{C6AE65C3-DFC2-484F-937E-482363581DE1}"
1111
EndProject
12-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{37596B72-254F-41F3-AD1C-F7F421EB5F02}"
12+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{37596B72-254F-41F3-AD1C-F7F421EB5F02}"
1313
EndProject
1414
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.WebApi", "samples\Sample.WebApi\Sample.WebApi.csproj", "{3F8DE4D5-C985-438C-B144-13813CD1583C}"
1515
EndProject

samples/GenericHostSample/Program.cs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
4+
using System.Linq;
35
using System.Net;
46
using System.Threading.Tasks;
57
using Microsoft.Extensions.Configuration;
68
using Microsoft.Extensions.DependencyInjection;
79
using Microsoft.Extensions.Hosting;
810
using Microsoft.Extensions.Logging;
11+
using Uragano.Abstractions.ConsistentHash;
912
using Uragano.Consul;
1013
using Uragano.Core;
1114
using Uragano.Logging.Exceptionless;
15+
using Uragano.Remoting.LoadBalancing;
1216

1317
namespace GenericHostSample
1418
{
1519
class Program
1620
{
21+
public class Node
22+
{
23+
public Node(string host)
24+
{
25+
Host = host;
26+
}
27+
28+
public string Host { get; set; }
29+
30+
public int Num { get; set; }
31+
32+
public override string ToString()
33+
{
34+
return $"{Host}:{Num}";
35+
}
36+
}
1737

1838
static async Task Main(string[] args)
1939
{
@@ -23,25 +43,91 @@ static async Task Main(string[] args)
2343
}).ConfigureAppConfiguration((context, builder) =>
2444
{
2545
builder.AddJsonFile("uragano.json", false, true);
26-
//builder.AddEnvironmentVariables("uragano");
2746
builder.AddCommandLine(args);
2847
})
2948
.ConfigureServices((context, service) =>
3049
{
3150
service.AddUragano(context.Configuration, builder =>
3251
{
3352
builder.AddServer();
34-
builder.AddClient();
53+
builder.AddClient(LoadBalancing.Polling);
3554
builder.AddCircuitBreaker();
3655
builder.AddExceptionlessLogger();
3756
builder.AddConsul();
3857
});
58+
3959
}).ConfigureLogging((context, builder) =>
4060
{
4161
builder.AddConfiguration(context.Configuration.GetSection("Logging"));
4262
builder.AddConsole();
4363
});
4464
await hostBuilder.RunConsoleAsync();
65+
66+
//var nodes = new List<Node> {
67+
// new Node("139f9cbb-be67-460c-9092-b4b29a6e574a"),
68+
// new Node("3f8fa9c8-4c56-486a-baca-bd7d4639e95b"),
69+
// new Node("c2ab77c7-84c7-4310-aaff-9fe767639135"),
70+
// new Node("55cf40c5-250d-4cb8-9cc7-8d1d361a53b0"),
71+
// new Node("6719662f-74b5-46c7-a652-031c3771b812")
72+
//};
73+
//var x = new ConsistentHash<Node>(500);
74+
//nodes.ForEach(item => { x.AddNode(item, item.Host); });
75+
//var dic = new Dictionary<string, Node>();
76+
//while (true)
77+
//{
78+
// var command = Console.ReadLine();
79+
// if (command == "exit")
80+
// break;
81+
// if (command == "gen")
82+
// {
83+
// for (var i = 0; i < 100000; i++)
84+
// {
85+
// var id = Guid.NewGuid().ToString();
86+
// var node = x.GetNodeForKey(id);
87+
// dic[id] = node;
88+
// node.Num++;
89+
// }
90+
91+
// Console.WriteLine("OK");
92+
// }
93+
94+
// if (command == "info")
95+
// {
96+
// nodes.ForEach(item =>
97+
// {
98+
// Console.WriteLine(item.ToString());
99+
// });
100+
101+
// }
102+
103+
// if (command == "add")
104+
// {
105+
// Console.Write("请输入Key:");
106+
// var k = Console.ReadLine();
107+
// var node = new Node(k);
108+
// nodes.Add(node);
109+
// x.AddNode(node, k);
110+
// }
111+
112+
// if (command == "retry")
113+
// {
114+
// var count = 0;
115+
// foreach (var item in dic)
116+
// {
117+
// var node = x.GetNodeForKey(item.Key);
118+
// if (node.Host != item.Value.Host)
119+
// {
120+
// count++;
121+
// node.Num++;
122+
// }
123+
// }
124+
125+
// Console.WriteLine($"{count}个数据重新分配节点");
126+
// }
127+
128+
//}
129+
130+
45131
}
46132
}
47133
}

samples/Sample.Server/Controllers/ValuesController.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ public async Task<IActionResult> Get()
3434
//await HelloService.SayHello();
3535
return Ok(new
3636
{
37-
name = await HelloService.SetMeta(("token", "bearer .....")).SayHello(Guid.NewGuid().ToString()),
38-
Reply = await HelloService.SayHello("Owen"),
39-
entity = await HelloService.SayHello(new TestModel { Id = 1, Name = "owen" }),
40-
gen = await HelloService.Test()
37+
name = await HelloService.SetMeta(("token", "bearer ....."), ("x-consistent-hash-key", Guid.NewGuid().ToString())).SayHello(Guid.NewGuid().ToString()),
38+
//Reply = await HelloService.SayHello("Owen"),
39+
//entity = await HelloService.SayHello(new TestModel { Id = 1, Name = "owen" }),
40+
//gen = await HelloService.Test()
4141

4242
});
4343
}

samples/Sample.Server/HelloService.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,5 @@ public async Task<ResponseResult<string>> Test()
4646
Result = "OK"
4747
});
4848
}
49-
50-
public Task Test(ResponseResult<string> r)
51-
{
52-
throw new NotImplementedException();
53-
}
5449
}
5550
}

samples/Sample.Server/Startup.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,16 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Net;
5-
using System.Threading.Tasks;
62
using Microsoft.AspNetCore.Builder;
73
using Microsoft.AspNetCore.Hosting;
84
using Microsoft.AspNetCore.Mvc;
95
using Microsoft.Extensions.Configuration;
106
using Microsoft.Extensions.DependencyInjection;
11-
using Microsoft.Extensions.Hosting;
12-
using Microsoft.Extensions.Logging;
13-
using Microsoft.Extensions.Options;
147
using Sample.Common;
15-
using Sample.Service.Interfaces;
168
using Uragano.Abstractions;
17-
using Uragano.Caching.Memory;
189
using Uragano.Caching.Redis;
19-
using Uragano.Codec.MessagePack;
2010
using Uragano.Consul;
2111
using Uragano.Core;
2212
using Uragano.Logging.Exceptionless;
23-
using Uragano.Logging.Log4Net;
24-
using Uragano.Logging.NLog;
13+
using Uragano.Remoting.LoadBalancing;
2514
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
2615

2716
namespace Sample.Server
@@ -41,7 +30,8 @@ public void ConfigureServices(IServiceCollection services)
4130
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
4231
services.AddUragano(Configuration, builder =>
4332
{
44-
builder.AddClient();
33+
34+
builder.AddClient(LoadBalancing.Polling);
4535
builder.AddServer();
4636

4737
builder.AddConsul();
@@ -50,8 +40,8 @@ public void ConfigureServices(IServiceCollection services)
5040
builder.AddExceptionlessLogger();
5141
//builder.AddLog4NetLogger();
5242
//builder.AddNLogLogger();
53-
//builder.AddRedisPartitionCaching();
54-
builder.AddRedisCaching();
43+
builder.AddRedisPartitionCaching();
44+
//builder.AddRedisCaching();
5545
//builder.AddMemoryCaching();
5646
builder.AddOption(UraganoOptions.Remoting_Invoke_CancellationTokenSource_Timeout, TimeSpan.FromSeconds(10));
5747
builder.AddOptions();

samples/Sample.Server/appsettings.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"Caching": {
3333
"Redis": {
3434
"KeyPrefix": "Uragano",
35-
"ExpireSeconds": 60,
35+
"ExpireSeconds": 3600,
3636
"KeyGenerator": null,
3737
"ConnectionStrings": [
3838
{
@@ -47,6 +47,19 @@
4747
"WriteBuffer": 10240,
4848
"TryIt": 0,
4949
"Name": ""
50+
},
51+
{
52+
"Host": "192.168.1.253",
53+
"Port": 6379,
54+
"Password": "nihao123",
55+
"DefaultDatabase": 13,
56+
"PoolSize": 50,
57+
"SSL": false,
58+
"ConnectionTimeout": -1,
59+
"PreHeat": true,
60+
"WriteBuffer": 10240,
61+
"TryIt": 0,
62+
"Name": ""
5063
}
5164
]
5265
},
@@ -61,7 +74,8 @@
6174
},
6275
"Options": {
6376
"ThreadPool_MinThreads": 100,
64-
"DotNetty_Event_Loop_Count": 100
77+
"DotNetty_Event_Loop_Count": 100,
78+
"Output_DynamicProxy_SourceCode": true
6579
}
6680
}
6781
}

samples/Sample.Service.Interfaces/IHelloService.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,5 @@ public interface IHelloService : IService
2828
Task<int> Age();
2929

3030
Task<ResponseResult<string>> Test();
31-
32-
Task Test(ResponseResult<string> r);
3331
}
3432
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace Uragano.Abstractions.ConsistentHash
7+
{
8+
public class ConsistentHash<T> : IConsistentHash<T>
9+
{
10+
private SortedDictionary<int, T> Ring { get; } = new SortedDictionary<int, T>();
11+
12+
private int VirtualReplication { get; set; }
13+
14+
public ConsistentHash(int virtualReplication = 200)
15+
{
16+
VirtualReplication = virtualReplication;
17+
}
18+
19+
public void SetVirtualReplicationCount(int count)
20+
{
21+
VirtualReplication = count;
22+
}
23+
24+
public List<T> GetAllNodes()
25+
{
26+
return Ring.Select(p => p.Value).Distinct().ToList();
27+
}
28+
29+
public void AddNode(T node, string key)
30+
{
31+
for (var i = 0; i < VirtualReplication; i++)
32+
{
33+
var hash = HashAlgorithm.Hash(key + i);
34+
Ring.Add(hash, node);
35+
}
36+
}
37+
38+
public void RemoveNode(string key)
39+
{
40+
for (var i = 0; i < VirtualReplication; i++)
41+
{
42+
var hash = HashAlgorithm.Hash(key + i);
43+
Ring.Remove(hash);
44+
}
45+
}
46+
47+
public T GetNodeForKey(string key)
48+
{
49+
if (!Ring.Any())
50+
throw new InvalidOperationException("Can not find the available nodes, please call the AddNode method to add nodes.");
51+
52+
var hash = HashAlgorithm.Hash(key);
53+
if (Ring.ContainsKey(hash))
54+
return Ring[hash];
55+
var node = Ring.Where(p => p.Key > hash).OrderBy(i => i.Key).Select(p => p.Value).FirstOrDefault();
56+
if (node != null)
57+
return node;
58+
return Ring.FirstOrDefault().Value;
59+
}
60+
}
61+
62+
internal class HashAlgorithm
63+
{
64+
private const uint m = 0x5bd1e995;
65+
private const int r = 24;
66+
public static int Hash(byte[] data, uint seed = 0xc58f1a7b)
67+
{
68+
var length = data.Length;
69+
if (length == 0)
70+
return 0;
71+
72+
var h = seed ^ (uint)length;
73+
var c = 0;
74+
while (length >= 4)
75+
{
76+
var k = (uint)(
77+
data[c++]
78+
| data[c++] << 8
79+
| data[c++] << 16
80+
| data[c++] << 24);
81+
k *= m;
82+
k ^= k >> r;
83+
k *= m;
84+
h *= m;
85+
h ^= k;
86+
length -= 4;
87+
}
88+
switch (length)
89+
{
90+
case 3:
91+
h ^= (ushort)(data[c++] | data[c++] << 8);
92+
h ^= (uint)(data[c] << 16);
93+
h *= m;
94+
break;
95+
case 2:
96+
h ^= (ushort)(data[c++] | data[c] << 8);
97+
h *= m;
98+
break;
99+
case 1:
100+
h ^= data[c];
101+
h *= m;
102+
break;
103+
}
104+
105+
h ^= h >> 13;
106+
h *= m;
107+
h ^= h >> 15;
108+
return (int)h;
109+
}
110+
111+
public static int Hash(string data, uint seed = 0xc58f1a7b)
112+
{
113+
return Hash(Encoding.UTF8.GetBytes(data), seed);
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)