使用 Docker 在 Linux 上托管 ASP.NET Core 应用程序

说在前面

在阅读本文之前,您必须对 Docker 的中涉及的基本概念以及常见命令有一定了解,本文侧重实战,不会对相关概念详述。

同时请确保您本地开发机器已完成如下安装:

  • Docker 18.06 或更高版本的 Docker 客户端

  • .NET Core SDK 2.2 或更高版本

  • Visual Studio Code 代码编辑器,以及 C# 语法插件 1.17.1 或更高版本

注:本文实验环境是 Ubuntu 18.04 LTS。如果您的机器是 Window,也可以把 Docker 装在虚拟机或服务器上。

创建演示项目

开始之前要先准备一个需要 Docker 容器化的 ASP.NET Core 应用程序,用于下面的操作演示。这里我用 .NET Core CLI 快速搭建一个全新的 Web API 项目。

启动 VS Code,打开集成终端,输入如下命令:

Copy

dotnet new webapi -o TodoApi
code -r TodoApi

以上便创建了一个名为TodoApi的 Web API 样板项目。

打开集成终端,输入dotnet run命令编译运行程序,然后打开浏览器跳转到 URL http://localhost:5000/api/values,如正常返回如下 JSON 数据,说明应用程序本地成功运行。

Copy

["value1","value2"]

现在让我们更进一步,在 Docker 中构建并运行该应用程序。

创建 Dockerfile 文件

Dockerfile 是一个文本文件,其用来定义单个容器的内容和启动行为,按顺序包含构建镜像所需的所有指令。Docker 会通过读取 Dockerfile 中的指令自动构建镜像。

在项目TodoApi根目录中,创建一个名为Dockerfile的文件,并粘贴以下内容:

Copy

FROM microsoft/dotnet:2.2-sdk AS build-env
WORKDIR /app


COPY *.csproj ./
RUN dotnet restore


COPY . ./
RUN dotnet publish -c Release -o out


FROM microsoft/dotnet:2.2-aspnetcore-runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "TodoApi.dll"]
  • FROM指令必须放在第一位,用于初始化镜像,为后面的指令设置基础镜像。

  • WORKDIR 指令为其他指令设置工作目录,如果不存在,则会创建该目录。

  • COPY指令会从源路径复制新文件或目录,并将它们添加到路径目标容器的文件系统中。

  • RUN指令可以在当前镜像之上的新 层 中执行任何命令并提交结果,生成的已提交镜像将用于 Dockerfile 中的下一步。

  • ENTRYPOINT指令支持以可执行文件的形式运行容器。

有关 Dockerfile 中指令用法的更多信息请参阅 Dockerfile reference。

同时,为了避免构建项目中的一些调试生成文件,可以在项目文件夹中新增.dockerignore文件,并粘贴如下内容:

Copy

bin\
obj\

构建应用容器镜像

在项目TodoApi根目录中,打开集成终端,执行如下命令构建容器镜像:

Copy

docker build -t todoapi .

-t参数用来指定镜像的名字及标签,通常是name:tag或者name格式。本例todoapi便是我们给镜像起的名字,没有设置标签即使用默认标签latest

如命令执行成功,终端会有类似如下输出:

Copy

$ docker build -t todoapi .
Sending build context to Docker daemon 1.137MB
Step 1/10 : FROM microsoft/dotnet:2.2-sdk AS build-env
2.2-sdk: Pulling from microsoft/dotnet
e79bb959ec00: Pull complete
d4b7902036fe: Pull complete
1b2a72d4e030: Pull complete
d54db43011fd: Pull complete
b3ae1535ac68: Pull complete
f04cf82b07ad: Pull complete
6f91a9d92092: Pull complete
Digest: sha256:c443ff79311dde76cb1acf625ae47581da45aad4fd66f84ab6ebf418016cc008
Status: Downloaded newer image for microsoft/dotnet:2.2-sdk
---> e268893be733
Step 2/10 : WORKDIR /app
---> Running in c7f62130f331
Removing intermediate container c7f62130f331
---> e8b6a73d3d84
Step 3/10 : COPY *.csproj ./
---> cfa03afa6003
Step 4/10 : RUN dotnet restore
---> Running in d96a9b89e4a9
Restore completed in 924.67 ms for /app/TodoApi.csproj.
Removing intermediate container d96a9b89e4a9
---> 14d5d32d40b6
Step 5/10 : COPY . ./
---> b1242ea0b0b8
Step 6/10 : RUN dotnet publish -c Release -o out
---> Running in 37c8eb07c86e
Microsoft (R) Build Engine version 16.0.450+ga8dc7f1d34 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

