Ver código fonte

第一次提交

master
杨雷 6 meses atrás
commit
96808327c6
46 arquivos alterados com 2852 adições e 0 exclusões
  1. +30
    -0
      .dockerignore
  2. +340
    -0
      .gitignore
  3. +460
    -0
      TelpoPush.Common/HttpHelperAsync.cs
  4. +137
    -0
      TelpoPush.Common/LimitedConcurrencyLevelTaskScheduler.cs
  5. +14
    -0
      TelpoPush.Common/TelpoPush.Common.csproj
  6. +28
    -0
      TelpoPush.Common/TimeHelper.cs
  7. +19
    -0
      TelpoPush.Models/CacheTemplates/ManufactorKafkaModel.cs
  8. +94
    -0
      TelpoPush.Models/Config/RedisConfig.cs
  9. +32
    -0
      TelpoPush.Models/Config/ServiceConfig.cs
  10. +16
    -0
      TelpoPush.Models/Dto/HeadersDto.cs
  11. +26
    -0
      TelpoPush.Models/Dto/MqHeader.cs
  12. +19
    -0
      TelpoPush.Models/Enum/MqDataTopic.cs
  13. +152
    -0
      TelpoPush.Models/Enum/MqDataType.cs
  14. +18
    -0
      TelpoPush.Models/MqTemplates/BaseModel.cs
  15. +41
    -0
      TelpoPush.Models/MqTemplates/ZkRealHeartRatesTemplate.cs
  16. +18
    -0
      TelpoPush.Models/PushTemplates/WxModel.cs
  17. +13
    -0
      TelpoPush.Models/TelpoPush.Models.csproj
  18. +22
    -0
      TelpoPush.Service/Biz/IZkRealHRMonitorService.cs
  19. +82
    -0
      TelpoPush.Service/Biz/Impl/ZkRealHRMonitorService.cs
  20. +82
    -0
      TelpoPush.Service/Cache/MemoryCacheUtil.cs
  21. +134
    -0
      TelpoPush.Service/Cache/RedisUtil.cs
  22. +37
    -0
      TelpoPush.Service/Cache/SqlMapper.cs
  23. +9
    -0
      TelpoPush.Service/Mq/Kafka/IKafkaService.cs
  24. +15
    -0
      TelpoPush.Service/Mq/Kafka/KafkaHeader.cs
  25. +138
    -0
      TelpoPush.Service/Mq/Kafka/KafkaService.cs
  26. +78
    -0
      TelpoPush.Service/Mq/Kafka/MessageProducer.cs
  27. +87
    -0
      TelpoPush.Service/Mq/Kafka/MqProcessMessage.cs
  28. +15
    -0
      TelpoPush.Service/Mq/Kafka/TopicModel.cs
  29. +29
    -0
      TelpoPush.Service/TelpoPush.Service.csproj
  30. +40
    -0
      TelpoPush.Worker.ThirdSsl/Dockerfile
  31. +67
    -0
      TelpoPush.Worker.ThirdSsl/Handlers/KafkaSubscribe.cs
  32. +71
    -0
      TelpoPush.Worker.ThirdSsl/Handlers/ThirdSslProcess.cs
  33. +103
    -0
      TelpoPush.Worker.ThirdSsl/Program.cs
  34. +15
    -0
      TelpoPush.Worker.ThirdSsl/Properties/launchSettings.json
  35. +26
    -0
      TelpoPush.Worker.ThirdSsl/TelpoPush.Worker.ThirdSsl.csproj
  36. +28
    -0
      TelpoPush.Worker.ThirdSsl/Worker.cs
  37. +34
    -0
      TelpoPush.Worker.ThirdSsl/appsettings.Development.json
  38. +77
    -0
      TelpoPush.Worker.ThirdSsl/appsettings.json
  39. +31
    -0
      TelpoPush.Worker.ThirdSsl/appsettings.production.json
  40. +34
    -0
      TelpoPush.Worker.ThirdSsl/appsettings.test.json
  41. +43
    -0
      TelpoPushThirdSsl.sln
  42. +7
    -0
      nuget.config
  43. +29
    -0
      pem/ca-root.pem
  44. +18
    -0
      setup_production.sh
  45. +17
    -0
      setup_test.sh
  46. +27
    -0
      telpo_push_third_ssl_run.sh

+ 30
- 0
.dockerignore Ver arquivo

@@ -0,0 +1,30 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**

+ 340
- 0
.gitignore Ver arquivo

@@ -0,0 +1,340 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# BeatPulse healthcheck temp database
healthchecksdb

+ 460
- 0
TelpoPush.Common/HttpHelperAsync.cs Ver arquivo

