ps:废话不多说。直接上代码:源码地址:https://github.com/786744873/Asp.Net-Core-2.1-All-Demos/tree/master/src
Configuration的配置
说明:基于三种方式的读取配置文件以及自定义读取自定义配置文件
文件结构
代码
PropertiesConfigurationProvider.cs
public class PropertiesConfigurationProvider:ConfigurationProvider
{
string _path = string.Empty;
public PropertiesConfigurationProvider(string path)
{
this._path = path;
} /// <summary>
/// 用于解析1.properties
/// </summary>
public override void Load()
{
var lines = File.ReadAllLines(this._path); var dict = new Dictionary<string, string>(); foreach (var line in lines)
{
var items = line.Split('=');
dict.Add(items[], items[]);
} this.Data = dict;
}
}
PropertiesConfigurationSource.cs
public class PropertiesConfigurationSource : IConfigurationSource
{ string _path = string.Empty;
public PropertiesConfigurationSource(string path)
{
this._path = path;
} public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new PropertiesConfigurationProvider(_path);
}
}
PropertiesConfigurationExtensions.cs
public static class PropertiesConfigurationExtensions
{
public static IConfigurationBuilder AddPropertiesFile(this IConfigurationBuilder builder, string path)
{
builder.Add(new PropertiesConfigurationSource(path));
return builder;
}
}
1.properties
port=
host=127.0.0.1
appsettings.json
{
"mysql": {
"host": "127.0.0.1",
"port":
},
"shopidlist": [
{ "entid": },
{ "entid": }
]
}
Program.cs
class Program
{
static void Main(string[] args)
{
IConfiguration Configuration = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("appsettings.json", optional:true,reloadOnChange:true)
.AddPropertiesFile("1.properties")//加载自定义文件
.Build(); Appsettings appsettings = new Appsettings();
Configuration.Bind(appsettings); Console.WriteLine(appsettings.mysql.port); Console.WriteLine(Configuration["mysql:port"]); Console.WriteLine(Configuration.GetValue<int>("mysql:port")); Console.WriteLine(Configuration.GetSection("mysql").GetSection("port").Value);
//读取自定义文件
Console.WriteLine(Configuration["host"]); Console.Read();
}
} public class Appsettings
{
public Mysql mysql { get; set; }
public Shopidlist[] shopidlist { get; set; }
} public class Mysql
{
public string host { get; set; }
public int port { get; set; }
} public class Shopidlist
{
public int entid { get; set; }
}
CollectionService注入
文件结构
代码
Program.cs
class Program
{
static void Main(string[] args)
{
//IOC容器
ServiceCollection services = new ServiceCollection(); //注册服务
services.AddScoped<IFlay, Pig>(); //注册日志服务
services.AddLogging(); var provider = services.BuildServiceProvider(); provider.GetService<ILoggerFactory>().AddConsole(LogLevel.Debug); var fly = provider.GetService<IFlay>(); fly.Flay(); }
} public interface IFlay
{
void Flay();
} public class Pig : IFlay
{
ILogger<Pig> logger = null; public Pig(ILoggerFactory loggerFactory)
{
logger=loggerFactory.CreateLogger<Pig>();
} public void Flay()
{
logger.LogInformation("这是Console日志");
Console.WriteLine("风口来了,猪都会飞了!");
}
}
AOP AspectCore
文件结构
代码
Program.cs
//https://github.com/dotnetcore/AspectCore-Framework
class Program
{
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection(); //注册AspectCore动态代理服务
services.AddDynamicProxy(); services.AddTransient<IMySql, MySql>(); var provider= services.BuildDynamicProxyServiceProvider(); var mysql = provider.GetService<IMySql>(); //走业务逻辑
var msg= mysql.GetData();
Console.WriteLine(msg); //走缓存
msg = mysql.GetData();
Console.WriteLine(msg); }
} public class MysqlInterceptorAttribute : AbstractInterceptorAttribute
{
private Dictionary<string, string> cacheDict = new Dictionary<string, string>(); public override Task Invoke(AspectContext context, AspectDelegate next)
{ //用id作为cachekey
var cacheKey = string.Join(",", context.Parameters);
if (cacheDict.ContainsKey(cacheKey))
{
context.ReturnValue = cacheDict[cacheKey];
return Task.CompletedTask;
} var task = next(context);
//ReturnValue实际上就是一个传递值的媒介
var cacheValue = context.ReturnValue; cacheDict.Add(cacheKey, $"from Cache:{cacheValue.ToString()}"); return task; //Console.WriteLine("开始记录日志。。。。");
//var task = next(context);
//Console.WriteLine("结束记录日志。。。。");
//return task;
}
} public interface IMySql
{
[MysqlInterceptor]
string GetData(int id);
} public class MySql : IMySql
{
public string GetData(int id)
{
var msg = $"已经获取到id={id}的数据";
//Console.WriteLine(msg);
return msg;
}
}
MemoryCache
文件结构
代码
Program.cs
class Program
{
static void Main(string[] args)
{ {//cache的最大限度为100 MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
{
SizeLimit =
}); for (int i = ; i < ; i++)
{
memoryCache.Set<string>(i.ToString(), i.ToString(), new MemoryCacheEntryOptions()
{
Size =
}); Console.WriteLine(memoryCache.Count);
}
} {//被动过期,设置过期回调 MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
{ }); var cacheOptions = new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(),//3秒过期
};
cacheOptions.RegisterPostEvictionCallback((key, value, reason, obj) =>
{
Console.WriteLine(reason);
Console.WriteLine("执行过期回调");
}); memoryCache.Set("key", "value", cacheOptions); Console.WriteLine("3秒后过期将执行回调");
while (true)
{
Thread.Sleep();
Console.WriteLine(memoryCache.Get<string>("key"));
}
Console.ReadKey();
} {//主动过期(10秒被动过期,2秒主动使用token让他过期) CancellationTokenSource tokenSource = new CancellationTokenSource();
MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()
{ }); var cacheOptions = new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(),//10秒过期
};
cacheOptions.AddExpirationToken(new CancellationChangeToken(tokenSource.Token));//加入Token
cacheOptions.RegisterPostEvictionCallback((key, value, reason, obj) =>
{
Console.WriteLine(reason);
Console.WriteLine("执行过期回调");
}); memoryCache.Set("key", "value", cacheOptions); Console.WriteLine("10秒后过期将执行回调"); tokenSource.CancelAfter(TimeSpan.FromSeconds());
while (true)
{
Thread.Sleep();
Console.WriteLine(memoryCache.Get<string>("key"));
}
Console.ReadKey();
}
}
}
Redis MongoDB
文件结构
代码
Program.cs
class Program
{
static void Main(string[] args)
{
//Redis
{
RedisCache redisCache = new RedisCache(new RedisCacheOptions()
{
Configuration = "127.0.0.1:6379",
InstanceName = "test"
}); //在Redis中是以Hash的模式存放的
redisCache.SetString("username", "jack", new DistributedCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddDays(),
}); var info = redisCache.GetString("username"); Console.WriteLine(info);
} //MongoDB
{
MongoDBCache mongoDBCache = new MongoDBCache(new MongoDBCacheOptions()
{
ConnectionString = "mongodb://127.0.0.1:27017",
DatabaseName = "mydb",
CollectionName = "mytest"
}); mongoDBCache.Set("username", Encoding.UTF8.GetBytes("jack"), new DistributedCacheEntryOptions {
AbsoluteExpiration = DateTime.Now.AddDays()
}); var info= Encoding.UTF8.GetString(mongoDBCache.Get("username"));
Console.WriteLine(info);
} }
}
Mysql.Data Dapper
文件结构
代码
class Program
{
static void Main(string[] args)
{
//MySql.Data
{
var connectString = "server=127.0.0.1;por=3306;userid=root;pwd=123456;database=datamip;SslMode=none;";
//MySqlConnection mySqlConnection = new MySqlConnection(connectString); //select
var ds = MySqlHelper.ExecuteDataset(connectString, "select * from users"); //select2
var reader = MySqlHelper.ExecuteReader(connectString, "select * from users");
var user = new Users();
while (reader.Read())
{
user.UserId = reader.GetInt32("UserID");
user.UserNick = reader.GetString("UserNick");
user.LoginIP = reader.GetString("LoginIP");
user.Email = reader.GetString("Email");
}
reader.Close(); //update
var result = MySqlHelper.ExecuteNonQuery(connectString, "update users set Email='786744873@qq.com' where UserID=1");
} //Dapper
{
var connectString = "server=127.0.0.1;por=3306;userid=root;pwd=123456;database=datamip;SslMode=none;";
MySqlConnection mySqlConnection = new MySqlConnection(connectString); //select
var userList = mySqlConnection.Query<Users>("select * from users where UserID=@UserID",new { UserID= }); //update
var nums = mySqlConnection.Execute("update users set Email='786744873@qq.com' where UserID=1");
} } class Users
{
public int UserId { get; set; }
public string UserNick { get; set; }
public string LoginIP { get; set; }
public string Email { get; set; }
}
}
nohup supervisord部署Unbuntu
不得不说Ubuntu18.04版本是个巨坑。还是老老实实用16.04吧,错了,是VirtualBox是个巨坑,这wtf软件各种问题,浪费我几天时间,艹
文件结构
代码
ConfigurationManager.cs
public class ConfigurationManager
{
public static IConfigurationRoot Configuration
{
get
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(string.Format("appsettings.{0}.json", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")),optional:true,reloadOnChange:true)
.AddJsonFile(string.Format("ops.{0}.json", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")),optional:true,reloadOnChange:true)
.Build();
return configuration;
}
}
}
Program.cs
class Program
{
static void Main(string[] args)
{
var tokenSource = new CancellationTokenSource(); Task.Factory.StartNew(() =>
{
while (!tokenSource.IsCancellationRequested)
{
Console.WriteLine($"{DateTime.Now}:业务逻辑处理中");
Thread.Sleep();
}
}).ContinueWith(t =>
{
Console.WriteLine("服务安全退出!");
Environment.Exit();//强制退出
}); Console.WriteLine("服务成功开启"); while (!"Y".Equals(ConfigurationManager.Configuration["isquit"],StringComparison.InvariantCultureIgnoreCase))
{
Thread.Sleep();
} tokenSource.Cancel();
}
}
ops.Development.json || ops.Production.json
{
"isquit": "N"
}
部署过程
直接发布,发布以及虚拟机安装参照之前的博客:Virtual Box虚拟机Ubuntu18.X系统安装及Mysql基本开发配置,这里主要讲如何进行持久化
ubuntu16.04开机提示:检测到系统程序出现问题
打开终端,输入 sudo gedit /etc/default/apport 把enabled=1改成enabled=
方案一:nohub部署
先执行 nohup dotnet 程序集名称 &
nohup dotnet ConsoleApp7.dll & #(符号&使程序在后台运行)
exit #(退出nohup模式)
然后输入 exit 进行退出,不然的话后台进程会被终结
启动后,会将程序运行输出记录在当前目录下的nohup.out文件下,如果当前目录不可写,则会被记录在Home目录下的nohup.out文件中
nohup dotnet ConsoleApp7.dll > my_nohup.log 2>&1 & #(将日志输出在my_nohup.log文件中,并将stderr重定向至stdout)
查看dotnet进程
ps -ef |grep dotnet
查看后10行nohup输出
tail /home/wyt/nohup.out
查看运行的后台进程
ps -ef | grep dotnet
停止程序
kill - #(根据进程号关闭程序)
方案二:supervisord部署
安装
ubuntu安装:
sudo apt-get install supervisor
centos安装:
yum install -y supervisor
安装成功后,会在 /etc/supervisor 目录下,生成 supervisord.conf 配置文件。
你也可以使用 echo_supervisord_conf > supervisord.conf 命令,生成默认的配置文件(不建议,内容比较多)。
supervisord.conf 示例配置:
; supervisor config file [unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod= ; sockef file mode (default ) [supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP) ; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket ; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves. [include]
files = /etc/supervisor/conf.d/*.conf
进程配置会读取 /etc/supervisor/conf.d 目录下的 *.conf 配置文件,我们在此目录下创建一个 ConsoleApp7.conf 进程配置文件:
[program:ConsoleApp7]
directory=/data/output
command=/usr/bin/dotnet /data/output/ConsoleApp7.dll
autostart=true
autorestart=true
startretries=
redirect_stderr=true
stdout_logfile=/data/output/logs/out.log
stderr_logfile=/data/output/logs/out.log
environment=ASPNETCORE_ENVIRONMENT="Development"
需要注意的是,如果不是 root 账号,需要对这些目录进行权限设置,要不然会报一些错误(一定要在 root 账号下进行配置,要不然一系列权限引起的问题