Restore completed in 663.74 ms for /app/TodoApi.csproj.
TodoApi -> /app/bin/Release/netcoreapp2.2/TodoApi.dll
TodoApi -> /app/out/
Removing intermediate container 37c8eb07c86e
---> 6238f4c1cf07
Step 7/10 : FROM microsoft/dotnet:2.2-aspnetcore-runtime
2.2-aspnetcore-runtime: Pulling from microsoft/dotnet
27833a3ba0a5: Pull complete
25dbf7dc93e5: Pull complete
0ed9cb15d3b8: Pull complete
874ea13b7488: Pull complete
Digest: sha256:ffd756d34bb0f976ba5586f6c88597765405af8014ae51b34811992b46ba40e8
Status: Downloaded newer image for microsoft/dotnet:2.2-aspnetcore-runtime
---> cb2dd04458bc
Step 8/10 : WORKDIR /app
---> Running in b0a3826d346b
Removing intermediate container b0a3826d346b
---> 4218db4cc2f5
Step 9/10 : COPY --from=build-env /app/out .
---> 765168aa2c7a
Step 10/10 : ENTRYPOINT ["dotnet", "TodoApi.dll"]
---> Running in f93bcaf5591f
Removing intermediate container f93bcaf5591f
---> 046226f5e9cb
Successfully built 046226f5e9cb
Successfully tagged todoapi:latest

如果您的机器是第一次构建,速度可能会有些慢,因为要从 Docker Hub 上拉取应用依赖的dotnet-sdkaspnetcore-runtime基础镜像。

构建完成后,我们可以通过docker images命令确认本地镜像仓库是否存在我们构建的镜像todoapi

Copy

REPOSITORY TAG IMAGE ID CREATED SIZE
todoapi latest c92a82f0efaa 19 hours ago 260MB
microsoft/dotnet 2.2-sdk 5e09f77009fa 26 hours ago 1.74GB
microsoft/dotnet 2.2-aspnetcore-runtime 08ed21b5758c 26 hours ago 260MB
...

运行应用容器

容器镜像构建完成后,就可以使用docker run命令运行容器了,有关该命令参数的更多信息请参阅 Reference - docker run 。

开发环境下,通常会通过docker run --rm -it命令运行应用容器,具体命令如下:

Copy

docker run --rm -it -p 5000:80 todoapi
  • -it参数表示以交互模式运行容器并为容器重新分配一个伪输入终端,方便查看输出调试程序。

  • --rm参数表示将会在容器退出后自动删除当前容器,开发模式下常用参数。

  • -p参数表示会将本地计算机上的5000端口映射到容器中的默认80端口,端口映射的关系为host:container

  • todoapi便是我们要启动的本地镜像名称。

如命令执行成功,终端会有类似如下输出:

Copy

$ docker run -it --rm -p 5000:80 todoapi
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {1a78d899-738b-4aea-a7d6-777302933f38} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http:
Application started. Press Ctrl+C to shut down.

生产环境下,通常会通过docker run -d命令运行应用容器,具体命令如下:

Copy

docker run -d --restart=always --name myapp -p 5000:80 todoapi
  • -d参数表示会将容器作为服务启动,不需要终端交互。

  • --name参数用来指定容器名称,本例指定容器名称为myapp

  • --restart是一个面向生产环境的参数,用来指定容器非正常退出时的重启策略,本例always表示始终重新启动容器,其他可选策略请参考 Restart policies (--restart)。