@@ -0,0 +1,460 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Common
{
/// <summary>
/// HTTP帮助类
/// </summary>
public class HttpHelperAsync
{
private IHttpClientFactory _httpClientFactory;
private readonly ILogger<HttpHelperAsync> _logger;
public HttpHelperAsync(IHttpClientFactory httpClientFactory, ILogger<HttpHelperAsync> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}


#region 异步
/// <summary>
/// 发起POST异步请求表单
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="body">POST提交的内容</param>
/// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
/// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回string</returns>
public async Task<string> PostFormAsync(string url, MultipartFormDataContent content,
Dictionary<string, string> headers = null,
int timeOut = 5)
{
try
{
var hostName = GetHostName(url);
using (HttpClient client = _httpClientFactory.CreateClient(hostName))
{
client.Timeout = TimeSpan.FromSeconds(timeOut);
if (headers?.Count > 0)
{
foreach (string key in headers.Keys)
{
client.DefaultRequestHeaders.Add(key, headers[key]);
}
}
content.Headers.Add("ContentType", "multipart/form-data");//声明头部
using (HttpResponseMessage response = await client.PostAsync(url, content))
{
return JsonConvert.SerializeObject(new { response.IsSuccessStatusCode, response.StatusCode });
//if (response.IsSuccessStatusCode)
//{
// string responseString = await response.Content.ReadAsStringAsync();
// return responseString;
//}
//else
//{
// return string.Empty;
//}
}
}
}
catch (Exception ex)
{
return $"推送完成:请求响应超过{timeOut}秒,异常 {ex.Message}";
}
}



/// <summary>
/// 发起GET异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回string</returns>
public async Task<string> GetAsync(string url, Dictionary<string, string> headers = null, int timeOut = 30)
{
var hostName = GetHostName(url);
using (HttpClient client = _httpClientFactory.CreateClient(hostName))
{
client.Timeout = TimeSpan.FromSeconds(timeOut);
if (headers?.Count > 0)
{
foreach (string key in headers.Keys)
{
client.DefaultRequestHeaders.Add(key, headers[key]);
}
}
using (HttpResponseMessage response = await client.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
else
{
return string.Empty;
}
}
}
}


/// <summary>
/// 发起POST异步请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="body">POST提交的内容</param>
/// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
/// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回string</returns>
public async Task<string> PostAsync(string url, string body,
Dictionary<string, string> headers = null,
int timeOut = 30,
string bodyMediaType = "application/json",
string responseContentType = "application/json;charset=utf-8")
{

//content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

//var clientHandler = new HttpClientHandler
//{
// ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true
//};
//using (var client = new HttpClient(clientHandler))
//{
// client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

try
{
var hostName = GetHostName(url);
using (HttpClient client = _httpClientFactory.CreateClient(hostName))
{
client.Timeout = TimeSpan.FromSeconds(timeOut);
if (headers?.Count > 0)
{
foreach (string key in headers.Keys)
{
client.DefaultRequestHeaders.Add(key, headers[key]);
}
}
StringContent content = new StringContent(body, System.Text.Encoding.UTF8, mediaType: bodyMediaType);
if (!string.IsNullOrWhiteSpace(responseContentType))
{
content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(responseContentType);
}
using (HttpResponseMessage response = await client.PostAsync(url, content))
{
if (response.IsSuccessStatusCode)
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
else
return $"请求异常:{response.IsSuccessStatusCode},{response.StatusCode}";
}
}
}
catch(Exception ex)
{
return $"请求异常:{ex.Message}";
}
}

/// <summary>
/// 发起POST异步请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="body">POST提交的内容</param>
/// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
/// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回string</returns>
public async Task<string> PutAsync(string url, string body,
string bodyMediaType = null,
string responseContentType = null,
Dictionary<string, string> headers = null,
int timeOut = 30)
{
var hostName = GetHostName(url);
using (HttpClient client = _httpClientFactory.CreateClient(hostName))
{
client.Timeout = TimeSpan.FromSeconds(timeOut);
if (headers?.Count > 0)
{
foreach (string key in headers.Keys)
{
client.DefaultRequestHeaders.Add(key, headers[key]);
}
}
StringContent content = new StringContent(body, System.Text.Encoding.UTF8, mediaType: bodyMediaType);
if (!string.IsNullOrWhiteSpace(responseContentType))
{
content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(responseContentType);
}
using (HttpResponseMessage response = await client.PutAsync(url, content))
{
if (response.IsSuccessStatusCode)
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
else
{
return string.Empty;
}
}
}
}

/// <summary>
/// 发起GET异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回string</returns>
public async Task<string> DeleteAsync(string url, Dictionary<string, string> headers = null, int timeOut = 30)
{
var hostName = GetHostName(url);
using (HttpClient client = _httpClientFactory.CreateClient(hostName))
{
client.Timeout = TimeSpan.FromSeconds(timeOut);
if (headers?.Count > 0)
{
foreach (string key in headers.Keys)
{
client.DefaultRequestHeaders.Add(key, headers[key]);
}
}
using (HttpResponseMessage response = await client.DeleteAsync(url))
{
if (response.IsSuccessStatusCode)
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
else
{
return string.Empty;
}
}
}
}

/// <summary>
/// 发起GET异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回T</returns>
public async Task<T> GetAsync<T>(string url, Dictionary<string, string> headers = null, int timeOut = 30) where T : new()
{
string responseString = await GetAsync(url, headers, timeOut);
if (!string.IsNullOrWhiteSpace(responseString))
{
return JsonConvert.DeserializeObject<T>(responseString);
}
else
{
return default(T);
}
}


/// <summary>
/// 发起POST异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="body">POST提交的内容</param>
/// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
/// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回T</returns>
public async Task<T> PostAsync<T>(string url, string body,
Dictionary<string, string> headers = null,
int timeOut = 30,
string bodyMediaType = "application/json",
string responseContentType = "application/json;charset=utf-8"
) where T : new()
{
string responseString = await PostAsync(url, body, headers, timeOut, bodyMediaType, responseContentType);
if (!string.IsNullOrWhiteSpace(responseString))
{
return JsonConvert.DeserializeObject<T>(responseString);
}
else
{
return default(T);
}
}

/// <summary>
/// 发起PUT异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="body">POST提交的内容</param>
/// <param name="bodyMediaType">POST内容的媒体类型,如:application/xml、application/json</param>
/// <param name="responseContentType">HTTP响应上的content-type内容头的值,如:application/xml、application/json、application/text、application/x-www-form-urlencoded等</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回T</returns>
public async Task<T> PutAsync<T>(string url, string body,
string bodyMediaType = null,
string responseContentType = null,
Dictionary<string, string> headers = null,
int timeOut = 30) where T : new()
{
string responseString = await PutAsync(url, body, bodyMediaType, responseContentType, headers, timeOut);
if (!string.IsNullOrWhiteSpace(responseString))
{
return JsonConvert.DeserializeObject<T>(responseString);
}
else
{
return default(T);
}
}

/// <summary>
/// 发起DELETE异步请求
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="url">请求地址</param>
/// <param name="headers">请求头信息</param>
/// <param name="timeOut">请求超时时间,单位秒</param>
/// <returns>返回T</returns>
public async Task<T> DeleteAsync<T>(string url, Dictionary<string, string> headers = null, int timeOut = 30) where T : new()
{
string responseString = await DeleteAsync(url, headers, timeOut);
if (!string.IsNullOrWhiteSpace(responseString))
{
return JsonConvert.DeserializeObject<T>(responseString);
}
else
{
return default(T);
}
}
#region 私有函数

/// <summary>
/// 获取请求的主机名
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private static string GetHostName(string url)
{
if (!string.IsNullOrWhiteSpace(url))
{
return url.Replace("https://", "").Replace("http://", "").Split('/')[0];
}
else
{
return "AnyHost";
}
}

#endregion


#endregion

#region 同步

/// <summary>
/// 发起GET同步请求
/// </summary>
/// <param name="url"></param>
/// <param name="headers"></param>
/// <param name="contentType"></param>
/// <returns></returns>
///


public string HttpGet(string url, Dictionary<string, string> headers = null, string contentType = "application/json;charset=utf-8")
{
if (string.IsNullOrEmpty(url)) return "";
try
{
using (HttpClient client = new HttpClient())
{
if (contentType != null)
client.DefaultRequestHeaders.Add("ContentType", contentType);
if (headers != null)
{
foreach (var header in headers)
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
HttpResponseMessage response = client.GetAsync(url).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
catch (Exception ex)
{
_logger.LogDebug($"HttpGet/URL:{url},headers:{JsonConvert.SerializeObject(headers)},异常:{ex.Message}|{ex.Source}|{ex.StackTrace}");
}
return "";
}
/// <summary>
/// 发起POST同步请求
/// </summary>
/// <param name="url"></param>
/// <param name="postData"></param>
/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
/// <param name="headers">填充消息头</param>
/// <returns></returns>
public string HttpPost(string url, string postData = null, Dictionary<string, string> headers = null, string contentType = "application/json")
{
if (string.IsNullOrEmpty(url)) return "";
try
{
postData = postData ?? "";
using (HttpClient client = new HttpClient())
{
if (headers != null)
{
foreach (var header in headers)
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
{
if (contentType != null)
httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);

HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
}
catch (Exception ex){
_logger.LogDebug($"HttpPost/URL:{url},postStr:{postData},headers:{JsonConvert.SerializeObject(headers)},异常:{ex.Message}|{ex.Source}|{ex.StackTrace}");
}
return "";
}

#endregion
}
}

+ 137
- 0
TelpoPush.Common/LimitedConcurrencyLevelTaskScheduler.cs Ver arquivo

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace TelpoPush.Common
{
/// <summary>
/// Provides a task scheduler that ensures a maximum concurrency level while
/// running on top of the ThreadPool.
/// </summary>
public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
{
/// <summary>Whether the current thread is processing work items.</summary>
[ThreadStatic]
private static bool _currentThreadIsProcessingItems;
/// <summary>The list of tasks to be executed.</summary>
private readonly LinkedList<Task> _tasks = new LinkedList<Task>(); // protected by lock(_tasks)
/// <summary>The maximum concurrency level allowed by this scheduler.</summary>
private readonly int _maxDegreeOfParallelism;
/// <summary>Whether the scheduler is currently processing work items.</summary>
private int _delegatesQueuedOrRunning = 0; // protected by lock(_tasks)

/// <summary>
/// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
/// specified degree of parallelism.
/// </summary>
/// <param name="maxDegreeOfParallelism">The maximum degree of parallelism provided by this scheduler.</param>
public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
{
if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
_maxDegreeOfParallelism = maxDegreeOfParallelism;
}

/// <summary>Queues a task to the scheduler.</summary>
/// <param name="task">The task to be queued.</param>
protected sealed override void QueueTask(Task task)
{
// Add the task to the list of tasks to be processed. If there aren't enough
// delegates currently queued or running to process tasks, schedule another.
lock (_tasks)
{
_tasks.AddLast(task);
if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
{
++_delegatesQueuedOrRunning;
NotifyThreadPoolOfPendingWork();
}
}
}

/// <summary>
/// Informs the ThreadPool that there's work to be executed for this scheduler.
/// </summary>
private void NotifyThreadPoolOfPendingWork()
{
ThreadPool.UnsafeQueueUserWorkItem(_ =>
{
// Note that the current thread is now processing work items.
// This is necessary to enable inlining of tasks into this thread.
_currentThreadIsProcessingItems = true;
try
{
// Process all available items in the queue.
while (true)
{
Task item;
lock (_tasks)
{
// When there are no more items to be processed,
// note that we're done processing, and get out.
if (_tasks.Count == 0)
{
--_delegatesQueuedOrRunning;
break;
}

// Get the next item from the queue
item = _tasks.First.Value;
_tasks.RemoveFirst();
}

// Execute the task we pulled out of the queue
base.TryExecuteTask(item);
}
}
// We're done processing items on the current thread
finally { _currentThreadIsProcessingItems = false; }
}, null);
}

/// <summary>Attempts to execute the specified task on the current thread.</summary>
/// <param name="task">The task to be executed.</param>
/// <param name="taskWasPreviouslyQueued"></param>
/// <returns>Whether the task could be executed on the current thread.</returns>
protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
// If this thread isn't already processing a task, we don't support inlining
if (!_currentThreadIsProcessingItems) return false;

// If the task was previously queued, remove it from the queue
if (taskWasPreviouslyQueued) TryDequeue(task);

// Try to run the task.
return base.TryExecuteTask(task);
}

/// <summary>Attempts to remove a previously scheduled task from the scheduler.</summary>
/// <param name="task">The task to be removed.</param>
/// <returns>Whether the task could be found and removed.</returns>
protected sealed override bool TryDequeue(Task task)
{
lock (_tasks) return _tasks.Remove(task);
}

/// <summary>Gets the maximum concurrency level supported by this scheduler.</summary>
public sealed override int MaximumConcurrencyLevel { get { return _maxDegreeOfParallelism; } }

/// <summary>Gets an enumerable of the tasks currently scheduled on this scheduler.</summary>
/// <returns>An enumerable of the tasks currently scheduled.</returns>
protected sealed override IEnumerable<Task> GetScheduledTasks()
{
bool lockTaken = false;
try
{
Monitor.TryEnter(_tasks, ref lockTaken);
if (lockTaken) return _tasks.ToArray();
else throw new NotSupportedException();
}
finally
{
if (lockTaken) Monitor.Exit(_tasks);
}
}
}
}

+ 14
- 0
TelpoPush.Common/TelpoPush.Common.csproj Ver arquivo

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="TelpoDataService.Util" Version="1.6.9.27-beta1" />
</ItemGroup>

</Project>

+ 28
- 0
TelpoPush.Common/TimeHelper.cs Ver arquivo

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Common
{
public class TimeHelper
{
/// <summary>
/// 时间戳转成时间类型
/// </summary>
/// <param name="timeStamp"></param>
/// <returns></returns>
public static DateTime ConvertToLocalDateTime(string timeStamp)
{
DateTime dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1), TimeZoneInfo.Utc, TimeZoneInfo.Local);
if (timeStamp.Length == 13)
{
long lTime = long.Parse(timeStamp + "0000");
TimeSpan toNow = new TimeSpan(lTime);
return dtStart.Add(toNow);
}
return dtStart.AddSeconds(long.Parse(timeStamp));
}
}
}

+ 19
- 0
TelpoPush.Models/CacheTemplates/ManufactorKafkaModel.cs Ver arquivo

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.CacheTemplates
{
public class ManufactorKafkaModel
{
public string manufactorId { get; set; }
public string manufactorName { get; set; }
public string kafkaServers { get; set; }
public string kafkaTopic { get; set; }
public string kafkaGroup { get; set; }
public string kafkaUsername { get; set; }
public string kafkaPassword { get; set; }
}
}

+ 94
- 0
TelpoPush.Models/Config/RedisConfig.cs Ver arquivo

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.Config
{
/// <summary>
/// Redis配置模板类
/// </summary>
public class RedisConfig
{
public string Server { get; set; }
/// <summary>
/// Redis server password
/// </summary>
public string Password { get; set; }
/// <summary>
/// Redis server database, default 0
/// </summary>
public int? DefaultDatabase { get; set; }
/// <summary>
/// The asynchronous method automatically uses pipeline, and the 10W concurrent time is 450ms(welcome to feedback)
/// </summary>
public bool? AsyncPipeline { get; set; }
/// <summary>
/// Connection pool size, default 50
/// </summary>
public int? Poolsize { get; set; }
/// <summary>
/// Idle time of elements in the connection pool(MS), suitable for connecting to remote redis server, default 20000
/// </summary>
public int? IdleTimeout { get; set; }
/// <summary>
/// Connection timeout(MS), default 5000
/// </summary>
public int? ConnectTimeout { get; set; }
/// <summary>
/// Send / receive timeout(MS), default 10000
/// </summary>
public int? SyncTimeout { get; set; }
/// <summary>
/// Preheat connections, receive values such as preheat = 5 preheat 5 connections, default 5
/// </summary>
public int? Preheat { get; set; }
/// <summary>
/// Follow system exit event to release automatically, default true
/// </summary>
public bool? AutoDispose { get; set; }
/// <summary>
/// Enable encrypted transmission, default false
/// </summary>
public bool? Ssl { get; set; }
/// <summary>
/// 是否尝试集群模式,阿里云、腾讯云集群需要设置此选项为 false, default true
/// </summary>
public bool? Testcluster { get; set; }
/// <summary>
/// Execution error, retry attempts, default 0
/// </summary>
public int? Tryit { get; set; }
/// <summary>
/// Connection name, use client list command to view
/// </summary>
public string Name { get; set; }
/// <summary>
/// key前辍,所有方法都会附带此前辍,csredis.Set(prefix + "key", 111)
/// </summary>
public string Prefix { get; set; }

public override string ToString()
{
if (string.IsNullOrWhiteSpace(Server)) throw new ArgumentNullException(nameof(Server));
var sb = new StringBuilder(Server);
if (!string.IsNullOrWhiteSpace(Password)) sb.Append($",password={Password}");
if (DefaultDatabase.HasValue) sb.Append($",defaultDatabase={DefaultDatabase}");
if (AsyncPipeline.HasValue) sb.Append($",asyncPipeline={AsyncPipeline}");
if (Poolsize.HasValue) sb.Append($",poolsize={Poolsize}");
if (IdleTimeout.HasValue) sb.Append($",idleTimeout={IdleTimeout}");
if (ConnectTimeout.HasValue) sb.Append($",connectTimeout={ConnectTimeout}");
if (SyncTimeout.HasValue) sb.Append($",syncTimeout={0}");
if (Preheat.HasValue) sb.Append($",preheat={Preheat}");
if (AutoDispose.HasValue) sb.Append($",autoDispose={AutoDispose}");
if (Ssl.HasValue) sb.Append($",ssl={Ssl}");
if (Testcluster.HasValue) sb.Append($",testcluster={Testcluster}");
if (Tryit.HasValue) sb.Append($",tryit={Tryit}");
if (!string.IsNullOrWhiteSpace(Name)) sb.Append($",name={Name}");
if (!string.IsNullOrWhiteSpace(Prefix)) sb.Append($",prefix={Prefix}");

return sb.ToString();
}
}
}

+ 32
- 0
TelpoPush.Models/Config/ServiceConfig.cs Ver arquivo

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.Config
{
public class ServiceConfig
{
/// <summary>
/// 数据服务Host Url
/// </summary>
public string TelpoDataUrl { get; set; }

/// <summary>
/// Kafka服务地址
/// </summary>
public string KafkaBootstrapServers { get; set; }
public List<string> KafkaTopics { get; set; }
public string KafkaGroupId { get; set; }
public string KafkaSaslUsername { get; set; }
public string KafkaSaslPassword { get; set; }
public string KafkaSslCaLocation { get; set; }

/// <summary>
/// 默认缓存时间
/// </summary>
public int CacheDurationSeconds { get; set; }
public int CacheDurationSeconds10 { get; set; }
}
}

+ 16
- 0
TelpoPush.Models/Dto/HeadersDto.cs Ver arquivo

@@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace TelpoPush.Models.Dto
{
/// <summary>
/// 消息数据头
/// </summary>
public class HeadersDto
{
[JsonProperty(PropertyName = "DataType")]
public int? DataType { get; set; }
[JsonProperty(PropertyName = "AlarmType")]
public int? AlarmType { get; set; }
[JsonProperty(PropertyName = "OperType")]
public int? OperType { get; set; }
}
}

+ 26
- 0
TelpoPush.Models/Dto/MqHeader.cs Ver arquivo

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.Dto
{
public static class MqHeader
{
/// <summary>
/// DataType
/// </summary>
public const string DataType = "DataType";

/// <summary>
/// OperType
/// </summary>
public const string OperType = "OperType";

/// <summary>
/// AlarmType
/// </summary>
public const string AlarmTypes = "AlarmType";
}
}

+ 19
- 0
TelpoPush.Models/Enum/MqDataTopic.cs Ver arquivo

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.Enum
{

public enum MqDataTopic : int
{
/// <summary>
/// 中高实时心率
/// </summary>
ZkRealHRMonitorTopic = 1


}
}

+ 152
- 0
TelpoPush.Models/Enum/MqDataType.cs Ver arquivo

@@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.Enum
{
/// <summary>
/// 数据类型,标识发布到kafka的消息的数据类型
/// </summary>
public enum MqDataType : int
{
/// <summary>
/// 报警消息
/// </summary>
AlarmInfo = 0,

/// <summary>
/// 温度数据信息
/// </summary>
TemperatureInfo = 1,

/// <summary>
/// 步数信息
/// </summary>
StepInfo = 2,

/// <summary>
/// 电量信息
/// </summary>
BatteryLevelInfo = 3,

/// <summary>
/// 设备配置信息
/// </summary>
DeviceConfigInfo = 4,

/// <summary>
/// 设备通话记录
/// </summary>
DeviceCallLog = 5,

/// <summary>
/// 设备短信记录
/// </summary>
DeviceSmsLog = 6,

/// <summary>
/// 位置信息
/// </summary>
PositionInfo = 7,

/// <summary>
/// 支付
/// </summary>
PayInfo = 8,

/// <summary>
/// 设备状态(offline,online)
/// </summary>
Status = 9,

/// <summary>
/// 设备激活状态(激活1,未激活0)
/// </summary>
Active = 10,

/// <summary>
/// 指令回调
/// </summary>
reply = 11,

/// <summary>
/// 天气查询
/// </summary>
Weather = 12,

/// <summary>
/// 短信阅读事件
/// </summary>
ReadMsg = 13,
/// <summary>
/// 学习能力状态上报事件
/// </summary>
StudyAINotifyStatusUpload = 14,
/// <summary>
/// 心率
/// </summary>
HeartRateInfo = 15,
/// <summary>
/// 血氧
/// </summary>
Spo2Info = 16,
/// <summary>
/// 周期性报体温数据。
/// </summary>
Temperature1Info = 17,
/// <summary>
/// 周期心率。
/// </summary>
HeartRate1Info = 18,
/// <summary>
/// 周期性血氧
/// </summary>
Spo21Info = 19,
/// <summary>
/// 溺水状态
/// </summary>
DrownReportInfo = 20,
/// <summary>
/// 手表佩戴状态
/// </summary>
WearStatusInfo = 21,
/// <summary>
/// 血压
/// </summary>
BloodPressInfo = 22,
/// <summary>
/// 周期性血压
/// </summary>
BloodPress1Info = 23,
/// <summary>
/// 心理监测
/// </summary>
PsychInfo = 24,

/// <summary>
/// AI呼叫回调结果
/// </summary>
AiCallResult = 25,

/// <summary>
/// 越界上报(围栏进出告警)
/// </summary>
CrossBorder = 26,

/// <summary>
/// 运动数据上报
/// </summary>
SportResult = 27,
/// <summary>
/// 运动数据上报
/// </summary>
BloodSugar = 28,

/// <summary>
/// 绑定业务
/// </summary>
BindDevice = 100
}
}

+ 18
- 0
TelpoPush.Models/MqTemplates/BaseModel.cs Ver arquivo

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.MqTemplates
{
public class BaseModel
{
public string MessageId { get; set; }
public string IMEI { get; set; }
public string TopicName { get; set; }
public string MessageTime { get; set; }
public object Content { get; set; }
}

}

+ 41
- 0
TelpoPush.Models/MqTemplates/ZkRealHeartRatesTemplate.cs Ver arquivo

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.MqTemplates
{
public class ZkRealHeartRatesTemplate
{
public ZkRealHeartRateData heartRates { get; set; }
}
public class ZkRealHeartRateData
{
public string imei { get; set; }
public string agencyid { get; set; }
public List<ZkRealHeartRateDataItem> data { get; set; }
}
public class ZkRealHeartRateDataItem
{
public int time { get; set; }
public int value { get; set; }
public int isAnomaly { get; set; }
}

public class ZkRealHeartRateAnomalyCancelTemplate
{
public ZkRealHeartRateAnomalyCancelData anomalyCancel { get; set; }
}
public class ZkRealHeartRateAnomalyCancelData
{
public string imei { get; set; }
public string agencyid { get; set; }
public int time { get; set; }
}

}





+ 18
- 0
TelpoPush.Models/PushTemplates/WxModel.cs Ver arquivo

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Models.PushTemplates
{
public class WxModel
{
public string deviceId { get; set; }
public string imei { get; set; }
public int alarmTypeId { get; set; }
public string alarmDeviceName { get; set; }
public string alarmRemarks { get; set; }
public string address { get; set; }
}
}

+ 13
- 0
TelpoPush.Models/TelpoPush.Models.csproj Ver arquivo

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

</Project>

+ 22
- 0
TelpoPush.Service/Biz/IZkRealHRMonitorService.cs Ver arquivo

@@ -0,0 +1,22 @@
using Confluent.Kafka;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Entities.GpsLocationHistory;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;
using TelpoPush.Common;
using TelpoPush.Models.MqTemplates;

namespace TelpoPush.Service.Biz
{
public interface IZkRealHRMonitorService
{
Task Save(ZkRealHeartRateData data, string MessageId);
Task SaveAnomalyCancel(ZkRealHeartRateAnomalyCancelData data, string MessageId);
}
}

+ 82
- 0
TelpoPush.Service/Biz/Impl/ZkRealHRMonitorService.cs Ver arquivo

@@ -0,0 +1,82 @@
using Confluent.Kafka;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoDataService.Util.Clients;
using TelpoDataService.Util.Entities.GpsLocationHistory;
using TelpoDataService.Util.Models;
using TelpoDataService.Util.QueryObjects;
using TelpoPush.Common;
using TelpoPush.Models.MqTemplates;
using TelpoPush.Service.Cache;

namespace TelpoPush.Service.Biz
{
public class ZkRealHRMonitorService : IZkRealHRMonitorService
{

private readonly ILogger<ZkRealHRMonitorService> _logger;
private readonly RedisUtil _redis;
private readonly GpsLocationHistoryAccessorClient<HisGpsRealHeartRate> _messageRealHeartRateAiClient;
public ZkRealHRMonitorService(
ILogger<ZkRealHRMonitorService> logger, RedisUtil redis,
GpsLocationHistoryAccessorClient<HisGpsRealHeartRate> messageRealHeartRateAiClient)
{
_logger = logger;
_redis = redis;
_messageRealHeartRateAiClient = messageRealHeartRateAiClient;
}

public async Task Save(ZkRealHeartRateData data, string MessageId)
{
string deviceKey = await _redis.GetHealthyDeviceKey(data.imei);
foreach (var item in data.data)
{
if (item.isAnomaly == 1)
{
DateTime lastUpdate = TimeHelper.ConvertToLocalDateTime(item.time.ToString());
HisGpsRealHeartRate model = new HisGpsRealHeartRate()
{
HeartRateId = item.time.ToString(),
MessageId = $"{MessageId}_{item.time}",
Serialno = data.imei,
ManufactorId = data.agencyid,
HeartRate = item.value,
IsAnomaly = item.isAnomaly,
LastUpdate = lastUpdate,
Method = 1,
IsDisplay = 1,
DeviceKey = deviceKey,
CreateTime = DateTime.Now,
};
await _messageRealHeartRateAiClient.AddAsync(model);
}
}
}

public async Task SaveAnomalyCancel(ZkRealHeartRateAnomalyCancelData data, string MessageId)
{
string deviceKey = await _redis.GetHealthyDeviceKey(data.imei);
DateTime lastUpdate = TimeHelper.ConvertToLocalDateTime(data.time.ToString());
HisGpsRealHeartRate model = new HisGpsRealHeartRate()
{
HeartRateId = data.time.ToString(),
MessageId = $"{MessageId}_{data.time}",
Serialno = data.imei,
ManufactorId = data.agencyid,
HeartRate = 0,
IsAnomaly = -1,
LastUpdate = lastUpdate,
Method = 1,
IsDisplay = 1,
DeviceKey = deviceKey,
CreateTime = DateTime.Now,
};
await _messageRealHeartRateAiClient.AddAsync(model);
}
}
}

+ 82
- 0
TelpoPush.Service/Cache/MemoryCacheUtil.cs Ver arquivo

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;

namespace TelpoPush.Service.Cache
{
internal class MemoryCacheUtil
{
static MemoryCache cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// 创建缓存项的文件
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="obj">object对象</param>
public static void Set(string key, object value)
{
if (key != null)
{
cache.Set(key, value);
}
}
/// <summary>
/// 创建缓存项过期
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="obj">object对象</param>
/// <param name="expires">过期时间(秒)</param>
public static void Set(string key, object value, int expires)
{
if (key != null)
{
cache.Set(key, value, new MemoryCacheEntryOptions()
//设置缓存时间,如果被访问重置缓存时间。设置相对过期时间x秒
.SetSlidingExpiration(TimeSpan.FromSeconds(expires)));
}
}

/// <summary>
/// 获取缓存对象
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns>object对象</returns>
public static object Get(string key)
{
object val = null;
if (key != null && cache.TryGetValue(key, out val))
{

return val;
}
else
{
return default(object);
}
}

/// <summary>
/// 获取缓存对象
/// </summary>
/// <typeparam name="T">T对象</typeparam>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static T Get<T>(string key)
{
object obj = Get(key);
return obj == null ? default(T) : (T)obj;
}


/// <summary>
/// 移除缓存项的文件
/// </summary>
/// <param name="key">缓存Key</param>
public static void Remove(string key)
{
cache.Remove(key);
}
}
}

+ 134
- 0
TelpoPush.Service/Cache/RedisUtil.cs Ver arquivo

@@ -0,0 +1,134 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoPush.Models.CacheTemplates;
using TelpoPush.Models.Config;

namespace TelpoPush.Service.Cache
{
public class RedisUtil
{
private const string CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG = "TELPO#MANUFACTOR_CONFG_HASH";

private readonly ILogger<RedisUtil> _logger;
private readonly ServiceConfig _configService;
private readonly SqlMapper _sqlMapper;
public RedisUtil(ILogger<RedisUtil> logger,IOptions<RedisConfig> optConfigRedis, IOptions<ServiceConfig> configService, SqlMapper sqlMapper)
{
_configService = configService.Value;
_logger = logger;
optConfigRedis.Value.Prefix = "";
optConfigRedis.Value.DefaultDatabase = 7;
var csredis = new CSRedis.CSRedisClient(optConfigRedis.Value.ToString());
RedisHelper.Initialization(csredis);
_sqlMapper = sqlMapper;
}


public async Task<string> GetHealthyDeviceKey(string imei)
{
if (string.IsNullOrWhiteSpace(imei)) return null;
string HealthyDeviceKey = $"Telpol:HealthyDeviceKey:{imei}";
string keyCache = $"{imei}_HealthyDeviceKey";
try
{
var objCache = MemoryCacheUtil.Get<string>(keyCache);
if (objCache == null)
{
string deviceKey = await RedisHelper.HGetAsync<string>(HealthyDeviceKey, "data");
if (!string.IsNullOrEmpty(deviceKey))
{
MemoryCacheUtil.Set(keyCache, deviceKey, _configService.CacheDurationSeconds10);
return deviceKey;
}
}
return objCache;
}
catch (Exception ex)
{
_logger.LogError($"GetHealthyDeviceKey,key={imei},缓存异常,重新获取数据,{ex.Message}|{ex.Source}|{ex.StackTrace}");
string deviceKey = await RedisHelper.HGetAsync<string>(HealthyDeviceKey, "data");
if (!string.IsNullOrEmpty(deviceKey))
{
MemoryCacheUtil.Set(keyCache, deviceKey, _configService.CacheDurationSeconds10);
return deviceKey;
}
else
return "";
}
}

//public async Task<string> ManufactorKafkaTopicQuery()
//{

// List<string> topics = new List<string>();
// string keyCache = $"ManufactorKafkaConfig";
// try
// {
// var objCache = MemoryCacheUtil.Get<List<string>>(keyCache);
// if (objCache == null)
// {
// var obj = await RedisHelper.HGetAsync<List<ManufactorKafkaModel>>(CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG, imei);
// if (obj == null)
// {
// var manufactors = _sqlMapper.ManufactorKafkaTopicQuery();
// if (manufactors != null)
// {
// foreach (var item in manufactors) {
// if (!string.IsNullOrEmpty(item.kafkaTopic))
// topics.Add(item.kafkaTopic);
// await RedisHelper.HSetAsync(CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG, item.manufactorId, item);
// }
// MemoryCacheUtil.Set(keyCache, topics, _configService.CacheDurationSeconds10);
// return topics;
// }
// }
// else
// {
// foreach (var item in obj)
// {
// if (!string.IsNullOrEmpty(item.kafkaTopic))
// topics.Add(item.kafkaTopic);
// await RedisHelper.HSetAsync(CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG, item.manufactorId, item);
// }
// MemoryCacheUtil.Set(keyCache, obj, _configService.CacheDurationSeconds10);
// return topics;
// }
// }
// return objCache;
// }
// catch (Exception ex)
// {
// _logger.LogError($"ManufactorKafkaTopicQuery,缓存异常,重新获取数据,{ex.Message}|{ex.Source}|{ex.StackTrace}");

// var manufactors = _sqlMapper.ManufactorKafkaTopicQuery();
// if (manufactors != null)
// {
// foreach (var item in manufactors)
// {
// if (!string.IsNullOrEmpty(item.kafkaTopic))
// topics.Add(item.kafkaTopic);
// await RedisHelper.HSetAsync(CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG, item.manufactorId, item);
// }
// MemoryCacheUtil.Set(keyCache, topics, _configService.CacheDurationSeconds10);
// return topics;
// }


// //var manufactors = _sqlMapper.ManufactorKafkaTopicQuery();
// //if (manufactors != null)
// //{
// // RedisHelper.HSetAsync(CACHE_HASH_KEY_TELPO_MANUFACTOR_CONFIG, imei, manufactor);
// // RedisHelper.Set(keyCache, manufactor, _configService.CacheDurationSeconds10);
// // return manufactor;
// //}
// }
// return null;
//}

}
}

+ 37
- 0
TelpoPush.Service/Cache/SqlMapper.cs Ver arquivo

@@ -0,0 +1,37 @@
using Dapper;
using Microsoft.Extensions.Configuration;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoPush.Models.CacheTemplates;

namespace TelpoPush.Service.Cache
{
public class SqlMapper
{
private readonly IConfiguration _config;
private static string gps_conn = "";
private static string telcommon_conn = "";
private static string healthy_conn = "";
public SqlMapper(IConfiguration config)
{
_config = config;
gps_conn = _config["ConnectionStrings:DB_Connection_String"].ToString();
telcommon_conn = _config["ConnectionStrings:Telpo_common_ConnString"].ToString();
healthy_conn = _config["ConnectionStrings:Telpo_Healthy_ConnString"].ToString();
}

public List<ManufactorKafkaModel> ManufactorKafkaTopicQuery()
{
using (IDbConnection connection = new MySqlConnection(telcommon_conn))
{
var sql = @"SELECT manufactor_id manufactorId,manufactor_name manufactorName,kafka_servers kafkaServers,kafka_topic kafkaTopic,kafka_username kafkaUsername, kafka_password kafkaPassword FROM manufactor_real_monitor";
return connection.Query<ManufactorKafkaModel>(sql).ToList();
}
}
}
}

+ 9
- 0
TelpoPush.Service/Mq/Kafka/IKafkaService.cs Ver arquivo

@@ -0,0 +1,9 @@
using Confluent.Kafka;

namespace TelpoPush.Service.Mq.Kafka
{
public interface IKafkaService
{
Task SubscribeAsync(Action<string, string, Headers> messageFunc, CancellationToken cancellationToken);
}
}

+ 15
- 0
TelpoPush.Service/Mq/Kafka/KafkaHeader.cs Ver arquivo

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Service.Mq.Kafka
{
public class KafkaHeader
{
public static readonly string DataType = "DataType";
public static readonly string AlarmType = "AlarmType";
public static readonly string OperType = "OperType";
}
}

+ 138
- 0
TelpoPush.Service/Mq/Kafka/KafkaService.cs Ver arquivo

@@ -0,0 +1,138 @@
using Confluent.Kafka;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using TelpoPush.Models.Config;

namespace TelpoPush.Service.Mq.Kafka
{
public class KafkaService: IKafkaService
{
private readonly ConsumerConfig _consumerConfig;
private readonly IHostEnvironment env;
private readonly ILogger<KafkaService> logger;
private readonly ServiceConfig _configService;
public KafkaService(ILogger<KafkaService> _logger, IHostEnvironment _env, IOptions<ServiceConfig> optConfigService)
{
//config = _configuration;
_configService = optConfigService.Value;
env = _env;
logger = _logger;

_consumerConfig = new ConsumerConfig
{
BootstrapServers = _configService.KafkaBootstrapServers,
SecurityProtocol = SecurityProtocol.SaslSsl,
SaslMechanism = SaslMechanism.ScramSha256,
GroupId = _configService.KafkaGroupId,
SaslUsername = _configService.KafkaSaslUsername,
SaslPassword = _configService.KafkaSaslPassword,
SslCaLocation = _configService.KafkaSslCaLocation
//SslCaLocation = @"D:\THOMAS\Project\SSJL\C#\Net8\TelpoPushThirdSsl\pem\ca-root.pem",
EnableAutoCommit = false, // 禁止AutoCommit
AutoOffsetReset = AutoOffsetReset.Earliest, // 从最早的开始消费起
};
}

public async Task SubscribeAsync(Action<string, string, Headers> messageFunc, CancellationToken cancellationToken)
{

List<string> topics = _configService.KafkaTopics;

using (var consumer = new ConsumerBuilder<Ignore, string>(_consumerConfig)
.SetErrorHandler((_, e) =>
{
Console.WriteLine($"Error: {e.Reason}");
})
.SetStatisticsHandler((_, json) =>
{
Console.WriteLine($" - {DateTime.Now:yyyy-MM-dd HH:mm:ss} > 消息监听中..");
})
.SetPartitionsAssignedHandler((c, partitions) =>
{
string partitionsStr = string.Join(", ", partitions);
Console.WriteLine($" - 分配的 kafka 分区: {partitionsStr}");
})
.SetPartitionsRevokedHandler((c, partitions) =>
{
string partitionsStr = string.Join(", ", partitions);
Console.WriteLine($" - 回收了 kafka 的分区: {partitionsStr}");
})
.Build())
{

consumer.Subscribe(topics);
try
{
while (true)
{
try
{

var consumeResult = consumer.Consume(cancellationToken);
int DataType = -1, AlarmType = -1, OperType = -1;
foreach (var item in consumeResult?.Headers)
{
if (item.Key == KafkaHeader.DataType)
DataType = BitConverter.ToInt32(item.GetValueBytes(), 0);
else if (item.Key == KafkaHeader.AlarmType)
AlarmType = BitConverter.ToInt32(item.GetValueBytes(), 0);
else if (item.Key == KafkaHeader.OperType)
OperType = BitConverter.ToInt32(item.GetValueBytes(), 0);
}
var Headers = new { DataType, AlarmType, OperType };
logger.LogInformation($"Consumed topic '{consumeResult.Topic}', message '{consumeResult.Message?.Value}' , headers '{JsonConvert.SerializeObject(Headers)}', at: '{consumeResult?.TopicPartitionOffset}'.");
if (consumeResult.IsPartitionEOF)
{
Console.WriteLine($" - {DateTime.Now:yyyy-MM-dd HH:mm:ss} 已经到底了:{consumeResult.Topic}, partition {consumeResult.Partition}, offset {consumeResult.Offset}.");
continue;
}
// 根据消息内容动态决定topic
//var dynamicTopic = GetDynamicTopic(consumeResult.Message?.Value);
//consumer.Subscribe(new List<string>() { dynamicTopic });

string messageResult = null;
Headers headers = null;
try
{
messageResult = consumeResult.Message.Value;
headers = consumeResult.Message.Headers;
}
catch (Exception ex)
{
var errorMessage = $" - {DateTime.Now:yyyy-MM-dd HH:mm:ss}【Exception 消息反序列化失败,Value:{consumeResult.Message.Value}】 :{ex.StackTrace?.ToString()}";
Console.WriteLine(errorMessage);
messageResult = null;
}
if (!string.IsNullOrEmpty(messageResult)/* && consumeResult.Offset % commitPeriod == 0*/)
{
string topic = consumeResult.Topic;
messageFunc(topic, messageResult, headers);

try
{
consumer.Commit(consumeResult);
}
catch (KafkaException e)
{
Console.WriteLine(e.Message);
}
}
}
catch (ConsumeException e)
{
Console.WriteLine($"Consume error: {e.Error.Reason}");
}
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Closing consumer.");
consumer.Close();
}
}
await Task.CompletedTask;
}
}
}

+ 78
- 0
TelpoPush.Service/Mq/Kafka/MessageProducer.cs Ver arquivo

@@ -0,0 +1,78 @@
using Confluent.Kafka;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using TelpoPush.Models.Config;

namespace TelpoPush.Service.Mq.Kafka
{
/// <summary>
/// 消息生产者
/// </summary>
public class MessageProducer
{
private readonly ILogger<MessageProducer> _logger;
private readonly ServiceConfig _configService;
private readonly IProducer<Null, string> _producer;

public MessageProducer(ILogger<MessageProducer> logger, IOptions<ServiceConfig> optConfigService)
{
_logger = logger;
_configService = optConfigService.Value;

var config = new ProducerConfig
{
BootstrapServers = _configService.KafkaBootstrapServers,
EnableIdempotence = true,
Acks = Acks.All,
//LingerMs=5000,
//BatchNumMessages =1000,
//BatchSize=32768,
//CompressionType= CompressionType.Lz4,
MessageSendMaxRetries = 3
};
_producer = new ProducerBuilder<Null, string>(config).Build();
}

public Headers CreateHeader(Dictionary<string, int> pair = null)
{
if (pair == null)
{
return null;
}
else
{
Headers headers = new Headers();

foreach (var item in pair)
{
headers.Add(item.Key, BitConverter.GetBytes(item.Value));
}
return headers;
}
}

public async Task ProduceAsync(List<TopicModel> topic, object message)
{
try
{
foreach (var item in topic)
{
// producer = new ProducerBuilder<Null, string>(config).Build();
await _producer.ProduceAsync(item.Topic, new Message<Null, string>
{
Headers = item.Headers,
Value = JsonConvert.SerializeObject(message)
});
}
}
catch (ProduceException<Null, string> e)
{
_logger.LogError($"推送到kafka失败,topic: {topic},\n message:{JsonConvert.SerializeObject(message)}: \n{e.Error.Reason}");
}
}



}
}

+ 87
- 0
TelpoPush.Service/Mq/Kafka/MqProcessMessage.cs Ver arquivo

@@ -0,0 +1,87 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelpoPush.Models.Dto;
using TelpoPush.Models.Enum;
using TelpoPush.Models.MqTemplates;
using TelpoPush.Models.PushTemplates;

namespace TelpoPush.Service.Mq.Kafka
{
public class MqProcessMessage
{
private readonly ILogger<MqProcessMessage> _logger;
private readonly MessageProducer _messageProducer;

public MqProcessMessage(ILogger<MqProcessMessage> logger, MessageProducer producer)
{
_logger = logger;
_messageProducer = producer;
}
public async Task ProcessWxAlarm(WxModel model, string timeString)
{
List<TopicModel> ls = new List<TopicModel>();

ls.Add(new TopicModel()
{
Topic = "topic.push.wx",
Headers = _messageProducer.CreateHeader(new Dictionary<string, int>
{
{MqHeader.DataType,(int)MqDataType.AlarmInfo },
})
});
await _messageProducer.ProduceAsync(ls, new
{
messageId = string.Format("{0:yyyyMMddHHmmssffff}", DateTime.Now),
topic = string.Join(",", ls.Select(e => e.Topic)), //MqTopic.Wx,
time = timeString,
data = model
});
_logger.LogInformation($"【成功】Third推送(topic.wx):IMEI<{model.imei}>,pushData:{JsonConvert.SerializeObject(model)}");
}

public async Task ProcessProperty(string imei, BaseModel model, HeadersDto headers)
{
List<TopicModel> ls = new List<TopicModel>();

ls.Add(new TopicModel()
{
Topic = "topic.push.property",
Headers = _messageProducer.CreateHeader(new Dictionary<string, int>
{
{MqHeader.DataType,headers.DataType.Value }
})
});
await _messageProducer.ProduceAsync(ls, model);
_logger.LogInformation($"【成功】Third推送(topic.property):IMEI<{imei}>,pushData:{JsonConvert.SerializeObject(model)}");
}

public async Task ProcessDataPushServer(string imei, object model, Dictionary<string, int> headers, string tag)
{
List<TopicModel> ls = new List<TopicModel>();
ls.Add(new TopicModel()
{
Topic = "topic.push",
Headers = _messageProducer.CreateHeader(headers)
});
await _messageProducer.ProduceAsync(ls, model);
_logger.LogInformation($"【{tag}-成功】Third推送(topic.push):IMEI<{imei}>,Header<{JsonConvert.SerializeObject(headers)}>,pushData:{JsonConvert.SerializeObject(model)}");
}

public async Task ProcessThirdhServer(string imei, object model, Dictionary<string, int> headers, string tag)
{
List<TopicModel> ls = new List<TopicModel>();
ls.Add(new TopicModel()
{
Topic = "topic.push.third",
Headers = _messageProducer.CreateHeader(headers)
});
await _messageProducer.ProduceAsync(ls, model);
_logger.LogInformation($"【{tag}-成功】Third推送(topic.push.third):IMEI<{imei}>,Header<{JsonConvert.SerializeObject(headers)}>,pushData:{JsonConvert.SerializeObject(model)}");
}
}
}

+ 15
- 0
TelpoPush.Service/Mq/Kafka/TopicModel.cs Ver arquivo

@@ -0,0 +1,15 @@
using Confluent.Kafka;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelpoPush.Service.Mq.Kafka
{
public class TopicModel
{
public string Topic { get; set; }
public Headers Headers { get; set; }
}
}

+ 29
- 0
TelpoPush.Service/TelpoPush.Service.csproj Ver arquivo

@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<Folder Include="Common\" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Confluent.Kafka" Version="2.4.0" />
<PackageReference Include="CSRedisCore" Version="3.8.803" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="MySql.Data" Version="8.4.0" />
<PackageReference Include="TelpoDataService.Util" Version="1.6.9.28-beta1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TelpoPush.Common\TelpoPush.Common.csproj" />
<ProjectReference Include="..\TelpoPush.Models\TelpoPush.Models.csproj" />
</ItemGroup>

</Project>

+ 40
- 0
TelpoPush.Worker.ThirdSsl/Dockerfile Ver arquivo

@@ -0,0 +1,40 @@
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS base
USER app
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["TelpoPush.Worker.ThirdSsl/TelpoPush.Worker.ThirdSsl.csproj", "TelpoPush.Worker.ThirdSsl/"]
COPY ["TelpoPush.Common/TelpoPush.Common.csproj", "TelpoPush.Common/"]
COPY ["TelpoPush.Models/TelpoPush.Models.csproj", "TelpoPush.Models/"]
COPY ["TelpoPush.Service/TelpoPush.Service.csproj", "TelpoPush.Service/"]

COPY ["nuget.config","."]
RUN dotnet nuget remove source nuget.org
RUN dotnet nuget add source https://repo.huaweicloud.com/repository/nuget/v3/index.json -n huaweicloud_nuget

RUN dotnet restore "./TelpoPush.Worker.ThirdSsl/TelpoPush.Worker.ThirdSsl.csproj"
COPY . .
WORKDIR "/src/TelpoPush.Worker.ThirdSsl"
RUN dotnet build "./TelpoPush.Worker.ThirdSsl.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./TelpoPush.Worker.ThirdSsl.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY pem /app/pem


ENV environment=Development
ENV TimeZone=Asia/Shanghai
ENV LANG C.UTF-8
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone

#ENTRYPOINT ["dotnet", "TelpoPush.Worker.ThirdSsl.dll"]
ENTRYPOINT ["sh", "-c", "dotnet TelpoPush.Worker.ThirdSsl.dll --environment=$environment"]

+ 67
- 0
TelpoPush.Worker.ThirdSsl/Handlers/KafkaSubscribe.cs Ver arquivo

@@ -0,0 +1,67 @@
using Confluent.Kafka;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using TelpoPush.Common;
using TelpoPush.Models.Config;
using TelpoPush.Service.Mq.Kafka;

namespace TelpoPush.Worker.ThirdSsl.Handlers
{
public class KafkaSubscribe
{
private readonly ILogger<KafkaSubscribe> _logger;
private readonly IHostEnvironment _env;
private readonly IKafkaService _kafkaService;
private readonly ThirdSslProcess _thirdSslProcess;
private readonly ServiceConfig _configService;


public KafkaSubscribe(
ILogger<KafkaSubscribe> logger, IHostEnvironment env,
IKafkaService kafkaService,
ThirdSslProcess thirdSslProcess)
{
_logger = logger;
_env = env;
_kafkaService = kafkaService;
_thirdSslProcess = thirdSslProcess;
}
public async Task SubscribeAsync()
{

//string msg = "{\"MessageTime\":\"2024-05-13 10:29:09.407\",\"TopicName\":\"topic.push.telpo.zkheartrate\",\"MessageId\":\"1715567350000\",\"IMEI\":\"868437060014409\",\"Content\":\"{\\\"heartRates\\\":{\\\"imei\\\":\\\"868437060014409\\\",\\\"agencyid\\\":\\\"77d562ac-dd78-40ea-af6d-224ada9d70dc\\\",\\\"data\\\":[{\\\"time\\\":1715567340,\\\"value\\\":172,\\\"isAnomaly\\\":1},{\\\"time\\\":1715567342,\\\"value\\\":174,\\\"isAnomaly\\\":1},{\\\"time\\\":1715567344,\\\"value\\\":174,\\\"isAnomaly\\\":1},{\\\"time\\\":1715567346,\\\"value\\\":174,\\\"isAnomaly\\\":1},{\\\"time\\\":1715567348,\\\"value\\\":174,\\\"isAnomaly\\\":1},{\\\"time\\\":1715567350,\\\"value\\\":174,\\\"isAnomaly\\\":1}]}}\"}";
//await _thirdSslProcess.SendSslThird(msg, "", null);

//string msg2 = "{\"MessageTime\":\"2024-05-13 14:10:43.814\",\"TopicName\":\"topic.push.telpo.zkheartrate\",\"MessageId\":\"1715580644000\",\"IMEI\":\"868437060014409\",\"Content\":\"{\\\"anomalyCancel\\\":{\\\"imei\\\":\\\"868437060014409\\\",\\\"agencyid\\\":\\\"77d562ac-dd78-40ea-af6d-224ada9d70dc\\\",\\\"time\\\":1715580644}}\"}";

//await _thirdSslProcess.SendSslThird(msg2, "", null);


//await _kafkaService.SubscribeAsync(DoReceive, CancellationToken.None);

LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(5);
TaskFactory factory = new TaskFactory(lcts);
try
{
await factory.StartNew(() =>
{
_kafkaService.SubscribeAsync(DoReceive, CancellationToken.None);
});
}
catch (Exception ex)
{
_logger.LogError($"Subscribe 处理Kafka数据发生异常 {ex.Message}|{ex.Source}|{ex.StackTrace}");
}
}
async void DoReceive(string topic, string message, Headers headers)
{
await _thirdSslProcess.SendSslThird(message, topic, headers);
}
}
}

+ 71
- 0
TelpoPush.Worker.ThirdSsl/Handlers/ThirdSslProcess.cs Ver arquivo

@@ -0,0 +1,71 @@
using Confluent.Kafka;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using TelpoPush.Models.MqTemplates;
using TelpoPush.Service.Biz;

namespace TelpoPush.Worker.ThirdSsl.Handlers
{
public class ThirdSslProcess
{
private readonly static object _syncLocker = new object();
private readonly IHostEnvironment _env;
private readonly ILogger<ThirdSslProcess> _logger;
private readonly IZkRealHRMonitorService _zkRealHRMonitorService;
public ThirdSslProcess(
IHostEnvironment env,
ILogger<ThirdSslProcess> logger,
IZkRealHRMonitorService zkRealHRMonitorService)
{
_env = env;
_logger = logger;
_zkRealHRMonitorService= zkRealHRMonitorService;
}

public async Task SendSslThird(string? message, string topic, Headers headers)
{
//lock (_syncLocker)
//{
_logger.LogInformation($"获取kafka数据Message:<{message}>");

if (!string.IsNullOrEmpty(message))
{
BaseModel model = JsonConvert.DeserializeObject<BaseModel>(message);
if (!string.IsNullOrEmpty(model.Content.ToString()))
{
switch (model.TopicName)
{
case "topic.push.telpo.zkheartrate":
await DataServiceZkRealHRMonitor(model);
break;
default:
break;
}
}
}
// }
}

public async Task DataServiceZkRealHRMonitor(BaseModel model)
{
string content = model.Content.ToString().ToLower();
if (content.Contains("heartrates"))
{
var data = JsonConvert.DeserializeObject<ZkRealHeartRatesTemplate>(content);
await _zkRealHRMonitorService.Save(data.heartRates, model.MessageId);
}
else if (content.Contains("anomalycancel"))
{
var data = JsonConvert.DeserializeObject<ZkRealHeartRateAnomalyCancelTemplate>(content);
await _zkRealHRMonitorService.SaveAnomalyCancel(data.anomalyCancel, model.MessageId);
}
}
}
}

+ 103
- 0
TelpoPush.Worker.ThirdSsl/Program.cs Ver arquivo

@@ -0,0 +1,103 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Serilog;
using TelpoDataService.Util.Clients;
using TelpoPush.Common;
using TelpoPush.Models.Config;
using TelpoPush.Service.Biz;
using TelpoPush.Service.Cache;
using TelpoPush.Service.Mq.Kafka;
using TelpoPush.Worker.ThirdSsl;
using TelpoPush.Worker.ThirdSsl.Handlers;


#region 日志
//using Serilog.Events;
//using Serilog;
//using Microsoft.AspNetCore.Builder;

//Log.Logger = new LoggerConfiguration()
//#if DEBUG
// .MinimumLevel.Debug()
//#else
// .MinimumLevel.Information()
//#endif
// .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
// .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
// .Enrich.FromLogContext()
// //.Filter.ByExcluding(c => c.Properties.Any(p => p.Value.ToString().Contains("Microsoft")))//过滤
// .WriteTo.Async(c => c.File("/var/telpo_pushthird_ssl2/logs/infos/info.log",
// restrictedToMinimumLevel: LogEventLevel.Information,
// rollingInterval: RollingInterval.Day,//滚动策略(天)
// //fileSizeLimitBytes: 20971520, //设置单个文件大小为3M 默认1G
// rollOnFileSizeLimit: true, //超过文件大小后创建新的
// retainedFileCountLimit: 7,//默认31,意思就是只保留最近的31个日志文件"
// outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff}[{Level:u3}] [Thread-{ThreadId}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}"
// )
// )
// .WriteTo.Async(c => c.File("/var/telpo_pushthird_ssl2/logs/errors/errors.log",
// restrictedToMinimumLevel: LogEventLevel.Error,
// rollingInterval: RollingInterval.Day,
// rollOnFileSizeLimit: true,
// retainedFileCountLimit: 7,
// outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff }[{Level:u3}] [Thread-{ThreadId}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}"
// )
// )
// .WriteTo.Async(c => c.Console())
// .CreateLogger();

//选择配置文件appsetting.json
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();

Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.WithThreadId()
.CreateLogger();
#endregion
try
{
Log.Information("Starting up");
var builder = Host.CreateApplicationBuilder(args);

var config = builder.Configuration;
builder.Services.Configure<ServiceConfig>(config.GetSection("ServiceConfig"));
builder.Services.Configure<RedisConfig>(config.GetSection("Redis"));

JsonSerializerSettings setting = new JsonSerializerSettings();
JsonConvert.DefaultSettings = () =>
{
setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
setting.ContractResolver = new CamelCasePropertyNamesContractResolver();
return setting;
};
builder.Services.AddTelpoDataServices(opt =>
{
opt.TelpoDataUrl = config["ServiceConfig:TelpoDataUrl"];
});

builder.Services.AddSerilog();
builder.Services.AddHttpClient();
builder.Services.AddTransient<HttpHelperAsync>();
builder.Services.AddSingleton<SqlMapper>();
builder.Services.AddSingleton<RedisUtil>();
builder.Services.AddSingleton<IZkRealHRMonitorService, ZkRealHRMonitorService>();
builder.Services.AddSingleton<IKafkaService, KafkaService>();
builder.Services.AddSingleton<KafkaSubscribe>();
builder.Services.AddSingleton<MessageProducer>();
builder.Services.AddSingleton<MqProcessMessage>();
builder.Services.AddSingleton<ThirdSslProcess>();
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application start-up failed");
}
finally
{
Log.CloseAndFlush();
}

+ 15
- 0
TelpoPush.Worker.ThirdSsl/Properties/launchSettings.json Ver arquivo

@@ -0,0 +1,15 @@
{
"profiles": {
"TelpoPush.Worker.ThirdSsl": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "test"
},
"dotnetRunMessages": true
},
"Container (Dockerfile)": {
"commandName": "Docker"
}
},
"$schema": "http://json.schemastore.org/launchsettings.json"
}

+ 26
- 0
TelpoPush.Worker.ThirdSsl/TelpoPush.Worker.ThirdSsl.csproj Ver arquivo

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-TelpoPush.Worker.ThirdSsl-c73c0758-309e-49cb-b0cb-49ecc2eaa9fe</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Confluent.Kafka" Version="2.4.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Exceptionless" Version="4.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TelpoPush.Common\TelpoPush.Common.csproj" />
<ProjectReference Include="..\TelpoPush.Models\TelpoPush.Models.csproj" />
<ProjectReference Include="..\TelpoPush.Service\TelpoPush.Service.csproj" />
</ItemGroup>
</Project>

+ 28
- 0
TelpoPush.Worker.ThirdSsl/Worker.cs Ver arquivo

@@ -0,0 +1,28 @@
using Microsoft.Extensions.Logging;
using TelpoPush.Worker.ThirdSsl.Handlers;

namespace TelpoPush.Worker.ThirdSsl
{
public class Worker : BackgroundService
{
private readonly IHostEnvironment _env;
private readonly ILogger<Worker> _logger;
KafkaSubscribe _kafkaSubscribe;

public Worker(ILogger<Worker> logger, IHostEnvironment env, KafkaSubscribe kafkaSubscribe)
{
_env = env;
_logger = logger;
_kafkaSubscribe = kafkaSubscribe;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await _kafkaSubscribe.SubscribeAsync();
await Task.Delay(30000, stoppingToken);
}
}
}
}

