首页 文章 精选 留言 我的

精选列表

搜索[php扩展],共10000篇文章
优秀的个人博客,低调大师

Unity C#基础之 多线程的前世今生(下) 扩展篇

在前面两篇Unity C#基础之 多线程的前世今生(上) 科普篇和Unity C#基础之 多线程的前世今生(中) 进阶篇中,相信大家对多线程有了一定的了解,这篇再详细的聊一聊在使用多线程中需要注意的地方~ 示例工程下载Unity 2017.3.0 P4 .NET版本4.6 本篇知识点 异常处理 线程取消 CancellationTokenSource 多线程临时变量 线程安全 lock 语法糖 await async 异常处理 首先我们先执行下面一段代码 循环20次用Task线程执行以下Code,当执行循环 i=11 或 i=12时抛出异常 打印信息中没有 11、12的打印信息,也没有抛出异常的信息,这是因为主线程的Trycatch已经跳过 然后我们在try块中添加 Task.WaitAll(taskList.ToArray()); 打印信息如下 出现抛出异常信息 然后我们去掉try块中的 Task.WaitAll(taskList.ToArray()); 在每个线程中添加Try Catch 打印结果可以捕捉到异常 所以要想捕捉到异常且不卡界面,捕捉异常最好在每个自己的线程中捕捉 相应的全部Code private void TryCatchOnClick() { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); Debug.Log($"TryCatchOnClick Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); try { TaskFactory taskFactory = new TaskFactory(); List<Task> taskList = new List<Task>(); #region 异常处理 //多线程里的异常是会被吞掉,除非waitall // 建议 多线程里面,是不允许异常的,也就是内部try catch,自己处理好 for (int i = 0; i < 20; i++) { string name = string.Format($"TryCatchOnClick{i}"); Action<object> act = t => { try { Thread.Sleep(2000); if (t.ToString().Equals("TryCatchOnClick11")) { throw new Exception(string.Format($"{t} 执行失败")); } if (t.ToString().Equals("TryCatchOnClick12")) { throw new Exception(string.Format($"{t} 执行失败")); } Debug.Log($"{t} 执行成功"); } catch (Exception ex) { Debug.Log(ex.Message); } }; taskList.Add(taskFactory.StartNew(act, name)); } //Task.WaitAll(taskList.ToArray()); #endregion } catch (AggregateException aex) { foreach (var item in aex.InnerExceptions) { Debug.Log(item.Message); } } catch (Exception ex) { Debug.Log(ex.Message); } watch.Stop(); Debug.Log($"TryCatchOnClick End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); } 线程取消 某个线程达到预期效果后需要取消其他的线程,我们可以用 CancellationTokenSource,当然可以用一个共享的bool变量,但是CancellationTokenSource的好处是可以让没来的及启动的线程直接取消,从根本上取消启动 private void TaskCancel() { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); Debug.Log($"TaskCancel Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}TaskCancel"); try { TaskFactory taskFactory = new TaskFactory(); List<Task> taskList = new List<Task>(); //线程取消不是操作线程,而是操作信号量(共享变量,多个线程都能访问到的东西,变量/数据库的数据/硬盘数据) //每个线程在执行的过程中,经常去查看下这个信号量,然后自己结束自己 //线程不能别人终止,只能自己干掉自己,延迟是少不了的 //CancellationTokenSource可以在cancel后,取消没有启动的任务 CancellationTokenSource cts = new CancellationTokenSource();//bool值 for (int i = 0; i < 200; i++) { string name = string.Format("btnThreadCore_Click{0}", i); Action<object> act = t => { try { Thread.Sleep(2000); if (t.ToString().Equals("btnThreadCore_Click11")) { throw new Exception(string.Format("{0} 执行失败", t)); } if (t.ToString().Equals("btnThreadCore_Click12")) { throw new Exception(string.Format("{0} 执行失败", t)); } if (cts.IsCancellationRequested)//检查信号量 { Debug.Log($"{t} 放弃执行"); return; } else { Debug.Log($"{t} 执行成功"); } } catch (Exception ex) { cts.Cancel(); Debug.Log(ex.Message); } }; taskList.Add(taskFactory.StartNew(act, name, cts.Token)); } Task.WaitAll(taskList.ToArray()); } catch (AggregateException aex) { foreach (var item in aex.InnerExceptions) { Debug.Log(item.Message); } } catch (Exception ex) { Debug.Log(ex.Message); } watch.Stop(); Debug.Log($"TaskCancel End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); } 打印结果如下 多线程临时变量 这个就比较简单了,直接上Code private void TaskTempVariable() { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); Debug.Log($"TaskTempVariable Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); try { TaskFactory taskFactory = new TaskFactory(); List<Task> taskList = new List<Task>(); ////i 只有一个,真实实行的时候,已经是5了, ////k 多个k,每次是独立的k,跟i没关系 ////int k; for (int i = 0; i < 5; i++) { int k = i; new Action(() => { Thread.Sleep(1000); Debug.Log($"对应的数值K:{k}"); Debug.Log($"对应的数值I:{i}"); }).BeginInvoke(null, null); } Task.WaitAll(taskList.ToArray()); } catch (AggregateException aex) { foreach (var item in aex.InnerExceptions) { Debug.Log(item.Message); } } catch (Exception ex) { Debug.Log(ex.Message); } watch.Stop(); Debug.Log($"TaskTempVariable End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); } 打印结果 线程安全 lock ConcurrentDictionary多线程版字典 多线程1000次操作一个int和List private static readonly object StaticAsyncLock = new object(); private int TotalCount = 0;// private List<int> IntList = new List<int>(20000); private void TaskSafe() { System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); Debug.Log($"TaskSafe Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); try { TaskFactory taskFactory = new TaskFactory(); List<Task> taskList = new List<Task>(); //共有变量:都能访问局部变量/全局变量/数据库的一个值/硬盘文件 //线程内部不共享的是安全 //解决多线程冲突第一个办法:lock ,lock的方法块儿里面是单线程的,所以将整个方法Lock多线程将变得毫无意义;lock里面的代码要尽量的少 //解决多线程冲突第二个办法:没有冲突,从数据上隔离开 for (int i = 0; i < 10000; i++) { int TempI = i; taskList.Add(taskFactory.StartNew(() => { lock (StaticAsyncLock)//lock后的方法块,任意时刻只有一个线程可以进入语法糖 lock(StaticAsyncLock) 编译后等于 Monitor.Enter(StaticAsyncLock) { //这里就是单线程 this.TotalCount += 1;//多个线程同时操作,有时候操作被覆盖了 IntList.Add(TempI); } })); //语法糖 lock(StaticAsyncLock) 编译后等于 Monitor.Enter(StaticAsyncLock) Monitor.Exit(StaticAsyncLock) //检查下这个变量(引用) 有没有被lock 有就等着,没有就占用,然后进去执行,执行完了释放 //lock(this) 锁定当前实例,别的地方如果要使用这个实力里面的其他变量,则都被锁定了无法使用(不推荐这么写) //如果每个实例想要单独的锁定 private object //string a="123456" lock(a) string b="123456" 享元模式的内存分配,字符串值是唯一的,会锁定别的变量b //private static readonly object StaticAsyncLock = new object(); } Task.WaitAll(taskList.ToArray()); Debug.Log(this.TotalCount); Debug.Log(IntList.Count); } catch (AggregateException aex) { foreach (var item in aex.InnerExceptions) { Debug.Log(item.Message); } } catch (Exception ex) { Debug.Log(ex.Message); } watch.Stop(); Debug.Log($"TaskSafe End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); } 添加Lock锁前后打印结果 语法糖 await async (C#5.0 .NET 4.5 CLR 4.0) 如果用一句话简单概括await async,那就是:多线程版的协程 先来一个简单的示例,做一个大象装冰箱,最后咱们再详细的分析 打印结果 是不是很有趣?这种书写逻辑基本上和原来的协程一样,而且是真正的多线程,但是依据不能运行UnityEngine中的组件(例如:GameObject),下面我们详细的说一说 await async 第一个示例 在基础的方法上添加关键字 async 根据提示只有aysnc没有await 会有一个警告,跟普通方法没有区别(不得不说VS2017还是很不错的,提示、自动修补都很友好) 打印结果 第二个是示例 在第一个示例的基础上添加await关键字,这时当主线程到达await task时就返回了,继续执行方法外部的函数,可以理解为unity协程中的yeild reture,当task的线程块执行完毕后再回调 awati task后面的函数部分,这个回调的线程是不确定的:可能是主线程 可能是子线程 也可能是其他线程 /// <summary> /// async/await /// 不能单独await /// await 只能放在task前面 /// 不推荐void返回值,使用Task来代替 /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。Async Void 不行 /// </summary> private async void NoReturn() { //主线程执行 Debug.Log($"NoReturn Sleep before await,线程ID:{Thread.CurrentThread.ManagedThreadId}"); TaskFactory taskFactory = new TaskFactory(); Task task = taskFactory.StartNew(() => { Debug.Log($"多线程 Sleep before,线程ID:{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(3000); Debug.Log($"多线程 Sleep after,线程ID:{Thread.CurrentThread.ManagedThreadId}"); }); await task;//主线程到这里就返回了,执行主线程任务 //子线程执行 其实是封装成委托,在task之后成为回调(编译器功能 状态机实现) //task.ContinueWith() //这个回调的线程是不确定的:可能是主线程 可能是子线程 也可能是其他线程 Debug.Log($"NoReturn Sleep after await,线程ID:{Thread.CurrentThread.ManagedThreadId}"); } 打印结果 第三个示例,如果需要获取这个返回的线程怎么办呢?直接把void 换成Task /// <summary> /// 无返回值 async Task == async void /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。Async Void 不行 /// </summary> /// <returns></returns> private async Task NoReturnTask() { //这里还是主线程的id Debug.Log($"NoReturnTask Sleep before await,线程ID:{Thread.CurrentThread.ManagedThreadId}"); await Task.Run(() => { Debug.Log($"多线程 Sleep before,线程ID:{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(9000); Debug.Log($"多线程 Sleep after,线程ID:{Thread.CurrentThread.ManagedThreadId}"); }); Debug.Log($"NoReturnTask Sleep after await,线程ID:{Thread.CurrentThread.ManagedThreadId}"); //return new TaskFactory().StartNew(() => { }); //不能return 没有async才行 } 然后执行 打印结果 第四个示例,也是最终版的示例 返回线程+返回数值 ,获取一个Task<T> ,其中T就是返回值的类型 /// <summary> /// 带返回值的Task /// 要使用返回值就一定要等子线程计算完毕 卡线程 /// </summary> /// <returns>async 就只返回long</returns> private async Task<long> FinallyAsync() { Debug.Log($"SumAsync start 线程ID:{Thread.CurrentThread.ManagedThreadId}"); long result = 0; await Task.Run(() => { Debug.Log($"SumAsync await Task.Run 线程ID:{Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); for (long i = 0; i < 999999999; i++) { result += i; } }); return result; } 然后执行 打印结果 非await版返回值 这种主线程获取result不会卡死 /// <summary> /// 真的返回Task 不是async /// /// 要使用返回值就一定要等子线程计算完毕 /// </summary> /// <returns>没有async Task</returns> private Task<int> TaskReturn() { Debug.Log($"TaskReturn start 线程ID:{Thread.CurrentThread.ManagedThreadId}"); TaskFactory taskFactory = new TaskFactory(); Task<int> iResult = taskFactory.StartNew<int>(() => { Thread.Sleep(3000); Debug.Log($"TaskReturn Task.Run 线程ID:{Thread.CurrentThread.ManagedThreadId}"); return 123; }); Debug.Log($"TaskReturn end 线程ID:{Thread.CurrentThread.ManagedThreadId}"); return iResult; } 执行函数 打印结果 以上就是await async 的相关内容,有需要补充的东西欢迎留言