如命令执行成功,终端会有类似如下输出:

Copy

$ docker run -d --restart=always --name myapp -p 5000:80 todoapi
e3d747d9d2b4cd14b2acb24f81bea9312f89c4eb689dba5f6559950c91db1600

容器启动后,在 Web 浏览器中再次访问http://localhost:5000/api/values,应该会和本地测试一样返回如下 JSON 数据:

Copy

["value1","value2"]

至此,我们的 ASP.NET Core 应用就成功运行在 Docker 容器中了。

多容器应用部署

目前我们创建的演示项目TodoApi过于简单,真实的生产项目肯定会涉及更多其他的依赖。例如:关系数据库 Mysql、文档数据库 MongoDB、分布式缓存 Redis、消息队列 RabbitMQ 等各种服务。

还有就是,生产环境我们一般不会将 ASP.NET Core 应用程序的宿主服务器 Kestrel 直接暴露给用户,通常是在前面加一个反向代理服务 Nginx。

这些依赖服务还要像传统部署方式那样,一个一个单独配置部署吗?不用的,因为它们本身也是可以被容器化的,所以我们只要考虑如何把各个相互依赖的容器联系到一起,这就涉及到容器编排,而 Docker Compose 正是用来解决这一问题的,最终可以实现多容器应用的一键部署。

Docker Compose 是一个用于定义和运行多容器的 Docker 工具。其使用YAML文件来配置应用程序的服务,最终您只要使用一个命令就可以从配置中创建并启动所有服务。

安装 Docker Compose

Linux 系统下的安装过程大致分为以下几步:

Step1:运行如下命令下载 Compose 最新稳定版本,截止发稿前最新版本为1.24.0

Copy

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Step2:对下载完成的二进制程序添加可执行权限。

Copy

sudo chmod +x /usr/local/bin/docker-compose

Step3:测试安装是否成功。

Copy

$ docker-compose --version
docker-compose version 1.24.0, build 0aa59064

若您在安装过程中遇到问题,或是其他系统安装请参阅 Install Docker Compose。

改造演示项目

现在来改造一下我们的演示项目TodoApi,添加 Redis 分布式缓存、使用 Nginx 做反向代理,准备构建一个具如下图所示架构的多容器应用。

640?wx_fmt=png

TodoApi项目根目录下,打开集成终端,输入如下命令新增 Redis 依赖包。

Copy

dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis --version 2.2.0

修改应用启动配置文件Startup.cs中的ConfigureServices方法:

Copy


public void ConfigureServices(IServiceCollection services)
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});

services.AddHttpContextAccessor();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

TodoApi项目Controllers目录下新建控制器HelloController,具体代码如下所示:

Copy

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;

namespace TodoApi.Controllers
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;

namespace TodoApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HelloController : ControllerBase
{
private readonly IDistributedCache _distributedCache;
private readonly IHttpContextAccessor _httpContextAccessor;

public HelloController(
IDistributedCache distributedCache,
IHttpContextAccessor httpContextAccessor
)
{
_distributedCache = distributedCache;
_httpContextAccessor = httpContextAccessor;
}

[HttpGet]
public ActionResult<string> Get()
{
var connection = _httpContextAccessor.HttpContext.Connection;
var ipv4 = connection.LocalIpAddress.MapToIPv4().ToString();
var message = $"Hello from Docker Container:{ipv4}";

return message;
}

[HttpGet("{name}")]
public ActionResult<string> Get(string name)
{
var defaultKey = $"hello:{name}";
_distributedCache.SetString(defaultKey, $"Hello {name} form Redis");
var message = _distributedCache.GetString(defaultKey);

return message;
}
}
}

以上控制器,提供了两个接口/api/hello/api/hello/{name},分别用来测试 Nginx 负载均衡和 Redis 的联通性。

创建 docker-compose.yml