+ 34
- 0
TelpoPush.Worker.ThirdSsl/appsettings.Development.json Ver arquivo

@@ -0,0 +1,34 @@
{
"ConnectionStrings": {
"DB_Connection_String": "server=139.224.254.18;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_common_ConnString": "server=139.224.254.18;port=3305;database=telpo_common;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_Healthy_ConnString": "server=139.224.254.18;port=3305;database=telpo_healthy;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none"

//"DB_Connection_String": "server=rm-uf6j529mu0v6g0btpco.mysql.rds.aliyuncs.com;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
//"Telpo_common_ConnString": "server=rm-uf6j529mu0v6g0btpco.mysql.rds.aliyuncs.com;port=3305;database=telpo_common;uid=linwl;pwd=linwl#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none"
},
"ServiceConfig": {
"TelpoDataUrl": "http://id.ssjlai.com/data",
"KafkaBootstrapServers": "k0.id.gdssjl.com:9094", // "172.19.42.53:9092",
"KafkaTopics": [ "topic.push.telpo.zkheartrate" ],
"KafkaGroupId": "telpo-tcp-group",
"KafkaSaslUsername": "telpo-consumer",
"KafkaSaslPassword": "telpo-consumer-pwd",
"KafkaSslCaLocation": "pem/ca-root.pem",
"CacheDurationSeconds": 1200, //20分钟
"CacheDurationSeconds10": 600 //10分钟
},
"Redis": {
//"Server": "139.224.254.18:8090",
"Server": "47.116.142.20:8090",
"Password": "telpo#1234",
"DefaultDatabase": 7,
"Poolsize": 150,
"Preheat": 50,
"Prefix": "_Third_",
"ConnectTimeout": 5000,
"IdleTimeout": 20000
},

"Environment": "dev"
}

