分享CommunityServer(6) --JOb

本文介绍了一种基于.NET的应用程序任务调度框架的设计与实现。该框架能够启动周期性或定时任务,适用于不需要HTTP请求触发的后台作业,例如数据统计、缓存更新及耗时任务处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
      作为一个应用程序,我们有时候希望代码的执行不是完全由web用户的请求驱动的,希望可以在启动web进程时候,可以定时、周期性执行某些特定工作,这类工作我们一般希望是自动调度或者系统控制下的逻辑性调度。CS实现了相关的工作,设计了一个基础任务调度的框架,可以让我们达到在此框架下执行非Web用户请求驱动的任务执行。
任务的启动框架通常是在整个CS的启动时候,也就是通常我们说的global.asax中的:
protected void Application_Start(Object sender, EventArgs e)
         {
              Jobs.Instance().Start();
              EventLogs.Info("CS.Web Started", "Application", 200);
         }
通过Jobs的静态实例化函数Instance得到单例实例,而Jobs实例的Start函数就是启动框架的细节:
public void Start()
         {
              if (jobList.Count != 0)          //jobList表示当前正在执行的任务数量,如果存在多个任务,那就没必要再次启动这些Job
                   return;
              CSConfiguration csConfig = CSConfiguration.GetConfig();//获得配置
              if (!csConfig.IsBackgroundThreadingDisabled) //查看配置是否允许存在背景线程
              {//如果允许
                   XmlNode node = csConfig.GetConfigSection("CommunityServer/Jobs");//查看job的配置节
                   bool isSingleThread = true;
//以下来获取是否是单线程任务
                   XmlAttribute singleThreadAttribute = node.Attributes["singleThread"];
                   if (singleThreadAttribute != null && !Globals.IsNullorEmpty(singleThreadAttribute.Value) && string.Compare(singleThreadAttribute.Value, "false", true) == 0)
                        isSingleThread = false;
                   else
                   {
                        isSingleThread = true;
                        XmlAttribute minutes = node.Attributes["minutes"];
                       if (minutes != null && !Globals.IsNullorEmpty(minutes.Value))
                       {//转换设定周期从分到毫秒
                            try
                            {
                                 Interval = Int32.Parse(minutes.Value) * 60000;
                            }
                            catch
                            {
                                 Interval = 15 * 60000;
                            }
                       }
                   }
                   foreach (XmlNode jnode in node.ChildNodes)
                   {//读取每一个任务的配置信息,具体大家对照communityserver.config中的Jobs节
                       if (jnode.NodeType != XmlNodeType.Comment)
                       {
                            XmlAttribute typeAttribute = jnode.Attributes["type"];
                            XmlAttribute nameAttribute = jnode.Attributes["name"];
                            Type type = Type.GetType(typeAttribute.Value);
                            if (type != null)
                            {//如果任务名存在于jobList就不要重复启动了
                                 if (!jobList.Contains(nameAttribute.Value))
                                 {//后面会分析Job ,此处是按照类型启动一个人物,并且改任务的构造会读取配置节点信息jnode
                                     Job j = new Job(type, jnode);
                                      jobList[nameAttribute.Value] = j;
                                     if (!isSingleThread || !j.SingleThreaded)
                                          j.InitializeTimer();//初始化Timer 如果是多线程任务
                                 }
                            }
                       }
                   }
 
                   if (isSingleThread)    
                   {
                        //Create a new timer to iterate over each job 15分钟一次
                        singleTimer = new Timer(new TimerCallback(call_back), null, Interval, Interval);
                   }
              }
         }
从上面看到,如果任务是单线程的就通过Job实例的单一Timer 实例 singleTimer 来执行调度,如果是多线程的,就必须先每个Job自己准备一个timer来执行自己的任务调度。
对于共用一个Timer的任务调度,回调函数处理是这样的:
private void call_back(object state)
         {
              _isRunning = true;
              _started = DateTime.Now;
              singleTimer.Change(Timeout.Infinite, Timeout.Infinite);//设置timer的间隔无限长是为了初始化此Job的时候,禁止其他任务的调度,避免重入引起麻烦
              foreach (Job job in jobList.Values)
                   if (job.Enabled && job.SingleThreaded)   //调度joblist中的全部单调度任务
                        job.ExecuteJob();
              singleTimer.Change(Interval, Interval);         //下次执行调度,这个可以看到是15分钟,也就是说单线程调度的任务是15分钟
              _isRunning = false;
              _completed = DateTime.Now;
         }
单独执行的timr执行是这样的:
private void timer_Callback(object state)
        {
            if(!Enabled)
                return;
           _timer.Change( Timeout.Infinite, Timeout.Infinite );
_firstRun = -1;
ExecuteJob();
            if(Enabled)
                _timer.Change( Interval, Interval);
            else
                this.Dispose();
        }
可以看到最终任务调度无论是共用CS的缺省Timer还是使用单独的每个Job的timer,都是最终执行ExecuteJob(),在这个函数中,会具体执行每个Job的真正逻辑。
public void ExecuteJob()
        {
            OnPreJob();        //事件调度
            _isRunning = true;
            IJob ijob = this.CreateJobInstance(); //IJob接口
            if(ijob != null)
            {
                _lastStart = DateTime.Now;
                try
                {
                    ijob.Execute(this._node);     //真正的逻辑在此
                  _lastEnd = _lastSucess = DateTime.Now;                    
                }
                catch(Exception)
                {
                    this._enabled = !this.EnableShutDown;
                    _lastEnd = DateTime.Now;
                }
            }
            _isRunning = false;
            OnPostJob();      //事件调度
        }
通过每一个Job都要实现Ijob接口,而CS通过执行框架最终实例化Job,并且获得接口,然后调度Ijob的必要函数,从而实现了任务调度。
关于Jobs的配置信息,如下:
         <Jobsminutes="15"singleThread="true">
                  <jobname="SiteStatisticsUpdates"type="CommunityServer.Components.SiteStatisticsJob, CommunityServer.Components"enabled="true"enableShutDown="false"/>
               …….
                  <job singleThread="false"minutes="5"name="Emails"type="CommunityServer.Components.EmailJob, CommunityServer.Components"enabled="true"enableShutDown="false"failureInterval="1"numberOfTries="10"/>
               。。。。。
              <jobname="DeleteStaleSpamCommentsJob"type="CommunityServer.Blogs.Components.DeleteStaleSpamCommentsJob, CommunityServer.Blogs"enabled="true"enableShutDown="false"expirationDays="30"/>
          </Jobs>
如果任务是不需要单独使用timer的,那么就可以使用jobs的缺省设置,我们看到大多数任务是 singleThread 的,而 Emails 因为发送邮件的任务可能比较频繁,所以设定 singleThread 为false,这样就单独实现调度,时间间隔是5分钟。关于Job的个性化设定,可以通过job节的Attribute来补充,并且在当前Jobs的实现框架下,可以传递给具体的Job实例,从而实现任务的调度。
要在现有调度框架下增加任务调度,比较简单:
1、 实现一个调度任务具体类,并实现Ijob接口,具体需要调度执行的逻辑在Execute方法中实现。
2、 在CommunityServer.config中Jobs节下登记,并根据需要添加Attribute来传递设定信息。
 
如果要在自己的项目中也实现任务调度,还需要:
1、 实现一个Jobs类,参考CS的实现。
2、 在config文件中,加入Jobs配置节
3、 在Gobal.asax中实现任务的调度配置读取 和 调度初始化。
4、 增加自己的调度任务,实现Ijob接口。
 
这样,我们可以将同asp.net应用程序关系紧密,但是需要定时调度或者不需要用户http请求也必须触发的工作交给调度框架。这些应用可举例但不限于如下:
更新全局设定等,如全局人数统计等、分析、应用程序发生的重大事件记录等
对于一些缓存的操作,可一定时统一执行。如,我们通常有记录PV操作的记录,如果每次点击都要数据库记录,那么会严重消耗服务器资源,可以将这些操作缓存在全局变量,然后统一通过定制的Job来执行入库并复位计数器的操作。
还有一些需要耗时的操作,可以交给Job执行,分析后将结果展示给访问用户,避免在Http请求中等待执行,占用宝贵Http管道资源。 
<think>好的,我现在需要给用户介绍一下MySQL Community Server - GPL。首先,我得确认自己对这个主题的理解是否正确。MySQL Community Server是MySQL的一个版本,遵循GPL协议,应该是一个开源的关系型数据库管理系统。不过,我需要详细整理相关信息,确保准确无误。 首先,我应该从基本定义开始。MySQL Community Server是MySQL AB公司开发的,后来被Sun收购,再后来Oracle收购了Sun,现在由Oracle维护。它基于GPL协议,意味着用户可以自由使用、修改和分发,但需要遵守GPL的规定。这点需要明确,尤其是许可证方面,GPL的特点是对衍生作品的要求,用户如果修改代码并分发,必须开源。 接下来,主要特点方面,我需要列出几个关键点。比如开源免费、跨平台支持、性能优化、支持事务处理(尤其是InnoDB存储引擎)、安全性措施(如SSL、用户权限管理)、复制和集群功能,以及丰富的工具支持,如MySQL Workbench。这些点都是用户关心的,尤其是社区版与企业版的区别,这里需要强调Community Server是免费版本,而企业版需要付费,并提供额外功能和技术支持。 然后,适用场景部分应该涵盖Web应用、中小企业、教育研发等场景。这里要说明为什么这些场景适合使用Community Server,比如成本低、社区支持好、灵活性高。 安装与使用部分,需要简明扼要地指导用户如何获取,比如官网下载,以及基本的使用步骤,如安装、启动、配置用户权限等。这部分不需要太详细,但要让用户知道大致流程。 最后,注意事项部分要提醒用户许可证合规、社区支持与企业支持的区别、版本兼容性等问题。比如,虽然社区版免费,但大规模商业应用可能需要考虑企业版的支持服务,或者自行处理问题。 在整理这些信息的时候,我需要确保技术术语准确,比如InnoDB、ACID事务、主从复制等,避免错误。同时,结构要清晰,按照定义、特点、场景、安装、注意事项分块,让用户容易理解。另外,要使用中文口语化的表达,避免过于生硬,同时保持专业性。 可能还需要检查是否有遗漏的重要点,比如MySQL的历史版本演变,或者与其他数据库(如PostgreSQL)的对比,但用户的问题主要关注Community Server本身,所以可能不需要展开。不过,如果有相关的重要信息,比如社区活跃度、插件生态等,可以适当提及。 另外,许可证部分需要特别小心,GPL的具体要求可能需要进一步确认,确保描述正确。例如,使用MySQL Community Server的项目是否需要全部开源?根据GPL的条款,如果作为单独的服务运行,可能不强制要求项目开源,但如果是直接链接到代码中,则可能需要。这点可能需要更准确的说明,但考虑到用户可能是一般开发者,详细的法律条款可能过于复杂,所以可以简化为“需遵守GPL协议,开源修改后的代码”,避免误导。 最后,确保整个回答符合用户给出的格式要求,比如数学公式的格式,但在这个问题中可能用不到数学公式,所以可以忽略。但需要检查是否有其他格式要求,如分点、段落分隔等,确保结构清晰。</think>MySQL Community Server(GPL)是一个开源的关系型数据库管理系统(RDBMS),由Oracle公司维护和发布。以下是关于它的详细介绍,分步骤梳理其核心特点和用途: --- ### 一、基本定义 - **开源性质**:基于**GNU通用公共许可证(GPL)**,允许用户免费使用、修改和分发代码,但修改后的衍生版本需遵循相同协议开源。 - **历史背景**:最初由瑞典公司MySQL AB开发,后被Sun Microsystems收购,最终归属Oracle旗下。 - **定位**:作为MySQL的社区版本,与企业版(Enterprise Edition)的主要区别在于**功能支持和技术服务**(社区版依赖开源社区支持,企业版提供付费商业支持)。 --- ### 二、核心特点 1. **高性能与扩展性** - 支持多种存储引擎(如InnoDB、MyISAM),默认使用**InnoDB**,支持ACID事务和行级锁。 - 优化查询执行效率,支持索引、分区表、全文检索等功能。 2. **跨平台兼容** - 支持Windows、Linux、macOS等主流操作系统。 3. **安全性保障** - 提供SSL加密通信、用户权限管理、审计日志等机制。 4. **高可用与容灾** - 支持主从复制(Replication)、组复制(Group Replication),以及集群方案(如MySQL NDB Cluster)。 5. **丰富的工具生态** - 配套工具包括: - **MySQL Workbench**:图形化管理工具。 - **mysqldump**:数据备份工具。 - **MySQL Shell**:支持SQL、Python、JavaScript的交互式接口--- ### 三、典型应用场景 1. **Web应用开发** - 作为LAMP(Linux + Apache + MySQL + PHP/Python)或MEAN(MongoDB + Express + Angular + Node.js)技术栈的数据库组件,广泛用于博客、电商等动态网站。 2. **中小企业数据管理** - 免费开源特性降低企业成本,支持中小规模的事务处理和分析需求。 3. **教育与研发** - 学习SQL语言、数据库设计的首选工具,支持快速搭建实验环境。 --- ### 四、安装与使用 1. **获取方式** - 官网下载:访问 [MySQL Community Server下载页](https://dev.mysql.com/downloads/mysql/),选择对应操作系统的安装包。 2. **基本操作步骤** ```bash # 示例:Linux系统通过APT安装 sudo apt update sudo apt install mysql-server sudo systemctl start mysql sudo mysql_secure_installation # 初始化安全配置 ``` 3. **连接与操作** ```sql -- 登录数据库 mysql -u root -p -- 创建用户与数据库 CREATE DATABASE mydb; CREATE USER 'user'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON mydb.* TO 'user'@'localhost'; ``` --- ### 五、注意事项 1. **许可证合规** - 若将MySQL Community Server集成到闭源商业软件中,需遵守GPL协议,可能要求整体代码开源。 2. **社区支持限制** - 社区版不提供官方技术支持,遇到问题需依赖文档、论坛(如[Stack Overflow](https://stackoverflow.com/))或第三方服务。 3. **版本选择** - 生产环境需注意版本兼容性,长期支持版本(如MySQL 8.0 LTS)更稳定。 --- ### 六、总结 MySQL Community Server凭借开源免费、稳定高效的特点,成为开发者和企业的常用数据库解决方案。适合需要低成本、高灵活性且具备基础技术能力的团队使用。对于大规模关键业务,可考虑结合云服务(如AWS RDS、阿里云RDS)或升级至企业版。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值