准备工作就绪,下面我们就可以使用 Docker Compose 来编排容器。

同样是在TodoApi项目根目录中,创建一个名为docker-compose.yml的文件,并粘贴以下内容:

Copy

version: "3.7"
services:
myproject-todoapi-1:
container_name: my-todoapi-1
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- "5001:80"
volumes:
- ./appsettings.json:/app/appsettings.json

myproject-todoapi-2:
container_name: my-todoapi-2
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- "5002:80"
volumes:
- ./appsettings.json:/app/appsettings.json

myproject-todoapi-3:
container_name: my-todoapi-3
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- "5003:80"
volumes:
- ./appsettings.json:/app/appsettings.json

myproject-nginx:
container_name: my-nginx
image: nginx
restart: always
ports:
- "80:80"
volumes:
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf

myproject-redis:
container_name: my-redis
image: redis
restart: always
ports:
- "6379:80"
volumes:
- ./conf/redis.conf:/etc/redis/redis.conf

其中version 用来指定 Compose 文件版本号,3.7是目前最新版本,具体哪些版本对应哪些特定的 Docker 引擎版本请参阅 Compose file versions and upgrading。

Compose 中强化了服务的概念,简单地理解就是, 服务是一种用于生产环境的容器。一个多容器 Docker 应用由若干个服务组成,如上文件即定义了 5 个服务

  • 3 个应用服务myproject-todoapi-1myproject-todoapi-2myproject-todoapi-3

  • 1 个 Nginx 服务myproject-reverse-proxy

  • 1 个 Redis 服务myproject-redis

以上 5 个服务的配置参数相差无几、也很简单,我就不展开叙述,不清楚的可以参阅 Compose file reference。

这里只讲一个配置参数volumes

我们知道,容器中的文件在宿主机上存在形式复杂,修改文件需要先通过如下命令进入容器后操作。

Copy

docker exec -it <CONTAINER ID/NAMES> /bin/bash

容器一旦删除,其内部配置以及产生的数据也会丢失。

为了解决这些问题,Docker 引入了数据卷 volumes 机制。即 Compose 中 volumes 参数用来将宿主机的某个目录或文件映射挂载到 Docker 容器内部的对应的目录或文件,通常被用来灵活挂载配置文件或持久化容器产生的数据。

创建相关配置文件

接下来,需要根据如上docker-compose.yml文件中涉及的volumes配置创建三个配置文件。要知道,它们最终是需要被注入到 Docker 容器中的

首先,在TodoApi项目根目录中,创建三个应用服务myproject-todoapi-*需要的程序配置文件appsettings.json,具体内容如下:

Copy

"ConnectionStrings": {
"Redis": "myproject-redis:6379,password=todoapi@2019"
},

以上配置,指定了 Redis 服务myproject-redis的连接字符串,其中myproject-redis可以看到是 Redis 服务的服务名称,当该配置文件注入到 Docker 容器中后,会自动解析为容器内部 IP,同时考虑到 Redis 服务的安全性,为其指定了密码,即password=todoapi@2019

然后,在TodoApi项目根目录中创建一个子目录conf,用来存放 Nginx 和 Redis 的配置文件。

Copy

mkdir conf && cd conf

先来创建 Redis 服务myproject-redis的配置文件。

可以通过如下命令,下载一个 Redis 官方提供的标准配置文件redis.conf

Copy

wget http:

然后打开下载后的redis.conf文件,找到SECURITY节点,根据如上应用服务的 Redis 连接字符串信息,启用并改下密码:

Copy

requirepass todoapi@2019

再来创建 Nginx 服务myproject-nginx的配置文件。

conf目录中,创建一个名为nginx.conf的配置文件,并粘贴如下内容:

Copy