+ 77
- 0
TelpoPush.Worker.ThirdSsl/appsettings.json Ver arquivo

@@ -0,0 +1,77 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"System.Net.Http.HttpClient": "Warning"
}
},
"Serilog": {
"Using": [ "Serilog.Sinks.File", "Serilog.Sinks.Async", "Serilog.Sinks.Console", "Serilog.Sinks.Exceptionless" ],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"System.Net.Http.HttpClient": "Warning"
}
},
"WriteTo:Information": {
"Name": "Async",
"Args": {
"Configure": [
{
"Name": "File",
"Args": {
"RestrictedToMinimumLevel": "Information",
"RollingInterval": "Day",
"RollOnFileSizeLimit": "true",
"OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss }[{Level:u3}] [Thread-{ThreadId}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}",
"Path": "/var/telpo_pushthird_ssl/logs/infos/info.log",
"RetainedFileCountLimit": 7 // "--设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件", "等于null时永远保留文件": null
// "FileSizeLimitBytes": 20971520, //设置单个文件大小为3M 默认1G
// "RollOnFileSizeLimit": true //超过文件大小后创建新的

}
}
]
}
},
"WriteTo:Error": {
"Name": "Async",
"Args": {
"Configure": [
{
"Name": "File",
"Args": {
"RestrictedToMinimumLevel": "Error",
"RollingInterval": "Day",
"RollOnFileSizeLimit": "true",
"OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss }[{Level:u3}] [Thread-{ThreadId}][{SourceContext:l}] {Message:lj}{NewLine}{Exception}",
"Path": "/var/telpo_pushthird_ssl/logs/errors/error.log",
"RetainedFileCountLimit": 7 // "--设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件", "等于null时永远保留文件": null
// "FileSizeLimitBytes": 20971520, //设置单个文件大小为3M 默认1G
// "RollOnFileSizeLimit": true //超过文件大小后创建新的
}
}
]
}
},
"WriteTo:Console": {
"Name": "Console",
"Args": {
"restrictedToMinimumLevel": "Verbose",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss }[{Level:u3}] [Thread-{ThreadId}] [{SourceContext:l}] {Message:lj}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
"WriteTo:Exceptionless": {
"Name": "Exceptionless",
"Args": {
"serverUrl": "http://8.134.157.154:5000",
"apiKey": "f2I0sng4BBQS9IAsbdBK1W71oOYGPpsC66s7pzJu"
}
}
}
}

