在本文中,我们将为您详细介绍Docker最全教程之使用.NETCore推送钉钉消息的相关知识,并且为您解答关于十九的疑问,此外,我们还会提供一些关于ASP.NETCore基于Socket实现消息推送实
在本文中,我们将为您详细介绍Docker最全教程之使用.NET Core推送钉钉消息的相关知识,并且为您解答关于十九的疑问,此外,我们还会提供一些关于ASP.NET Core基于Socket实现消息推送实战演练、C#实现推送钉钉消息的方法示例、DingTalk 钉钉消息推送(.net core 3 WebApi 尝鲜记)、Docker 最全教程 —— 从理论到实战(二)的有用信息。
本文目录一览:- Docker最全教程之使用.NET Core推送钉钉消息(十九)(docker 推送harbor)
- ASP.NET Core基于Socket实现消息推送实战演练
- C#实现推送钉钉消息的方法示例
- DingTalk 钉钉消息推送(.net core 3 WebApi 尝鲜记)
- Docker 最全教程 —— 从理论到实战(二)
Docker最全教程之使用.NET Core推送钉钉消息(十九)(docker 推送harbor)
前言
上一篇我们通过实战分享了使用Go推送钉钉消息,由于技痒,笔者现在也编写了一个.NET Core的Demo,作为简单的对照和说明。
最后,由于精力有限,笔者希望有兴趣的朋友可以分享下使用CoreRT将.NET Core编译成机器代码这块的实践。
目录
-
使用.NET Core推送钉钉消息
-
获取参数
-
设置消息数据格式
-
发送请求
-
设置Dockerfile
-
运行并设置环境变量推送消息
使用.NET Core推送钉钉消息
这里我们使用.NET Core来完成相关需求,注意,这里是.NET Core,而不是ASP.NET Core。需求和上面类似,工程相关依赖如下所示:
<PackageReferenceInclude="Microsoft.Extensions.Configuration"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Configuration.CommandLine"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Configuration.EnvironmentVariables"Version="2.2.0"/>
<PackageReferenceInclude="Microsoft.Extensions.Http"Version="2.2.0"/>
<PackageReferenceInclude="Newtonsoft.Json"Version="12.0.1"/>
以下是相关的主体代码:
获取参数
从环境变量或者命令行参数获取配置:
///<summary>
///环境变量列表
///</summary>
privatestaticreadonlystring[] EnvList =
{
//钉钉机器人地址
"WEBHOOK",
//@的手机号码
"AT_MOBILES",
//@所有人
"IS_AT_ALL",
//消息内容
"MESSAGE",
//消息类型(仅支持文本和markdown)
"MSG_TYPE"
};
privatestaticvoid Main(string[] args)
{
var config = newConfigurationBuilder()
//支持命令行参数
.AddCommandLine(args)
//支持环境变量
.AddEnvironmentVariables()
.Build();
#region参数检查
foreach (var envName in EnvList)
{
var value =config[envName];
if (string.IsNullOrWhiteSpace(value)&& envName != "AT_MOBILES" && envName !="IS_AT_ALL")
{
Console.WriteLine($"{envName}不能为空!");
return;
}
}
if (string.IsNullOrWhiteSpace(config["AT_MOBILES"]) &&string.IsNullOrWhiteSpace(config["IS_AT_ALL"]))
{
Console.WriteLine("必须设置参数 AT_MOBILES 和 IS_AT_ALL 两者之一!");
return;
}
#endregion
try
{
//推送消息
SetDataAndSendWebhooks(config).Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
设置消息数据格式
设置消息格式,为了简单,这里我们使用匿名类:
///<summary>
///设置消息并调用Webhook
///</summary>
///<param name="config"></param>
///<returns></returns>
privatestaticasync Task SetDataAndSendWebhooks(IConfigurationRoot config)
{
var at = new
{
AtMobiles = config["AT_MOBILES"]?.Split('',''),
IsAtAll = Convert.ToBoolean(config["IS_AT_ALL"] ?? "false")
};
switch (config["MSG_TYPE"])
{
case"text":
{
var data = new
{
Msgtype = "text",
Text = new
{
Content =config["MESSAGE"]
},
At = at
};
awaitSendWebhooks(config["WEBHOOK"], data);
break;
}
case"markdown":
{
var data = new
{
Msgtype = "markdown",
Markdown = new
{
Title = "钉钉通知",
Text = config["MESSAGE"]
},
At = at
};
awaitSendWebhooks(config["WEBHOOK"], data);
break;
}
default:
{
Console.WriteLine($"不支持的格式:{config["MSG_TYPE"]}");
break;
}
}
}
发送请求
此处代码使用Newtonsoft.Json做JSON序列化,然后使用Microsoft.Extensions.Http的HttpClient库来发送Post请求。
在数据格式这块,我们通过配置做了以下设置:
-
忽略Null值。也就是为null的属性不做JSON序列化。
-
设置属性命名规则为Camel-Case驼峰式命名法,首字母小写。
主体代码如下所示:
///<summary>
///调用webhook
///</summary>
///<typeparamname="T"></typeparam>
///<param name="url">webhook地址</param>
///<param name="data">消息</param>
///<returns></returns>
privatestaticasync Task SendWebhooks<T>(string url, T data) where T : class
{
JsonConvert.DefaultSettings = newFunc<JsonSerializerSettings>(() =>newJsonSerializerSettings()
{
NullValueHandling =NullValueHandling.Ignore,
ContractResolver = newCamelCasePropertyNamesContractResolver()
});
var jsonData =JsonConvert.SerializeObject(data);
Console.WriteLine(jsonData);
using (var httpClient = new HttpClient())
{
var content = newStringContent(jsonData);
content.Headers.ContentType = newMediaTypeHeaderValue("application/json");
var result = awaithttpClient.PostAsync(url, content);
result.EnsureSuccessStatusCode();
Console.WriteLine($"Send webhook succeed. StatusCode:{result.StatusCode}");
}
}
设置Dockerfile
在之前我们已经讲述过,使用了分阶段构建。整个Dockerfile基本上使用VS Docker tool生成:
FROMmicrosoft/dotnet:2.2-runtime AS base
WORKDIR /app
FROMmicrosoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY DingTalk.NET/DingTalk.NET.csprojDingTalk.NET/
RUN dotnet restoreDingTalk.NET/DingTalk.NET.csproj
COPY . .
WORKDIR /src/DingTalk.NET
RUN dotnet buildDingTalk.NET.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish DingTalk.NET.csproj-c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish/app .
ENTRYPOINT ["dotnet", "DingTalk.NET.dll"]
# 注意不要单独使用 MAINTAINER 指令,MAINTAINER已被Label标签代替
LABEL MAINTAINER ="xinlai@xin-lai.com"
# LABEL指令用于将元数据添加到镜像,支持键值对和JSON,我们可以使用 docker inspect 命令来查看
LABELDingtalkComponent=''{\
"description": "使用钉钉发送通知消息.",\
"input": [\
{"name": "WEBHOOK","desc": "必填, 钉钉机器人Webhook地址"},\
{"name":"AT_MOBILES", "desc": "非必填,被@人的手机号"},\
{"name":"IS_AT_ALL", "desc": "非必填,@所有人时:true, 否则为:false"},\
{"name": "MESSAGE","desc": "必填,自定义发送的消息内容"},\
{"name":"MSG_TYPE", "desc": "必填,自定义发送的消息类型,目前仅支持text和markdown"}\
]\
}''
编译完成后,我们来查看下镜像大小:
注意:
通过上图我们可以看到,镜像大小不到200M,相比GO体重大了许多,但是相比其他语言却轻了不少。不过,我们可以通过官方开源库CoreRT将.NET Core编译成机器代码,也就是.NET Core也可以做到编译完成后只有几M大小。有兴趣的朋友可以分享下这块的实践。
运行并设置环境变量推送消息
我们使用PowerShell编写简单脚本如下所示:
docker build --rm-f "Dockerfile" -t dingtalk.net:latest .
docker run --rm -e"WEBHOOK=https://oapi.dingtalk.com/robot/send?access_token={yourAccess Token}" `
-e "MESSAGE=*使用.NET Core发送钉钉消息。*" `
-e "IS_AT_ALL=true" `
-e "MSG_TYPE=markdown" `
-d dingtalk.net
效果如图:
原文出处:https://www.cnblogs.com/codelove/p/10576322.html
ASP.NET Core基于Socket实现消息推送实战演练
1、课程介绍和实例演示
1、课程介绍
在前面的分享课程中关于ASP.NET Core中如何实现消息推送,我们已经学过了《ASP.NET Core基于SignalR实现消息推送实战演练》、《ASP.NET Core基于WebSocket实现消息推送实战演练》,《ASP.NET Core基于SuperWebSocket实现消息推送实战演练》今天我们要学习的是如何通过微软原生的System.Net.sockets来实现消息推送实战演练。
特别注意本次分享课程是在《C#网络编程技术Socket实战演练》的基础之上演变和升级过来了,原来的课程是.NET Framework平台,现在给大家分享的是ASP.NET Core跨平台。
2、实例演示
1)、客户端与服务端互发消息
2)、客户端断线重连。
2、Socket客户端与服务端通信原理
3、Socket类库介绍和选择
4、用户(User)如何与Socket对象建立关系
5、ASP.NET Core使用自定义中间件添加Socket
《ASP.NET Core基于第三方WebSocket框架实战演练》
1、课程介绍
2、WebSocket介绍
3、为什么选择第三方WebSocket框架
4、第三方WebSocket框架如何选择
5、用户(User)如何与Socket对象建立关系
6、.NET中使用Fleck框架入门体验
7、ASP.NET Core如何通过自定义中间件集成Fleck框架
8、使用.NET客户端实现与Fleck服务端通信
9、ASP.NET Core如何通过标准中间件集成Fleck框架
《ASP.NET Core基于第三方websocket-sharp框架实战演练》
1、WebSocketSharp介绍2、WebSocketSharp简单使用
3、ASP.NET Core使用后台系统服务
4、ASP.NET Core使用后台系统服务集成websocket-sharp框架
5、websocket-sharp客户端与服务通信
C#实现推送钉钉消息的方法示例
本文实例讲述了C#实现推送钉钉消息的方法。分享给大家供大家参考,具体如下:
利用钉钉提供的API可以推送消息到用户的钉钉app。根据钉钉的官方文档,调用钉钉的api需要一个AccessToken,我们先获取这个AccessToken。
string CorpId = "你的CorpId "; string CorpSecret = "你的CorpSecret "; public string AccessToken = ""; string AccessUrl = string.Format("https://oapi.dingtalk.com/gettoken?corpid={0}&corpsecret={1}", CorpId, CorpSecret); Newtonsoft.Json.Linq.JToken json = Newtonsoft.Json.Linq.JToken.Parse(HttpGet(AccessUrl)); AccessToken = json["access_token"].ToString();
这里利用到了Newtonsoft.Json类解析返回来的json数据,用法网上很多资料可以查找到。HttpGet是我封装好的一个类,可以在这篇《C#基于HttpWebRequest实现发送HTTP请求的方法》查看,下面的HttpPost也是如此。
有了AccessToken,我们就可以调用钉钉的api了,发送推送的相关api 在,文档已经写得很清晰了,我们只需要发送一个json格式的数据过去,就可以推送数据了。
string MessageUrl = "https://oapi.dingtalk.com/message/send?access_token=" + AccessToken; var json_req = new { touser = "用户id1|用户id2", //接受推送userid,不同用户用|分割 toparty = "", //接受推送部门id agentid = "1", msgtype = "text", //推送类型 text = new { content = "要推送的内容" } }; string jsonRequest = JsonConvert.SerializeObject(json_req);//将对象转换为json HttpPost(MessageUrl, jsonRequest);
其中HttpPost是我已经封装好的一个类,需要注意的是,agentid指的是以哪个应用的身份推送消息,这个id可以在钉钉管理后台的应用里面查看得到。
最后的效果:
更多关于C#相关内容感兴趣的读者可查看本站专题:《C#程序设计之线程使用技巧总结》、《C#窗体操作技巧汇总》、《C#常见控件用法教程》、《WinForm控件用法总结》、《C#数据结构与算法教程》、《C#数组操作技巧总结》及《C#面向对象程序设计入门教程》
希望本文所述对大家C#程序设计有所帮助。
- C#如何实现调取钉钉考勤接口的功能
DingTalk 钉钉消息推送(.net core 3 WebApi 尝鲜记)
我发了个朋友圈,Swagger 真他妈的牛 B,解放了开发 API 的码农,麻麻再也不用担心我们写 API 文档耽误回家吃饭了。
/// <summary>
/// 发送钉钉消息
/// </summary>
/// <param name="toUser">Employee的userid,多个使用|分隔</param>
/// <param name="title">标题</param>
/// <param name="content">发送内容</param>
/// <param name="sourceUrl">消息向导地址</param>
/// <returns></returns>
private ApiResult SendCardMessageToEmployee(string toUser, string title, string content, string sourceUrl)
{
var result = new ApiResult
{
Success = false,
ResponseDatetime = DateTime.Now.ToString(),
ResultMessage = "操作失败!",
ResultObject = null
};
try
{
toUser = toUser.Trim(''|'');
string JSONData = "{\"touser\":\"" + toUser +
"\",\"toparty\":\"\",\"agentid\":\"" + _settings.Value.sendmessage_agentid + "\",\"msgtype\":\"action_card\",\"action_card\":{\"title\":\"" + title + "\",\"markdown\":\"<font size=7 face=\''黑体\''>DingTalk中间件提醒: </font> \n \n " +
content + "\r \n " + "\r \n " + "\r \n " + DateTime.Now.ToString() +
"\",\"single_title\": \"查看详情\",\"single_url\": \"" + sourceUrl + "\"}}";
var access_token = GetAccessToke();
var tokenObj = access_token.ResultObject as AccessToken;
string url = "https://oapi.dingtalk.com/message/send?access_token=" + tokenObj.access_token;
string response = GetResponseData(JSONData, url);
result.ResultObject = response;
result.Success = string.IsNullOrEmpty(response);
result.ResultMessage = "API调用成功!Requst Url:[" + url + "],Content:[" + JSONData + "]";
}
catch (Exception ex)
{
result.ResultObject = ex;
_logger.LogError(ex, ex.Message, new object[] { });
}
return result;
}
/// <summary>
/// 发送钉钉消息
/// </summary>
/// <param name="toUser">Employee的userid,多个使用|分隔</param>
/// <param name="content">发送内容</param>
/// <param name="sourceUrl">发送内容</param>
/// <returns></returns>
private ApiResult SendMediaMessageToEmployee(string toUser, string content, string sourceUrl)
{
var result = new ApiResult
{
Success = false,
ResponseDatetime = DateTime.Now.ToString(),
ResultMessage = "操作失败!",
ResultObject = null
};
try
{
toUser = toUser.Trim(''|'');
string JSONData = "{\"touser\":\"" + toUser + "\",\"toparty\":\"\",\"agentid\":\"" + _settings.Value.sendmessage_agentid + "\",\"" + content + ",\"single_title\": \"查看详情\",\"single_url\": \"" + sourceUrl + "\"}}";
var access_token = GetAccessToke();
var tokenObj = access_token.ResultObject as AccessToken;
string url = "https://oapi.dingtalk.com/message/send?access_token=" + tokenObj.access_token;
string response = GetResponseData(JSONData, url);
result.ResultObject = response;
result.Success = string.IsNullOrEmpty(response);
result.ResultMessage = "API调用成功!Requst Url:[" + url + "],Content:[" + JSONData + "]";
}
catch (Exception ex)
{
result.ResultObject = ex;
_logger.LogError(ex, ex.Message, new object[] { });
}
return result;
}
/// <summary>
/// 给指定员工发送钉钉消息1
/// </summary>
/// <param name="userid">指定员工的职员ID</param>
/// <param name="title">标题</param>
/// <param name="content">发送内容</param>
/// <param name="sourceUrl">消息向导地址</param>
/// <returns></returns>
[HttpGet]
[HttpPost]
public ApiResult SendDingTalkMessage(string userid, string title, string content, string sourceUrl = "http://www.cquni.com")
{
if (string.IsNullOrEmpty(title))
title = "通知";
var result = new ApiResult
{
Success = false,
ResponseDatetime = DateTime.Now.ToString(),
ResultMessage = "操作失败!",
ResultObject = null
};
try
{
var rs = SendCardMessageToEmployee(userid, title, content, sourceUrl);
result.Success = rs.Success;
result.ResultMessage = rs.ResultMessage;
result.ResultObject = rs.ResultObject;
}
catch (Exception ex)
{
result.ResultObject = ex;
}
return result;
}
/// <summary>
/// 给指定员工发送钉钉消息2
/// </summary>
/// <param name="departmentName">部门名称</param>
/// <param name="employeeName">人员姓名</param>
/// <param name="title">消息标题</param>
/// <param name="content">消息内容</param>
/// <param name="sourceUrl">url</param>
/// <returns></returns>
[HttpGet]
[HttpPost]
public ApiResult SendDingTalkMessageExt(string departmentName, string employeeName, string title, string content, string sourceUrl = "http://www.cquni.com")
{
var result = new ApiResult
{
Success = false,
ResponseDatetime = DateTime.Now.ToString(),
ResultMessage = "操作失败!",
ResultObject = null
};
if (string.IsNullOrEmpty(title))
title = "通知";
var deptment = GetDepartmentInfo().department;
if (deptment != null && deptment.Count > 0)
{
var currDept = deptment.Where(d => d.name.Contains(departmentName)).FirstOrDefault();
if (currDept == null)
{
result.ResultMessage = "获取人员的部门信息出错,输入部门名称:" + departmentName;
}
else
{
var employeeList = GetDepartmentEmployeeList(currDept).userlist;
if (employeeList != null && employeeList.Count > 0)
{
var currentEmp = employeeList.Where(e => e.name.Contains(employeeName)).FirstOrDefault();
try
{
var rs = SendCardMessageToEmployee(currentEmp.userid, title, content, sourceUrl);
return rs;
}
catch (Exception ex)
{
_logger.LogError(ex.Message, new object[]
{
ex,
ex.InnerException
});
}
}
else
{
result.ResultMessage = string.Format("很奇怪,这个部门''{0}''一个人也没有!", departmentName);
}
}
}
else
{
result.ResultMessage = "获取公司部门信息出错!";
}
return result;
}
/// <summary>
/// 给指定员工发送钉钉消息(支持图文,文件,图片等格式)
/// </summary>
/// <param name="departmentName">部门名称</param>
/// <param name="employeeName">人员姓名</param>
/// <param name="mediaContent">消息内容 eg: "msgtype": "voice","voice": {"media_id": "MEDIA_ID","duration": "10" }
/// 格式说明请看钉钉官网文档 https://ding-doc.dingtalk.com/doc#/serverapi2/ye8tup </param>
/// <param name="sourceUrl"></param>
/// <returns></returns>
[HttpGet]
[HttpPost]
public ApiResult SendDingTalkMediaMessage(string departmentName, string employeeName, string mediaContent, string sourceUrl = "http://www.cquni.com")
{
var result = new ApiResult
{
Success = false,
ResponseDatetime = DateTime.Now.ToString(),
ResultMessage = "操作失败!",
ResultObject = null
};
var deptment = GetDepartmentInfo().department;
if (deptment != null && deptment.Count > 0)
{
var currDept = deptment.Where(d => d.name.Contains(departmentName)).FirstOrDefault();
if (currDept == null)
{
result.ResultMessage = "获取人员的部门信息出错,输入部门名称:" + departmentName;
}
else
{
var employeeList = GetDepartmentEmployeeList(currDept).userlist;
if (employeeList != null && employeeList.Count > 0)
{
var currentEmp = employeeList.Where(e => e.name.Contains(employeeName)).FirstOrDefault();
try
{
var rs = SendMediaMessageToEmployee(currentEmp.userid, mediaContent, sourceUrl);
return rs;
}
catch (Exception ex)
{
_logger.LogError(ex.Message, new object[]
{
ex,
ex.InnerException
});
}
}
else
{
result.ResultMessage = string.Format("很奇怪,这个部门''{0}''一个人也没有!", departmentName);
}
}
}
else
{
result.ResultMessage = "获取公司部门信息出错!";
}
return result;
}
Docker 最全教程 —— 从理论到实战(二)
上篇内容链接: https://www.cnblogs.com/codelove/p/10030439.html
Docker 和 ASP.NET Core
Docker 正在逐渐成为容器行业的事实标准,受到 Windows 和 Linux 生态系统领域最重要供应商的支持。 (Microsoft 是支持 Docker 的主要云供应商之一。)现在,Docker 基本上已经在各大云或本地的任何数据中心普及了。
如何将.NET 程序托管到 Docker 之中,相信这是广大.NET 开发者的一个疑问。事实上,.NET Framework 支持在 Docker 中运行,但是仅能在 windows 容器中运行,这并不符合我们的预期,因此,本篇我们只侧重于讨论 ASP.NET Core 和 Docker。
在使用之前,笔者还是有必要介绍下 ASP.NET Core。如果您对此非常熟悉和了解或者对此节不感兴趣,可以跳过本节。
ASP.NET Core 简介
ASP.NET Core 是一个跨平台的高性能开源框架,用于生成基于云且连接 Internet 的新式应用程序。使用 ASP.NET Core,我们可以:
-
建置 Web 应用程序和服务、IoT 应用和移动后端。
-
能够在 Windows、macOS 和 Linux 上进行开发和运行。部署到云或本地。
-
在 .NET Core 或 .NET Framework 上运行。
-
能够在 IIS、Nginx、Apache、Docker 上进行托管或在自己的进程中进行自托管我们的应用。
性能是.NET Core 的一个关键特性,这里有必要介绍下。在这块,我们摘取了一份社区的测试汇总统计,仅供参考:
具体过程大家可以访问此链接来查看详情:https://www.cnblogs.com/savorboard/archive/2016/10/17/dotnet-benchmarks.html
ASP.NET Core 和 Docker
刚才说了这么多,我们回到主题。.NET Core 天生就为跨平台设计,并且和 Docker 搭配非常友好,而且微软官方在这块提供了很多支持。比如说:
- 轻量
- 跨平台,天生对 Linux 友好
- 模块化
- 提供了轻量型容器镜像高性能(领先于 Java servlets、Go 和 node.js)
接下来,我们一起来了解官方镜像。ASP.NET Core 的官方镜像名称为 microsoft/aspnetcore,微软针对 Docker 上的 ASP.NET Core 应用进行了优化,因此容器可以更快启动。为开发人员生成 Docker 镜像时,Microsoft 侧重于提供了以下主要方案:
- 用于开发和生成 .NET Core 应用的镜像。
- 用于运行 .NET Core 应用的镜像。
例如.NET Core 2.1,官方提供的镜像:
为什么是多个镜像?因为在开发、生成和运行容器化应用程序时,通常具有不同的优先级。 通过为这些单独的任务提供不同的镜像,有助于独立优化开发、生成和部署应用程序的过程。在开发期间,我们侧重的是开发更改的速度以及调试的能力。在生产环境,我们侧重的是应用部署和容器启动的速度和效率。
这里我们顺便提下我们基于.NET Core 2.1 开发的免费开源框架 ——Magicodes.Admin,其 demo 现在已经完全托管在 Docker 之中,部署在腾讯云的容器服务之中,大家可以点击访问测试下速度和稳定性,启动速度这点没得说。推荐访问 Https 地址,因域名在备案之中,http 域名可能无法访问。
Magicodes.Admin 开源库地址:https://gitee.com/xl_wenqiang/Magicodes.Admin.Core
Demo 地址:https://demoadmin.xin-lai.com
Admin
123456abcD
在本篇 Docker 教程中,我们会结合 Magicodes.Admin 的实践进行讲解,同时我们也会尽量提供一些实践案例分享给大家,比如 Magicodes.Admin demo、Magicodes 云服务、小程序商城(即将开源)、爱车 APP 等 Docker 完整托管案例,以便大家更易于理解和使用 Docker。在 Magicodes.Admin 框架中,接口服务使用.NET Core 2.1 开发,在 docker 上基于 microsoft/dotnet:2.1-aspnetcore-runtime 镜像使用 Kestrel web 服务器,后台前端使用 Angular 开发,在 docker 上基于 nginx 镜像使用 nginx 服务器进行托管,并启用了 HTTPS 支持和 GZIP 压缩。
我们回过来继续。.NET 镜像 (microsoft/dotnet) 同样适用于基于 .NET Core 的控制台应用。使用 Docker 和 .NET Core 非常适用于生产部署和托管,主要有以下几点:
-
无需本地安装 —— 可以直接使用 .NET Framework,而无需本地安装。只下载相关的 Docker 镜像,其中包含 .NET Framework。
-
在容器中开发 —— 你可以在一致的环境中开发,使开发和生产环境类似(可避免一些问题,例如开发人员计算机上的全局状态)。 通过 VS 的一些扩展插件,我们甚至可以直接从 Visual Studio 启动容器。
-
容器中测试 —— 可以在容器中测试,减少由于环境配置不当或上次测试遗留的其他更改而导致的故障。
-
在容器中生成 —— 可以在容器中生成代码。
-
在所有环境中部署 —— 可以通过你的所有环境部署镜像。 这种方法减少了配置差异导致的故障,通常通过外部配置(例如,注入的环境变量)改变镜像行为。
注意:
Docker 镜像容器可以在 Linux 和 Windows 上本机运行。 但是,Windows 镜像仅能在 Windows 主机上运行,Linux 镜像可以在 Linux 主机和 Windows 主机上运行(到目前为止,使用 Hyper-V Linux VM),其中主机是指服务器或 VM。
注意:
.NET Framework 也可以使用 Docker 进行托管,不过仅能托管到 windows 容器之中。
在具体应用和实践之前,我们有必要了解以下内容。
Kestrel
Kestrel 是一个基于 libuv 的跨平台 ASP.NET Core web 服务器,libuv 是一个跨平台的异步 I/O 库。ASP.NET Core 模板项目使用 Kestrel 作为默认的 web 服务器。
Kestrel 支持以下功能:
-
HTTPS
-
用于启用不透明升级的 WebSockets
-
位于 Nginx 之后的高性能 Unix sockets
Kestrel 被.NET Core 支持的所有平台和版本所支持。Kestrel 可以单独使用,也可以与反向代理服务器(如 IIS、Nginx 或 Apache)一起使用。 反向代理服务器接收到来自 Internet 的 HTTP 请求,并在进行一些初步处理后将这些请求转发到 Kestrel。
在没有 Kestrel 或自定义服务器实现的情况下,不能使用 IIS、Nginx 和 Apache。 ASP.NET Core 设计为在其自己的进程中运行,以实现跨平台统一操作。 IIS、Nginx 和 Apache 规定自己的启动过程和环境。 若要直接使用这些服务器技术,ASP.NET Core 必须满足每个服务器的需求。 使用 Kestrel 等 Web 服务器实现时,ASP.NET Core 可以控制托管在不同服务器技术上的启动过程和环境。
注意:
Kestrel 可以单独使用,也可以与反向代理服务器(如 IIS、Nginx 或 Apache)一起使用。在 docker 容器中,我们推荐使用 Kestrel。
在大部分情况下,我们推荐使用反向代理服务器。主要是有以下好处:
-
可以限制所承载的应用中的公开的公共外围应用。
-
可以提供额外的配置和防护层。
-
可以更好地与现有基础结构集成。
-
可以简化负载均衡和 SSL 配置。 仅反向代理服务器需要 SSL 证书,并且该服务器可使用普通 HTTP 在内部网络上与应用服务器通信。
说了这么多,总归还是 “纸上得来终觉浅,绝知此事要躬行”。我们来一起实践:
首先我们需要安装以下包:
Install-Package Microsoft.AspNetCore.Server.Kestrel -Version 2.1.3
然后就可以编写启动代码:
在上面的代码中,我们通过了配置文件来配置 Kestrel,我们也推荐大家使用配置文件来配置 Kestrel。相关配置 Demo 如下:
当然,我们也可以通过代码来配置 kestrel:
按环境加载配置
ASP.NET Core 基于使用环境变量的运行时环境配置应用行为。ASP.NET Core 在应用启动时读取环境变量 ASPNETCORE_ENVIRONMENT,并将该值存储在 IHostingEnvironment.EnvironmentName 中。 ASPNETCORE_ENVIRONMENT 可设置为任意值,但框架支持三个值:Development、Staging 和 Production。 如果未设置 ASPNETCORE_ENVIRONMENT,则默认为 Production。
注意:
在 Docker 容器中,我们经常会修改 ASPNETCORE_ENVIRONMENT 环境变量来模拟开发、测试和生产环境。
因此在代码中,我们可以根据环境变量来启用或关闭相应的功能,其中场景最广泛的一点是 —— 根据不同的环境加载不同的配置。同时,内置的环境变量配置提供程序(EnvironmentVariablesConfigurationProvider)还可以在运行时从环境变量键值对加载配置。具体见以下代码:
内置的日志记录提供程序
ASP.NET Core 提供以下内置日志记录提供程序,在很多情况下,对我们会很有帮助:
-
控制台日志提供程序
-
调试日志提供程序
-
EventSource 日志提供程序
-
EventLog 日志提供程序
控制台日志提供程序
在 Docker 环境下,为了便于排错,我们推荐启用此日志提供程序。在平常的情况下,我们通过控制台运行程序(比如通过 dotnet run 运行)也会输出控制台日志。在使用之前,需要安装以下包:
Install-Package Microsoft.Extensions.Logging.Console -Version 2.1.1
然后我们可以在代码中通过以下代码启用:
logging.AddConsole();
完整代码如图所示:
添加了之后,我们在云端的容器服务的日志中,就可以看到控制台日志了。下面以腾讯云容器服务为例。首先打开腾讯云【容器服务】的【服务】页面,如图所示:
我们可以点击【日志】操作按钮的图标来查看日志:
我们也可以点击具体的某个实例来查看相关日志,这里就不多写了。
注意:
通过控制台日志,我们可以输出一些启动信息以用来做启动诊断,同时我们也可以根据控制台日志来查看请求状况和运行状况。
调试日志提供程序
和控制台日志一样,也需要安装相关依赖包:
Install-Package Microsoft.Extensions.Logging.Debug -Version 2.1.1
该包使用 System.Diagnostics.Debug 类(Debug.WriteLine 方法调用)来写入日志输出。注意,在 Linux 中,此提供程序将日志写入 /var/log/message。
代码启用方式如下所示:
logging.AddDebug();
EventSource 日志提供程序
包依赖关系如下:
Install-Package Microsoft.Extensions.Logging.EventSource -Version 2.1.1
该提供程序可实现事件跟踪。不过值得注意的是,该提供程序尚无支持 Linux 或 macOS 的事件集合和显示工具。期待官方提供相关工具。
而在 windows server,可以通过开源工具 https://github.com/Microsoft/perfview 来收集和查看日志,如下图所示:
EventLog 日志提供程序
需要添加包:Microsoft.Extensions.Logging.EventLog。
主要用于向 Windows 事件日志发送日志输出。
关于 ASP.NET Core 的相关内容,我们先介绍到这里。接下来我们主要是围绕 Docker 开发工作流程在进行讲解。
搭建并使用 Docker
Docker 的安装非常简单,我们这里仅以 windows 10 操作系统(推荐)为例进行讲解。
安装 Docker
这里以 Docker for windows 为例,其他环境请参考官网教程。
注意:
不推荐使用 Docker Toolbox,Docker Toolbox 适用于较旧的 Mac 和 Windows 系统。
要安装 Docker,请先查看用于 Windows 的 Docker:安装须知了解相关信息。
安装须知链接:https://docs.docker.com/docker-for-windows/install/#what-to-know-before-you-install
注意:
使用 Docker for windows 需要启用 Hyper-V 功能。以下是系统要求:
-
Windows 10 64 位:Pro,Enterprise 或 Education(Build 14393 或更高版本)。
-
在 BIOS 中启用虚拟化。通常,默认情况下启用虚拟化。这与启用 Hyper-V 不同。
-
支持 CPU SLAT 的功能。
-
至少 4GB 的 RAM。
Docker for Windows 安装包括:安装提供 Docker Engine,Docker CLI 客户端,Docker Compose,Docker Machine 和 Kitematic。
安装包下载链接:https://store.docker.com/editions/community/docker-ce-desktop-windows
参考:https://docs.docker.com/docker-for-windows/
安装完后,会提示点击重启电脑。重启后会自动启动 Docker 程序,如果弹出下图所示提示,则需要在 Windows 功能中启用 Hyper-V 功能和 在 BIOS CPU 配置中打开 “虚拟化配置”,打开之后,如下图所示,虚拟化会显示已启用。反之安装成功。
注意虚拟化已启用,如下图所示(这里秀一把我 NB 的台式机,是不是比你们的服务器都高端 N 个档次):
以上配置完成后我们推荐将 docker 容器切换到 Linux 环境,选择右下角 Docker 图标右键选择” Switch to Linux containers” 进行切换,如果显示” Switch to Windows containers” 则已处于 Linux 容器。
这是我们可以测试 Docker 环境是否正常,打开命令行,输入 docker –version:
注意:
我们推荐使用 Linux 容器服务,因为目前主流的容器系统是 Linux,并且从资源的利用来说,Linux 可以让资源得到更大的利用。
关于 docker 的安装和配置,这里不再细说,大家可以关注我们的公众号 “magiccodes“来查阅相关的教程以及录屏。
配置 Docker 本地环境
安装完成并且启动后,右下角有个小图标:
右键打开设置。
Docker for Windows 中的共享驱动器必须配置为支持卷映射和调试。右键单击系统托盘中的 Docker 图标,单击 “设置”,然后选择 “共享驱动器”。 选择 Docker 存储文件的驱动器。 单击 “应用”。
其他的配置我们这里就不多说了,具体见公众号 “magiccodes” 中提供的录屏教程。
运行一个简单的 demo
我们先运行官方的 Hello world 示例:
docker run hello-world
我们也可以简单运行一个 web 示例,比如:
docker run --name aspnetcore_sample --rm -it -p 8000:80 microsoft/dotnet-samples:aspnetapp
应用程序启动后,使用浏览器打开 http://localhost:8000,即可看到以下界面:
Docker 的安装和配置在 Windows 10 操作系统下非常简单,我们也极力推荐大家使用此环境。毕竟,一个好的开发环境可以大大提高大家的使用和开发效率。
今天关于Docker最全教程之使用.NET Core推送钉钉消息和十九的分享就到这里,希望大家有所收获,若想了解更多关于ASP.NET Core基于Socket实现消息推送实战演练、C#实现推送钉钉消息的方法示例、DingTalk 钉钉消息推送(.net core 3 WebApi 尝鲜记)、Docker 最全教程 —— 从理论到实战(二)等相关知识,可以在本站进行查询。
本文标签: