@@ -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/** |
@@ -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 |
@@ -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 | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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> |
@@ -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)); | |||||
} | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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"; | |||||
} | |||||
} |
@@ -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 | |||||
} | |||||
} |
@@ -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 | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} | |||||
@@ -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; } | |||||
} | |||||
} |
@@ -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> |
@@ -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); | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} | |||||
} |
@@ -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; | |||||
//} | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
using Confluent.Kafka; | |||||
namespace TelpoPush.Service.Mq.Kafka | |||||
{ | |||||
public interface IKafkaService | |||||
{ | |||||
Task SubscribeAsync(Action<string, string, Headers> messageFunc, CancellationToken cancellationToken); | |||||
} | |||||
} |
@@ -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"; | |||||
} | |||||
} |
@@ -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; | |||||
} | |||||
} | |||||
} |
@@ -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}"); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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)}"); | |||||
} | |||||
} | |||||
} |
@@ -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; } | |||||
} | |||||
} |
@@ -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> |
@@ -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"] |
@@ -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); | |||||
} | |||||
} | |||||
} |
@@ -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); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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(); | |||||
} |
@@ -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" | |||||
} |
@@ -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> |
@@ -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); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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" | |||||
} |
@@ -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" | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -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" | |||||
} |
@@ -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" | |||||
} |
@@ -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 |
@@ -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> |
@@ -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----- |
@@ -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 |
@@ -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 |
@@ -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 |