优秀的个人博客,低调大师

服务器架构之性能扩展-第四章(5)

第四章、MYSQL主从复制和分区技术 Mysql作为web数据库,对于越来越大的数据存储,主从复制、分区技术和SQL语句优化,对于提高访问量有很大的帮助。 4.1mysql用户授权 主服务器首先对远程服务器建立一个授权用户,可以在从服务器上登录主服务器的数据库。 Mysql〉grant all on *.* touser@192.168.10.2identified by "123"; Mysql>use mysql Mysql>select user,password,host from user;//查看用户情况 测试:从服务器登陆,可以看到内容和主服务器是一样的 4.2 mysql bin-log日志 Mysql的bin-log日志是记录与数据的增删改查有关的数据库语句。于是bin-log可以作为数据库恢复的文件来使用,也是mysql能够主从复制的基础。 4.2.1开启mysql的bin-log日志 Vi /etc/my.cnf Log-bin=mysql-bin//增加这个语句,重启mysql即可 4.2.2查看是否开启bin-log: Mysql>show variables like ‘%bin%’; 1.2.3.mysql的bin-log日志管理 mysql>flush logs;//此时就会多一个新的bin-log日志 mysql>show master status;//查看目前使用的bin-log日志 mysql>reset master;//清空所有日志 4.2.4用bin-log进行数据的备份和恢复 备份数据库:测试数据库名为test,表为t。 Mysqldump –uroot –p test –l –F > ‘/tmp/test.sql’ -L锁定表,-F是刷新bin-log日志,这样便可以用刷新之前的日志进行恢复到备份时刻 Mysql>insert into t values(1);//插入新纪录 Mysq>flush logs; Mysql>drop table t;//删除表 恢复数据库 Mysql test </tmp/test.sql 如果要恢复数据库备份后那段时间的记录,就需要恢复bin-log日志 Mysqlbinlog mysql-00002.bin |mysql –uroot –p test 下图是bin-log的日志内容我们可以看到它是包含position点的。恢复日志也可以指定position点。--stop-position=“193”. 4.3mysql主从复制 Mysql主从复制的优点: 1.如果主服务器出现问题,可以快速切换到从服务器提供服务 2.可以在从服务器上执行查看操作,降低主服务器的访问压力 3.可以在从服务器上执行备份,以避免备份期间影响主服务器的服务 4.3.1Mysql主服务器的配置: Mysql>grant all slave on *.* tosaisai@192.168.10.2identified by “123”; Vi /etc/my.cnf Log-bin=mysql-bin//开启log-bin功能 Server-id=1//指定server ID Service mysql restart Mysql>show master status;//查看是否开启和bin ID 4.3.2mysql从服务器的配置 Vi /etc/my.cnf 指定主服务器ip和server id(这里id要不为1),以及主服务器的端口和连接主服务器的用户名和密码,开启bin-log,然后重启mysql服务器,同步之前要确保主从服务器有相同的数据库名和表结构。 Mysql>show slave status\G 这里要保证两个yes选项,第一个slave_io_running为yes表示可以成功从主服务器上读取binlog日志并写入从服务上,第二个slave_Sql_running为yes表示可以成功读取本机binlog日志同步数据。可以看到它们也具有相同的bin-log。 如果数据无法同步: 如果是slave_io_running失败,要检查一下从数据库能否登陆主数据,然后检查从数据库是否和主数据有一致的数据库和表结构。 如果是slave_sql_running失败,要检查从服务是否启动和配置文件。 如slave stop;set global sql_slave_skip_counter=1;slave start. 4.4Mysql表分区 4.4.1分区技术简介 当mysql的数据记录超过千万或上亿条纪录时,数据的性能会出现下降,这时就要用到分表分区技术或优化sql语句的方法来提高数据库的使用效率。 分表技术通常有垂直分表和水平分表,垂直分表是对数据库字段进行分表;水平分表是对数据记录进行分表。垂直分表技术复杂,不易操作,水平分表更常用。 水平分表可以将一个表分成多个表,但是如果多个表使用不同的表名,则查询语句要更改,于是引入了分区分表的概念,它不改变表名。 分区分表是在逻辑层进行水平分表,对与应用程序而言,它依然是一张表。Mysql5.1中,它有5钟分区类型: 4.4.2分区技术类型 Range分区:基于属于一个给定的连续区间的列值,把匹配的多行分配给相应分区 List分区:类似range分区,区别在于list分区是基于列值匹配一个离散值集合中的某个值来进行选择 Hash分区:基于用户定义的表达式的返回值进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算,这个函数可以包含mysql中有效的,产生非负整数值的任何表达式 Key分区:类似于hash分区,区别在于key分区只支持计算一列或多列,且mysql服务器提供其自身的哈希函数 查看mysql的版本信息:mysql>status; 查看是否支持分区技术:mysql>show plugins;//看到partion选项 4.4.3range分区技术 例1:假定如下的表,该表有20加音像店的职员记录,这二十家的音像编号从1到20,如果采用range分区为4个小分区,如何实现呢? Mysql>create table employees( >id int not null, >fname varchar(30), >lname varchar(30), >hired date not null default ‘1970-01-01’, >separated date not null default ‘9999-12-31’, >job_code int not null, >store_id int not null >) >partition by range(store_id)( >partition p0 values less than(6), >partition p1 values less than(11), >partition p2 values less than(16), >partition p3 values less than(21), >); 根据store_id(店号)进行分区,less than根据店号ID进行分区。 如果要按离职时间进行分区可以使用: >partition by range(year(separated))( >partition p0 values less than(1991), >partition p1 values less than(1996), >partition p2 values less than(2001), >partition p3 values less than maxvalue, >);//使用year()函数转为整形 4.4.4 list分区技术 List分区类似于range分区,但他是根据离散值来分区。 例3.还是该表保存有20家音像店,编号从1到20,而这20家音像店分布在四个区域: >partition by list(store_id)( >partition pnorthvalues in (3,5,6,9,17), >partition peast values in(1,2,10,11,19,20), >partition pwest values in(4,12,13,14,18), >partition pcentral values in( 7,8,15,16), >); 4.4.5hash分区技术 Hash分区主要是用来保护数据在预先确定数目的分区中平均分布。他可以在基于用户定义的表达式的返回值来进行选择分区,该表达式使用将要插入到表中的这些行的列值进行计算 例4:把不同时期的入职时间进行hash >Partition by hash(year(hired)) >partitions 4 >; 例5、 可以查看到数库分为5个分区,从0到4,在加上frm文件和par文件,供12个文件。 4.4.4range分区技术 不同分区技术对比 创建索引,也是一种提高数据库效率的方法。 Mysql>Create index idx_id on t2(id); Mysql>show index from t2; 测试1:大数据测试 首先建立一个表,插入几个数据进行测试,然后使用select into t2 select * fromt2;进行倍数的增加 再打开一个终端,发现是均匀分配数据的。还有一个发现,有时索引比数据更大,造成空间浪费。 插入1000万行记录,然后看时间和大小,1000万条记录。 查看数据库文件大小 实验二、用存储过程生成大数据 存储过程:是一种通过创建语句,然后调用数据库的方法。 通过存储过程灌入800万条测试数据库 Mysql>delimiter // Mysql>create procedure load_part_tab() Begin Declare v <8000000 Do Insert into part_tab Values (v,’testing partitions’,adddate(‘2000-01-01’,(rand(v)*36520)mod 3652)); Set v=v+1; End while; End // Mysql>delimiter; 分别插入数值和字段“testingpartition“和随机时间。 Mysql>? procedure//查看存储帮助 再创建一个两个表,一个使用分区实例,一个不使用分区实例,然后调用存储过程即可完成内容的插入,最后测试。 Mysql分区实例: Mysql>create table part_tab (c1 int default null,c2 varchar(30) default null, c3 date default null ) engine=myisam Partition by range(year(c3))( Partition p0 values less than(2000), Partition p1values less than(2001), Partition p2 values less than(2002), Partition p3 values less than(2003), Partition p4 values less than(2004), Partition p5 values less than(2005), Partition p6 values less than(2006), Partition p7 values less than(2006), Partition p8 values less than(2007), Partition p9 values less than(2008), Partition p10 vlues less than maxvalue); 创建未分区实例: Mysql> create table no_part_tab (c1 int default null,c2 varchar(30) default null, c3 date default null ) engine=myisam; 利用存储过程插入数据: Mysql>call load_part_tab(); Mysql>inset into no_part_tab select * from part_tab; 测试:SQL性能 Mysql>select count(*) from part_tab where c3>date ‘2000-01-01’ and c3<’2000-12-31’;//大约0.55秒 Mysql> select count(*) from no_part_tab where c3>date ‘2000-01-01’ and c3<’2000-12-31’;//大约5秒 相差10倍,说明分区技术可以有效降低查询时间。 检索范围查看到,分区表查找范围明显很小为79万。 如果创建索引再查看结果: Mysql>create index_c3 on no_part_tab(c3); Mysql> create index_c3 on part_tab(c3); 测试: 发现创建索引之后测试访问时间发现明显二者都显著变小,说明索引也是一种优化查询的方法。下图是查找未索引的字段。 4.5innodb表创建分区表 Innodb是一种事务型的表存储引擎。对于innodb表,要区分两个概念。共享表空间和独占表空间。 共享表空间:某个数据库的所有表的数据,存储在一个数据文件中,默认的文件名为ibdata1,初始化为10MB。 独占表空间:每一个表都将会生成独立的文件来存储数据,每一个表除了一个frm文件还有一个.ibd文件。 只有把innodb设置成独立表空间以后,才能创建innodb的表分区。 Vi /etc/my.cnf//将innodb_file_per_table =1,重启mysql即可 然后创建表,指定引擎和分区情况,查看数据文件即可看到分区文件顺利生成。 本文转自zsaisai 51CTO博客,原文链接:http://blog.51cto.com/3402313/966578