+ 31
- 0
TelpoPush.Worker.ThirdSsl/appsettings.production.json Ver arquivo

@@ -0,0 +1,31 @@
{
"ConnectionStrings": {
"DB_Connection_String": "server=rm-uf6j529mu0v6g0btp.mysql.rds.aliyuncs.com;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_common_ConnString": "server=rm-uf6j529mu0v6g0btp.mysql.rds.aliyuncs.com;port=3305;database=telpo_common;uid=linwl;pwd=linwl#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_Healthy_ConnString": "server=rm-uf6j529mu0v6g0btp.mysql.rds.aliyuncs.com;port=3305;database=telpo_healthy;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none"
},
"ServiceConfig": {
"TelpoDataUrl": "http://ai.ssjlai.com/data",
"KafkaBootstrapServers": "k0.id.gdssjl.com:9094", // "172.19.42.53:9092",
"KafkaTopics": [ "topic.push.telpo.zkheartrate" ],
"KafkaGroupId": "telpo-tcp-group",
"KafkaSaslUsername": "telpo-consumer",
"KafkaSaslPassword": "telpo-consumer-pwd",
"KafkaSslCaLocation": "pem/ca-root.pem",
"CacheDurationSeconds": 1200, //20分钟
"CacheDurationSeconds10": 600 //10分钟
},
"Redis": {
"Server": "139.224.254.18:8090",
//"Server": "47.116.142.20:8090",
"Password": "telpo#1234",
"DefaultDatabase": 7,
"Poolsize": 150,
"Preheat": 50,
"Prefix": "_Third_",
"ConnectTimeout": 5000,
"IdleTimeout": 20000
},

"Environment": "production"
}

+ 34
- 0
TelpoPush.Worker.ThirdSsl/appsettings.test.json Ver arquivo

@@ -0,0 +1,34 @@
{
"ConnectionStrings": {
"DB_Connection_String": "server=139.224.254.18;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_common_ConnString": "server=139.224.254.18;port=3305;database=telpo_common;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
"Telpo_Healthy_ConnString": "server=139.224.254.18;port=3305;database=telpo_healthy;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none"

//"DB_Connection_String": "server=rm-uf6j529mu0v6g0btpco.mysql.rds.aliyuncs.com;port=3305;database=gps_card;uid=root;pwd=telpo#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none",
//"Telpo_common_ConnString": "server=rm-uf6j529mu0v6g0btpco.mysql.rds.aliyuncs.com;port=3305;database=telpo_common;uid=linwl;pwd=linwl#1234;CharSet=utf8;MinimumPoolSize=10;MaximumPoolSize=1000;SslMode=none"
},
"ServiceConfig": {
"TelpoDataUrl": "http://id.ssjlai.com/data",
"KafkaBootstrapServers": "k0.id.gdssjl.com:9094", // "172.19.42.53:9092",
"KafkaTopics": [ "topic.push.telpo.zkheartrate" ],
"KafkaGroupId": "telpo-tcp-group",
"KafkaSaslUsername": "telpo-consumer",
"KafkaSaslPassword": "telpo-consumer-pwd",
"KafkaSslCaLocation": "pem/ca-root.pem",
"CacheDurationSeconds": 1200, //20分钟
"CacheDurationSeconds10": 600 //10分钟
},
"Redis": {
//"Server": "139.224.254.18:8090",
"Server": "47.116.142.20:8090",
"Password": "telpo#1234",
"DefaultDatabase": 7,
"Poolsize": 150,
"Preheat": 50,
"Prefix": "_Third_",
"ConnectTimeout": 5000,
"IdleTimeout": 20000
},

"Environment": "test"
}