upstream todoapi {
server myproject-todoapi-1:80;
server myproject-todoapi-2:80;
server myproject-todoapi-3:80;
}
server {
listen 80;
location / {
proxy_pass http://todoapi;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

以上配置,是一个 Nginx 中具备负载均衡的代理配置,其默认采用轮循策略将请求转发给 Docker 服务myproject-todoapi-1myproject-todoapi-2myproject-todoapi-3

运行并测试多容器应用

经过以上几个小节,容器编排的过程就完成了,接下来就可以直接定义并启动我们创建的多容器应用实例了。

切换到docker-compose.yml文件所在的目录,也就是TodoApi项目的根目录,执行如下命令:

Copy

docker-compose up -d

如命令执行成功,终端最后会有类似如下输出:

Copy

......
Creating my-todoapi-1 ... done
Creating my-redis ... done
Creating my-todoapi-3 ... done
Creating my-nginx ... done
Creating my-todoapi-2 ... done

至此,我们的多容器应用就已经在运行了,可以通过docker-compose ps命令来确认下。

Copy

$ docker-compose ps
Name Command State Ports

my-nginx nginx -g daemon off; Up 0.0.0.0:80->80/tcp
my-redis docker-entrypoint.sh redis ... Up 6379/tcp, 0.0.0.0:6379->80/tcp
my-todoapi-1 dotnet TodoApi.dll Up 0.0.0.0:5001->80/tcp
my-todoapi-2 dotnet TodoApi.dll Up 0.0.0.0:5002->80/tcp
my-todoapi-3 dotnet TodoApi.dll Up 0.0.0.0:5003->80/tcp

可以通过连续三次请求/api/hello接口测试应用的负载均衡。

Copy

curl http:
curl http:
curl http:



Hello from Docker Container:172.30.0.2
Hello from Docker Container:172.30.0.4
Hello from Docker Container:172.30.0.5

三个应用服务分别部署在不同容器中,所以理论上来讲,他们的容器内部 IP 也是不同的,所以/api/hello接口每次输出信息不会相同。

请求/api/hello/{name}接口测试 Redis 服务连通性。

Copy

curl http:



Hello esofar form Redis

小结

本文从零构建了一个 ASP.NET Core 应用,并通过 Docker 部署,然后由浅入深,引入 Docker Compose 演示了多容器应用的部署过程。通过本文的实战您可以更深入地了解 Docker。本文涉及的代码已托管到以下地址,您在实验过程中遇到问题可以参考。

https://github.com/esofar/dockerize-aspnetcore-samples

Docker 命令附录

Copy

$ docker --help

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
--config string Location of client config files (default "/root/.docker")
-D, --debug Enable debug mode
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit

Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
engine Manage the docker engine
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes

Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container
events Get real time events from the server
exec Run a command in a running container
export Export a container
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes

Docker Compose 命令附录

Copy

$ docker-compose
Define and run multi-container applications with Docker.

Usage:
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|

Options:
-f,
(default: docker-compose.yml)
-p,
(default: directory name)



-v,
-H,







name specified in the client certificate

(default: the path of the Compose file)

in v3 files to their non-Swarm equivalent

Commands:
build Build or rebuild services
bundle Generate a Docker bundle from the Compose file
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show the Docker-Compose version information

相关阅读

  • ASP.NET Core Docker Sample

  • Dockerize a .NET Core application

  • Best practices for writing Dockerfiles

  • Fun With Docker-Compose Using .NET Core And NGINX

  • ASP.NET Core 2.2: implementando Load Balancing com Nginx, Docker e Docker Compose

原文地址:https://www.cnblogs.com/esofar/p/10694319.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316060.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ICPC网络赛第二场G Limit

ICPC网络赛第二场G Limit 题意&#xff1a; 给你数组a和b&#xff0c;求解&#xff1a; 1≤n≤100000,−100≤ai,bi≤100,0≤t≤5.1≤n≤100000,−100≤a_{i},b_{i}≤100,0≤t≤5.1≤n≤100000,−100≤ai​,bi​≤100,0≤t≤5. 题解&#xff1a; 要用到洛必达来做&#xf…

[VSCode插件推荐] REST Client: 也许是比Postman更好的选择

在测试REST API的时候&#xff0c;想必大家都会有不同的工具选择。如果是基于CLI的话&#xff0c;大家应该会选择cURL。如果是GUI工具的话&#xff0c;相信很多人都会使用Postman。不过今天&#xff0c;笔者要推荐的是REST Client插件。也许&#xff0c;它是比Postman更好的选择…

.Net资讯 | 一大波开发者福利来了, 一份微软官方Github上发布的开源项目清单等你签收...

目录微软Github开源项目入口微软开源项目受欢迎程度排名Visual Studio CodeTypeScriptRxJS.NET Core 基础类库CNTKMicrosoft calculatorMonaco editorMS-DOSRedis windows版.NET Core CLR (公共语言运行时)ASP.NET CoreEntity Framework CorePowerShell如何在其中搜索自己需要的…

C#位运算实际作用之操作整型某一位

1.前言前几天写了两篇关于c#位运算的文章c#位运算基本概念与计算过程C#位运算实际运用在文中也提到了位运算的实际作用之一就是合并整型&#xff0c;当时引用了一个问题&#xff1a;C# 用两个short&#xff0c;一个int32拼成一个long型&#xff0c;高16位用short&#xff0c;中…

使用高性能Pipelines构建.NET通讯程序

.NET Standard支持一组新的API&#xff0c;System.Span, System.Memory&#xff0c;还有System.IO.Pipelines。这几个新的API极大了提升了.NET程序的效能&#xff0c;将来.NET很多基础API都会使用它们进行重写。Pipelines旨在解决.NET编写Socket通信程序时的很多困难&#xff0…

全球开发者的年度盛宴:微软全球开发者大会 Build 2019邀您一同加入

一年一度的微软全球开发者大会&#xff08;Build&#xff09;将于5月6日至8日在美国西雅图举办。本届大会将围绕全球当下的热门技术展开&#xff0c;包括人工智能、机器学习、容器、DevOps、物联网、混合现实以及Power Platforms等&#xff1b;微软热爱开发者、重视开发者&…

Oracle杀死Java EE:名正言顺转到.NET Core

Eclipse 基金会执行董事 Mike Milinkovich 昨日在博客发表了 Oracle 与 Eclipse 基金会之间关于 Java 商标谈判的结果 —— 双方的谈判最后以失败告终&#xff0c;Oracle 拒绝出让 Java 商标。Mike 在博客中还提及了 Eclipse 基金会和 Oracle 之间关于 Jakarta EE 的协议、Java…

程序员修神之路--redis做分布式锁可能不那么简单

点击上方“蓝字”带你去看小星星菜菜哥&#xff0c;复联四上映了&#xff0c;要不要一起去看看&#xff1f;又想骗我电影票&#xff0c;对不对&#xff1f;呵呵&#xff0c;想去看了叫我呀看来你工作不饱和呀哪有&#xff0c;这两天我刚基于redis写了一个分布式锁&#xff0c;很…

CF1548A Web of Lies

CF1548A Web of Lies 题意&#xff1a; 题解&#xff1a; 第一感觉是先建边然后跑dfs&#xff0c;但是看数据范围肯定不对&#xff0c;现在我们开始考虑其中的性质 对于第三个操作&#xff0c;我们是要将所有>2的连通块进行判断的&#xff0c;我们考虑对于编号为x的点&…

Abp CLI 上线

Abp vNext CLI 工具随着0.17.0版本的发布已经上线.Abp中文网第一时间制作 Cn.Abp.Cli 工具. 目前提供下载加速, 后续Abp中文网CLI将会提供更多本土化功能, 并随时与官方CLI代码同步.源码(查看原文): https://github.com/cnAbp/abp-cli原文地址&#xff1a;https://mp.weixin.qq…

一篇短文带您了解一下EasyCaching

前言从2017年11月11号在Github创建EasyCaching这个仓库&#xff0c;到现在也已经将近一年半的时间了&#xff0c;基本都是在下班之后和假期在完善这个项目。由于EasyCaching目前只有英文的文档托管在Read the Docs上面&#xff0c;当初选的MkDocs现在还不支持多语言&#xff0c…

[开源]OSharpNS - .net core 快速开发框架 - 简介

OSharpNS全称OSharp Framework with .NetStandard2.0&#xff0c;是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架。这个框架使用最新稳定版的.NetCore SDK&#xff08;当前是.NET Core 2.2&#xff09;&#xff0c;对 AspNetCore 的配置、依赖注入、日志、缓存、实体…

2019年了,C#发展的怎么样了呢?

C# 8.0我估计大多数程序员对于C# 5.0之后的改进都没有什么太多的认知&#xff0c;的确从C# 5.0开始C#已经没什么太多东西可以从其他语言借鉴&#xff0c;Anders的重心也开始逐步倾斜到TypeScript&#xff0c;所以从5.0引入async之后C#语言发展速度开始减缓了。C#6引入了大量的语…

微软宣布新命令行工具 Windows Terminal 和 WSL2

微软在 Build 2019 已经宣布推出名为Windows Terminal的新款命令行工具 , 这款工具可以访问多种环境的中心位置。例如可以直接访问PowerShell、CMD.EXE、Windows Linux子系统等等&#xff0c;开发者使用此工具可以简化工作。这款新工具支持多选项卡同时连接多个环境或服务器&a…

CF1305E Kuroni and the Score Distribution

CF1305E Kuroni and the Score Distribution 题意&#xff1a; 题解&#xff1a; 一开始想这个题&#xff0c;想法是一开始顺着填1&#xff0c;2&#xff0c;3…然后多删少补 如果1&#xff0c;2&#xff0c;3&#xff0c;4…这样顺延的填&#xff0c;对于akka_{k}kak​k可以…

微软 Build 2019:Windows 10 隐退,IE 重生,Azure 成主角

019 年 5 月 6 日&#xff0c;一年一度的微软 Build 开发者大会正式到来。作为本次大会最为重磅的 Keynote 环节&#xff0c;微软 CEO Satya Nadella 的开场演讲无疑展示了这家巨头对于未来科技发展趋势的洞察和判断&#xff0c;并且也能够让人更加清晰地看到微软在 Azure 云计…

普通人看Build 2019 值得留心的亮点有哪些?

一场Keynote下来&#xff0c;是不是对纳德拉那套“Azure&#xff0c;azure&#xff0c;azure”&#xff0c;云云云的套路感觉有些乏味呢&#xff1f;当然这也不是你的问题&#xff0c;原本Build大会就是为开发者而设的&#xff0c;将近两个小时下来没看到什么能让自己眼前一亮的…

Build 2019:微软正式宣布 .NET 5

今天&#xff0c;我们宣布 .NET Core 3.0 之后的下一个版本将是 .NET 5 。这将是 .NET 系列的下一个重要版本。将来只会有一个 .NET &#xff0c;您将能够使用它来开发 Windows&#xff0c;Linux&#xff0c;macOS&#xff0c;iOS&#xff0c;Android&#xff0c;tvOS&#xff…

LGV定理

老早就听说&#xff0c;一直没学&#xff0c;今天遇到一个LGV比较裸的题&#xff0c;特地学习一下 选自oi-wiki 定义&#xff1a; e(u,v)表示u到v这条路径上所有边的边权之积(路径计数时&#xff0c;可以将边权都设为1),很多路径统计问题就是用到这一点 引理&#xff1a; 答案…

2019牛客多校Monotonic Matrix

Monotonic Matrix 题意&#xff1a; 问有多少个n * m的矩阵A满足一下情况&#xff1a;答案mod 1e97 矩阵A的所有元素∈{0,1,2}Ai,j<Ai1,jA_{i,j}<A_{i1,j}Ai,j​<Ai1,j​Ai,j<Ai,j1A_{i,j}<A_{i,j1}Ai,j​<Ai,j1​ 题解&#xff1a; 我们先看看这个式子…