优秀的个人博客,低调大师

服务器架构之性能扩展-第六章(7)

第六章 nagios网络监控和shell邮件报警 对于nagios比较感兴趣的朋友,对于nagios警报的部分可以参考我的网络监控漫谈系列。 6.1网络管理概念 网络管理:监督、组织和控制网络通信服务和信息处理所必须的各种活动的总称。 常见的监控设备有交换机、路由器,windows或linux主机,它一般包含监控端和被监控端,监控端定时检测叫轮训,被监控端的紧急情况的主动报告叫中断。 监控协议:SNMP(simple network manager protocol) 6.1.1windows部署snmp 开始-》控制面板-》添加删除windows组件-》管理和监视工具-》详细信息-》简单网络管理协议 6.2postfix邮件报警 6.2.1postfix的部署 Postfix是一款比sendmail速度更快的邮件服务器,我们这里选择centos服务器上搭建postfix和dovecat邮件服务,然后通过windows8的outlook进行访问。 1. 关闭 sendmail 邮件服务 Service sendmail stop Chkconfig sendmail off 2. 安装 postfix Postfix是发送服务,使用25端口,dovecat完成邮件的接收,使用110端口,共同完成邮件的收发。 Yum install postfix* Yum install dovecat* 3. 修改配置文件 Vi /etc/postfix/main.cf Myhostname指定邮件主机域名 Mydomain指定邮件域名后缀 Myorigin指定发件人后缀 Inet_interface指定all,注释localhost,这样允许所有客户端的使用 Mydestination指定目标主机 myNetworks指定服务器的网段 Relay_domains允许中继转发 Service postfix restart Chkconfig postfix on Vi /etc/dovecot.conf 取消protocal的注释,开启110端口 4. 更改默认邮件服务器 Alternative –config mta然后选择2,即postfix 5 、新建账户 即可使用user1@saisai.com和user2@saisai.com邮箱 Vi /etc/hosts//解析域名 2. 测试 首先服务器和客户机可以ping通 打开outlook-》工具-》创建用户 输入账户信息,本地测试,选择”手动配置服务器或其他服务器类型”,输入服务器ip和用户名和密码即可。设置完毕,然后单击“测试账户设置”进行测试。 然后通过发送/接收选项,进行选择账户,然后进行“新建”,进行邮件发送测试。 选择账户2,进行查看是否可以接收邮件 命令方式测试: telnet 192.168.211.128 25 Telnet发邮件,ip+端口,然后写mail from:设置发送方,rcpt to:设置接收方,data:写数据,以点结束邮件内容,以quit退出。 登陆用户查看邮件 回复邮件,回复给root用户 Root用户邮件,用Mail 命令查看,输入id号查看内容 Mail命令发送邮件 Echo为内容,-s为主机,mail后接邮箱 实验一:测试test.sh脚本 建立一个sh命令,然后赋予写的权限,执行即可。 主题test shell,内容shell test 执行之后,到邮箱进行查看 实验二:apache服务脚本Apache.sh Nc -w2 localhost 80 该命令执行成功后两秒自动退出,然后使用$?判断端口是否开放,如果上条命令成功则结果为0,否则为1。 于是通过检测80端口是否正常,不正常则重启apache 到邮箱进行检测 实验三:mysql数据库脚本mysql.sh 通过检测3306端口,如果不正常则重启mysql 到邮箱进行检测 实验四:磁盘检测disk.sh 通过awk来检测磁盘使用情况,awk ‘NR==3{print $4}’它可以抠取第三行第四列的值,然后利用它来判断磁盘的大小。 用dd命令,增加一个大文件,进行测试 打开邮件进行验证 实验五:建立Crontab计划任务 Crontab –e 本文转自zsaisai 51CTO博客,原文链接:http://blog.51cto.com/3402313/967782

