【.Net7-性能优化篇】.Net7+WebApi+EFCore+SqlServer读写分离封装

这篇博客描述的是运行环境是.Net 7下使用WebApi,ORM框架使用EF Core的DbFirst模式,再配合上SqlServer的1主,2从3个数据库,完成的读写分离封装。

一.先准备3个数据库,1主,2从
我先准备了3个数据库,分别是:SchoolDB(作为主库,到时候只负责写)、SchoolDB_Read_1(作为从库1,到时候只负责读)、SchoolDB_Read_2(作为从库2,到时候只负责读),里面都有张学生表。

 

二.EFCore DbFirst模式生成实体和DbContext

根据数据库生成实体,工具=>NuGet包管理器=>程序包管理器控制台(项目设置为启动项)

生成命令:

Scaffold-DbContext -Connection "Server=meng\MSSQLSERVERML;Database=SchoolDB;uid=sa;pwd=123456abc;Trusted_Connection=True;TrustServerCertificate=true" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -ContextDir Context 命令说明: -OutputDir:实体文件存放的目录 -ContextDir:DbContext文件存放的目录 -Context:DdContext文件名 -Force:强制执行,重写已经存在的实体文件

 

三.封装前的其他类准备

3.1.数据库连接配置

namespace MengLin.Shopping.SchoolDB.DbFirst.ConfigureOptions
{
    /// <summary>
    /// 数据库连接配置
    /// </summary>
    public class ConnectionStringOptions
    {
        /// <summary>
        /// 写链接-主库Mast
        /// </summary>
        public string WriteConnection
        {
            get;
            set;
        }

        /// <summary>
        /// 读链接-从库Salve
        /// </summary>
        public List<string> ReadConnectionList
        {
            get;
            set;
        }
    }
}

 

3.2.appsettings.json映射ConnectionStringOptions数据库连接配置的json文件

 

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStringOptions": {
    "WriteConnection": "Server=meng\\MSSQLSERVERML;Database=SchoolDB;uid=sa;pwd=123456abc;Trusted_Connection=True;TrustServerCertificate=true",
    "ReadConnectionList": [
      "Server=meng\\MSSQLSERVERML;Database=SchoolDB_Read_1;uid=sa;pwd=123456abc;Trusted_Connection=True;TrustServerCertificate=true",
      "Server=meng\\MSSQLSERVERML;Database=SchoolDB_Read_2;uid=sa;pwd=123456abc;Trusted_Connection=True;TrustServerCertificate=true"
    ]
  }
}

 

3.3.操作数据库是读还是写的枚举

namespace MengLin.Shopping.SchoolDB.DbFirst.Enum
{
    public enum WriteAndReadEnum
    {
        //主库操作
        Write,
        //从库操作
        Read
    }
}

 

四.定义接口-IBaseService

定义一些常用、共性操作,比如:增删改查,为了简化代码,我这里只是定义了Insert添加、Where分页查询、Commit提交三个方法。

    /// <summary>
    /// 基本操作接口
    /// </summary>
    public interface IBaseService
    {
        /// <summary>
        /// 添加数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        T Insert<T>(T t) where T : class;
/// <summary> /// 根据表达式目录树进行分页查找数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression">表达式目录树</param> /// <param name="writeAndReadEnum">默认从库操作</param> /// <returns></returns> (IQueryable<T>, int totalCount) Where<T>(Expression<Func<T, bool>> expression,int pageIndex,int pageSize, WriteAndReadEnum writeAndReadEnum = WriteAndReadEnum.Read) where T : class; /// <summary> /// 保存提交 /// </summary> void Commit(); }

 

五.定义基本操作实现类-BaseService

继承IBaseService接口,实现接口里面的Insert添加、Where分页查询、Commit提交这三个方法。

   /// <summary>
    /// 基本操作实现
    /// </summary>
    public class BaseService : IBaseService, IDisposable
    {
        /// <summary>
        /// 数据访问工厂
        /// </summary>
        private DBContextFactory _dbContextFactory = null;

        /// <summary>
        /// 构造函数注入DbContext工厂
        /// </summary>
        /// <param name="dbContext"></param>
        public BaseService(DBContextFactory dbContextFactory)
        {
            _dbContextFactory = dbContextFactory;
        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">主键</param>
        /// <returns></returns>
        public T Insert<T>(T t) where T : class
        {
//只能对主库增加 _dbContext = _dbContextFactory.GetSetupDbContext(WriteAndReadEnum.Write); _dbContext.Set<T>().Add(t); return t; }
/// <summary> /// 保存提交 /// </summary> public void Commit() { _dbContext.SaveChanges(); } /// <summary> /// 释放资源 /// </summary> public void Dispose() { if (_dbContext != null) { _dbContext.Dispose(); } }

/// <summary> /// 根据表达式目录树进行分页查找数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expression">表达式目录树</param> /// <param name="writeAndReadEnum">默认从库操作</param> /// <returns></returns> public (IQueryable<T>,int totalCount) Where<T>(Expression<Func<T, bool>> expression, int pageIndex, int pageSize, WriteAndReadEnum writeAndReadEnum = WriteAndReadEnum.Read) where T : class { //选择其中一个从库进行查询 _dbContext = _dbContextFactory.GetSetupDbContext(writeAndReadEnum); return (_dbContext.Set<T>().Where(expression).Skip((pageIndex-1) * pageSize).Take(pageSize), _dbContext.Set<T>().Where(expression).Count()); } }

 

六.定义学生服务类-IStudentService、StudentService

学生服务,除了基本的增删改查,还要有自己的行为,比如:打游戏,学习。

   /// <summary>
    /// 学生接口
    /// </summary>
    public interface IStudentService:IBaseService
    {
        /// <summary>
        /// 学习
        /// </summary>
        public void Study();


        /// <summary>
        /// 玩游戏
        /// </summary>
        public void PalyGame();
    }
    /// <summary>
    /// 学生服务
    /// </summary>
    public class StudentService:BaseService, IStudentService
    {

        public StudentService(DBContextFactory dbContextFactory) : base(dbContextFactory)
        {

        }

        /// <summary>
        /// 学习
        /// </summary>
        public void Study()
        {
            Console.WriteLine("我要学习了!");
        }


        /// <summary>
        /// 玩游戏
        /// </summary>
        public void PalyGame()
        {
            Console.WriteLine("我要玩游戏了!");
        }
    }

 

七.最重要的来了,DBContext工厂类-DBContextFactory

.Net 7框架中动不动来个工厂,比如DefaultServiceProviderFactory(IOC容器工厂,造容器的)、DefaultControllerFactory(控制器工厂,造控制器的),我也借鉴.Net 7框架的思想,我来个DBContextFactory,造DBContext的,其实也不算造DBContext,只是指定DBContext的数据库连接字符串。

在DBContextFactory中完成了对DBContext连接数据库字符串的指定。

namespace MengLin.Shopping.SchoolDB.DbFirst.Factory
{
    /// <summary>
    /// DBContext制造工厂
    /// </summary>
    public class DBContextFactory
    {
        /// <summary>
        /// DbContext数据库上下文
        /// </summary>
        private readonly DbContext _dbContext = null;

        /// <summary>
        /// 读/写数据库连接字符串配置
        /// </summary>
        private readonly ConnectionStringOptions _connectionStringOptions = null;

        /// <summary>
        /// 构造函数注入DbContext实例
        /// 构造函数Option注入读/写数据库连接字符串配置
        /// </summary>
        /// <param name="dbContext"></param>
        public DBContextFactory(DbContext dbContext, IOptionsSnapshot<ConnectionStringOptions> connectionStringOptions)
        {
            _dbContext = dbContext;
            _connectionStringOptions = connectionStringOptions.Value;
        }

        /// <summary>
        /// 得到已经重新设置过数据库连接的DbContext
        /// </summary>
        /// <param name="writeAndReadEnum">标记读或写</param>
        /// <returns></returns>
        public DbContext GetSetupDbContext(WriteAndReadEnum writeAndReadEnum)
        {
            //设置读数据库连接字符串
            if (writeAndReadEnum is WriteAndReadEnum.Read)
            {
                SetReadConnectionString();
            }
            else if(writeAndReadEnum is WriteAndReadEnum.Write)//设置写数据库连接字符串
            {
                SetWriteConnectionString();
            }

            return _dbContext;
        }

        /// <summary>
        /// 设置写数据库连接字符串
        /// </summary>
        private void SetWriteConnectionString()
        {
            //从注入的Options配置中获取写的数据库链接字符串
            string writeConnectionString = _connectionStringOptions.WriteConnection;

            if (_dbContext is SchoolDBContext)
            {
                var schoolDBContext = (SchoolDBContext)_dbContext; 

                schoolDBContext.SetWriteOrReadConnectionString(writeConnectionString);
            }
        }

        private static int seed = 0;//种子
        /// <summary>
        /// 设置读数据库连接字符串
        /// </summary>
        private void SetReadConnectionString()
        {//随机策略--取得读的数据库链接字符串
            //int connectionStringCount = _connectionStringsOptions.ReadConnectionList.Count;
            //int index = new Random().Next(0, connectionStringCount);
            //string readConnectionString = _connectionStringsOptions.ReadConnectionList[index];

            //均衡策略---第1次index为0,第2次index为1,第3次index为0
            //          第4次index为1,第5次index为0,第6次index为1
            //          第7次index为0,第8次index为1,第9次index为0
            //          0 % 2 = 0      1 % 2 = 1      2 % 2 = 0
            //          3 % 2 = 1      4 % 2 = 0      5 % 2 = 1
            //          6 % 2 = 0      7 % 2 = 1      8 % 2 = 0
            int connectionStringCount = _connectionStringOptions.ReadConnectionList.Count;
            int index = seed++ % connectionStringCount;
            string readConnectionString = _connectionStringOptions.ReadConnectionList[index];//索引不是0就是1

            if (_dbContext is SchoolDBContext)
            {
                var schoolDBContext = (SchoolDBContext)_dbContext; 
                schoolDBContext.SetWriteOrReadConnectionString(readConnectionString);
            }
        }
    }
}

 

八.SchoolDBContext
设置它自己的访问数据库的连接字符串。

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
       {
            if (!optionsBuilder.IsConfigured)
            {
                //这里写死了
                //optionsBuilder.UseSqlServer("Server=meng\\MSSQLSERVERML;Database=SchoolDB;uid=sa;pwd=123456abc;Trusted_Connection=True;TrustServerCertificate=true");

                //动态使用数据库链接字符串
                optionsBuilder.UseSqlServer(connectionString);
            }
        }


        //数据库链接字符串
        private string connectionString = string.Empty;

        /// <summary>
        /// 设置读或者写的数据库链接字符串
        /// </summary>
        /// <param name="connString">链接字符串</param>
        public void SetWriteOrReadConnectionString(string connString)
        {
            connectionString = connString;
        }

 

 

九.程序入口Program中注册数据库上下文类(SchoolDBContext)、数据库上下文工厂类(DBContextFactory)、学生服务类(StudentService)

    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.

            builder.Services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at http://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();

            #region 注册服务,以及数据库上下文工厂
            {
                //注册数据库上下文类
                builder.Services.AddScoped<DbContext, SchoolDBContext>();
                //注注册数据库上下文工厂类-目的:为了修改数据库上下文类的数据库连接字符串
                builder.Services.AddScoped<DBContextFactory, DBContextFactory>();
                //注册学生服务
                builder.Services.AddScoped<IStudentService, StudentService>();
            }
            #endregion

            #region 注册配置
            {
                //注册配置实例到哪个TOptions
                builder.Services.Configure<ConnectionStringOptions>(builder.Configuration.GetSection("ConnectionStringOptions"));
            }
            #endregion

            //添加跨越策略
            builder.Services.AddCors(options => options.AddPolicy("any", policy =>
            {
                //设定允许跨域的来源,有多个可以用','隔开
                policy.WithOrigins("http://localhost:8080", "http://localhost:8080")
                .AllowAnyHeader()//允许任何标头
                .AllowAnyMethod()//允许任何方法访问
                .AllowCredentials();//允许凭据的策略
            }));


            builder.Services.AddSwaggerGen(s =>
            {
                s.SwaggerDoc("V1", new OpenApiInfo()
                {
                    Title = "通用后台系统",
                    Version = "Version-01",
                    Description = "通用后台系统"
                });
                var currentDirectory = AppContext.BaseDirectory;
                s.IncludeXmlComments($"{currentDirectory}/MengLin.DotNet7.WebAPI.xml");
            });

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI(s =>
                {
                    s.SwaggerEndpoint("/swagger/V1/swagger.json", "test1");
                });
            }
            //使用跨越策略
            app.UseCors("any");

            app.UseHttpsRedirection();

            app.UseAuthorization();


            app.MapControllers();

            app.Run();
        }
    }

 

十.访问学生的控制器

在StudentService服务去做查询的时候,内部设置了下SchoolDBContext连接的字符串为读库的连接字符串。

namespace MengLin.DotNet7.WebAPI.Controllers
{
    /// <summary>
    /// 学生
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class StudentsController : ControllerBase
    {
        /// <summary>
        /// 获取学生列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [Route("{pageindex}/{pagesize}")]
        public RespResult Get(IStudentService studentService)
        {
            //从请求中获取路由数据
            RouteValueDictionary dicRouteValue = HttpContext.Request.RouteValues;
            //url中的页索引和页大小
            int.TryParse(dicRouteValue["pageindex"]?.ToString(),out int pageIndex);
            int.TryParse(dicRouteValue["pageSize"]?.ToString(), out int pageSize);

            var respResult = new RespResult<IQueryable<Student>>();
            //查询满足条件的学生,且带分页
            (IQueryable<Student> studentList,int totalCount) = studentService.Where<Student>(c => c.Sex == "", pageIndex, pageSize);

            respResult.data = studentList;//结果集
            respResult.TotalCount = totalCount;//记录总条数

            return respResult;
        }
    }
}

 

 

最后附上一张项目图

 

旧书不厌百回读,熟读深思子自知。
本文转载于网络 如有侵权请联系删除

相关文章

  • Supesite 参数说明

    大家好,又见面了,我是你们的朋友全栈君。supesite有人看到的是强大的功能,我看到的是坑爷的一些用法,第一次看到block,我晕了。对于参数一头雾水,下面收集了一些,备用吧。supesite标签调用参数详解参数:blocktype模块名称,系统有一下模块blocktype=category系统分类模块blocktype=spacenews  资讯模块blocktype=poll  投票模块blocktype=spaceblog日志模块blocktype=spaceimage  图片模块blocktype=spacefile文件模块blocktype=spacegoods  商品模块blocktype=spacelink书签模块blocktype=tag    TAG模块blocktype=spacetag   TAG文章信息模块blocktype=spacecomment用户回复模块blocktype=userspace个人空间列表模块blocktype=announcement站点公告模块blocktype=friendlink站点友情链接模块blocktype=spacevid

  • 如何删除kafka消费组原创

    当一个topic写入到kafka,而我们接入了多了个消费组,这种情况下,其中某个消费组停止消费,却会看到对应消费组的消息堆积依然在叠加,这是个奇怪的问题,暂时不知道什么原因,不过可以通过如下方式,将这个消费组删除,如果这些消息内容不是很重要的话。堆积如下图:此时来到kafka集群,进行一波查看:cd/usr/local/kafka/bin复制查看对应消费组:./kafka-consumer-groups.sh--bootstrap-server10.3.9.105:9092--list|grepvector复制查看该消费组详情:./kafka-consumer-groups.sh--bootstrap-server10.3.9.105:9092--describe--groupvector-group Consumergroup'vector-group'hasnoactivemembers. TOPICPARTITIONCURRENT-OFFSETLOG-END-OFFSETLAGCONSUMER-IDHOSTCLIENT-ID nginx_access-js

  • 超详细十大经典排序算法总结(java代码)c或者cpp的也可以明白[通俗易懂]

    大家好,又见面了,我是你们的朋友全栈君。0、排序算法说明0.1排序的定义 对一序列对象根据某个关键字进行排序。0.2术语说明稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;内排序:所有排序操作都在内存中完成;外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;时间复杂度:一个算法执行所耗费的时间。空间复杂度:运行完一个程序所需内存的大小。0.3算法总结图片名词解释:n:数据规模k:“桶”的个数In-place:占用常数内存,不占用额外内存Out-place:占用额外内存0.5算法分类0.6比较和非比较的区别常见的快速排序、归并排序、堆排序、冒泡排序等属于比较排序。在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置。 在冒泡排序之类的排序中,问题规模为n,又因为需要比较n次,所以平均时间复杂度为O(n²)。在归并排序、快速排序之类的排序中,问题规模通过分治法消减为logN次,所以时间复杂度平均O(nlogn)。 比较排

  • ASP.NET 大学场地预约借用系统(源码+数据库)

    这个是我在修专业课《Web应用开发技术》时的结课作业,分组是按5人一组的。结果由于我是大四老学长回来补修的。就自己单干了。采用了asp.net技术开发的,前端用了一些CSS框架进行美化。数据交互采用AJAX,数据库用的SQLSever。1、目标与应用场景同学们在进行各类活动时,通常需要一定的场地配合。如果是室外场地,例如操场等无需进行借用预约便可使用。但是大部分活动都需要在室内场地完成,例如开团员大会,开班会,班级联谊等。再者,教师群体需要举办学术交流活动等也需要室内的场地完成。华中科技大学的教室和公用场地十分充足,即使在工作日,也有很多空闲的场地剩余。场地包括启明学院、教学楼、学生公寓内部的公用房、学院内的教室等。为满足广大同学的学习活动需求,促进同学之间的交流,同时更加充分地利用公共教室范围内的场地,我们小组决定设计并实现华中科技大学的场地预约系统,该系统的需求如下:用户可以登录系统,进行教室的预约。系统需要支持多用户使用,用户之间同一教室的预约时间段不能冲突。如果不需要教室了,用户可以选择取消自己的预约。用户能看到自己的历史预约信息。根据以上的需求,拟实现的系统功能如下:登录注册

  • SpringCloud中Hystrix容错保护原理及配置,看它就够了!

    1什么是灾难性雪崩效应?如下图的过程所示,灾难性雪崩形成原因就大致如此:造成灾难性雪崩效应的原因,可以简单归结为下述三种:服务提供者不可用。如:硬件故障、程序BUG、缓存击穿、并发请求量过大等。重试加大流量。如:用户重试、代码重试逻辑等。服务调用者不可用。如:同步请求阻塞造成的资源耗尽等。雪崩效应最终的结果就是:服务链条中的某一个服务不可用,导致一系列的服务不可用,最终造成服务逻辑崩溃。这种问题造成的后果,往往是无法预料的。2如何解决灾难性雪崩效应?解决灾难性雪崩效应的方式通常有:降级、隔离、熔断、请求缓存、请求合并。在Springcloud中处理服务雪崩效应,都需要依赖hystrix组件。在pom文件中都需要引入下述依赖:<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> 复制通常来说,开发的时候,使用ribbon处

  • 知识科学家:解锁数据驱动的组织结构(cs.DB)

    所有部门的组织正日益向数据驱动型运营进行深层次的转型和重组。数据的核心问题在于对可靠和干净的数据的需求。不可靠、错误和不完整的数据会导致管道处理中的重点瓶颈,并最终导致服务故障,这对组织的竞争绩效是灾难性的。鉴于其重要性,认识到并采取措施获取可靠数据的组织将在今后十年中更富优势。我们认为,产生可靠数据的技术是由不同的关注和专业知识推动产生的,这些关注和专业知识与数据科学家和数据工程师的担心和专业知识相辅相成。那些能够意识到有意义、可解释、可重复和可维护数据的核心重要性的组织将处于可靠数据民主化的最前沿。知识科学家被我们称之为新的角色,用以发展,以填补这一重要需求。支持知识科学家的工作并将知识科学家这一构想,变为现实的组织结构、工具、方法和技术仍处于起步阶段。随着组织不再仅仅使用数据,而且越来越依赖于数据,所以现在是时候赋予权力给处于这一组织转型过程中的中心人物:知识科学家。原文标题:KnowledgeScientists:Unlockingthedata-drivenorganization原文:Organizationsacrossallsectorsareincreasinglyu

  • 建立Wolfram自己的ERP系统:我们发现十条新游戏规则

    当人们想到Wolfram科技的时候,公司企业资源管理(ERP)肯定不会是第一个进入脑海的科技。而且当我们开始搜索一种可以管理我们自己的账目、客服、许可证和人力资源需要的解决方案时,Wolfram科技也不是我们的第一个选择。但是在研究目前很多的ERP的系统介绍后,我们发现市面上的购买选项都不能满足我们的要求。 所以我们想,为什么不自己建一个呢?结果开发出的项目是一个意外的惊喜。我们不但做出了自己想要的东西,而且还是和其他系统完全不同的东西:新的结构、新的界面和新的方法。使用Wolfram的技术不仅让开发过程变得更简单,还给予了一个变革性的新角度。通过我们独特强大的技术栈——并将其和现有结构紧密联系——我们在重新定义ERP系统。 我们改变ERP范式的方法1符号表示在开发ERP系统的时候,一个很关键的因素是有精确有效辨别业务经营的真实世界实体的类型的能力——客户、订单、产品、地点、货币等。Wolfram语言是一个可以表达信息的优雅的语言,它允许混合了简单列表、关键值数据、模式甚至代码的嵌套结构。这种丰富性让你可以用一种理想的方式开发ERP系统,在这之中实体类型都优雅地以一种可读可保存的方式集

  • 2D MMO中角色动画的优化总结

    在深圳Cocos沙龙上,有幸结识了社区中大名顶顶的Colin,Shawn在社区论坛上第一次看到Colin的团队用CocosCreator制作的《热血暗黑》时就被深深地震撼到了!更为重要的是,Colin将他的技术心得和宝贵开发经验写成文字,每一篇分享都是满满的干货。而且幸运的是Shawn得到Colin的授权许可,将他的文章散播到奎特尔星球,我们一起欣赏一起成长!2DMMO中角色动画的优化总结1概述我们的项目是传统的2DMMO,即人物动画是以图片帧的方式表现的,一个角色大约有8个动作,1个动作有8个方向,1个方向约有10到20帧的图片。这样算起来一个角色由近千张图片帧组成。这样的量对内存和性能都有很高的要求。从立项到目前经历了很多次优化,终于在流畅度和内存占用上达到比较理想的状态。不知道群里有多少人也在用Creator做类似的MMO手游,我在这里把优化的经历大概写出来供大家参考,也许你们有更好的优化方案,都欢迎一起讨论。2最初的实现方案最初为了快速实现效果,采有很直接的方式:一个动作一张图集(Plist),8个动作则有8个图集。每个动作只包含5个方向的图片帧,另外3个方向通过翻转实现。动画

  • 【技术综述】人脸年龄估计研究现状

    今天给大家带来一篇人脸识别中的年龄估计技术,年龄特征作为人类的一种重要生物特征,计算机要如何基于人脸图像估计年龄呢?01概述 简单地说,基于人脸图像的年龄估计是指机器根据面部图像推测出人的大概年龄或所属的年龄范围(年龄段)。基于人脸图像的年龄估计系统一般分为人脸检测与定位,年龄特征提取,年龄估计,系统性能评价几个部分。根据提取特征方式的不同又分为传统方法和深度学习方法。同一张图在不同应用中的测定(左商汤右年龄检测器)不同的人脸在同一应用中测定(百度云AI为例)不同年龄不同肤色在年龄估计系统中评分测试 如果基于人脸图像的年龄估计问题得到解决,那么在日常生活中基于年龄信息的各种人机交互系统将在现实生活中有着极大的应用需求。市场主流年龄估计软件包括商汤科技,face++,百度云AI体验中心,腾讯云AI体验中心,年龄检测仪。我们随机拿了一些名人照片做测试,总体说来face++在测试集上表现最好。02人脸年龄数据集与算法评价指标2.1公开数据集2.1.1TheIMDB-WIKIdataset数据集【1】网址:https://data.vision.ee.ethz.ch/cvl/rrothe/im

  • python3 =>>>>虚拟环境的搭建

    在linux搭建虚拟环境:在centos中装Python3的在线安装命令:0.yummakecache1.yuminstallepel-release2.yumlist|greppython33.yuminstall-ypython36(1)virtualenv-ppython3flasky---创建虚拟环境(2)sourceflasky/bin/activate---进入虚拟环境(3)pipinstall-rrequirements/dev.txt-ihttps://pypi.tuna.tsinghua.edu.cn/simple--安装依赖的包-rcommon.txt ForgeryPy==0.1 Pygments==1.6 colorama==0.2.7 coverage==3.7.1 httpie==0.7.2 requests==2.1.0 selenium==2.45.0(4)搭建环境的效果:(5)ubutun下的flask链接mysql数据库需要安装的包:a------pipinstallflask-MySQLdbb-----sudoapt-getinstallmysql

  • Prometheus监控学习笔记之全面学习Prometheus

    0x00概述Prometheus是继Kubernetes后第2个正式加入CNCF基金会的项目,容器和云原生领域事实的监控标准解决方案。在这次分享将从Prometheus的基础说起,学习和了解Prometheus强大的数据处理能力,了解如何使用Prometheus进行白盒和黑盒监控,以及Prometheus在规模化监控下的解决方案等。最后将从0开始构建完整的Kubernetes监控架构。0x01 监控的目标在《SRE:Google运维解密》一书中指出,监控系统需要能够有效的支持白盒监控和黑盒监控。通过白盒能够了解其内部的实际运行状态,通过对监控指标的观察能够预判可能出现的问题,从而对潜在的不确定因素进行优化。而黑盒监控,常见的如HTTP探针,TCP探针等,可以在系统或者服务在发生故障时能够快速通知相关的人员进行处理。通过建立完善的监控体系,从而达到以下目的:长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们可以提前预测在未来什么时间节点上需要对资源进行扩容。对照分析:两个版本的系统运行资源使用情况的差异如何?在不同容量情况

  • 一步步解析Attention is All You Need!

    本文将通过细节剖析以及代码相结合的方式,来一步步解析Attentionisallyouneed这篇文章。这篇文章的下载地址为:https://arxiv.org/abs/1706.03762本文的部分图片来自文章:https://mp.weixin.qq.com/s/RLxWevVWHXgX-UcoxDS70w,写的非常好!本文边讲细节边配合代码实战,代码地址为:https://github.com/princewen/tensorflow_practice/tree/master/basic/Basic-Transformer-Demo数据地址为:https://pan.baidu.com/s/14XfprCqjmBKde9NmNZeCNg密码:lfwu好了,废话不多说,我们进入正题!我们从简单到复杂,一步步介绍该模型的结构!1、整体架构模型的整体框架如下:整体架构看似复杂,其实就是一个Seq2Seq结构,简化一下,就是这样的:Encoder的输出和decoder的结合如下,即最后一个encoder的输出将和每一层的decoder进行结合:好了,我们主要关注的是每一层Encoder和

  • 极客时间全部VIP课程百度云(2021-2022年)

    今天给大家分享极客时间全部VIP课程,百度云链接在文章结尾处!!!大家自行下载即可~极客时间全部课程vip百度云一、全部的极客时间VIP视频课程目录大纲┣━━001-050[0B] ┃┣━━01-数据结构与算法之美(完结) ┃┣━━02-Java核心技术面试精讲(完结) ┃┣━━03-从0开始学架构(完结) ┃┣━━04-左耳听风(完结) ┃┣━━05-趣谈网络协议(完结) ┃┣━━06-MySQL实战45讲(完结) ┃┣━━07-重学前端(完结) ┃┣━━08-深入拆解Java虚拟机(完结) ┃┣━━09-Go语言核心36讲(完结) ┃┣━━10-如何设计一个秒杀系统(完结) ┃┣━━11-程序员的数学基础课(完结) ┃┣━━12-Linux性能优化实战(完结) ┃┣━━13-深入剖析Kubernetes(完结) ┃┣━━14-许式伟的架构课(完结) ┃┣━━15-趣谈Linux操作系统(完结) ┃┣━━16-从0开始学微服务(完结) ┃┣━━17-深入浅出区块链(完结) ┃┣━━18-技术管理实战36讲(完结) ┃┣━━19-数据分析实战45讲(完结) ┃┣━━20-技术领导力30

  • 优化后的Levensthein distance算法实现

    在上一篇文章Levenshteindistance算法实现中,笔者已经讲解了一般最小编辑距离的算法。该算法采用动态规划,时间复杂度是O(m*n),m,n分别为两个字符串的长度,而空间复杂度也是O(m*n),如果使用int作为矩阵元素的类型,则矩阵的占用空间大小为sizeof(int)*m*n,假如两个字符串的长度均为10000个字符,则矩阵大小为400MB,相当可观。参考一个快速、高效的Levenshtein算法实现,笔者重新实现了一遍Levenshteindistance算法,其主要思想就是利用两个列向量来代替矩阵,每次只保存当前状态和上一次运算状态,算法结束后并不能获得该两个字符串任意子序列之间的最小编辑距离。算法采用Python实现,代码如下:#!/usr/bin/envpython #-*-coding:utf-8-*- __author__='xanxus' s1,s2=raw_input('String1:'),raw_input('String2:') m,n=len(s1),len(s2) colsize,v1

  • 题目:判断一个单链表是否回文链表

    题目:判断一个单链表是否回文链表Givenasinglylinkedlist,determineifitisapalindrome. CouldyoudoitinO(n)timeandO(1)space? 分析:判断是否回文定义两个指针 begin:指向第一个位置R end指向最后一个位置R 然后 begin++;end--; 1end--因为单链表不可逆转如何end倒转功能 利用函数栈变化在函数传递中 2begin++变化在函数内部因此采取采取二级指针 recursivecall. 1)Sub-listispalindrome. 2)Valueatcurrentleftandrightarematching.代码:3演示过程函数调用层次第一次比较1beging指向headRend指向headR直到end移动最后一个元素 2退上一层第二个元素和倒数第二个元素有点模糊执行结果:https://leetcode.com/submissions/detail/100664863/

  • [译]ABP框架v2.0 和 ABP商业版

    ABP框架v2.0和ABP商业版 ABP框架2.0版已经在本周公布.这篇文章解释了为什么我们发布了一个抢先主版本,和2.0版本中的变化. 除了v2.0版本,我们很高兴地宣布ABP商业版,这是建立在开源ABP框架的之上的一套专业的模块,工具,主题和服务. ABP框架V2.0 为什么2.0,而不是1.2? 本来在V1.1.2发布后计划发布1.2版.然而,有报告称1.x版在Linux上有一些性能和稳定性问题,尤其是当应用程序部署在低配CPU和内存的Linux容器上. 我们深入研究了这一问题,并已查明问题的根本原因与拦截async方法的实现有关.此外,也有一些async套sync的用法影响了线程池的优化. 最后,在社区在大力协助下我们解决了所有的问题.但是,我们也有一些重要的设计决策导致了一些破坏性变更,因为语义版本,我们不得不改变框架的主版号. 大多数的应用程序不会受到破坏性变更的影响,或者只需要做一些微小的修改. 破坏性变更 删除了一些同步的API 一些拦截器需要使用async的API.当他们拦截sync方法时,他们需要调用async套sync.这最终导致了async套sync的问题.这就

  • 验证输入的字符串是否为合法日期

    几年前,有写过一个angularjs验证日期的后端和js。 《验证用户输入的字符串是否为日期时间》https://www.cnblogs.com/insus/p/6923845.html今,想参考这个,再优化一下,加上正则和限制日期格式。   正则: Regexregex=newRegex(@"(((19|20)\d\d)\-(0[1-9]|1[0-2])\-((0|1)[0-9]|2[0-9]|3[0-1]))$");复制 SourceCode 格式: string[]formats={"yyyy-MM-dd","yyyy-M-d","yyyy-M-dd","yyyy-MM-d"};复制 SourceCode  

  • python-selenium环境搭建

    set集合 怎么把列表种相同的数据和不同的数据取出来 1.把列表转为set集合2.按照集合的交集                 selenium 自动化测试:自动化测试就是通过代码或者是工具模拟人的行为来进行对WEB(APP)来进行操作。 QTP(HP公司):以录制回放的模式来测试WEB系统seleniumideselenium1.0selenium2.0=webdriver+selenum1.0selenium4.X selenium:是WEB的UI测试框架,可以和主流的编程语言(Python,Java,Net,PHP,JavaScript)整合来测试WEB系统,同时也是支持主流的浏览器(IE,Firefox,Chrome)。Selenium通过driver的驱动方式来操作浏览器,对浏览器进行各种交互式的验证(点击,输入,下拉框选项。。。) Selenium环境搭建步骤: 1、按照selenium:pipinstallselenium     2、安装Chrome浏览器 1.1打

  • Oracle系统表整理+常用SQL语句收集

    --DBA/ALL/USER/V_$/GV_$/SESSION/INDEX开头的绝大部分都是视图 --DBA_TABLES意为DBA拥有的或可以访问的所有的关系表。 --ALL_TABLES意为某一用户拥有的或可以访问的所有的关系表。 --USER_TABLES意为某一用户所拥有的所有的关系表。 --当某一用户本身就为数据库DBA时,DBA_TABLES与ALL_TABLES等价。 --DBA_TABLES>=ALL_TABLES>=USER_TABLES --需要注意的是在ORACLE数据库中大小写是敏感的,而此三表中数据默认都是大写的,所以在进行查询的时候注意小写的数据可能会造成数据无法查到。 SELECT*FROMdba_viewsWHEREview_nameLIKE'DBA%'; SELECT*FROMdba_viewsWHEREview_nameLIKE'ALL%'; SELECT*FROMdba_viewsWHEREview_nameLIKE'USER%'; SELECT*FROMdba_viewsWHEREview_nameLIKE'V_$%';--针对某个实

  • Linux Ubuntu 之路(1)

    第一章文件系统篇 目录 作用 缩写 / 根目录   /etc 系统配置文件   /etc/group   /etc/sudoers 决定系统用户是否具有sudo权限   /usr 放置用户共享的资源文件 UnixSystemResource /usr/include includefilefromccompiler   /usr/include/linux       第二章命令篇 sudo  总:使用另一账户的身份来执行命令 sudosu--切换到root adduser/addgroup/deluser/delgroup 2.1文件相关 2.1.1搜索文件 (1)find  --在某一个目录中递归的浏览文件 Syn:find[-H][-L][-P][-Ddebugopts][-Olevel][Path...][expression] 描述:GNUfind搜索所给文件的目录树,通过从左到右判断所给的表达式(根据规则的优先权),直到结果

  • springboot集成springcloud,启动时报错java.lang.AbstractMethodError: null

    出现这个问题是springboot和springcloud的版本不匹配。 我此处使用了springboot2.0.4.RELEASE,springcloud使用了Finchley.SR2。 修改方法是将springboot版本改为2.1.1RELEASE。  

相关推荐

推荐阅读