2.增加内存队列只实现消息的处理和应答 3.增加简单的压力测试 4.修改文档及ci配置tags/pipeline-1.0.0
@@ -36,6 +36,6 @@ jobs: | |||
- name: dotnet JT808.Gateway restore | |||
run: dotnet restore ./src/JT808.Gateway.sln | |||
- name: dotnet JT808.Gateway build | |||
run: dotnet build ./src/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||
run: dotnet build ./src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||
- name: dotnet JT808.Gateway test | |||
run: dotnet test ./src/JT808.Gateway.Test/JT808.Gateway.Test.csproj | |||
run: dotnet test ./src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj |
@@ -12,9 +12,9 @@ | |||
[了解JTNE协议进这边](https://github.com/SmallChi/JTNewEnergy) | |||
[玩一玩压力测试](https://github.com/SmallChi/JT808DotNetty/blob/master/doc/README.md) | |||
[玩一玩压力测试](https://github.com/SmallChi/JT808Gateway/blob/master/doc/README.md) | |||
[](https://github.com/SmallChi/JT808DotNetty/blob/master/LICENSE)[]() | |||
[](https://github.com/SmallChi/JT808Gateway/blob/master/LICENSE)[]() | |||
## 新网关的优势 | |||
@@ -25,7 +25,7 @@ | |||
## 设计模型 | |||
 | |||
 | |||
## 集成接口功能 | |||
@@ -85,8 +85,9 @@ | |||
| --------------------- | -------------------------------------------------- | --------------------------------------------------- | | |||
| Install-Package JT808.Gateway.Abstractions|  |  | | |||
| Install-Package JT808.Gateway |  |  | | |||
| Install-Package JT808.Gateway.Kafka|  |  | | |||
| Install-Package JT808.Gateway.Client|  |  | | |||
| Install-Package JT808.Gateway.InMemoryMQ|  |  | | |||
| Install-Package JT808.Gateway.Kafka|  |  | | |||
| Install-Package JT808.Gateway.Transmit |  |  | | |||
| Install-Package JT808.Gateway.Traffic |  | | | |||
| Install-Package JT808.Gateway.SessionNotice |  | | | |||
@@ -94,106 +95,7 @@ | |||
| Install-Package JT808.Gateway.MsgLogging |  | | | |||
| Install-Package JT808.Gateway.MsgIdHandler |  | | | |||
## 举个栗子1 | |||
``` demo1 | |||
static async Task Main(string[] args) | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory); | |||
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((context, logging) => | |||
{ | |||
logging.AddConsole(); | |||
logging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808NettyCore(hostContext.Configuration) | |||
.AddJT808TcpNettyHost() | |||
.AddJT808UdpNettyHost() | |||
.AddJT808WebApiNettyHost() | |||
//扩展webapi JT808MsgIdHttpHandlerBase | |||
//.ReplaceMsgIdHandler<JT808MsgIdHttpCustomHandler>() | |||
.Builder(); | |||
//添加kafka插件 | |||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||
//.Builder(); | |||
//使用微软自带的webapi客户端 | |||
//services.AddHttpClient("jt808webapi", c => | |||
//{ | |||
// c.BaseAddress = new Uri("http://localhost:828/"); | |||
// c.DefaultRequestHeaders.Add("token", "123456); | |||
//}) | |||
//.AddTypedClient<JT808HttpClient>(); | |||
//var client = services.BuildServiceProvider().GetRequiredService<JT808HttpClient>(); | |||
//var result = client.GetTcpAtomicCounter(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
``` | |||
如图所示: | |||
 | |||
## 举个栗子2 | |||
``` 1 | |||
static async Task Main(string[] args) | |||
{ | |||
var serverHostBuilder = new HostBuilder() | |||
.ConfigureAppConfiguration((hostingContext, config) => | |||
{ | |||
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory) | |||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{ hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true); | |||
}) | |||
.ConfigureLogging((context, logging) => | |||
{ | |||
Console.WriteLine($"Environment.OSVersion.Platform:{Environment.OSVersion.Platform.ToString()}"); | |||
NLog.LogManager.LoadConfiguration($"Configs/nlog.{Environment.OSVersion.Platform.ToString()}.config"); | |||
logging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); | |||
logging.SetMinimumLevel(LogLevel.Trace); | |||
}) | |||
.ConfigureServices((hostContext, services) => | |||
{ | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
//.AddJT808Gateway(options => | |||
//{ | |||
// options.TcpPort = 808; | |||
// options.UdpPort = 808; | |||
//}) | |||
.AddJT808Gateway(hostContext.Configuration) | |||
.AddTcp() | |||
.AddUdp() | |||
.AddGrpc() | |||
//InMemoryMQ | |||
.AddJT808ServerInMemoryMQ() | |||
.AddJT808InMemoryReplyMessage() | |||
//kafka插件 | |||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||
; | |||
//services.AddHostedService<CallGrpcClientJob>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
} | |||
``` | |||
## 举个栗子3 | |||
## 举个栗子 | |||
1.打开项目进行还原编译生成 | |||
@@ -202,4 +104,4 @@ static async Task Main(string[] args) | |||
3.进入JT808.DotNetty.SimpleClient项目下的Debug目录运行客户端 | |||
如图所示: | |||
 | |||
 |
@@ -1,31 +1,15 @@ | |||
# 压力测试 | |||
## 基于DotNetty | |||
[感谢泥水佬提供的压力测试工具](https://www.cnblogs.com/smark/p/4496660.html?utm_source=tuicool) | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| win server 2016 | 4c8g | 压力测试客户端 | | |||
| centos7 | 4c8g | JT808服务端 | | |||
 | |||
 | |||
 | |||
 | |||
## 基于pipeline | |||
**由于【参数配置】不同导致测试的效果可能不同,只是谁便测试玩玩,反正机器便宜。** | |||
**只是谁便测试玩玩,反正机器便宜。** | |||
> 注意1:连接数和并发数要区分开; | |||
> 注意2:阿里云的机器默认有连接数限制(5000),可以先创建一台,把该装的软件安装好,tcp参数内核调优后,在备份一个系统镜像在玩。 | |||
> 注意2:阿里云的机器默认有连接数限制(5000),可以先创建一台,把该装的软件安装好,tcp参数内核调优后,在备份一个系统镜像在玩; | |||
> 注意3: 使用的是内存队列(InMemoryMQ)进行测试。 | |||
``` 1 | |||
使用PM2托管 | |||
//使用PM2托管 | |||
//服务端 | |||
cd /data/JT808.Gateway | |||
@@ -35,6 +19,7 @@ pm2 start "dotnet JT808.Gateway.TestHosting.dll ASPNETCORE_ENVIRONMENT=Productio | |||
cd /data/JT808Client | |||
pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Production" --max-restarts=1 -n "JT808.Gateway.CleintBenchmark" -o "/data/pm2Logs/JT808.Gateway.CleintBenchmark/out.log" -e "/data/pm2Logs/JT808.Gateway.CleintBenchmark/error.log" | |||
//可选的 | |||
修改wwwroot下index.html的webapi接口地址 | |||
127.0.0.1:15004/index.html | |||
``` | |||
@@ -55,11 +40,22 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 10000, | |||
"Interval": 10, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 80960, | |||
"SoBacklog": 102400 | |||
} | |||
``` | |||
 | |||
 | |||
@@ -82,18 +78,29 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 20000, | |||
"Interval": 300, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 80960, | |||
"SoBacklog": 102400 | |||
} | |||
``` | |||
 | |||
 | |||
 | |||
### 40K | |||
### 30K | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
@@ -108,39 +115,130 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 40000, | |||
"DeviceCount": 30000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 80960, | |||
"SoBacklog": 102400 | |||
} | |||
``` | |||
 | |||
 | |||
 | |||
### 40K | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| centos7 | 8c16g | JT808服务端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||
客户端1参数配置appsettings.json | |||
``` 1 | |||
"urls": "http://*:15004;", | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
修改wwwroot下index.html的webapi接口地址 | |||
127.0.0.1:15004/index.html | |||
``` | |||
``` 2 | |||
"urls": "http://*:15005;", | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
修改wwwroot下index.html的webapi接口地址 | |||
127.0.0.1:15005/index.html | |||
``` | |||
> 一个进程的线程是有限的,所以分两个进程进行测试 | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 80960, | |||
"SoBacklog": 102400 | |||
} | |||
``` | |||
 | |||
 | |||
 | |||
> 由于资源被占满了,所以客户端的界面访问不到,但是不影响总体。 | |||
### 60K | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| centos7 | 8c16g | JT808服务端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端1 | | |||
| centos7 | 8c16g | JT808客户端2 | | |||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||
客户端参数配置appsettings.json | |||
客户端1参数配置appsettings.json | |||
``` 1 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 60000, | |||
"DeviceCount": 30000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端2参数配置appsettings.json | |||
``` 2 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 30000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 102400, | |||
"SoBacklog": 102400 | |||
} | |||
``` | |||
 | |||
 | |||
@@ -151,10 +249,13 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| centos7 | 8c16g | JT808服务端 | | |||
| centos7 | 16c24g | JT808服务端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
> 计算网络增强型 sn1ne ecs.sn1ne.3xlarge 12 vCPU 24 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2.5 Gbps 130 万 PPS | |||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||
客户端1的参数配置appsettings.json | |||
@@ -163,8 +264,8 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 40000, | |||
"Interval": 3000, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
@@ -175,14 +276,196 @@ pm2 start "dotnet JT808.Gateway.CleintBenchmark.dll ASPNETCORE_ENVIRONMENT=Produ | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 40000, | |||
"Interval": 3000, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端3的参数配置appsettings.json | |||
``` 3 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 300000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端3的参数配置appsettings.json | |||
``` 4 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 20000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 400000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 204800, | |||
"SoBacklog": 204800 | |||
} | |||
``` | |||
 | |||
 | |||
 | |||
### 100K | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| centos7 | 16c24g | JT808服务端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
| centos7 | 8c16g | JT808客户端 | | |||
> 计算网络增强型 sn1ne ecs.sn1ne.3xlarge 12 vCPU 24 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2.5 Gbps 130 万 PPS | |||
> 计算网络增强型 sn1ne ecs.sn1ne.2xlarge 8 vCPU 16 GiB Intel Xeon E5-2682v4 / Intel Xeon(Skylake) Platinum 8163 2.5 GHz 2 Gbps 100 万 PPS | |||
客户端1的参数配置appsettings.json | |||
``` 1 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 25000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 100000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端2的参数配置appsettings.json | |||
``` 2 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 25000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 200000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端3的参数配置appsettings.json | |||
``` 3 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 25000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 300000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
客户端3的参数配置appsettings.json | |||
``` 4 | |||
"ClientBenchmarkOptions": { | |||
"IP": "", | |||
"Port": 808, | |||
"DeviceCount": 25000, | |||
"Interval": 1000, | |||
"DeviceTemplate": 400000 //需要多台机器同时访问,那么可以根据这个避开重复终端号 100000-200000-300000 | |||
} | |||
``` | |||
服务器参数配置appsettings.json | |||
``` 1 | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 204800, | |||
"SoBacklog": 204800 | |||
} | |||
``` | |||
 | |||
 | |||
### 参考Centos7内核参数调优 | |||
``` 99 | |||
vi /etc/security/limits.conf | |||
修改如下: | |||
root soft nofile 204800 | |||
root hard nofile 204800 | |||
* soft nofile 204800 | |||
* hard nofile 204800 | |||
vi /etc/pam.d/login | |||
添加如下: | |||
session required pam_limits.so | |||
vi /etc/sysctl.conf | |||
添加如下: | |||
vm.swappiness = 0 | |||
net.ipv4.neigh.default.gc_stale_time = 120 | |||
# see details in https://help.aliyun.com/knowledge_detail/39428.html | |||
net.ipv4.conf.all.rp_filter = 0 | |||
net.ipv4.conf.default.rp_filter = 0 | |||
net.ipv4.conf.default.arp_announce = 2 | |||
net.ipv4.conf.lo.arp_announce = 2 | |||
net.ipv4.conf.all.arp_announce = 2 | |||
# see details in https://help.aliyun.com/knowledge_detail/41334.html | |||
net.ipv4.tcp_synack_retries = 2 | |||
net.ipv4.tcp_syn_retries = 1 | |||
net.ipv4.tcp_synack_retries = 1 | |||
net.ipv4.tcp_keepalive_time = 600 | |||
net.ipv4.tcp_keepalive_probes = 3 | |||
net.ipv4.tcp_keepalive_intvl =15 | |||
net.ipv4.tcp_retries2 = 5 | |||
net.ipv4.tcp_fin_timeout = 1 | |||
net.ipv4.tcp_max_tw_buckets = 65535 | |||
net.ipv4.tcp_tw_recycle = 1 | |||
net.ipv4.tcp_tw_reuse = 1 | |||
net.ipv4.tcp_max_orphans = 32768 | |||
net.ipv4.tcp_syncookies = 1 | |||
net.ipv4.tcp_max_syn_backlog = 65535 | |||
net.ipv4.tcp_wmem = 8192 131072 16777216 | |||
net.ipv4.tcp_rmem = 32768 131072 16777216 | |||
net.ipv4.tcp_mem = 94500000 915000000 927000000 | |||
net.ipv4.ip_local_port_range = 1024 65000 | |||
net.core.somaxconn = 65535 | |||
net.core.netdev_max_backlog = 65535 | |||
fs.file-max = 265535 | |||
net.ipv6.conf.lo.disable_ipv6 = 1 | |||
kernel.sysrq = 1 | |||
net.ipv6.conf.all.disable_ipv6 = 1 | |||
net.ipv6.conf.default.disable_ipv6 = 1 | |||
最后重启机器下: | |||
reboot | |||
``` | |||
## 基于DotNetty | |||
[感谢泥水佬提供的压力测试工具](https://www.cnblogs.com/smark/p/4496660.html?utm_source=tuicool) | |||
| 操作系统 | 配置 | 使用 | | |||
|:-------:|:-------:|:-------:| | |||
| win server 2016 | 4c8g | 压力测试客户端 | | |||
| centos7 | 4c8g | JT808服务端 | | |||
 | |||
 | |||
 | |||
 |
@@ -1,14 +1,15 @@ | |||
dotnet pack .\src\JT808.Gateway\JT808.Gateway.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway\JT808.Gateway.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Client\JT808.Gateway.Client.csproj -c Release --output nupkgs | |||
echo 'push service pacakge...' | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgIdHandler\JT808.Gateway.MsgIdHandler.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgLogging\JT808.Gateway.MsgLogging.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.SessionNotice\JT808.Gateway.SessionNotice.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Traffic\JT808.Gateway.Traffic.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Transmit\JT808.Gateway.Transmit.csproj --no-build --output ../../nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgIdHandler\JT808.Gateway.MsgIdHandler.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.MsgLogging\JT808.Gateway.MsgLogging.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.SessionNotice\JT808.Gateway.SessionNotice.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Traffic\JT808.Gateway.Traffic.csproj -c Release --output nupkgs | |||
dotnet pack .\src\JT808.Gateway.Services\JT808.Gateway.Transmit\JT808.Gateway.Transmit.csproj -c Release --output nupkgs | |||
pause |
@@ -22,7 +22,9 @@ | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="wwwroot\echarts.min.js"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
@@ -68,7 +68,7 @@ namespace JT808.Gateway.CleintBenchmark | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
.AddJT808Client(); | |||
.AddClient(); | |||
services.AddHostedService<CleintBenchmarkHostedService>(); | |||
}); | |||
await serverHostBuilder.RunConsoleAsync(); | |||
@@ -25,6 +25,8 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||
private readonly IJT808TcpClientFactory jT808TcpClientFactory; | |||
private TaskFactory taskFactory; | |||
public CleintBenchmarkHostedService( | |||
ILoggerFactory loggerFactory, | |||
IJT808TcpClientFactory jT808TcpClientFactory, | |||
@@ -33,6 +35,7 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||
this.jT808TcpClientFactory = jT808TcpClientFactory; | |||
clientBenchmarkOptions = clientBenchmarkOptionsAccessor.Value; | |||
logger = loggerFactory.CreateLogger("CleintBenchmarkHostedService"); | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
@@ -41,24 +44,21 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||
ThreadPool.GetMaxThreads(out var maxWorkerThreads, out var maxCompletionPortThreads); | |||
logger.LogInformation($"GetMinThreads:{minWorkerThreads}-{minCompletionPortThreads}"); | |||
logger.LogInformation($"GetMaxThreads:{maxWorkerThreads}-{maxCompletionPortThreads}"); | |||
taskFactory = new TaskFactory(cancellationToken); | |||
for (int i=0;i< clientBenchmarkOptions.DeviceCount; i++) | |||
{ | |||
string deviceNo = (i + 1 + clientBenchmarkOptions.DeviceTemplate).ToString(); | |||
var client = jT808TcpClientFactory.Create(new JT808DeviceConfig(deviceNo, | |||
clientBenchmarkOptions.IP, | |||
clientBenchmarkOptions.Port), cancellationToken); | |||
} | |||
ThreadPool.QueueUserWorkItem((state) => | |||
{ | |||
while (!cancellationToken.IsCancellationRequested) | |||
{ | |||
foreach (var item in jT808TcpClientFactory.GetAll()) | |||
taskFactory.StartNew(async (state) => { | |||
string deviceNo = ((int)state + 1 + clientBenchmarkOptions.DeviceTemplate).ToString(); | |||
var client = await jT808TcpClientFactory.Create(new JT808DeviceConfig(deviceNo, | |||
clientBenchmarkOptions.IP, | |||
clientBenchmarkOptions.Port), cancellationToken); | |||
while (!cancellationToken.IsCancellationRequested) | |||
{ | |||
try | |||
{ | |||
int lat = new Random(1000).Next(100000, 180000); | |||
int Lng = new Random(1000).Next(100000, 180000); | |||
item.Send(JT808MsgId.位置信息汇报.Create(item.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||
await client.SendAsync(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||
{ | |||
Lat = lat, | |||
Lng = Lng, | |||
@@ -74,10 +74,10 @@ namespace JT808.Gateway.CleintBenchmark.Services | |||
{ | |||
logger.LogError(ex.Message); | |||
} | |||
await Task.Delay(clientBenchmarkOptions.Interval); | |||
} | |||
Thread.Sleep(clientBenchmarkOptions.Interval); | |||
} | |||
}); | |||
}, i); | |||
} | |||
return Task.CompletedTask; | |||
} | |||
@@ -30,5 +30,7 @@ | |||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" /> | |||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||
</ItemGroup> | |||
</Project> |
@@ -10,7 +10,7 @@ namespace JT808.Gateway.Client | |||
{ | |||
public static class JT808ClientExtensions | |||
{ | |||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder) | |||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder) | |||
{ | |||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | |||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | |||
@@ -19,7 +19,7 @@ namespace JT808.Gateway.Client | |||
jT808Builder.Services.AddHostedService<JT808ReportHostedService>(); | |||
return jT808Builder; | |||
} | |||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder, IConfiguration Configuration) | |||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder, IConfiguration Configuration) | |||
{ | |||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | |||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | |||
@@ -29,7 +29,7 @@ namespace JT808.Gateway.Client | |||
return jT808Builder; | |||
} | |||
public static IJT808Builder AddJT808Client(this IJT808Builder jT808Builder, Action<JT808ReportOptions> reportOptions) | |||
public static IJT808Builder AddClient(this IJT808Builder jT808Builder, Action<JT808ReportOptions> reportOptions) | |||
{ | |||
jT808Builder.Services.AddSingleton<JT808SendAtomicCounterService>(); | |||
jT808Builder.Services.AddSingleton<JT808ReceiveAtomicCounterService>(); | |||
@@ -176,7 +176,7 @@ namespace JT808.Gateway.Client | |||
consumed = buffer.GetPosition(totalConsumed); | |||
} | |||
} | |||
public void Send(JT808ClientRequest message) | |||
public async ValueTask SendAsync(JT808ClientRequest message) | |||
{ | |||
if (disposed) return; | |||
if (IsOpen && socketState) | |||
@@ -185,8 +185,9 @@ namespace JT808.Gateway.Client | |||
{ | |||
try | |||
{ | |||
var sendData = JT808Serializer.SerializeReadOnlySpan(message.Package, minBufferSize: message.MinBufferSize); | |||
clientSocket.Send(sendData); | |||
var sendData = JT808Serializer.Serialize(message.Package, minBufferSize: message.MinBufferSize); | |||
//clientSocket.Send(sendData); | |||
await clientSocket.SendAsync(sendData, SocketFlags.None); | |||
SendAtomicCounterService.MsgSuccessIncrement(); | |||
} | |||
catch (System.Net.Sockets.SocketException ex) | |||
@@ -6,16 +6,17 @@ using System.Text; | |||
using JT808.Protocol.Enums; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Gateway.Client.Metadata; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Client | |||
{ | |||
public static class JT808TcpClientExtensions | |||
{ | |||
public static void Send(this JT808TcpClient client, JT808Package package, int minBufferSize = 4096) | |||
public static async ValueTask SendAsync(this JT808TcpClient client, JT808Package package, int minBufferSize = 4096) | |||
{ | |||
package.Header.TerminalPhoneNo = client.DeviceConfig.TerminalPhoneNo; | |||
JT808ClientRequest request = new JT808ClientRequest(package, minBufferSize); | |||
client.Send(request); | |||
await client.SendAsync(request); | |||
} | |||
} | |||
@@ -1,7 +1,6 @@ | |||
using JT808.Gateway.Abstractions; | |||
using JT808.Gateway.InMemoryMQ.Services; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.DependencyInjection.Extensions; | |||
namespace JT808.Gateway.InMemoryMQ | |||
{ | |||
@@ -12,14 +11,14 @@ namespace JT808.Gateway.InMemoryMQ | |||
/// </summary> | |||
/// <param name="jT808GatewayBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerInMemoryMQ(this IJT808GatewayBuilder jT808GatewayBuilder) | |||
public static IJT808GatewayBuilder AddServerInMemoryMQ(this IJT808GatewayBuilder jT808GatewayBuilder) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808MsgService>(); | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMsgService>(); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgConsumer), typeof(JT808MsgConsumer), ServiceLifetime.Singleton)); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyProducer), typeof(JT808MsgReplyProducer), ServiceLifetime.Singleton)); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgProducer, JT808MsgProducer>(); | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgConsumer, JT808MsgConsumer>(); | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgReplyProducer, JT808MsgReplyProducer>(); | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<IJT808MsgReplyConsumer, JT808MsgReplyConsumer>(); | |||
return jT808GatewayBuilder; | |||
} | |||
} |
@@ -21,11 +21,6 @@ namespace JT808.Gateway.InMemoryMQ.Services | |||
await _channel.Writer.WriteAsync((terminalNo, data)); | |||
} | |||
public bool TryRead(out (string TerminalNo, byte[] Data) item) | |||
{ | |||
return _channel.Reader.TryRead(out item); | |||
} | |||
public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | |||
{ | |||
return await _channel.Reader.ReadAsync(cancellationToken); | |||
@@ -20,12 +20,6 @@ namespace JT808.Gateway.InMemoryMQ.Services | |||
{ | |||
await _channel.Writer.WriteAsync((terminalNo, data)); | |||
} | |||
public bool TryRead(out (string TerminalNo, byte[] Data) item) | |||
{ | |||
return _channel.Reader.TryRead(out item); | |||
} | |||
public async ValueTask<(string TerminalNo, byte[] Data)> ReadAsync(CancellationToken cancellationToken) | |||
{ | |||
return await _channel.Reader.ReadAsync(cancellationToken); | |||
@@ -10,7 +10,7 @@ namespace JT808.Gateway.Kafka | |||
{ | |||
public static class JT808ClientKafkaExtensions | |||
{ | |||
public static IJT808ClientBuilder AddJT808ClientKafka(this IJT808Builder builder) | |||
public static IJT808ClientBuilder AddClientKafka(this IJT808Builder builder) | |||
{ | |||
return new JT808ClientBuilderDefault(builder); | |||
} | |||
@@ -47,7 +47,7 @@ namespace JT808.Gateway.Kafka | |||
public static IJT808ClientBuilder AddMsgReplyConsumer(this IJT808ClientBuilder jT808ClientBuilder, IConfiguration configuration) | |||
{ | |||
jT808ClientBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | |||
jT808ClientBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||
jT808ClientBuilder.JT808Builder.Services.TryAddSingleton<IJT808MsgReplyConsumer, JT808MsgReplyConsumer>(); | |||
return jT808ClientBuilder; | |||
} | |||
/// <summary> | |||
@@ -14,7 +14,7 @@ namespace JT808.Gateway.Kafka | |||
/// <param name="jT808GatewayBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808MsgProducerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
public static IJT808GatewayBuilder AddServerKafkaMsgProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgProducerConfig>(configuration.GetSection("JT808MsgProducerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgProducer), typeof(JT808MsgProducer), ServiceLifetime.Singleton)); | |||
@@ -26,7 +26,7 @@ namespace JT808.Gateway.Kafka | |||
/// <param name="jT808GatewayBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808MsgReplyConsumerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
public static IJT808GatewayBuilder AddServerKafkaMsgReplyConsumer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808MsgReplyConsumerConfig>(configuration.GetSection("JT808MsgReplyConsumerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808MsgReplyConsumer), typeof(JT808MsgReplyConsumer), ServiceLifetime.Singleton)); | |||
@@ -38,7 +38,7 @@ namespace JT808.Gateway.Kafka | |||
/// <param name="jT808GatewayBuilder"></param> | |||
/// <param name="configuration">GetSection("JT808SessionProducerConfig")</param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808ServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
public static IJT808GatewayBuilder AddServerKafkaSessionProducer(this IJT808GatewayBuilder jT808GatewayBuilder, IConfiguration configuration) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.Configure<JT808SessionProducerConfig>(configuration.GetSection("JT808SessionProducerConfig")); | |||
jT808GatewayBuilder.JT808Builder.Services.Replace(new ServiceDescriptor(typeof(IJT808SessionProducer), typeof(JT808SessionProducer), ServiceLifetime.Singleton)); | |||
@@ -51,7 +51,7 @@ namespace JT808.Gateway.ReplyMessage | |||
/// </summary> | |||
/// <param name="jT808GatewayBuilder"></param> | |||
/// <returns></returns> | |||
public static IJT808GatewayBuilder AddJT808InMemoryReplyMessage(this IJT808GatewayBuilder jT808GatewayBuilder) | |||
public static IJT808GatewayBuilder AddInMemoryReplyMessage(this IJT808GatewayBuilder jT808GatewayBuilder) | |||
{ | |||
jT808GatewayBuilder.JT808Builder.Services.AddSingleton<JT808ReplyMessageHandler>(); | |||
jT808GatewayBuilder.JT808Builder.Services.AddHostedService<JT808ReplyMessageHostedService>(); | |||
@@ -1,8 +0,0 @@ | |||
{ | |||
"JT808Configuration": { | |||
"TcpPort": 808, | |||
"UdpPort": 808, | |||
"MiniNumBufferSize": 51200, | |||
"SoBacklog": 65535 | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||
<IsPackable>false</IsPackable> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> | |||
<PackageReference Include="xunit" Version="2.4.0" /> | |||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | |||
<PackageReference Include="coverlet.collector" Version="1.0.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -0,0 +1,22 @@ | |||
using JT808.Gateway.InMemoryMQ.Services; | |||
using System; | |||
using System.Collections.Concurrent; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using Xunit; | |||
namespace JT808.Gateway.InMemoryMQ.Test.Services | |||
{ | |||
public class JT808MsgServiceTest | |||
{ | |||
[Fact] | |||
public void Test1() | |||
{ | |||
JT808MsgService jT808MsgService = new JT808MsgService(); | |||
jT808MsgService.WriteAsync("132", new byte[] { 1, 2, 3 }).GetAwaiter().GetResult(); | |||
var result = jT808MsgService.ReadAsync(CancellationToken.None).GetAwaiter().GetResult(); | |||
Assert.Equal("132", result.TerminalNo); | |||
Assert.Equal(new byte[] { 1, 2, 3 }, result.Data); | |||
} | |||
} | |||
} |
@@ -22,7 +22,7 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -158,7 +158,7 @@ namespace JT808.Gateway.Test.Session | |||
var session = new JT808TcpSession(new Socket(SocketType.Stream, ProtocolType.Tcp)); | |||
var result1 = jT808SessionManager.TryAdd(session); | |||
jT808SessionManager.TryLink(tno, session); | |||
jT808SessionManager.TrySendByTerminalPhoneNo(tno, new byte[] { 0x7e, 0, 0, 0x7e }); | |||
jT808SessionManager.TrySendByTerminalPhoneNoAsync(tno, new byte[] { 0x7e, 0, 0, 0x7e }).GetAwaiter().GetResult(); | |||
}); | |||
} | |||
@@ -180,8 +180,8 @@ namespace JT808.Gateway.Test.Session | |||
Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno1)); | |||
Assert.True(jT808SessionManager.TerminalPhoneNoSessions.ContainsKey(tno2)); | |||
var sessions = jT808SessionManager.GetTcpAll(); | |||
Assert.Equal(session1.SessionID, sessions[0].SessionID); | |||
Assert.Equal(session2.SessionID, sessions[1].SessionID); | |||
Assert.Contains(sessions, (item) => item.SessionID == session1.SessionID); | |||
Assert.Contains(sessions, (item) => item.SessionID == session2.SessionID); | |||
} | |||
} | |||
} |
@@ -4,6 +4,8 @@ | |||
<OutputType>Exe</OutputType> | |||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | |||
<!--<ServerGarbageCollection>true</ServerGarbageCollection> | |||
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>--> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
@@ -14,11 +16,11 @@ | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | |||
<ProjectReference Include="..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||
<ProjectReference Include="..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
<ProjectReference Include="..\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj" /> | |||
<ProjectReference Include="..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway\JT808.Gateway.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway.Client\JT808.Gateway.Client.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway.InMemoryMQ\JT808.Gateway.InMemoryMQ.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj" /> | |||
<ProjectReference Include="..\..\JT808.Gateway.Services\JT808.Gateway.ReplyMessage\JT808.Gateway.ReplyMessage.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> |
@@ -38,7 +38,7 @@ namespace JT808.Gateway.TestHosting.Jobs | |||
{ | |||
int lat = new Random(1000).Next(100000, 180000); | |||
int Lng = new Random(1000).Next(100000, 180000); | |||
client.Send(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||
client.SendAsync(JT808MsgId.位置信息汇报.Create(client.DeviceConfig.TerminalPhoneNo, new JT808_0x0200() | |||
{ | |||
Lat = lat, | |||
Lng = Lng, |
@@ -37,23 +37,24 @@ namespace JT808.Gateway.TestHosting | |||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | |||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | |||
services.AddJT808Configure() | |||
//.AddJT808Client() | |||
//.AddJT808Gateway(options => | |||
//{ | |||
// options.TcpPort = 808; | |||
// options.UdpPort = 808; | |||
//}) | |||
.AddJT808Gateway(hostContext.Configuration) | |||
//添加客户端工具 | |||
//.AddClient() | |||
//.AddGateway(options => | |||
////{ | |||
//// options.TcpPort = 808; | |||
//// options.UdpPort = 808; | |||
////}) | |||
.AddGateway(hostContext.Configuration) | |||
.AddTcp() | |||
.AddUdp() | |||
.AddGrpc() | |||
//InMemoryMQ | |||
.AddJT808ServerInMemoryMQ() | |||
.AddJT808InMemoryReplyMessage() | |||
.AddServerInMemoryMQ() | |||
.AddInMemoryReplyMessage() | |||
//kafka插件 | |||
//.AddJT808ServerKafkaMsgProducer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||
//.AddJT808ServerKafkaSessionProducer(hostContext.Configuration) | |||
//.AddServerKafkaMsgProducer(hostContext.Configuration) | |||
//.AddServerKafkaMsgReplyConsumer(hostContext.Configuration) | |||
//.AddServerKafkaSessionProducer(hostContext.Configuration) | |||
; | |||
//grpc客户端调用 | |||
//services.AddHostedService<CallGrpcClientJob>(); |
@@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29409.12 | |||
MinimumVisualStudioVersion = 10.0.40219.1 | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway", "JT808.Gateway\JT808.Gateway.csproj", "{4C8A2546-8333-416D-B123-91062B630087}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.TestHosting", "JT808.Gateway.TestHosting\JT808.Gateway.TestHosting.csproj", "{AE40AFE0-0950-442C-A74C-10CDF53E9F36}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Abstractions", "JT808.Gateway.Abstractions\JT808.Gateway.Abstractions.csproj", "{3AA17DF7-A1B3-449C-93C2-45B051C32933}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Kafka", "JT808.Gateway.Kafka\JT808.Gateway.Kafka.csproj", "{274C048E-A8E3-4422-A578-A10A97DF36F2}" | |||
@@ -31,10 +29,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Client", "JT8 | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7CBAACEE-19BF-499A-8C41-36A1324D45E9}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Test", "JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{1E230D1B-BDFC-4D0A-9B34-592280A723BD}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.CleintBenchmark", "JT808.Gateway.CleintBenchmark\JT808.Gateway.CleintBenchmark.csproj", "{0FBC9E4F-8585-4820-ACF1-145A14B3A727}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.Test", "JT808.Gateway.Tests\JT808.Gateway.Test\JT808.Gateway.Test.csproj", "{E3DC260E-0B55-4993-B051-402E44D4E883}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Gateway.TestHosting", "JT808.Gateway.Tests\JT808.Gateway.TestHosting\JT808.Gateway.TestHosting.csproj", "{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808.Gateway.InMemoryMQ.Test", "JT808.Gateway.Tests\JT808.Gateway.InMemoryMQ.Test\JT808.Gateway.InMemoryMQ.Test.csproj", "{E103E89D-3069-4AAE-99CE-2AD633AD351E}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
@@ -45,10 +47,6 @@ Global | |||
{4C8A2546-8333-416D-B123-91062B630087}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{4C8A2546-8333-416D-B123-91062B630087}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{3AA17DF7-A1B3-449C-93C2-45B051C32933}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
@@ -89,27 +87,36 @@ Global | |||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{AC3070AC-A938-4213-A562-C079BB4A3F9E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{0FBC9E4F-8585-4820-ACF1-145A14B3A727}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{E3DC260E-0B55-4993-B051-402E44D4E883}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{E103E89D-3069-4AAE-99CE-2AD633AD351E}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
EndGlobalSection | |||
GlobalSection(NestedProjects) = preSolution | |||
{AE40AFE0-0950-442C-A74C-10CDF53E9F36} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||
{D62E3054-6924-4F1A-9BEF-E52B191F16B6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{A242A839-4F00-4434-A7E8-7E3BEBA5B75C} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{1CB84599-5F56-4461-A451-DF16E3854AB9} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{604BB5CF-9ED1-4D78-9328-59436E2B4EB4} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{598E445A-AF2E-42F0-98F4-18EC22E473FC} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{8FCC6D65-8A49-4AE7-8B19-F255100849D6} = {3EF8490D-C993-49D8-8A3D-493B7F259D70} | |||
{1E230D1B-BDFC-4D0A-9B34-592280A723BD} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||
{E3DC260E-0B55-4993-B051-402E44D4E883} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||
{69C815FE-3C32-473E-99C9-F3C4B3BCFF81} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||
{E103E89D-3069-4AAE-99CE-2AD633AD351E} = {7CBAACEE-19BF-499A-8C41-36A1324D45E9} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
SolutionGuid = {AA9303A7-6FB3-4572-88AA-3302E85330D1} | |||
@@ -16,7 +16,7 @@ namespace JT808.Gateway | |||
{ | |||
public static partial class JT808GatewayExtensions | |||
{ | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder,Action<JT808Configuration> config) | |||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jt808Builder,Action<JT808Configuration> config) | |||
{ | |||
IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | |||
server.JT808Builder.Services.Configure(config); | |||
@@ -24,7 +24,7 @@ namespace JT808.Gateway | |||
return server; | |||
} | |||
public static IJT808GatewayBuilder AddJT808Gateway(this IJT808Builder jt808Builder, IConfiguration configuration) | |||
public static IJT808GatewayBuilder AddGateway(this IJT808Builder jt808Builder, IConfiguration configuration) | |||
{ | |||
IJT808GatewayBuilder server = new JT808GatewayBuilderDefault(jt808Builder); | |||
server.JT808Builder.Services.Configure<JT808Configuration>(configuration.GetSection("JT808Configuration")); | |||
@@ -21,7 +21,7 @@ using Microsoft.Extensions.Options; | |||
namespace JT808.Gateway | |||
{ | |||
public class JT808TcpServer:IHostedService | |||
public class JT808TcpServer : IHostedService | |||
{ | |||
private readonly Socket server; | |||
@@ -44,34 +44,38 @@ namespace JT808.Gateway | |||
JT808SessionManager jT808SessionManager, | |||
IJT808MsgProducer jT808MsgProducer, | |||
JT808AtomicCounterServiceFactory jT808AtomicCounterServiceFactory) | |||
{ | |||
SessionManager = jT808SessionManager; | |||
Logger = loggerFactory.CreateLogger("JT808TcpServer"); | |||
Serializer = jT808Config.GetSerializer(); | |||
MsgProducer = jT808MsgProducer; | |||
AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp); | |||
Configuration = jT808ConfigurationAccessor.Value; | |||
var IPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, Configuration.TcpPort); | |||
server = new Socket(IPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); | |||
server.LingerState = new LingerOption(false, 0); | |||
server.Bind(IPEndPoint); | |||
server.Listen(Configuration.SoBacklog); | |||
} | |||
{ | |||
SessionManager = jT808SessionManager; | |||
Logger = loggerFactory.CreateLogger("JT808TcpServer"); | |||
Serializer = jT808Config.GetSerializer(); | |||
MsgProducer = jT808MsgProducer; | |||
AtomicCounterService = jT808AtomicCounterServiceFactory.Create(JT808TransportProtocolType.tcp); | |||
Configuration = jT808ConfigurationAccessor.Value; | |||
var IPEndPoint = new System.Net.IPEndPoint(IPAddress.Any, Configuration.TcpPort); | |||
server = new Socket(IPEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, true); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, Configuration.MiniNumBufferSize); | |||
server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, Configuration.MiniNumBufferSize); | |||
server.LingerState = new LingerOption(false, 0); | |||
server.Bind(IPEndPoint); | |||
server.Listen(Configuration.SoBacklog); | |||
} | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
Logger.LogInformation($"JT808 TCP Server start at {IPAddress.Any}:{Configuration.TcpPort}."); | |||
Task.Run(async() => { | |||
Task.Factory.StartNew(async () => | |||
{ | |||
while (!cancellationToken.IsCancellationRequested) | |||
{ | |||
var socket = await server.AcceptAsync(); | |||
JT808TcpSession jT808TcpSession = new JT808TcpSession(socket); | |||
SessionManager.TryAdd(jT808TcpSession); | |||
await Task.Factory.StartNew(async (state) => | |||
{ | |||
var session = (JT808TcpSession)state; | |||
SessionManager.TryAdd(session); | |||
if (Logger.IsEnabled(LogLevel.Information)) | |||
{ | |||
Logger.LogInformation($"[Connected]:{session.Client.RemoteEndPoint}"); | |||
@@ -86,7 +90,7 @@ namespace JT808.Gateway | |||
}, cancellationToken); | |||
return Task.CompletedTask; | |||
} | |||
private async Task FillPipeAsync(JT808TcpSession session, PipeWriter writer) | |||
private async Task FillPipeAsync(JT808TcpSession session, PipeWriter writer) | |||
{ | |||
while (true) | |||
{ | |||
@@ -101,7 +105,7 @@ namespace JT808.Gateway | |||
} | |||
writer.Advance(bytesRead); | |||
} | |||
catch(OperationCanceledException ex) | |||
catch (OperationCanceledException ex) | |||
{ | |||
Logger.LogError($"[Receive Timeout]:{session.Client.RemoteEndPoint}"); | |||
break; | |||
@@ -126,7 +130,7 @@ namespace JT808.Gateway | |||
} | |||
writer.Complete(); | |||
} | |||
private async Task ReadPipeAsync(JT808TcpSession session, PipeReader reader) | |||
private async Task ReadPipeAsync(JT808TcpSession session, PipeReader reader) | |||
{ | |||
while (true) | |||
{ | |||
@@ -143,13 +147,13 @@ namespace JT808.Gateway | |||
if (result.IsCanceled) break; | |||
if (buffer.Length > 0) | |||
{ | |||
ReaderBuffer(ref buffer, session,out consumed, out examined); | |||
ReaderBuffer(ref buffer, session, out consumed, out examined); | |||
} | |||
} | |||
#pragma warning disable CA1031 // Do not catch general exception types | |||
catch (Exception ex) | |||
{ | |||
SessionManager.RemoveBySessionId(session.SessionID); | |||
Logger.LogError(ex, $"[ReadPipe Error]:{session.Client.RemoteEndPoint}"); | |||
break; | |||
} | |||
#pragma warning restore CA1031 // Do not catch general exception types | |||
@@ -160,7 +164,7 @@ namespace JT808.Gateway | |||
} | |||
reader.Complete(); | |||
} | |||
private void ReaderBuffer(ref ReadOnlySequence<byte> buffer, JT808TcpSession session, out SequencePosition consumed, out SequencePosition examined) | |||
private void ReaderBuffer(ref ReadOnlySequence<byte> buffer, JT808TcpSession session, out SequencePosition consumed, out SequencePosition examined) | |||
{ | |||
consumed = buffer.Start; | |||
examined = buffer.End; | |||
@@ -177,22 +181,22 @@ namespace JT808.Gateway | |||
{ | |||
if (mark == 1) | |||
{ | |||
ReadOnlySpan<byte> contentSpan=ReadOnlySpan<byte>.Empty; | |||
ReadOnlySpan<byte> contentSpan = ReadOnlySpan<byte>.Empty; | |||
try | |||
{ | |||
contentSpan = seqReader.Sequence.Slice(totalConsumed, seqReader.Consumed - totalConsumed).FirstSpan; | |||
var package = Serializer.HeaderDeserialize(contentSpan,minBufferSize:10240); | |||
var package = Serializer.HeaderDeserialize(contentSpan, minBufferSize: 10240); | |||
AtomicCounterService.MsgSuccessIncrement(); | |||
if (Logger.IsEnabled(LogLevel.Debug)) Logger.LogDebug($"[Atomic Success Counter]:{AtomicCounterService.MsgSuccessCount}"); | |||
if (Logger.IsEnabled(LogLevel.Trace)) Logger.LogTrace($"[Accept Hex {session.Client.RemoteEndPoint}]:{package.OriginalData.ToArray().ToHexString()}"); | |||
SessionManager.TryLink(package.Header.TerminalPhoneNo, session); | |||
MsgProducer.ProduceAsync(package.Header.TerminalPhoneNo, package.OriginalData.ToArray()); | |||
MsgProducer.ProduceAsync(package.Header.TerminalPhoneNo, package.OriginalData.ToArray()); | |||
} | |||
catch (JT808Exception ex) | |||
{ | |||
AtomicCounterService.MsgFailIncrement(); | |||
if (Logger.IsEnabled(LogLevel.Information)) Logger.LogInformation($"[Atomic Fail Counter]:{AtomicCounterService.MsgFailCount}"); | |||
Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{contentSpan.ToArray().ToHexString()}"); | |||
Logger.LogError($"[HeaderDeserialize ErrorCode]:{ ex.ErrorCode},[ReaderBuffer]:{contentSpan.ToArray().ToHexString()}"); | |||
} | |||
totalConsumed += (seqReader.Consumed - totalConsumed); | |||
if (seqReader.End) break; | |||
@@ -206,7 +210,7 @@ namespace JT808.Gateway | |||
seqReader.Advance(1); | |||
} | |||
} | |||
if (seqReader.Length== totalConsumed) | |||
if (seqReader.Length == totalConsumed) | |||
{ | |||
examined = consumed = buffer.End; | |||
} | |||
@@ -93,17 +93,17 @@ namespace JT808.Gateway.Services | |||
return Task.FromResult(reply); | |||
} | |||
public override Task<UnificationSendReply> UnificationSend(UnificationSendRequest request, ServerCallContext context) | |||
public override async Task<UnificationSendReply> UnificationSend(UnificationSendRequest request, ServerCallContext context) | |||
{ | |||
Auth(context); | |||
try | |||
{ | |||
var flag = jT808SessionManager.TrySendByTerminalPhoneNo(request.TerminalPhoneNo, request.Data.ToByteArray()); | |||
return Task.FromResult(new UnificationSendReply { Success = flag }); | |||
var flag = await jT808SessionManager.TrySendByTerminalPhoneNoAsync(request.TerminalPhoneNo, request.Data.ToByteArray()); | |||
return new UnificationSendReply { Success = flag }; | |||
} | |||
catch (Exception) | |||
{ | |||
return Task.FromResult(new UnificationSendReply { Success = false }); | |||
return new UnificationSendReply { Success = false }; | |||
} | |||
} | |||
@@ -2,6 +2,9 @@ | |||
using JT808.Gateway.Configurations; | |||
using JT808.Gateway.Session; | |||
using Microsoft.Extensions.Hosting; | |||
using Microsoft.Extensions.Logging; | |||
using System; | |||
using System.Diagnostics; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
@@ -12,6 +15,7 @@ namespace JT808.Gateway.Services | |||
private readonly JT808SessionManager JT808SessionManager; | |||
private readonly IJT808MsgReplyConsumer JT808MsgReplyConsumer; | |||
public JT808MsgReplyHostedService( | |||
IJT808MsgReplyConsumer jT808MsgReplyConsumer, | |||
JT808SessionManager jT808SessionManager) | |||
@@ -22,9 +26,9 @@ namespace JT808.Gateway.Services | |||
public Task StartAsync(CancellationToken cancellationToken) | |||
{ | |||
JT808MsgReplyConsumer.OnMessage(item => | |||
JT808MsgReplyConsumer.OnMessage(async(item) => | |||
{ | |||
JT808SessionManager.TrySendByTerminalPhoneNo(item.TerminalNo, item.Data); | |||
await JT808SessionManager.TrySendByTerminalPhoneNoAsync(item.TerminalNo, item.Data); | |||
}); | |||
JT808MsgReplyConsumer.Subscribe(); | |||
return Task.CompletedTask; | |||
@@ -8,6 +8,7 @@ using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Threading.Tasks; | |||
namespace JT808.Gateway.Session | |||
{ | |||
@@ -66,36 +67,40 @@ namespace JT808.Gateway.Session | |||
internal void TryLink(string terminalPhoneNo, IJT808Session session) | |||
{ | |||
DateTime curretDatetime= DateTime.Now; | |||
session.ActiveTime = curretDatetime; | |||
session.TerminalPhoneNo = terminalPhoneNo; | |||
Sessions.TryUpdate(session.SessionID, session, session); | |||
TerminalPhoneNoSessions.AddOrUpdate(terminalPhoneNo, session, (key, oldValue)=> | |||
if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out IJT808Session cacheSession)) | |||
{ | |||
if(session.SessionID!= oldValue.SessionID) | |||
if (session.SessionID != cacheSession.SessionID) | |||
{ | |||
//从转发到直连的数据需要更新缓存 | |||
session.ActiveTime = curretDatetime; | |||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, session, cacheSession); | |||
//会话通知 | |||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, key); | |||
return session; | |||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); | |||
} | |||
else | |||
{ | |||
oldValue.StartTime = curretDatetime; | |||
cacheSession.ActiveTime = curretDatetime; | |||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, cacheSession, cacheSession); | |||
} | |||
return oldValue; | |||
}); | |||
} | |||
else | |||
{ | |||
if(TerminalPhoneNoSessions.TryAdd(terminalPhoneNo, session)) | |||
{ | |||
//会话通知 | |||
JT808SessionProducer?.ProduceAsync(JT808GatewayConstants.SessionOnline, terminalPhoneNo); | |||
} | |||
} | |||
} | |||
public IJT808Session TryLink(string terminalPhoneNo, Socket socket, EndPoint remoteEndPoint) | |||
{ | |||
if (TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo, out IJT808Session currentSession)) | |||
{ | |||
if (Sessions.TryGetValue(currentSession.SessionID, out IJT808Session sessionInfo)) | |||
{ | |||
sessionInfo.ActiveTime = DateTime.Now; | |||
sessionInfo.TerminalPhoneNo = terminalPhoneNo; | |||
sessionInfo.RemoteEndPoint = remoteEndPoint; | |||
Sessions.TryUpdate(currentSession.SessionID, sessionInfo, sessionInfo); | |||
} | |||
currentSession.ActiveTime = DateTime.Now; | |||
currentSession.TerminalPhoneNo = terminalPhoneNo; | |||
currentSession.RemoteEndPoint = remoteEndPoint; | |||
TerminalPhoneNoSessions.TryUpdate(terminalPhoneNo, currentSession, currentSession); | |||
} | |||
else | |||
{ | |||
@@ -118,17 +123,17 @@ namespace JT808.Gateway.Session | |||
return Sessions.TryAdd(session.SessionID, session); | |||
} | |||
public bool TrySendByTerminalPhoneNo(string terminalPhoneNo, byte[] data) | |||
public async ValueTask<bool> TrySendByTerminalPhoneNoAsync(string terminalPhoneNo, byte[] data) | |||
{ | |||
if(TerminalPhoneNoSessions.TryGetValue(terminalPhoneNo,out var session)) | |||
{ | |||
if (session.TransportProtocolType == JT808TransportProtocolType.tcp) | |||
{ | |||
session.Client.Send(data, SocketFlags.None); | |||
await session.Client.SendAsync(data, SocketFlags.None); | |||
} | |||
else | |||
{ | |||
session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); | |||
await session.Client.SendToAsync(data, SocketFlags.None, session.RemoteEndPoint); | |||
} | |||
return true; | |||
} | |||
@@ -138,17 +143,17 @@ namespace JT808.Gateway.Session | |||
} | |||
} | |||
public bool TrySendBySessionId(string sessionId, byte[] data) | |||
public async ValueTask<bool> TrySendBySessionIdAsync(string sessionId, byte[] data) | |||
{ | |||
if (Sessions.TryGetValue(sessionId, out var session)) | |||
{ | |||
if(session.TransportProtocolType== JT808TransportProtocolType.tcp) | |||
{ | |||
session.Client.Send(data, SocketFlags.None); | |||
await session.Client.SendAsync(data, SocketFlags.None); | |||
} | |||
else | |||
{ | |||
session.Client.SendTo(data, SocketFlags.None, session.RemoteEndPoint); | |||
await session.Client.SendToAsync(data, SocketFlags.None, session.RemoteEndPoint); | |||
} | |||
return true; | |||
} | |||
@@ -208,12 +213,12 @@ namespace JT808.Gateway.Session | |||
public List<JT808TcpSession> GetTcpAll() | |||
{ | |||
return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.tcp).Select(s => (JT808TcpSession)s.Value).ToList(); | |||
return TerminalPhoneNoSessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.tcp).Select(s => (JT808TcpSession)s.Value).ToList(); | |||
} | |||
public List<JT808UdpSession> GetUdpAll() | |||
{ | |||
return Sessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.udp).Select(s => (JT808UdpSession)s.Value).ToList(); | |||
return TerminalPhoneNoSessions.Where(w => w.Value.TransportProtocolType == JT808TransportProtocolType.udp).Select(s => (JT808UdpSession)s.Value).ToList(); | |||
} | |||
} | |||
} |