优秀的个人博客,低调大师

ARM要将服务器扩展到物联网领域

ARM在11月10日(星期二)召开的年会上审视了公司从服务器到物联网云服务过渡的各项工作。ARM公司技术总监Mike Muller在开幕式上做主题演讲时对半导体行业的未来表示乐观。 Muller 表示,“有些人说摩尔定律已经趋向平坦,但我仍然认为前方有大量令人难以置信的创新。” 为了强调他的观点,他在印刷电路板上展示了六英寸硅片的等价物。Muller表示,此款2微米NMOS设计“不是非常强大,但它开辟了一个全新的计算世界”。他称,“这东西将永远滞后硅20年,但它可以开拓新的应用,尺寸并不是一定要越来越小, 10万个晶体管已经可以做许多事情了。” 作为前方创新的例子,Muller展示一塑料膜上的硅片 Muller还描述了一款高端、基于ARM的服务器和SoC,几家公司已经在销售这些产品。ARM自己的网站现在是在惠普基于ARM的服务器上运行。ARM在今年早些时候宣布,AMR认为 AMR可以获取服务器处理器市场25%的份额,并称到2020年可获取用于通信设备的嵌入式处理器45%的份额。 另一方面,Muller还宣布了新的连接物联网和云的服务。该款Mbed设备服务器在网上已经有售,开发人员可以免费使用,但连接限于100台设备及事件处理低于10,000次/小时。 ARM还宣布了一项利用智能手机进行身份验证和安全部署消费者物联网设备的网络服务。明年,ARM计划提供更多用于部署和管理物联网设备网络服务。 Muller表示,新服务的目标之一是“令物联网像个移动网络,而不是像嵌入式控制”,这对于数以百万计的应用程序开发人员来说意义重大,因为“他们是推动大多数未来创新的一群人”。 ARM去年推出了自己的物联网节点操作系统Mbed。ARM 物联网项目经理Christian Flautner,表示,“操作系统需要与各种标准和安全性共存,我们在操作系统生态圈里看到一大块空白。为了简化这些设备的构建,我们做了多年的努力。” Muller表示,去年ARM在自己的主流市场获取了移动处理器插座市场85%的份额,到明年,ARM将获取对应的64位系统市场份额的一半以上。尽管移动设备增长速度下降到了10%左右,ARM预计到2020年移动设备将达28亿件,其中10亿是低端手机。 Muller在主题演讲中宣布了一款新的入门级智能手机处理器以及一个用于32位ARM微控制器的安全系统。 ARM没有提供代号为Artemis的下一代高端移动处理器的细节。但ARM的CPU集团总经理James McNiven表示,ARM计划继续强化自己的Big.little(大.小)法,将大核和小核混合起来。 原文发布时间为:2015年11月11日 本文来自云栖社区合作伙伴至顶网,了解相关信息可以关注至顶网。e

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册