+ 43
- 0
TelpoPushThirdSsl.sln Ver arquivo

@@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34723.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelpoPush.Worker.ThirdSsl", "TelpoPush.Worker.ThirdSsl\TelpoPush.Worker.ThirdSsl.csproj", "{3E174613-0E05-49C4-9DAE-B3556D183697}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelpoPush.Common", "TelpoPush.Common\TelpoPush.Common.csproj", "{E53008EA-CF26-4539-A419-33E30475A279}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelpoPush.Models", "TelpoPush.Models\TelpoPush.Models.csproj", "{68D9CFA2-857A-46D0-8A3C-E9AE77538A93}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelpoPush.Service", "TelpoPush.Service\TelpoPush.Service.csproj", "{1D83D4E9-FDFD-4CD5-AE03-F0FBAA8C1193}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3E174613-0E05-49C4-9DAE-B3556D183697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E174613-0E05-49C4-9DAE-B3556D183697}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E174613-0E05-49C4-9DAE-B3556D183697}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E174613-0E05-49C4-9DAE-B3556D183697}.Release|Any CPU.Build.0 = Release|Any CPU
{E53008EA-CF26-4539-A419-33E30475A279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E53008EA-CF26-4539-A419-33E30475A279}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E53008EA-CF26-4539-A419-33E30475A279}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E53008EA-CF26-4539-A419-33E30475A279}.Release|Any CPU.Build.0 = Release|Any CPU
{68D9CFA2-857A-46D0-8A3C-E9AE77538A93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68D9CFA2-857A-46D0-8A3C-E9AE77538A93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68D9CFA2-857A-46D0-8A3C-E9AE77538A93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68D9CFA2-857A-46D0-8A3C-E9AE77538A93}.Release|Any CPU.Build.0 = Release|Any CPU
{1D83D4E9-FDFD-4CD5-AE03-F0FBAA8C1193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1D83D4E9-FDFD-4CD5-AE03-F0FBAA8C1193}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1D83D4E9-FDFD-4CD5-AE03-F0FBAA8C1193}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1D83D4E9-FDFD-4CD5-AE03-F0FBAA8C1193}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E0EFD813-32E2-4D4C-B69A-493EFBBA7EE9}
EndGlobalSection
EndGlobal

+ 7
- 0
nuget.config Ver arquivo

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="company" value="http://139.224.254.18:3344" />
</packageSources>
</configuration>

+ 29
- 0
pem/ca-root.pem Ver arquivo

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE/zCCAuegAwIBAgIJAIgzt1mx6ZClMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNV
BAMMC2thZmthLWFkbWluMB4XDTI0MDUwNjA2NDE1NloXDTM0MDUwNDA2NDE1Nlow
FjEUMBIGA1UEAwwLa2Fma2EtYWRtaW4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQDUCuuolDbpE6O8IvAK0YDvK+p96hjQ4bqD7UWKzie60q2OWHOfrcr3
ra4FYiEtpZMSa52Y9K+VmXnP/Ol1kJHqcJPyIEkgqnC3nMDLNtO4BTqbXb7/eL7n
ln+Sn4v96Qc6+248yV87Of7NhW0Ou7Q7Qa7Y8Podvox6CANwQcVDAuAp1segHtsl
3w3Tmz4Ty9A919lGLfSRr1XQUGGt2DLrU4GajBEs8FJoWrCWnOBH251oSwQrisLw
+/PNRR8f8NE9uxE1/qmWwwtPg0a978WaUpqaLLUd7dU+TrbbptkAAcTdV0+JPrGJ
7JCleO9akmquRrSVQfKXKCq0ardQpndGEGhfAxoqPi5BuFyn0Sx2d+NsDIQKyW7U
e7lwLafrXFwnNmKPCfigE4IvPonz6HcJORRtJDzORbjSCB347MMlkmKY+ANB5fKc
UiqEaV+/NOw99/qNICEmBUa24aU3O5ASr5hPGNz+vAtGDGKokf0K9CLcPE/FKkvY
AYzM4O/kyqJhWgs8qoHITnv0BTb9psJEZp5VLJP6iPQhJXksnCQRX9+e0Rd+4d5B
d6JZ++KfmgxMy0YhTqz58IZe0yHolxTE6S0S5IULKkPk8GnIHPgw7/zfvsOM/eFs
676401tafc/Y7gC3H/GEPHo/T8/tuHLGz7GKwcytUFQdI2YgBl0kMwIDAQABo1Aw
TjAdBgNVHQ4EFgQULe3CAIvXjKYJOGF+zt1Lm87u6p0wHwYDVR0jBBgwFoAULe3C
AIvXjKYJOGF+zt1Lm87u6p0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
AgEAfktPTwfBKTONVi5ILH6/70bvIxNRQljFdRP6Ktj76FlmkGXetYQMh0Fc+Wwd
meaU7z3JFV3BJOlQkh7UPKTbmXfIrk+Kvf14sSKYf4O47GatoSY/ifZrocs+owr2
FP/6Oh3l70+vcUbLmU/328VHHumAuZjQ/199CnKgvgarEPRsekHDg0erzCu7fwVk
9ZIpRW5Kiyav+VBbg2SUVxaOHeGzy1eHxWHYeUpBpryLh4VDU1Va9LPR6nhmKPQI
GzJUgDjx9OK7Lhr6IHDWGbbOjKmHhL5nPtVOi9JPqTdJ0DXHhj94RlQdw3OxCa47
ZhvCE5re8fJGtDpExQBbaPTXR0SGJ/q8td9bcJ+zHLcCALKXwHW7cf21YiPoiQ9J
I1DmYIwxEUqbngpCA6guDoL0HONVPOwG1SG/yLHy+jaKaMHUHTptbiRpPf2znxSm
UxUxEUEg+bhtoHd3Areky4RsuPQUFbDyYEDtduSjV+00vAicxcC/sLeZRWoKsPfb
Bp4xf7Jn5OO+jNcTfjoXnlVpyBI7zdwkbyMdF/xxcaj+POIgaljTQHoGxc31taJo
vwlNqD7oLHysuL06Qzos8nEbJMT/MJzDOSIRZ3FL3aTtdnP92j/G6hVoN5XnAAXS
O31Nvpo+6guwJmFg4SuBGwT8x2wlM35nHs84vR36ScNBvq8=
-----END CERTIFICATE-----

+ 18
- 0
setup_production.sh Ver arquivo

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
image_version=$version
# 删除镜像
docker rmi -f $(
docker images | grep registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl | awk '{print $3}'
)
# 构建telpo/mrp:$image_version镜像
docker build -f ./TelpoPush.Worker.ThirdSsl/Dockerfile . -t telpo/telpo_push_third_ssl:$image_version
#TODO:推送镜像到阿里仓库
echo '=================开始推送镜像======================='
docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com
docker tag telpo/telpo_push_third_ssl:$image_version registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl:$image_version
docker push registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl:$image_version
echo '=================推送镜像完成======================='
#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
docker images

+ 17
- 0
setup_test.sh Ver arquivo

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
image_version=$version
# 删除镜像
docker rmi -f $(
docker images | grep 139.224.254.18:5000/telpo_push_third_ssl | awk '{print $3}'
)
# 构建telpo/mrp:$image_version镜像
docker build -f ./TelpoPush.Worker.ThirdSsl/Dockerfile . -t telpo/telpo_push_third_ssl:$image_version
#TODO:推送镜像到私有仓库
echo '=================开始推送镜像======================='
docker tag telpo/telpo_push_third_ssl:$image_version 139.224.254.18:5000/telpo_push_third_ssl:$image_version
docker push 139.224.254.18:5000/telpo_push_third_ssl:$image_version
echo '=================推送镜像完成======================='
#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
docker images

+ 27
- 0
telpo_push_third_ssl_run.sh Ver arquivo

@@ -0,0 +1,27 @@
#!/bin/bash
environment=$1
version=$2
echo "环境变量为${environment},版本为$version!"
if [[ ${environment} == 'production' ]]; then
echo "开始远程构建容器"
docker stop telpo_push_third_ssl || true
docker rm telpo_push_third_ssl || true
docker rmi -f $(docker images | grep registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl | awk '{print $3}')
docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com
docker pull registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl:$version
docker run -d --network=host -e environment=production -v /home/data/telpo_push_third_ssl/log:/var/telpo_pushthird_ssl/logs --restart=always --name telpo_push_third_ssl registry.cn-shanghai.aliyuncs.com/gps_card/telpo_push_third_ssl:$version;
#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
docker ps -a

elif [[ ${environment} == 'test' ]]; then
echo "开始在测试环境远程构建容器"
docker stop telpo_push_third_ssl || true
docker rm telpo_push_third_ssl || true
docker rmi -f $(docker images | grep 139.224.254.18:5000/telpo_push_third_ssl | awk '{print $3}')
docker pull 139.224.254.18:5000/telpo_push_third_ssl:$version
docker run -d --network=host -e environment=${environment} -v /home/data/telpo_push_third_ssl/log:/var/telpo_pushthird_ssl/logs --restart=always --name telpo_push_third_ssl 139.224.254.18:5000/telpo_push_third_ssl:$version;
#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
docker ps -a
fi

Carregando…
Cancelar
Salvar