text: INSERT INTO `article` VALUES ('1', '国足的态度终于开了', '国足的中国杯首战，0比6惨败威尔士。赛后，里皮少有地批评了球员，说是某些球员比赛态度不够积极。国足次战捷克，里皮大面积更换首发球员，上了一些边缘国脚，用了一些年轻球员，嘿，真是神了，国足率先进球，据电视转播评论员们说，这场上球员的态度真好！', '1', 'http://tech.cnr.cn/techhlw/201410/W020141028527076231850.jpg', '<font style=\"font-size: 18px;\">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>\r\n国足的中国杯首战，0比6惨败威尔士。赛后，里皮少有地批评了球员，说是某些球员比赛态度不够积极。国足次战捷克，里皮大面积更换首发球员，上了一些边缘国脚，用了一些年轻球员，嘿，真是神了，国足率先进球，据电视转播评论员们说，这场上球员的态度真好！<br>\r\n<br />\r\n&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>\r\n捷克队在失球以后基本接管了比赛，但是，他们像是“送牛奶”的，到门口放下就走，没有进门的习惯。他们进攻的小套路特别娴熟，但似乎不太善射，既使球已经到了门线前，也很难有真正像样的射门。<br>\r\n<br />\r\n&nbsp;<wbr>\r\n&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>\r\n半场下来，一球领先， 国足的信心有点升。\r\n令人意外的是，下半场更换了前锋的捷克，立马来了神奇一射，竟然背对球门，小腿挡了一下球，接着用脚后跟一磕，皮球擦着门柱内侧入了球门。这个球进得实在是太邪乎了！以至于弄得国足集体懵圈，五分钟内连丢三球。好在，捷克没有威尔士那么强，也没有威尔士那么不给面子，他们在攻入三球之后，开始玩着踢了。最后，国足以1比4大败。国足的态度是开锅了，但没有“烫”伤对手，却还是弄伤了自己。<br>\r\n<br />\r\n&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>\r\n赛后，媒体表现了少有的宽容大度，没有指责球员，更没有把矛头对准里皮。大咖们说，中国杯这项赛事的意义就是让我们清醒地认识到差距。还说，中国足球的落后是系统性的，不能让哪个人背锅等等。这些系统性的大话都无比正确，却屁用不中。“系统性”的问题，不能用一句系统性就带过了，也得列出个一二三来，才有可能解决一二。另外，也不能用系统性、全方位来掩盖具体问题。比如，举办中国杯的目的到底是什么？在中超联赛刚刚开打三轮，球员刚刚热乎了身心的时候，就停下来踢这个比赛是不是得不偿失？再比如，里皮首战在战术指导思想上的“冒进”，次战虽然在战术思想上有所调整，增加了防守型球员，但防守的针对性并不强。这届中国杯，态度有些欠的不只是个别球员，里皮同样用心不够。<br>\r\n<br />\r\n&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>\r\n输球也好，赢球也好，要想进步，就得查找问题。包容但不纵容。包容是爱，纵容是害。<br></font>', '1', '2018-03-27 15:18:58','0','2');
  INSERT INTO `article` VALUES ('2', '没了“前世”的“大棚房”，还得关注它的“今生”', '8月15日，是北京“大棚房”的大限。此前，北京市政府常务会决定，全市清理“大棚房”要在8月15日前整改到位。', '1', '', '<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;font-family:宋体;\" lang=\"EN-US\">8</span><span style=\"font-size:16.0pt;\r\n font-family:宋体;\">月<span lang=\"EN-US\">15</span>日</span><span style=\"font-size:16.0pt;font-family:宋体;\">，是北京“大棚房”的大限。此前，北京市政府常务会决定，全市清理<span lang=\"EN-US\">“</span>大棚房<span lang=\"EN-US\">”</span>要在<span lang=\"EN-US\">8</span>月<span lang=\"EN-US\">15</span>日前整改到位。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">“大棚房”清零已是箭在弦上。借助“疏整促”的东风，北京地毯式清查全市“大棚房”，还定下了<span lang=\"EN-US\">8</span>月<span lang=\"EN-US\">15</span>日这个最后时限，力度空前，推进迅速。据媒体报道，目前各区基本完成了清理任务。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;font-family:宋体;\" lang=\"EN-US\">“</span><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">大棚房<span lang=\"EN-US\">”</span>，顾名思义就是盖在农田上的房子，一般都是违法建设，不然也与违法建设有千丝万缕的联系。“大棚房”硬化了耕地，几乎都改变了“看护用房”的用途，而且面积动辄百十平米以上，盖在农田上十分刺眼，是一块块农田上的硬伤。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">既然“大棚房”即将全部根除，也就没了“前世”，不妨把更多的注意力放在它的“今生”上。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">盯紧拆除现状，尽快清除干净，严防反弹，是当下的紧要任务。“大棚房”存在已久，为什么能形成“天女散花”之势，各区普遍都有呢？原因在于“第一个大棚房”没有被及时制止，没有依法拆除，于是你看我、我看你、大家纷纷效仿。现在，有些“大棚房”拆除了主体，有些拆除了门窗，还未达到完全清除干净，有可能出现反弹现象。时刻盯紧，坚决看住，才能确保不出现反弹。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">尽快恢复土地原有用途，是接下来要抓紧做好的事情。土地恢复起来并不容易，属地政府要负起责任，遇到个人恢复确有困难的要及时出手相助，别让拆除后的土地被“撂荒”。如不尽快恢复，仅从视觉来说也有碍观瞻，那些“大棚房”被拆除后的现状很不美观，也影响各区的地方形象。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">“大棚房”被拆除了，还要警惕新生“大棚房”。“大棚房”有利可“图”，才造成了过去区区“开花”的现象，所以，严格控制新“大棚房”产生，也是一项重要的工作。虽有拆除违法建设的大气候，但也不排除有人“顶风作案”，杜绝新增“大棚房”不是一句空话，也不是“杞人忧天”。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">管控“大棚房”违法用地违法建设，就要压实各区和乡镇政府的主体责任。问责是最凌厉的推进手段，市、区监察委将加大对不作为问题的问责力度，对典型问题严肃问责，点名道姓通报曝光；涉嫌违纪违法的，按照相关程序办理。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:33.0pt;\"><span style=\"font-size:16.0pt;\r\nfont-family:宋体;\">“大棚房”拆了，还土地一片整洁，还土地本来的用途，也有利于营造社会公平的氛围。清理“大棚房”的任务基本完成，关注“大棚房”的任务还未结束。<span lang=\"EN-US\"></span></span></p>\r\n\r\n', '1', '2018-03-27 15:21:03','0','2');
  INSERT INTO `article` VALUES ('3', '记录一次邮件容灾恢复过程', '客户目前使用的是Exchange Server 2013,两前两后，数据盘是存储挂载过来的，邮件备份使用的是NBU，由于机房漏水，导致存储服务器宕机。导致绝大部分数据丢失。', '2', '', '<div class=\"artical-content-bak main-content\">\r\n						<div class=\"con artical-content editor-preview-side\"><h1>背景介绍</h1>\r\n<p>客户目前使用的是Exchange Server 2013,两前两后，数据盘是存储挂载过来的，邮件备份使用的是NBU，由于机房漏水，导致存储服务器宕机。导致绝大部分数据丢失。</p>\r\n<h1>Exchange恢复过程</h1>\r\n<ol>\r\n<li>使用新存储重新划分磁盘，并使用NBU逐个恢复数据库，按照原路径恢复。</li>\r\n<li>检查已恢复的数据库所在的服务器（以数据库L14DB3为例）</li>\r\n</ol>\r\n<blockquote>\r\n<p>Get–MailboxDatabase L14DB2 | Get-MailboxDatabaseCopyStatus</p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/bdae14db041f0af7a40dec69ac141f3c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>3.检查数据库和log路径</p>\r\n<blockquote>\r\n<p>Get-MailboxDatabase L14DB3 | fl Name,edb<em>,Log</em></p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/ffbae1fca2287884d87d7c1ebcabe848.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>4.检查是否有日志缺失</p>\r\n<ul>\r\n<li>进入到HQEXMB01服务器上，以管理员运行命令提示符，进入到数据库目录</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/e14a301018ccc1d26d612f24275bbc70.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<blockquote>\r\n<p>输入Eseutil /mh L14db3.edb</p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/ee5ad62b1a3f7ee9b6037929ad6a937e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<blockquote>\r\n<p>检查数据状态及是否有日志缺失：<br>如图：Log Required项显示有日志缺失</p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/c468ce0e0173afcd7f4edf4f364bffb4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>5.修复缺失Log文件</p>\r\n<blockquote>\r\n<p>eseutil /r E0C /L G:\\Mailboxlog\\L14DB3 </p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/e344fe9d24b9574ff52fad39408a32a4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>再次检查，状态如下：</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/bb373a27a1af876b310044e0fcfa532c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>6.检查多余的Log文件</p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/f7b8133e32210394fc0c6be87bfe7d93.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/08002cf8a5ae69dbcefa97b74031351b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>7.删除此数据库的DAG副本</p>\r\n<blockquote>\r\n<p>Remove-MailboxDatabaseCopy –Identity L14DB3\\ HQEXMB01  –Confirm:$False </p>\r\n</blockquote>\r\n<p>8.装入数据库</p>\r\n<blockquote>\r\n<p>mount-database L14DB3 -Force</p>\r\n</blockquote>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/d832b17613440a1448d2c8184ddb79cd.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>检查数据库是否已经装入</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/ae6aafe6d5c6b91ee6823f86aef56317.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>9.其他情况</p>\r\n<p>如果日志未丢失，执行以下步骤恢复：</p>\r\n<ul>\r\n<li>eseutil /mh O:\\Mailbox\\Line04C006\\line04c006.edb  （PS：检查数据库日志缺失状态，发现未丢失）</li>\r\n<li>eseutil /p O:\\Mailbox\\Line04C006\\line04c006.edb     （PS：使用命令强制修复数据库）</li>\r\n<li>mount-database 数据库名称 -Force</li>\r\n<li>强制修复的数据库用户可能无法正常收发邮件，报错如下：</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/e2dd0354052fabbddbc08b0947a3f53e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<blockquote>\r\n<p>解决办法：将此邮箱移动到其他数据库；</p>\r\n</blockquote>\r\n<h1>Exchange DAG副本添加</h1>\r\n<blockquote>\r\n<p>说明：此文档以数据库public001-t为例：</p>\r\n</blockquote>\r\n<p>1.卸载和装入数据库：</p>\r\n<ul>\r\n<li>打开Exchange ECP服务器数据库选择要添加副本的数据库…卸载</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/597e738cd0760b9b477b435dfaee5a1a.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>弹出警告-点击“是”</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/86cfdde003108078fcf91d4258e4161b.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>检查数据库是否已经卸载</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/c785eeddf499388ed559323fe54f8ce0.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>打开Exchange Powershell命令</li>\r\n<li>挂载数据库：(指定参数-force参数)</li>\r\n<li>Mount-Database Public001-t –force </li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/8960e2bd6dbc8a05d90ede079af3c04f.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>通过ECP检查数据库是否已经装入</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/96d2f36300a8865a8ed3158a48c9b912.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>2.添加数据库副本</p>\r\n<ul>\r\n<li>Exchange Powershell中运行：</li>\r\n<li>Add-MailboxDatabaseCopy –Identity Public001-t –MailboxServer hqexmb01\r\n<blockquote>\r\n<p>(说明：–MailboxServer 后面跟副本服务器的名称；先检查此数据库在哪台服务器上装入，则另外一台服务器为添加副本的服务器)</p>\r\n</blockquote></li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/922c343e3ab9d69846bee9925f20edd7.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>添加完成</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/5e7d8d147e5a7bce95f5b6464f1ae33c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<ul>\r\n<li>重启Exchange信息存储服务</li>\r\n</ul>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/17122cc71aa1d09af18011a683d9b460.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p>3.检查DAG状态</p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/24/202402b8e047d1389533a3180d9d03f5.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/19/9201fb780292b1f842646d00868a9f7e.gif\" alt=\"记录一次邮件容灾恢复过程\" style=\"cursor: pointer;\"></p></div>\r\n					</div>', '1', '2018-03-27 15:22:06','0','2');
  INSERT INTO `article` VALUES ('4', 'Nginx+Tomcat+memcached高可用会话保持', '之前文章已经描述了企业高可用负载相关的架构及实现,其中常用的nginx或haproxy,LVS结合keepalived做前端高可用调度器;但之前没有提到会话高可用保持;', '2', 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1182790825,3992631659&fm=27&gp=0.jpg', '<div class=\"artical-content-bak main-content\">\r\n						<div class=\"con artical-content editor-preview-side\"><h1>一、概述</h1>\r\n<p>之前文章已经描述了企业高可用负载相关的架构及实现,其中常用的nginx或haproxy,LVS结合keepalived做前端高可用调度器;但之前没有提到会话高可用保持;<br>本文通过 Tomcat Session Replication Cluster(tomcat自带)和tomcat结合memcat及第三方组件实现Tomcat Memcache Session Server高可用会话缓存服务;<br>实现的效果:<br>同一客户端访问业务网站,经过调度器负载调度到达后端,不管选择的是那个后端,session ID都不变,都保存在两台或多台的memcached缓存中(负载冗余);以保持持会话;</p>\r\n<p><strong>架构图:</strong><br><img src=\"http://i2.51cto.com/images/blog/201803/23/9c5f97eb5aeff57b09dfae2053c331f9.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>说明:客户端请求时nginx通过负载调度算法将请求调度至某一后端服务器;tomcat 把会话通过组播的方式复制到集群各节点;所有节点共享会话;</p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/23/4658e3d0263f63bd3a265cf9f1fd42ce.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>说明:客户端请求时nginx通过负载调度算法将请求调度至某一后端服务器;并把session存储到两台memcached中;客户端刷新(不换浏览器)时,请求换成另一个后端服务器响应时session ID保持不变;</p>\r\n<p><strong>测试环境:</strong><br>nginx: CentOS7  epel 安装nginx   WAN:172.16.3.152   LAN:192.168.10.254<br>tomcat A:  CentOS7   node1.san.com      epel 安装 tomcat 7  openjdk-1.8.0  memcached(现实环境中单独服务器)<br>tomcat B:  CentOS7   nodde2.san.com   epel 安装 tomcat 7  openjdk-1.8.0  memcached  现实环境中单独服务器)<br>测试客户端ubuntu 16.04  </p>\r\n<pre><code class=\"hljs nginx\"><span class=\"hljs-attribute\">cat</span> /etc/hosts\r\n<span class=\"hljs-number\">172.16.3.152</span>       www.san.com</code></pre>\r\n<h1>二、安装配置集群</h1>\r\n<p>nginx安装</p>\r\n<pre><code class=\"hljs coffeescript\">[root@nginx ~]<span class=\"hljs-comment\"># yum install epel-release -y</span>\r\n[root@nginx ~]<span class=\"hljs-comment\"># yum install nginx -y</span></code></pre>\r\n<p>nginx配置<br>在/etc/nginx/nginx.conf  http段添加如下行</p>\r\n<pre><code class=\"hljs nginx\">    <span class=\"hljs-attribute\">upstream</span> tcsrvs {\r\n        <span class=\"hljs-attribute\">server</span> <span class=\"hljs-number\">192.168.10.11:8080</span>;\r\n        <span class=\"hljs-attribute\">server</span> <span class=\"hljs-number\">192.168.10.12:8080</span>;\r\n        }\r\n</code></pre>\r\n<p>cat /etc/nginx/conf.d/san.com.conf</p>\r\n<pre><code class=\"hljs perl\">[root@nginx ~]<span class=\"hljs-comment\"># cat /etc/nginx/conf.d/san.com.conf </span>\r\nserver {\r\n            <span class=\"hljs-keyword\">listen</span> <span class=\"hljs-number\">80</span>;\r\n            server_name www.san.com;\r\n            location / {\r\n                proxy_pass http:<span class=\"hljs-regexp\">//tcsrvs</span>;\r\n                }\r\n        }\r\n</code></pre>\r\n<p>Tomcat配置:<br>两台均需要安装</p>\r\n<pre><code class=\"hljs css\"><span class=\"hljs-selector-id\">#yum</span> <span class=\"hljs-selector-tag\">install</span> <span class=\"hljs-selector-tag\">epel-release</span> <span class=\"hljs-selector-tag\">-y</span>\r\n<span class=\"hljs-selector-id\">#yum</span> <span class=\"hljs-selector-tag\">install</span> <span class=\"hljs-selector-tag\">java-1</span><span class=\"hljs-selector-class\">.8</span><span class=\"hljs-selector-class\">.0</span> <span class=\"hljs-selector-tag\">java-1</span><span class=\"hljs-selector-class\">.8</span><span class=\"hljs-selector-class\">.0-openjdk-devel</span> <span class=\"hljs-selector-tag\">tomcat</span> <span class=\"hljs-selector-tag\">tomcat-webapps</span> <span class=\"hljs-selector-tag\">tomcat-admin-webapps</span> <span class=\"hljs-selector-tag\">tomcat-docs-webapp</span>  <span class=\"hljs-selector-tag\">-y</span></code></pre>\r\n<p>说明:也可以通过<a href=\"http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">oracle官方下载jdk </a><a href=\"https://tomcat.apache.org/download-80.cgi\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">下载tomcat</a> 解压到指定目录并添加环境变量;一般企业推荐此种方式;为了快捷,我们用epel仓库中的稳定版本;</p>\r\n<p><strong>添加测试页</strong><br>yum 安装的tomcat工作目录在/var/lib/tomcat/webapps 分别在node1与node2上,此目录下创建测试项目,title 分别叫Tomcat A与Tomcat B 颜色分别为green与red;以示区别;生产环境node1 与node2内容一致;这里为了测试区别node1与node2内容;</p>\r\n<pre><code class=\"hljs xml\">#mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,classes,lib}\r\n#cat /var/lib/tomcat/webapps/test/index.jsp\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%@</span> <span class=\"hljs-attr\">page</span> <span class=\"hljs-attr\">language</span>=<span class=\"hljs-string\">\"java\"</span> %&gt;</span>\r\n <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html</span>&gt;</span>\r\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title</span>&gt;</span>Tomcat A<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">title</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">head</span>&gt;</span>\r\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body</span>&gt;</span>\r\n             <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">font</span> <span class=\"hljs-attr\">color</span>=<span class=\"hljs-string\">\"red\"</span>&gt;</span>TomcatA.san.com<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">font</span>&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">h1</span>&gt;</span>\r\n           <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">table</span> <span class=\"hljs-attr\">align</span>=<span class=\"hljs-string\">\"centre\"</span> <span class=\"hljs-attr\">border</span>=<span class=\"hljs-string\">\"1\"</span>&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr</span>&gt;</span>\r\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td</span>&gt;</span>Session ID<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">td</span>&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%</span> <span class=\"hljs-attr\">session.setAttribute</span>(\"<span class=\"hljs-attr\">san.com</span>\",\"<span class=\"hljs-attr\">san.com</span>\"); %&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%=</span> <span class=\"hljs-attr\">session.getId</span>() %&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">td</span>&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">tr</span>&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">tr</span>&gt;</span>\r\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td</span>&gt;</span>Created on<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">td</span>&gt;</span>\r\n           <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td</span>&gt;</span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">%=</span> <span class=\"hljs-attr\">session.getCreationTime</span>() %&gt;</span><span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">td</span>&gt;</span>\r\n           <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">tr</span>&gt;</span>\r\n      <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">table</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">body</span>&gt;</span>\r\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">html</span>&gt;</span></code></pre>\r\n<p><strong>配置管理页密码</strong><br>tomcat与管理程序安装好后配置访问密码<br>修改注释/etc/tomcat/tomcat-users.xml文件</p>\r\n<pre><code class=\"hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">role</span> <span class=\"hljs-attr\">rolename</span>=<span class=\"hljs-string\">\"admin-gui\"</span>/&gt;</span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">role</span> <span class=\"hljs-attr\">rolename</span>=<span class=\"hljs-string\">\"manager-gui\"</span>/&gt;</span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">user</span> <span class=\"hljs-attr\">username</span>=<span class=\"hljs-string\">\"tomcat\"</span> <span class=\"hljs-attr\">password</span>=<span class=\"hljs-string\">\"tomcat\"</span> <span class=\"hljs-attr\">roles</span>=<span class=\"hljs-string\">\"manager-gui,admin-gui\"</span>/&gt;</span></code></pre>\r\n<p><strong>备份默认/etc/tomcat/server.xml文件</strong></p>\r\n<pre><code class=\"hljs bash\"><span class=\"hljs-built_in\">cd</span> /etc/tomcat\r\ncp server.xml server.xml_def</code></pre>\r\n<p><strong>测试页访问</strong><br><a href=\"http://www.san.com/test\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">http://www.san.com/test</a> 如图:出现Tomcat A<br><img src=\"http://i2.51cto.com/images/blog/201803/23/dba1dfa5cc409e9a7533765640b020b0.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>Ctrl+F5强制刷新 又出现Tomcat B<br><img src=\"http://i2.51cto.com/images/blog/201803/23/447fd0c2b649abceb657619e059bb851.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"></p>\r\n<p>引发问题:如果是两台内容一样的配置,客户端访问刷新一下就换到另一个后端处理;类似通过session保留信息的服务(购买物车)如何保留?换句话说,如何保持会话不中断,无论请求被分配到那一个后端?</p>\r\n<p><strong>解决方案</strong><br>1)会话sticky(粘性):分为source_ip 基于源ip和cookie<br>source_ip在不同的调度器上有不同的实现方式:<br>lvs:sh算法;<br>nginx:ip_hash或hash $request_uri consistent(一致性哈希算法)<br>haproxy: source</p>\r\n<p>cookie:<br>nginx:hash 或 hash $cookie_name consistent;<br>haproxy:cookie</p>\r\n<p>2)会话集群(session cluster):delta session manager<br>3)session server: redis(store),memcached(cache)</p>\r\n<p>以下基于tomcat自带会话集群与memcached实现会话保持 功能;</p>\r\n<h1>三、Tomcat Session Replication Cluster配置</h1>\r\n<p>Tomcat Session Replication Cluster中文又叫 tomcat 会话复制集群,即会话通过组播方式复制到每一个后端tomcat节点;<br>可参考自带帮助文档:<a href=\"http://www.san.com/docs/cluster-howto.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">http://www.san.com/docs/cluster-howto.html</a><br>两台node1 node2节点/etc/hosts中添加如下:</p>\r\n<pre><code class=\"hljs shell\"><span class=\"hljs-meta\">#</span><span class=\"bash\">cat /etc/hosts</span>\r\n192.168.10.11 node1.san.com node1\r\n192.168.10.12 node2.san.com node2</code></pre>\r\n<p>两台tomcat 节点sever.xml的Host字段中添加如下内容:</p>\r\n<pre><code class=\"hljs bash\">&lt;Cluster className=<span class=\"hljs-string\">\"org.apache.catalina.ha.tcp.SimpleTcpCluster\"</span>\r\n                 channelSendOptions=<span class=\"hljs-string\">\"8\"</span>&gt;\r\n\r\n          &lt;Manager className=<span class=\"hljs-string\">\"org.apache.catalina.ha.session.DeltaManager\"</span>\r\n                   expireSessionsOnShutdown=<span class=\"hljs-string\">\"false\"</span>\r\n                   notifyListenersOnReplication=<span class=\"hljs-string\">\"true\"</span>/&gt;\r\n\r\n          &lt;Channel className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.group.GroupChannel\"</span>&gt;\r\n            &lt;Membership className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.membership.McastService\"</span>\r\n                        address=<span class=\"hljs-string\">\"228.10.0.4\"</span>\r\n                        port=<span class=\"hljs-string\">\"45564\"</span>\r\n                        frequency=<span class=\"hljs-string\">\"500\"</span>\r\n                        dropTime=<span class=\"hljs-string\">\"3000\"</span>/&gt;\r\n            &lt;Receiver className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.transport.nio.NioReceiver\"</span>\r\n                      address=<span class=\"hljs-string\">\"auto\"</span>           &lt;!--   如果没有/etc/hosts解析则需要本机ip   --&gt;\r\n                      port=<span class=\"hljs-string\">\"4000\"</span>\r\n                      autoBind=<span class=\"hljs-string\">\"100\"</span>\r\n                      selectorTimeout=<span class=\"hljs-string\">\"5000\"</span>\r\n                      maxThreads=<span class=\"hljs-string\">\"6\"</span>/&gt;\r\n\r\n            &lt;Sender className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.transport.ReplicationTransmitter\"</span>&gt;\r\n              &lt;Transport className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.transport.nio.PooledParallelSender\"</span>/&gt;\r\n            &lt;/Sender&gt;\r\n            &lt;Interceptor className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.group.interceptors.TcpFailureDetector\"</span>/&gt;\r\n            &lt;Interceptor className=<span class=\"hljs-string\">\"org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor\"</span>/&gt;\r\n          &lt;/Channel&gt;\r\n\r\n          &lt;Valve className=<span class=\"hljs-string\">\"org.apache.catalina.ha.tcp.ReplicationValve\"</span>\r\n                 filter=<span class=\"hljs-string\">\"\"</span>/&gt;\r\n          &lt;Valve className=<span class=\"hljs-string\">\"org.apache.catalina.ha.session.JvmRouteBinderValve\"</span>/&gt;\r\n\r\n          &lt;Deployer className=<span class=\"hljs-string\">\"org.apache.catalina.ha.deploy.FarmWarDeployer\"</span>\r\n                    tempDir=<span class=\"hljs-string\">\"/tmp/war-temp/\"</span>\r\n                    deployDir=<span class=\"hljs-string\">\"/tmp/war-deploy/\"</span>\r\n                    watchDir=<span class=\"hljs-string\">\"/tmp/war-listen/\"</span>\r\n                    watchEnabled=<span class=\"hljs-string\">\"false\"</span>/&gt;\r\n\r\n          &lt;ClusterListener className=<span class=\"hljs-string\">\"org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener\"</span>/&gt;\r\n          &lt;ClusterListener className=<span class=\"hljs-string\">\"org.apache.catalina.ha.session.ClusterSessionListener\"</span>/&gt;\r\n        &lt;/Cluster&gt;</code></pre>\r\n<p>复制 /etc/tomcat/web.xml  /var/lib/tomcat/webapps/test/WEB-INF/   下并在web.xml的\"&lt;web-app &gt;\"字段下添加 \"&lt;distributable/&gt;\";<br>重启tomcat 并再次访问http://www.san.com/test 如图:<br><img src=\"http://i2.51cto.com/images/blog/201803/23/ed089d13b475862398b359b2c824d5b2.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>Ctrl + F5强制刷新如图:<br><img src=\"http://i2.51cto.com/images/blog/201803/23/2647a96c5e215a21e9eda476dc5310ee.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>可以可出会话得到保持,只要是从同一个客户端中请求,刷新或关闭重新打开(基于同一个浏览器) 只要会话没有过期,会话(session id) 无论来自那个后端,均是一样;</p>\r\n<p><strong>缺点:</strong><br>tomcat自带支持会话集群(能过多播方式发送各节点);但有一个缺点;后端tomcat节点过多时效率低下,不适用大规模;</p>\r\n<h1>四、Tomcat Memcache Session Server高可用配置</h1>\r\n<p>原理说明:<br>客户端请求到达前端nginx调度器并分配到后端某tomcat节点时,tomcat会优先使用本机内存保存session，当一个请求结束后，tomcat会通过第三方组件(kryo,javolution,xstream,flexjson)把session序列化并发送到memcached节点上存放作备份，第二次请求时，如果本地有session就直接返回，第二次请求结束，把session修改后的信息更新到后端的memcached服务器，以这样的方式来保持本地的session与memcached上的session同步。当这个tomcat节点宕机时，那么用户的下一次请求就会被前端的负载均衡器路由到另一个tomcat节点上，而这个节点上并没有这个用户的session信息，这个节点就从memcached服务器上去读取session，并把session保存到本地的内存，当请求结束，session又被修改，再送回到memcached进行存放备份<br>当后端配置了多台memcached时，tomcat在更新session信息时会同时向多个memcached节点更新session，当一个memcached节点故障时，tomcat可以从选择一个正常工作的memcached节点读取session信息来发送给用户的浏览器，让其重置session信息，这样，memcached也达到了高可用的目的;<br>以下操作均在两台node上操作<br><strong>还原默认配置文件</strong></p>\r\n<pre><code class=\"hljs shell\"><span class=\"hljs-meta\">#</span><span class=\"bash\"><span class=\"hljs-built_in\">cd</span> /etc/tomcat/</span>\r\n<span class=\"hljs-meta\">#</span><span class=\"bash\">cp server.xml server.xml_cluster</span>\r\n<span class=\"hljs-meta\">#</span><span class=\"bash\">cp server.xml_def server.xml</span>\r\n<span class=\"hljs-meta\">#</span><span class=\"bash\">systemctl stop tomcat</span></code></pre>\r\n<p><strong>安装memcached服务</strong></p>\r\n<pre><code class=\"hljs shell\"><span class=\"hljs-meta\">#</span><span class=\"bash\">yum install memcached -y</span>\r\n<span class=\"hljs-meta\">#</span><span class=\"bash\">systemctl start memcached</span></code></pre>\r\n<p>memcache配置(默认即可,生产环境时需要加大内存与并发连接数)</p>\r\n<pre><code class=\"hljs ini\"><span class=\"hljs-comment\"># cat /etc/sysconfig/memcached </span>\r\n<span class=\"hljs-attr\">PORT</span>=<span class=\"hljs-string\">\"11211\"</span>\r\n<span class=\"hljs-attr\">USER</span>=<span class=\"hljs-string\">\"memcached\"</span>\r\n<span class=\"hljs-attr\">MAXCONN</span>=<span class=\"hljs-string\">\"1024\"</span>\r\n<span class=\"hljs-attr\">CACHESIZE</span>=<span class=\"hljs-string\">\"64\"</span>\r\n<span class=\"hljs-attr\">OPTIONS</span>=<span class=\"hljs-string\">\"\"</span></code></pre>\r\n<p>两台/etc/tomcat/server.xml Host段中添加如下内容:</p>\r\n<pre><code class=\"hljs javascript\">&lt;Context path=<span class=\"hljs-string\">\"/test\"</span> docBase=<span class=\"hljs-string\">\"test\"</span> reloadable=<span class=\"hljs-string\">\"true\"</span>&gt;\r\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Manager</span> <span class=\"hljs-attr\">className</span>=<span class=\"hljs-string\">\"de.javakaffee.web.msm.MemcachedBackupSessionManager\"</span>\r\n                <span class=\"hljs-attr\">memcachedNodes</span>=<span class=\"hljs-string\">\"m1:192.168.10.11:11211,m2:192.168.10.12:11211\"</span>\r\n                <span class=\"hljs-attr\">failoverNodes</span>=<span class=\"hljs-string\">\"m1\"</span>\r\n                <span class=\"hljs-attr\">requestUriIgnorePattern</span>=<span class=\"hljs-string\">\".*\\.(ico|png|gif|jpg|css|js)$\"</span>\r\n                <span class=\"hljs-attr\">transcoderFactoryClass</span>=<span class=\"hljs-string\">\"de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory\"</span>/&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">Context</span>&gt;</span></span></code></pre>\r\n<p>说明:<br>添加两个冗余备份memcached节点分别叫m1,m2   failoverNodes=\"m1\" 表示m1作为备份;当m2失败时连接;即使用m2;</p>\r\n<p>安装对应版本组件</p>\r\n<pre><code class=\"hljs cs\">下载以下JAR包到tomcat库目录;\r\ncd /usr/share/tomcat/lib \r\nwget http:<span class=\"hljs-comment\">//www.java2s.com/Code/JarDownload/javolution/javolution-5.5.1.jar.zip  </span>\r\n<span class=\"hljs-meta\">#需要解压 unzip javolution-5.5.1.jar.zip</span>\r\nwget http:<span class=\"hljs-comment\">//repo1.maven.org/maven2/net/spy/spymemcached/2.12.1/spymemcached-2.12.1.jar</span>\r\nwget http:<span class=\"hljs-comment\">//repo1.maven.org/maven2/de/javakaffee/msm/msm-javolution-serializer/2.1.1/msm-javolution-serializer-2.1.1.jar</span>\r\nwget http:<span class=\"hljs-comment\">//repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager-tc7/2.1.1/memcached-session-manager-tc7-2.1.1.jar</span>\r\nwget http:<span class=\"hljs-comment\">//repo1.maven.org/maven2/de/javakaffee/msm/memcached-session-manager/2.1.1/memcached-session-manager-2.1.1.jar</span></code></pre>\r\n<p>注意:epel安装的tomcat 和openjdk版本如下:<br>openjdk: \"1.8.0_161\"<br>tomcat : \"7.0.76\"<br>以上第三方插件须和对应的版本是兼容的;如发现tomcat启动有问题;无法访问或如下类似错误 </p>\r\n<pre><code class=\"hljs makefile\"><span class=\"hljs-comment\">#tail -fn 100 /var/log/tomcat/catalina.xxxx.log</span>\r\n三月 23, 2018 4:12:52 下午 org.apache.catalina.core.StandardContext startInternal\r\n<span class=\"hljs-section\">严重: The session manager failed to start</span>\r\n<span class=\"hljs-section\">org.apache.catalina.LifecycleException: Failed to start component [de.javakaffee.web.msm.MemcachedBackupSessionManager[/test]]</span>\r\n    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)\r\n    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5643)\r\n    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)\r\n</code></pre>\r\n<p>则表示第三方组件与tomcat不兼容!请重新下载版本;</p>\r\n<p>测试:<br>浏览器访问http://www.san.com/test 如图:<br><img src=\"http://i2.51cto.com/images/blog/201803/23/4548206a5ac982db0c59226987a8d5d2.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"><br>Ctrl+F5强刷新 如图:<br><img src=\"http://i2.51cto.com/images/blog/201803/23/d132f1eb157f0cee0e9addd97158dcc9.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"Nginx+Tomcat+memcached高可用会话保持\" style=\"cursor: pointer;\"></p>\r\n<p>从测试上可以看出目前已经通过memcache存储session等缓存信息;并同步到两台memcache上;当前只使用m2节点;</p>\r\n<h1>总结:</h1>\r\n<p>通过nginx快速实现负载tomcat应用;引用session不可保持问题;通过自带的Tomcat Session Replication Cluster和结合memcached及第三方组件实现高可用会话缓存服务来保持会话;前者不适合大规模应用;</p></div>\r\n					</div>', '1', '2018-03-27 15:29:28','0','1');
  INSERT INTO `article` VALUES ('5', '女生梦寐想嫁的是哪种男人', '春末夏初是绝大多数女生爱做梦的季节，也是许多少女在情窦初开的怀春岁月，在这种季节里，女生们都会梦想可以找到一个世界上最优秀的男士，并且能够成功地嫁给他。', '1', '', '<div class=\"bct fc05 fc11 nbw-blog ztag\"><div style=\"text-align: center;\"><img alt=\"女生梦寐想嫁的是哪种男人 - 周晓群 - 周晓群 的原创博客\" style=\"margin:0 10px 0 0;\" src=\"http://img2.ph.126.net/aUaNANOT3MxPSGL_oTY-fQ==/6632127694911713393.jpg\"></div><p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"line-height: 28px;\">&nbsp;</span><span style=\"font-size: 12pt; font-family: 微软雅黑;\">春末夏初是绝大多数女生爱做梦的季节，也是许多少女在情窦初开的怀春岁月，在这种季节里，女生们都会梦想可以找到一个世界上最优秀的男士，并且能够成功地嫁给他。当然，女生希望这是一位集天下所有精英男士的优秀品格于一身，集天下所有聪明男士的智商于一身，在事业上是受人尊敬的成功人士，而回到家又是可以无微不至照顾自己的体贴男人，而且，还是那种可以让女人放心花钱、放心依靠、放心生活的精品好男人。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">从少女、女生甚至女人的角度来看，这样的梦想还是要有的，万一实现了呢？<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">一、身体一定要健康强健，最最重要的是男人必须要有强壮健康的身体。这是家庭和事业的基础，也是夫妻生活的基本保障，没有完美的夫妻生活就很难保全和谐的家庭，很难确保夫妻之间的感情和睦，因此，绝大多数女人都不会嫁个病殃殃的男人。当然，床事要有能力，要有能彻底征服老婆的方法和手段。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">二、本质一定要端正老实，但绝对不能是常做蠢事的榆木脑袋男人。男人应该老实本分，应该品格端正，不能有任何不良的生活嗜好，尤其是吃喝玩乐不能超越底线，当然，榆木脑袋的男人比喜欢吃喝玩乐的男人更加让女人无法接受，尤其是本分到了愚笨程度的男人更加可恶，到了经常做错事会错意的男人会是可恶之可恶。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">三、懂得适时会制造浪漫，但绝对不能是对其他女人过分殷勤的花心男人。绝大多数的女人都能够理解男人们为了自己的事业可以忙忙碌碌，但同时希望男人能够在平淡的生活中适当制造一点浪漫气息来增添生活的乐趣，当然，这种浪漫仅限于夫妻之间，绝对不能出现花心。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">四、情商一定要饱满丰富，对老婆应该要用情专一不得花心。感情丰富的男人可以在刚强坚毅的性格中流露出柔情似水的一面，可以让女人感受到被男人呵护的安心，但是，女人最担心男人的滥情，最担心男人的随性生活被其他女人利用，因此，用情专一是必须的。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">五、情感一定要溺爱老婆，可以让老婆蜕变成为小女人的男人。男人应该时时让着女人，不能凡事都跟女人计较，应该像宠女儿那样宠爱自己的老婆，应该让女人从心理上产生出小女人的可爱，当然，也要允许女人的“小作”，毕竟，女人就是希望可以依偎在男人的怀里撒娇的。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">六、工作一定要事业有成，但必须要是依然顾家爱老婆的男人。事业有成的男人更加自信，对生活更加热爱，更有能力让老婆过上丰衣足食心情舒畅的生活，但是，绝大多数的女人更希望自己的男人能够事业与家庭两头兼顾，当然，如果在事业成功的前提下，依然是顾家恋家男人就更好了。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">七、生活一定要懂得享受，但要懂得生活，懂得享受二人世界的浪漫。事业是男人的第二生命，男人对事业的执着不能成为冷落老婆情感的借口，老公除了会赚钱养家以外，还要懂得为老婆营造舒适的生活环境，当然其中也包括了舒畅的心情和和谐的两性生活。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">八、男人表面上可以强势，但骨子里必须服从老婆，勇于担当承认错误。现在的女人都很独立，不喜欢有超强大男子主义的男生做自己的老公，在小家庭里要有绝对的话语权，就算老公凡事不能顺着自己，也最好是能够尊重自己，从骨子里绝对服从自己的领导。尤其是夫妻吵架后，不管男人是否有道理，都必须首先向老婆承认错误。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">九、生活中能够善解人意，但别像八婆女人一样整天罗里八嗦。女人喜欢男人在忙于事业的过程中能够适时地停下脚步搂抱一下自己的女人，回到家里能够伴着女人说说话听听女人的唠叨，或者能够及时察觉女人的心情，当然，如果男人反过来像女人那样爱唠叨罗嗦，那就让人受不了了。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">十、性格一定要懂得包容，但绝对不能是“扶不起阿斗”的窝囊男人。独生子女政策下已经逐渐消失了脾气暴躁性格特别的男人，绝大多数男孩从小已经习惯了被父母的驯养，从而不再具有强烈的叛逆性格，然而，如果逆来顺受变成了懦弱窝囊也是女人非常不喜欢的，特别是像刘阿斗那样烂泥扶不上墙的男人，是女人极其厌恶的。当然，女人更喜欢略有一点大男子主义的阳刚男人。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">女人一旦进入老婆的角度看待男人，就会汇集目光所及精英男士的所有优点来塑造自己寻找的男人形象，男人太刚强显得不温柔，太温柔又显得太娇情，太执着会担心不懂生活，太琐碎又显得不懂情调，懂得情调又显得太浪漫花心，而老实本分又被看成是性情木讷。因此，在女生看来，最好的老公就是可以同时具备上述条件并能让自己生活在无忧无虑之中的精英男人。<span lang=\"EN-US\"></span></span></p>\r\n\r\n<p style=\"text-indent:24.0pt;mso-char-indent-count:2.0;\"><span style=\"font-size: 12pt; font-family: 微软雅黑;\">这就是女人所归纳出精英男人必须具备的十大基本条件，让男人们自我对照，如果能够对号入座的，自然会成为广大女生们心目中的追求对象。<span lang=\"EN-US\"></span></span></p>\r\n', '1', '2018-03-28 15:36:36','0','2');
  INSERT INTO `article` VALUES ('6', '谈恋爱不装逼，压根就没戏！谈恋爱不装逼，鬼都不理你！', '谈恋爱不装逼，压根就没戏！谈恋爱不装逼，鬼都不理你！', '1', '', '<div class=\"bct fc05 fc11 nbw-blog ztag\"><div><div id=\"sina_keyword_ad_area2\" class=\"articalContent   newfont_family\">\r\n			<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n谈恋爱不装逼，压根就没戏！谈恋爱不装逼，鬼都不理你！</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n爱神陈保才专栏</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n最近受妇联邀请，连续讲授十堂爱情课。也因此接触许多年轻人，看到他们急吼吼地想结婚，但又如无头苍蝇似的乱飞，找不到方向找不到自己，急得热锅上的蚂蚁似的，只想给他们一点建议。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n那就是，越想嫁越嫁不了。越想结婚，越难结婚。虽然有些人会跟你说，你有多渴望就会有多成功，比如追逐梦想，对金钱的渴望，但婚姻真的不是这样，当你很想很想结婚的的时候，你就会慌乱，那时候，你根本找不到合适的人，即使结了，婚了，也是错嫁。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n关于，这点，我们已经见的太多。所以，必须坦诚地指出他们的误解。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n比如，有一个女生，在国企上班，拿了教师资格证和心理咨询证，但现在的她什么都不想，只想结婚。她说，为了结婚，工作的心思都没了。你看，这完全不是一个现代女性的作为，先谋生，后谋爱。如果没有爱情就连工作都不好好干了，只能说，心智不成熟。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n还有，她也不想学习婚恋相处的智慧，只想找个人结了。但问题是，如果这样恨嫁，这样急吼吼地，多半找不到合适的人，因为时间仓促，很难有机会好好考察，仔细辨别，容易陷入错嫁。而且，她自己这么浮躁，焦躁，也不知道什么人适合自己，到最后就为结婚而结婚，很容易陷入悲剧。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n还有个男生，大专毕业，30多岁，四处发自己的征婚信息，可是，征婚信息弄得像简历一样，完全没有吸引力，甚至让人觉得有点LOW，说白了，就是价值低。他还在群里说自己去楼下的两个快餐店吃饭，人家都关门了，只好买了韭菜肉回家，打算自己做，但又不会做，哪个姑娘来一起做？他说，男人吃韭菜，你懂得……这话说的，大家都不敢接了。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n其实，单身人士要脱光，还是要塑造一下价值和神秘感的，不说多高价值，最起码不能LOW，要不然，别人一看你这档次，一下子就吓跑了。比如这个男生，絮絮叨叨，自己的生活琐事，甚至不顺的事，都一咕噜倒了出来，让人看了碎，明显屌丝。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n而且，根据价值的基本原则，越是四处晒的越不值钱，所以当一个人在群里，天天说自己想结婚，恨嫁，盼婚的时候，他基本就已经被大家定为:不想和他结婚，不可爱，没魅力，没价值，所以，越表示自己想结婚，越没人理你。这就是人性的微妙之处，也是爱情的经济学原则，追涨抛低。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n但是，很遗憾，好多单身人士不懂得。或者懂得，而不愿意改变。以那个女生为例，有人给她提醒，要帮她修炼，她说没时间，没心思，问题是你越没时间久越陷入艰难。明明有人指路，为什么不追着光明而去？如果我20岁的时候有人给我指路，你这样做可以迅速追到女神，我一定二话不说就跟他学习，这就是心态问题。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n还有形象。一定要性感，一定要好看。如果不能做到性感，好看，最起码不难看，干净，舒服，这是最起码的，为什么有些人不懂呢？</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n比如，有个女生在单身群里发了几张照片，很像恐怖片的女主角，脸色看起来暗淡，缺乏光泽，别人提醒她，可以发一些好看的照片啊，她说没有好看的，这是随机拍的，没有好看的就不要发了嘛，随机拍的这么吓人，谁敢和你搭讪？</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n另一个男的则发了赤裸上身的照片，坦胸露乳，肚腩肥厚，好像个屠夫，他也许觉得自己坦诚，但别人看了后怎么想呢。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n但是，以上这四个人都是最想结婚的，他们的征婚信息刷了屏，让全天下都知道他非常想结婚，但却始终无人接招。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n这就是人性的奇妙之处，你越想结，你就越结不了，你越想婚，你就越没人要。归根结底，人们都想看到更有价值的人，都想和最有魅力的人结婚。所以，那些不能展现高价值高魅力的人，那些将自己生活的低潮低谷、甚至很LOW的一面展现出来的人，大家看都不看一眼。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n但是，作为当事人却并觉察，或者他们将这归为坦诚，真实，但他们不知道，谈恋爱的时候大家都是“遮掩”的，没人敢露出真本性。尤其是在刚开始的时候，没人想看到你的真实面目，因为真实都是不够好看的，也无法吸引人，大家都想看到你光鲜亮丽的一面——哪怕是假模假式——这样才能调动起情欲，性欲，才有动力去追，去谈，要不然，根本就没激情开始。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n而一旦结婚，大家就立即暴露出真实，那时候才知道对方是什么人了。正所谓女人结婚后才知道男人不是东西，男人结婚后才知道女人要什么东西，但已经晚了。是否可以不装呢？那似乎也不太可能，因为装也是另一种人性。</p>\r\n<p style=\"margin: 1em 0px; word-wrap: break-word; line-height: 24px; color: rgb(93, 93, 93); font-family: helvetica, Arial, \'Hiragino sans GB\', \'Microsoft YaHei\', simsun; font-size: 16px; background-color: rgb(255, 255, 255);\">\r\n陈保才，爱神，情感教父，实战派顶级婚恋专家，畅销作家，江苏卫视《蒙面歌王》凤凰卫视《社会正能量》深圳都市频道《第一调解》香港卫视《东边西边》腾讯视频《夜夜谈》等多家卫视特邀嘉宾。给你全球华人最独到的爱情智慧，让你迅速获得甜蜜的爱情，幸福的婚姻。著有畅销书《第三只眼看男人》《恋上你的味儿》《爱就疯狂不爱就坚强》等。</p>\r\n							\r\n		</div></div></div>', '1', '2018-03-28 15:36:55','0','2');
  INSERT INTO `article` VALUES ('7', 'Spring Boot 2.0(五)：Docker Compose + Spring Boot +', '我知道大家这段时间看了我写关于 docker 相关的几篇文章，不疼不痒的，仍然没有感受 docker 的便利，是的，我也是这样认为的，I know your felling 。', '2', '', '<div class=\"artical-content-bak main-content\">\r\n						<div class=\"con artical-content editor-preview-side\"><p>我知道大家这段时间看了我写关于 docker 相关的几篇文章，不疼不痒的，仍然没有感受 docker 的便利，是的，我也是这样认为的，I know your felling 。</p>\r\n<p>前期了解概念什么的确实比较无聊，请不要着急精彩马上开始，当大家对 docker 相关概念有所了解之后，后面我会结合 Spring Boot 给大家来一系列的小例子，会让大家感受到使用 Docker 就是这么爽！</p>\r\n<p>今天给大家演出的导演是 Docker 家族的 docker-compare ，主演是 Spring Boot、Nginx、Mysql 三位又红又紫的大碗，名导名演在一起的时候往往是准备搞事情，接下来又一场经典大片值得大家期待。</p>\r\n<p><img src=\"https://user-gold-cdn.xitu.io/2018/3/28/1626a0f7a94b0a35?w=300&amp;h=300&amp;f=gif&amp;s=18436\" alt=\"Spring Boot 2.0(五)：Docker Compose + Spring Boot +\" style=\"cursor: pointer;\"></p>\r\n<p>Spring Boot + Nginx + Mysql 是实际工作中最常用的一个组合，最前端使用 Nginx 代理请求转发到后端 Spring Boot 内嵌的 Tomcat 服务，Mysql 负责业务中数据相关的交互，那么在没有 docker 之前，我们是如何来搞定这些环境的呢？</p>\r\n<ul>\r\n<li>1、安装 Nginx，配置 Nginx 相关信息，重启。</li>\r\n<li>2、安装 Mysql ，配置字符集时区等信息，重启，最后初始化脚本。</li>\r\n<li>3、启动 Spring Boot 项目，整体进行联调测试。</li>\r\n</ul>\r\n<p>大家看我只写了三行，但其实搭建这些环境的时候还挺费事的，但这还不是结局，在用了一段时间时候需要迁移到另外一个环境，怎么办又需要重新搞一次？正常情况下，测试环境、SIT 环境、UAT 环境、生产环境！我们需要重复搭建四次。有人说不就是搭建四次吗？也没什么大不了的，那么我想告诉你，Too yong ,Too Simple 。</p>\r\n<p><img src=\"https://user-gold-cdn.xitu.io/2018/3/28/1626a0f7ab573ea0?w=640&amp;h=355&amp;f=jpeg&amp;s=13252\" alt=\"Spring Boot 2.0(五)：Docker Compose + Spring Boot +\" style=\"cursor: pointer;\"></p>\r\n<p>让我们看看以下几个因素：</p>\r\n<p>第一，这只是一个最简单的案例，如果项目涉及到 MongoDB、Redis、ES ... 一些列的环境呢？<br>第二，如果你经常搭建环境或者调试程序，你就会知道什么是环境问题？有的时候明明是一模一样的配置，但是到了另外一个环境就是跑不起来。于是你花费很多时间来查找，最后才发现是少了一个参数或者逗号的问题，或者是系统内核版本不一致、或者你最后也没搞懂是为什么！只能再换另外一台服务器，那么使用 Docker 呢就可以完美的避开这些坑。</p>\r\n<p>好了，废话不多说我们就开始吧！</p>\r\n<h2>Spring Boot 案例</h2>\r\n<p>首先我们先准备一个 Spring Boot 使用 Mysql 的小场景，我们做这样一个示例，使用 Spring Boot 做一个 Web 应用，提供一个按照 IP 地址统计访问次数的方法，每次请求时将统计数据存入 Mysql 并展示到页面中。</p>\r\n<h3>配置信息</h3>\r\n<p><strong>依赖包</strong></p>\r\n<pre><code class=\"language-xml hljs\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencies</span>&gt;</span>\r\n     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId</span>&gt;</span>org.springframework.boot<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">groupId</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId</span>&gt;</span>spring-boot-starter-web<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">artifactId</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId</span>&gt;</span>org.springframework.boot<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">groupId</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId</span>&gt;</span>spring-boot-starter-data-jpa<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">artifactId</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId</span>&gt;</span>mysql<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">groupId</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId</span>&gt;</span>mysql-connector-java<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">artifactId</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId</span>&gt;</span>org.springframework.boot<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">groupId</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId</span>&gt;</span>spring-boot-starter-test<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">artifactId</span>&gt;</span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope</span>&gt;</span>test<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">scope</span>&gt;</span>\r\n    <span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">dependency</span>&gt;</span>\r\n<span class=\"hljs-tag\">&lt;/<span class=\"hljs-name\">dependencies</span>&gt;</span></code></pre>\r\n<p>主要添加了 Spring Boot Web 支持，使用 Jpa 操作数据库、添加 Myql 驱动包等。</p>\r\n<p><strong>配置文件</strong></p>\r\n<pre><code class=\"language-xml hljs\">spring.datasource.url=jdbc:mysql://localhost:3306/test\r\nspring.datasource.username=root\r\nspring.datasource.password=root\r\nspring.datasource.driver-class-name=com.mysql.jdbc.Driver\r\n\r\nspring.jpa.properties.hibernate.hbm2ddl.auto=update\r\nspring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect\r\nspring.jpa.show-sql=true</code></pre>\r\n<p>配置了数据库的链接信息，以及 Jpa 更新表模式、方言和是否显示Sql</p>\r\n<h3>核心代码</h3>\r\n<p>核心代码很简单，每过来一个请求，判断是否已经统计过，如果没有统计新增数据，如果有统计数据更新数据。</p>\r\n<pre><code class=\"language-java hljs\"><span class=\"hljs-meta\">@RestController</span>\r\n<span class=\"hljs-keyword\">public</span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class</span> <span class=\"hljs-title\">VisitorController</span> </span>{\r\n\r\n    <span class=\"hljs-meta\">@Autowired</span>\r\n    <span class=\"hljs-keyword\">private</span> VisitorRepository repository;\r\n\r\n    <span class=\"hljs-meta\">@RequestMapping</span>(<span class=\"hljs-string\">\"/\"</span>)\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public</span> String <span class=\"hljs-title\">index</span><span class=\"hljs-params\">(HttpServletRequest request)</span> </span>{\r\n        String ip=request.getRemoteAddr();\r\n        Visitor visitor=repository.findByIp(ip);\r\n        <span class=\"hljs-keyword\">if</span>(visitor==<span class=\"hljs-keyword\">null</span>){\r\n            visitor=<span class=\"hljs-keyword\">new</span> Visitor();\r\n            visitor.setIp(ip);\r\n            visitor.setTimes(<span class=\"hljs-number\">1</span>);\r\n        }<span class=\"hljs-keyword\">else</span> {\r\n            visitor.setTimes(visitor.getTimes()+<span class=\"hljs-number\">1</span>);\r\n        }\r\n        repository.save(visitor);\r\n        <span class=\"hljs-keyword\">return</span> <span class=\"hljs-string\">\"I have been seen ip \"</span>+visitor.getIp()+<span class=\"hljs-string\">\" \"</span>+visitor.getTimes()+<span class=\"hljs-string\">\" times.\"</span>;\r\n    }\r\n}</code></pre>\r\n<p>实体类和 Repository 层代码比较简单，这里就不贴出来了，大家感兴趣可以下载源码查看。</p>\r\n<p>以上内容都完成后，启动项目，访问：<code>http://localhost:8080/</code> 我们就可以看到这样的返回结果：</p>\r\n<pre><code class=\"language-text\">I have been seen ip 0:0:0:0:0:0:0:1 1 times.</code></pre>\r\n<p>再访问一次会变成</p>\r\n<pre><code class=\"language-text\">I have been seen ip 0:0:0:0:0:0:0:1 2 times.</code></pre>\r\n<p>多次访问一直叠加，说明演示项目开发完成。</p>\r\n<h2>Docker 化改造</h2>\r\n<p>首先我们将目录改造成这样一个结构</p>\r\n<p><img src=\"https://user-gold-cdn.xitu.io/2018/3/28/1626a0f7ab672efd?w=369&amp;h=492&amp;f=png&amp;s=16253\" alt=\"Spring Boot 2.0(五)：Docker Compose + Spring Boot +\" style=\"cursor: pointer;\"></p>\r\n<p>我们先从最外层说起：</p>\r\n<ul>\r\n<li><code>docker-compose.yaml</code>：docker-compose 的核心文件，描述如何构建整个服务</li>\r\n<li><code>nginx</code>：有关 nginx 的配置</li>\r\n<li><code>app</code>：Spring Boot 项目地址</li>\r\n</ul>\r\n<p>如果我们需要对 Mysql 有特殊的定制，也可以在最外层创建 mysql 文件夹，在此目录下进行配置。</p>\r\n<h3><code>docker-compose.yaml</code> 文件详解</h3>\r\n<pre><code class=\"language-xml hljs\">version: \'3\'\r\nservices:\r\n  nginx:\r\n   container_name: v-nginx\r\n   image: nginx:1.13\r\n   restart: always\r\n   ports:\r\n   - 80:80\r\n   - 443:443\r\n   volumes:\r\n   - ./nginx/conf.d:/etc/nginx/conf.d\r\n\r\n  mysql:\r\n   container_name: v-mysql\r\n   image: mysql/mysql-server:5.7\r\n   environment:\r\n    MYSQL_DATABASE: test\r\n    MYSQL_ROOT_PASSWORD: root\r\n    MYSQL_ROOT_HOST: \'%\'\r\n   ports:\r\n   - \"3306:3306\"\r\n   restart: always\r\n\r\n  app:\r\n    restart: always\r\n    build: ./app\r\n    working_dir: /app\r\n    volumes:\r\n      - ./app:/app\r\n      - ~/.m2:/root/.m2\r\n    expose:\r\n      - \"8080\"\r\n    depends_on:\r\n      - nginx\r\n      - mysql\r\n    command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker</code></pre>\r\n<ul>\r\n<li><code>version: \'3\'</code>： 表示使用第三代语法来构建 docker-compose.yaml 文件。</li>\r\n<li><code>services</code>: 用来表示 compose 需要启动的服务，我们可以看出此文件中有三个服务分别为：nginx、mysql、app。</li>\r\n<li><code>container_name</code>:  容器名称</li>\r\n<li><code>environment</code>: 此节点下的信息会当作环境变量传入容器，此示例中 mysql 服务配置了数据库、密码和权限信息。</li>\r\n<li><code>ports</code>: 表示对外开放的端口</li>\r\n<li><code>restart: always</code> 表示如果服务启动不成功会一直尝试。</li>\r\n<li><code>volumes</code>: 加载本地目录下的配置文件到容器目标地址下</li>\r\n<li><code>depends_on</code>：可以配置依赖服务，表示需要先启动 <code>depends_on</code> 下面的服务后，再启动本服务。</li>\r\n<li><code>command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker</code>: 表示以这个命令来启动项目，<code>-Dspring-boot.run.profiles=docker</code>表示使用 <code>application-docker.properties</code>文件配置信息进行启动。</li>\r\n</ul>\r\n<h3>Nginx 文件解读</h3>\r\n<p>nginx 在目录下有一个文件 app.conf，主要配置了服务转发信息</p>\r\n<pre><code class=\"language-xml hljs\">server {\r\n    listen 80;\r\n    charset utf-8;\r\n    access_log off;\r\n\r\n    location / {\r\n        proxy_pass http://app:8080;\r\n        proxy_set_header Host $host:$server_port;\r\n        proxy_set_header X-Forwarded-Host $server_name;\r\n        proxy_set_header X-Real-IP $remote_addr;\r\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\n    }\r\n\r\n    location /static {\r\n        access_log   off;\r\n        expires      30d;\r\n\r\n        alias /app/static;\r\n    }\r\n}</code></pre>\r\n<p>这块内容比较简单，配置请求转发，将80端口的请求转发到服务 app 的8080端口。其中<code>proxy_pass http://app:8080</code>这块的配置信息需要解释一下，这里使用是<code>app</code>而不是<code>localhost</code>，是因为他们没有在一个容器中，在一组 compose 的服务通讯需要使用 services 的名称进行访问。  </p>\r\n<h3>Spring Boot 项目改造</h3>\r\n<p>在<code>app</code>目录下也就是和<code>pom.xm</code>文件同级添加<code>Dockerfile</code>文件，文件内容如下：</p>\r\n<pre><code class=\"language-xml hljs\">FROM maven:3.5-jdk-8</code></pre>\r\n<p>只有一句，依赖于基础镜像<code>maven3.5</code>和<code>jdk 1.8</code>。因为在<code>docker-compose.yaml</code>文件设置了项目启动命令，这里不需要再添加启动命令。</p>\r\n<p>在项目的<code>resources</code>目录下创建<code>application-dev.properties</code>和<code>application-docker.properties</code>文件</p>\r\n<ul>\r\n<li><code>application-dev.properties</code> 中的配置信息和上面一致</li>\r\n<li><code>application-docker.properties</code> 中的配置信息做稍微的改造，将数据库的连接信息由<code>jdbc:mysql://localhost:3306/test</code>改为<code>jdbc:mysql://mysql:3306/test</code> 。</li>\r\n</ul>\r\n<p>这样我们所有的配置都已经完成。</p>\r\n<h2>部署</h2>\r\n<p>我们将项目拷贝到服务器中进行测试，服务器需要先安装 Docker 和 Docker Compos 环境，如果不了解的朋友可以查看我前面的两篇文章：</p>\r\n<ul>\r\n<li><a href=\"http://www.ityouknow.com/docker/2018/03/07/docker-introduction.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">Docker(一)：Docker入门教程</a></li>\r\n<li><a href=\"http://www.ityouknow.com/docker/2018/03/22/docker-compose.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">Docker(四)：Docker 三剑客之 Docker Compose</a></li>\r\n</ul>\r\n<p>将项目拷贝到服务器中，进入目录<code>cd  dockercompose-springboot-mysql-nginx</code></p>\r\n<p><strong>启动服务：<code>docker-compose up</code></strong></p>\r\n<pre><code class=\"language-xml hljs\">[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose up\r\nCreating network \"dockercomposespringbootmysqlnginx_default\" with the default driver\r\nCreating v-nginx ... done\r\nCreating v-mysql ... done\r\nCreating dockercomposespringbootmysqlnginx_app_1 ... done\r\nAttaching to v-nginx, v-mysql, dockercomposespringbootmysqlnginx_app_1\r\nv-mysql  | [Entrypoint] MySQL Docker Image 5.7.21-1.1.4\r\nv-mysql  | [Entrypoint] Initializing database\r\napp_1    | [INFO] Scanning for projects...\r\n... \r\napp_1    | 2018-03-26 02:54:55.658  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path \'\'\r\napp_1    | 2018-03-26 02:54:55.660  INFO 1 --- [           main] com.neo.ComposeApplication               : Started ComposeApplication in 14.869 seconds (JVM running for 30.202)</code></pre>\r\n<p>看到信息<code>Tomcat started on port(s): 8080</code>表示服务启动成功。也可以使用<code>docker-compose up -d</code>后台启动</p>\r\n<p>访问服务器地址；<code>http://58.87.69.230/</code>，返回：<code>I have been seen ip 172.19.0.2 1 times.</code> 表示整体服务启动成功</p>\r\n<p><strong>使用<code>docker-compose ps</code>查看项目中目前的所有容器</strong></p>\r\n<pre><code class=\"language-text\">[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose ps\r\n                 Name                                Command                  State                        Ports                  \r\n----------------------------------------------------------------------------------------------------------------------------------\r\ndockercomposespringbootmysqlnginx_app_1   /usr/local/bin/mvn-entrypo ...   Up             8080/tcp                                \r\nv-mysql                                   /entrypoint.sh mysqld            Up (healthy)   0.0.0.0:3306-&gt;3306/tcp, 33060/tcp       \r\nv-nginx                                   nginx -g daemon off;             Up             0.0.0.0:443-&gt;443/tcp, 0.0.0.0:80-&gt;80/tcp</code></pre>\r\n<p>可以看到项目中服务的状态、命令、端口等信息。</p>\r\n<p><strong>关闭服务<code>docker-compose down</code></strong></p>\r\n<pre><code class=\"language-text\">[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose down\r\nStopping dockercomposespringbootmysqlnginx_app_1 ... done\r\nStopping visitor-nginx                           ... done\r\nStopping visitor-mysql                           ... done\r\nRemoving dockercomposespringbootmysqlnginx_app_1 ... done\r\nRemoving visitor-nginx                           ... done\r\nRemoving visitor-mysql                           ... done</code></pre>\r\n<h3>docker-compose 顺序</h3>\r\n<p>在使用 docker-compose 启动的时候经常会出现项目报 Mysql 连接异常，跟踪了一天终于发现了问题。 docker-compose 虽然可以通过<code>depends_on</code> 来定义服务启动的顺序，但是无法确定服务是否启动完成，因此会出现这样一个现象，Mysql 服务启动比较慢，当 Spring Boot 项目已经启动起来，但是 Mysql 还没有初始化好，这样当项目连接 Mysql 数据库的时候，就会出现连接数据库的异常。</p>\r\n<p>针对这样的问题，有两种解决方案:</p>\r\n<p>1、足够的容错和重试机制，比如连接数据库，在初次连接不上的时候，服务消费者可以不断重试，直到连接上服务。也就是在服务中定义： <code>restart: always</code></p>\r\n<p>2、同步等待，使用<code>wait-for-it.sh</code>或者其他<code>shell</code>脚本将当前服务启动阻塞，直到被依赖的服务加载完毕。这种方案后期可以尝试使用。</p>\r\n<h2>总结</h2>\r\n<p>没有对比就没有伤害，在没有使用 Docker 之前，我们需要搭建这样一个环境的话，需要安装 Nginx、Mysql ，再进行一系列的配置调试，还要担心各种环境问题；使用 Docker 之后简单两个命令就完成服务的上线、下线。</p>\r\n<pre><code class=\"language-sh hljs bash\">docker-compose up\r\ndocker-compose down</code></pre>\r\n<p>其实容器技术对部署运维的优化还有很多，这只是刚刚开始，后面使用了 Swarm 才会真正感受到它的便利和强大。</p>\r\n<p><strong><a href=\"https://github.com/ityouknow/spring-boot-examples\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">示例代码-github</a></strong></p>\r\n<p><strong><a href=\"https://gitee.com/ityouknow/spring-boot-examples\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">示例代码-码云</a></strong></p>\r\n<h2>参考</h2>\r\n<p><a href=\"https://hellokoding.com/docker-compose-with-spring-boot-mysql-nginx/\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">Docker Compose with Spring Boot, MySQL and NGINX</a>  </p></div>\r\n					</div>', '1', '2018-03-28 15:38:21','0','2');
  INSERT INTO `article` VALUES ('8', 'CentOS7搭建FastDFS+Nginx', 'FastDFS是一个开源的分布式文件系统，她对文件进行管理，功能包括：文件存储、文件同步、文件访问（文件上传、文件下载）等，解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务，如相册网站、视频网站等等。', '2', '', '<div class=\"artical-content-bak main-content\">\r\n						<div class=\"con artical-content editor-preview-side\"><h1>CentOS7搭建FastDFS+Nginx</h1>\r\n<p>[TOC]</p>\r\n<h2>1. FastDFS 介绍</h2>\r\n<p>FastDFS是一个开源的分布式文件系统，她对文件进行管理，功能包括：文件存储、文件同步、文件访问（文件上传、文件下载）等，解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务，如相册网站、视频网站等等。</p>\r\n<p>FastDFS服务端有两个角色：跟踪器（tracker）和存储节点（storage）。跟踪器主要做调度工作，在访问上起负载均衡的作用。</p>\r\n<p>存储节点存储文件，完成文件管理的所有功能：存储、同步和提供存取接口，FastDFS同时对文件的meta data进行管理。所谓文件的meta data就是文件的相关属性，以键值对（key value pair）方式表示，如：width=1024，其中的key为width，value为1024。文件meta data是文件属性列表，可以包含多个键值对。</p>\r\n<p>FastDFS系统结构如下图所示：</p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/27/9faaa0e36fbaaa99d9a647ad248630b4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"FastDFS系统结构\" style=\"cursor: pointer;\"></p>\r\n<p>跟踪器和存储节点都可以由一台或多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的，可以根据服务器的压力情况随时增加或减少。</p>\r\n<p>为了支持大容量，存储节点（服务器）采用了分卷（或分组）的组织方式。存储系统由一个或多个卷组成，卷与卷之间的文件是相互独立的，所有卷 的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成，一个卷下的存储服务器中的文件都是相同的，卷中的多台存储服务器起 到了冗余备份和负载均衡的作用。</p>\r\n<p>在卷中增加服务器时，同步已有的文件由系统自动完成，同步完成后，系统自动将新增服务器切换到线上提供服务。</p>\r\n<p>当存储空间不足或即将耗尽时，可以动态添加卷。只需要增加一台或多台服务器，并将它们配置为一个新的卷，这样就扩大了存储系统的容量。<br>FastDFS中的文件标识分为两个部分：卷名和文件名，二者缺一不可。</p>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/27/7b72d4428d589d12858426545682d219.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"FastDFS file upload\" style=\"cursor: pointer;\"></p>\r\n<p>上传文件交互过程：</p>\r\n<ol>\r\n<li>client询问tracker上传到的storage，不需要附加参数；</li>\r\n<li>tracker返回一台可用的storage；</li>\r\n<li>client直接和storage通讯完成文件上传。 </li>\r\n</ol>\r\n<p><img src=\"http://i2.51cto.com/images/blog/201803/27/3b0869f6977a2ba45b099f03bbfe80e4.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=\" alt=\"FastDFS file download\" style=\"cursor: pointer;\"></p>\r\n<p>下载文件交互过程：</p>\r\n<ol>\r\n<li>client询问tracker下载文件的storage，参数为文件标识（卷名和文件名）；</li>\r\n<li>tracker返回一台可用的storage；</li>\r\n<li>client直接和storage通讯完成文件下载。</li>\r\n</ol>\r\n<p>需要说明的是，client为使用FastDFS服务的调用方，client也应该是一台服务器，它对tracker和storage的调用均为服务器间的调用。</p>\r\n<h2>2. FastDFS单机部署</h2>\r\n<h3>2.1 准备</h3>\r\n<p>系统：<br>CentOS7</p>\r\n<p>安装包：</p>\r\n<pre><code class=\"hljs ruby\">[root@SUNQFASTDFS01 fastdfs]<span class=\"hljs-comment\"># pwd</span>\r\n/tmp/fastdfs\r\n[root@SUNQFASTDFS01 fastdfs]<span class=\"hljs-comment\"># ll</span>\r\ntotal <span class=\"hljs-number\">1896</span>\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root  <span class=\"hljs-number\">22192</span> Dec  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">14</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">29</span> fastdfs-nginx-<span class=\"hljs-class\"><span class=\"hljs-keyword\">module</span>-<span class=\"hljs-title\">master</span>.<span class=\"hljs-title\">zip</span></span>\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">425467</span> Dec  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">14</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">25</span> fastdfs-master.zip\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">478937</span> Dec  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">14</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">27</span> libfastcommon-master.zip\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">988415</span> Aug  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">23</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">11</span> nginx-<span class=\"hljs-number\">1.13</span>.<span class=\"hljs-number\">4</span>.tar.gz\r\n[root@SUNQFASTDFS01 fastdfs]<span class=\"hljs-comment\"># </span></code></pre>\r\n<h3>2.2 安装依赖包和开始工具</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-comment\">#安装依赖软件</span>\r\nyum -y install gcc gcc-c++ libstdc++-devel pcre-devel zlib-devel wget make\r\nyum -y groupinstall <span class=\"hljs-string\">\'Development Tools\'</span> </code></pre>\r\n<h3>2.3 安装libfastcommon</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /tmp/fastdfs/\r\nunzip libfastcommon-master.zip\r\nmv libfastcommon-master /usr/<span class=\"hljs-built_in\">local</span>/libfastcommon\r\n<span class=\"hljs-built_in\">cd</span> /usr/<span class=\"hljs-built_in\">local</span>/libfastcommon\r\n./make.sh\r\n./make.sh install</code></pre>\r\n<h3>2.4 安装fastdfs</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /tmp/fastdfs\r\nunzip fastdfs-master.zip\r\nmv fastdfs-master /usr/<span class=\"hljs-built_in\">local</span>/fastdfs\r\n./make.sh\r\n./make.sh install</code></pre>\r\n<pre><code class=\"hljs coffeescript\">[root@SUNQFASTDFS01 fastdfs]<span class=\"hljs-comment\"># ls -l /etc/fdfs/</span>\r\ntotal <span class=\"hljs-number\">40</span>\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">1461</span> Jan  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">16</span>:<span class=\"hljs-number\">50</span> client.conf.sample\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">7927</span> Jan  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">16</span>:<span class=\"hljs-number\">50</span> storage.conf.sample\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root  <span class=\"hljs-number\">105</span> Jan  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">16</span>:<span class=\"hljs-number\">50</span> storage_ids.conf.sample\r\n-rw-r--r-- <span class=\"hljs-number\">1</span> root root <span class=\"hljs-number\">7389</span> Jan  <span class=\"hljs-number\">8</span> <span class=\"hljs-number\">16</span>:<span class=\"hljs-number\">50</span> tracker.conf.sample\r\n[root@SUNQFASTDFS01 fastdfs]<span class=\"hljs-comment\"># </span></code></pre>\r\n<p>安装好之后，在/usr/bin目录下，可以看fdfs开头的命令工具</p>\r\n<blockquote>\r\n<p>FastDFS安装完成之后，所有配置文件在/etc/fdfs目录下，<br>tracker需要tracker.conf配置文件，<br>storage需要storage.conf配置文件。</p>\r\n</blockquote>\r\n<h3>2.5 配置tracker</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /etc/fdfs/\r\ncp tracker.conf.sample tracker.conf\r\nvim tracker.conf</code></pre>\r\n<p>修改<code>base_path</code>（文件存储路径）为<code>/opt/fastdfs</code></p>\r\n<pre><code class=\"hljs ini\"><span class=\"hljs-comment\"># the base path to store data and log files</span>\r\n<span class=\"hljs-attr\">base_path</span>=/opt/fastdfs</code></pre>\r\n<pre><code class=\"hljs makefile\"><span class=\"hljs-comment\"># 启用配置文件</span>\r\ndisabled=false\r\n<span class=\"hljs-comment\"># 设置tracker的端口号</span>\r\nport=22122\r\n<span class=\"hljs-comment\"># 设置tracker的数据文件和日志目录（需手动创建）</span>\r\nbase_path=/opt/fastdfs\r\n<span class=\"hljs-comment\"># 设置http端口号</span>\r\nhttp.server_port=8080</code></pre>\r\n<p>使用<code>fdfs_trackerd /etc/fdfs/tracker.conf start</code>尝试启动tracker</p>\r\n<p>检查是否启动</p>\r\n<pre><code class=\"hljs ruby\">[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># fdfs_trackerd /etc/fdfs/tracker.conf start                                                                                                                                                  </span>\r\n[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># ps -ef|grep tracker.conf</span>\r\nroot      <span class=\"hljs-number\">3438</span>     <span class=\"hljs-number\">1</span>  <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">17</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">01</span> ?        <span class=\"hljs-number\">00</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span> fdfs_trackerd /etc/fdfs/tracker.conf start\r\nroot      <span class=\"hljs-number\">3446</span>  <span class=\"hljs-number\">2670</span>  <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">17</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">01</span> pts/<span class=\"hljs-number\">0</span>    <span class=\"hljs-number\">00</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span> grep --color=auto tracker.conf\r\n[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># netstat -pln|grep fdfs</span>\r\ntcp        <span class=\"hljs-number\">0</span>      <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">22122</span>           <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span><span class=\"hljs-symbol\">:*</span>               LISTEN      <span class=\"hljs-number\">3438</span>/fdfs_trackerd  \r\n[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># tail /opt/fastdfs/logs/trackerd.log </span>\r\n[<span class=\"hljs-number\">2018</span>-<span class=\"hljs-number\">01</span>-08 <span class=\"hljs-number\">17</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">01</span><span class=\"hljs-symbol\">:</span>08] INFO - FastDFS v5.<span class=\"hljs-number\">12</span>, base_path=<span class=\"hljs-regexp\">/opt/fastdfs</span>, run_by_group=, run_by_user=, connect_timeout=<span class=\"hljs-number\">30</span>s, network_timeout=<span class=\"hljs-number\">60</span>s, port=<span class=\"hljs-number\">22122</span>, bind_addr=, max_connections=<span class=\"hljs-number\">256</span>, accept_threads=<span class=\"hljs-number\">1</span>, work_threads=<span class=\"hljs-number\">4</span>, min_buff_size=<span class=\"hljs-number\">8192</span>, max_buff_size=<span class=\"hljs-number\">131072</span>, store_lookup=<span class=\"hljs-number\">2</span>, store_group=, store_server=<span class=\"hljs-number\">0</span>, store_path=<span class=\"hljs-number\">0</span>, reserved_storage_space=<span class=\"hljs-number\">10.00</span>%, download_server=<span class=\"hljs-number\">0</span>, allow_ip_count=-<span class=\"hljs-number\">1</span>, sync_log_buff_interval=<span class=\"hljs-number\">10</span>s, check_active_interval=<span class=\"hljs-number\">120</span>s, thread_stack_size=<span class=\"hljs-number\">64</span> KB, storage_ip_changed_auto_adjust=<span class=\"hljs-number\">1</span>, storage_sync_file_max_delay=<span class=\"hljs-number\">86400</span>s, storage_sync_file_max_time=<span class=\"hljs-number\">300</span>s, use_trunk_file=<span class=\"hljs-number\">0</span>, slot_min_size=<span class=\"hljs-number\">256</span>, slot_max_size=<span class=\"hljs-number\">16</span> MB, trunk_file_size=<span class=\"hljs-number\">64</span> MB, trunk_create_file_advance=<span class=\"hljs-number\">0</span>, trunk_create_file_time_base=<span class=\"hljs-number\">02</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span>, trunk_create_file_interval=<span class=\"hljs-number\">86400</span>, trunk_create_file_space_threshold=<span class=\"hljs-number\">20</span> GB, trunk_init_check_occupying=<span class=\"hljs-number\">0</span>, trunk_init_reload_from_binlog=<span class=\"hljs-number\">0</span>, trunk_compress_binlog_min_interval=<span class=\"hljs-number\">0</span>, use_storage_id=<span class=\"hljs-number\">0</span>, id_type_in_filename=ip, storage_id_count=<span class=\"hljs-number\">0</span>, rotate_error_log=<span class=\"hljs-number\">0</span>, error_log_rotate_time=<span class=\"hljs-number\">00</span><span class=\"hljs-symbol\">:</span><span class=\"hljs-number\">00</span>, rotate_error_log_size=<span class=\"hljs-number\">0</span>, log_file_keep_days=<span class=\"hljs-number\">0</span>, store_slave_file_use_link=<span class=\"hljs-number\">0</span>, use_connection_pool=<span class=\"hljs-number\">0</span>, g_connection_pool_max_idle_time=<span class=\"hljs-number\">3600</span>s</code></pre>\r\n<h3>2.6 配置storage</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /etc/fdfs/\r\ncp storage.conf.sample storage.conf\r\nvim storage.conf</code></pre>\r\n<p>主要修改<code>base_path</code>，<code>store_path</code>以及tracker的连接地址以及storage的http服务端口配置等。</p>\r\n<pre><code class=\"hljs makefile\">group_name=group1                   <span class=\"hljs-comment\"># 组名（第一组为group1，第二组为group2，依次类推...）</span>\r\nbase_path=/opt/fastdfs             <span class=\"hljs-comment\"># 数据和日志文件存储根目录</span>\r\nstore_path0=/opt/fastdfs           <span class=\"hljs-comment\"># 第一个存储目录，第二个存储目录起名为：store_path1=xxx，其它存储目录名依次类推...</span>\r\nstore_path_count=1                  <span class=\"hljs-comment\"># 存储路径个数，需要和store_path个数匹配</span>\r\ntracker_server=172.30.47.156:22122          <span class=\"hljs-comment\"># tracker服务器IP和端口，有多个则添加多行</span></code></pre>\r\n<p>检查是否启动</p>\r\n<pre><code class=\"hljs perl\">[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># fdfs_storaged /etc/fdfs/storage.conf start</span>\r\n[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># netstat -unltp|grep fdfs</span>\r\ntcp        <span class=\"hljs-number\">0</span>      <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>:<span class=\"hljs-number\">22122</span>           <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>:*               LISTEN      <span class=\"hljs-number\">3438</span>/fdfs_trackerd  \r\ntcp        <span class=\"hljs-number\">0</span>      <span class=\"hljs-number\">0</span> <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>:<span class=\"hljs-number\">23000</span>           <span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>.<span class=\"hljs-number\">0</span>:*               LISTEN      <span class=\"hljs-number\">4571</span>/fdfs_storaged  \r\n[root@SUNQFASTDFS01 fdfs]<span class=\"hljs-comment\"># tail /opt/fastdfs/logs/storaged.log </span>\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FA ...\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FB ...\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FC ...\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FD ...\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FE ...\r\n<span class=\"hljs-keyword\">mkdir</span> data path: FF ...\r\ndata path: <span class=\"hljs-regexp\">/opt/fastdfs</span><span class=\"hljs-regexp\">/data, mkdir sub dir done.\r\n[2018-01-09 10:15:08] INFO - file: storage_param_getter.c, line: 191, use_storage_id=0, id_type_in_filename=ip, storage_ip_changed_auto_adjust=1, store_path=0, reserved_storage_space=10.00%, use_trunk_file=0, slot_min_size=256, slot_max_size=16 MB, trunk_file_size=64 MB, trunk_create_file_advance=0, trunk_create_file_time_base=02:00, trunk_create_file_interval=86400, trunk_create_file_space_threshold=20 GB, trunk_init_check_occupying=0, trunk_init_reload_from_binlog=0, trunk_compress_binlog_min_interval=0, store_slave_file_use_link=0\r\n[2018-01-09 10:15:08] INFO - file: storage_func.c, line: 257, tracker_client_ip: 172.30.47.156, my_server_id_str: 172.30.47.156, g_server_id_in_filename: -1674633556\r\n[2018-01-09 10:15:08] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 172.30.47.156:22122, as a tracker client, my ip is 172.30.47.156\r\n[root@SUNQFASTDFS01 fdfs]# </span></code></pre>\r\n<p>在任一存储节点上使用如下命令查看集群的状态信息：<br><code>fdfs_monitor /etc/fdfs/storage.conf</code></p>\r\n<p>如果出现ip_addr = Active, 则表明storage服务器已经登记到tracker服务器，如下：</p>\r\n<pre><code class=\"hljs cs\">server_count=<span class=\"hljs-number\">1</span>, server_index=<span class=\"hljs-number\">0</span>\r\n\r\ntracker server <span class=\"hljs-keyword\">is</span> <span class=\"hljs-number\">172.30</span><span class=\"hljs-number\">.47</span><span class=\"hljs-number\">.156</span>:<span class=\"hljs-number\">22122</span>\r\n\r\n<span class=\"hljs-keyword\">group</span> count: <span class=\"hljs-number\">1</span>\r\n\r\nGroup <span class=\"hljs-number\">1</span>:\r\n<span class=\"hljs-keyword\">group</span> name = group1\r\ndisk total space = <span class=\"hljs-number\">50871</span> MB\r\ndisk free space = <span class=\"hljs-number\">40771</span> MB\r\ntrunk free space = <span class=\"hljs-number\">0</span> MB\r\nstorage server count = <span class=\"hljs-number\">1</span>\r\nactive server count = <span class=\"hljs-number\">1</span>\r\nstorage server port = <span class=\"hljs-number\">23000</span>\r\nstorage HTTP port = <span class=\"hljs-number\">8888</span>\r\nstore path count = <span class=\"hljs-number\">1</span>\r\nsubdir count per path = <span class=\"hljs-number\">256</span>\r\ncurrent write server index = <span class=\"hljs-number\">0</span>\r\ncurrent trunk file id = <span class=\"hljs-number\">0</span>\r\n\r\n        Storage <span class=\"hljs-number\">1</span>:\r\n                id = <span class=\"hljs-number\">172.30</span><span class=\"hljs-number\">.47</span><span class=\"hljs-number\">.156</span>\r\n                ip_addr = <span class=\"hljs-number\">172.30</span><span class=\"hljs-number\">.47</span><span class=\"hljs-number\">.156</span> (SUNQFASTDFS01)  ACTIVE</code></pre>\r\n<h3>2.7 在storage上安装nginx</h3>\r\n<blockquote>\r\n<p>&lt;font color=\"red\"&gt;<em>注意</em>&lt;/font&gt;：<br>fastdfs-nginx-module模块只需要安装到storage上。</p>\r\n</blockquote>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /tmp/fastdfs\r\nunzip fastdfs-nginx-module-master.zip\r\nmv fastdfs-nginx-module-master /usr/<span class=\"hljs-built_in\">local</span>/fastdfs-nginx-module\r\ntar -zxf nginx-1.13.4.tar.gz\r\n<span class=\"hljs-built_in\">cd</span> nginx-1.13.4\r\n./configure --prefix=/usr/<span class=\"hljs-built_in\">local</span>/nginx --add-module=/usr/<span class=\"hljs-built_in\">local</span>/fastdfs-nginx-module/src/</code></pre>\r\n<p>没有报错则执行下一步：</p>\r\n<pre><code class=\"language-bash hljs\">make\r\nmake install</code></pre>\r\n<p>如下结果则表示安装成功</p>\r\n<pre><code class=\"hljs ruby\">[root@SUNQFASTDFS01 nginx-<span class=\"hljs-number\">1.13</span>.<span class=\"hljs-number\">4</span>]<span class=\"hljs-comment\"># /usr/local/nginx/sbin/nginx -V</span>\r\nnginx <span class=\"hljs-symbol\">version:</span> nginx/<span class=\"hljs-number\">1.13</span>.<span class=\"hljs-number\">4</span>\r\nbuilt by gcc <span class=\"hljs-number\">4.8</span>.<span class=\"hljs-number\">5</span> <span class=\"hljs-number\">20150623</span> (Red Hat <span class=\"hljs-number\">4.8</span>.<span class=\"hljs-number\">5</span>-<span class=\"hljs-number\">16</span>) (GCC) \r\nconfigure <span class=\"hljs-symbol\">arguments:</span> --prefix=<span class=\"hljs-regexp\">/usr/local</span><span class=\"hljs-regexp\">/nginx --add-module=/usr</span><span class=\"hljs-regexp\">/local/fastdfs</span>-nginx-<span class=\"hljs-class\"><span class=\"hljs-keyword\">module</span>/<span class=\"hljs-title\">src</span>/</span></code></pre>\r\n<h3>2.8 配置client</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /etc/fdfs/\r\ncp client.conf.sample client.conf\r\nvim client.conf</code></pre>\r\n<pre><code class=\"hljs makefile\">base_path=/opt/fastdfs              <span class=\"hljs-comment\"># 数据和日志文件存储根目录        </span>\r\ntracker_server=172.30.47.156:22122  <span class=\"hljs-comment\"># tracker服务器IP和端口，有多个按行添加         </span>\r\nhttp.tracker_server_port=8080       <span class=\"hljs-comment\"># 服务端IP和端口号</span></code></pre>\r\n<pre><code class=\"hljs coffeescript\">[root@SUNQFASTDFS01 data]<span class=\"hljs-comment\"># ls /tmp/test01.png </span>\r\n/tmp/test01.png\r\n[root@SUNQFASTDFS01 data]<span class=\"hljs-comment\"># fdfs_upload_file /etc/fdfs/client.conf /tmp/test01.png </span>\r\ngroup1/M00/<span class=\"hljs-number\">00</span>/<span class=\"hljs-number\">00</span>/rB4vnFpUPN-Adut0AANMVnJruQg458.png</code></pre>\r\n<h3>2.9 配置fastdfs-nginx-module和nginx</h3>\r\n<pre><code class=\"language-bash hljs\"><span class=\"hljs-built_in\">cd</span> /etc/fdfs/\r\ncp /usr/<span class=\"hljs-built_in\">local</span>/fastdfs-nginx-module/src/mod_fastdfs.conf .\r\nvim mod_fastdfs.conf</code></pre>\r\n<p>一般只需改动以下几个参数即可：</p>\r\n<pre><code class=\"hljs makefile\">base_path=/opt/fastdfs            <span class=\"hljs-comment\"># 保存日志目录</span>\r\ntracker_server=172.30.47.156:22122  <span class=\"hljs-comment\"># tracker服务器IP和端口，有多个按行添加</span>\r\nstorage_server_port=23000         <span class=\"hljs-comment\"># storage服务器的端口号</span>\r\ngroup_name=group1                 <span class=\"hljs-comment\"># 当前服务器的group名</span>\r\nurl_have_group_name = true        <span class=\"hljs-comment\"># 文件url中是否有group名</span>\r\nstore_path_count=1                <span class=\"hljs-comment\"># 存储路径个数，需要和store_path个数匹配</span>\r\nstore_path0=/opt/fastdfs          <span class=\"hljs-comment\"># 存储路径</span>\r\ngroup_count = 0                   <span class=\"hljs-comment\"># 设置组的个数，设置为0则为单组</span></code></pre>\r\n<pre><code class=\"language-bash hljs\">cp /usr/<span class=\"hljs-built_in\">local</span>/fastdfs/conf/http.conf /usr/<span class=\"hljs-built_in\">local</span>/fastdfs/conf/mime.types /etc/fdfs/\r\nvim /usr/<span class=\"hljs-built_in\">local</span>/nginx/conf/nginx.conf</code></pre>\r\n<p>内容：</p>\r\n<pre><code class=\"hljs nginx\"><span class=\"hljs-comment\"># nginx.conf</span>\r\n<span class=\"hljs-attribute\">user</span>  nobody;\r\n<span class=\"hljs-attribute\">worker_processes</span>  <span class=\"hljs-number\">8</span>;\r\n\r\n<span class=\"hljs-attribute\">error_log</span>  logs/info.log  <span class=\"hljs-literal\">info</span>;\r\n\r\n<span class=\"hljs-comment\">#pid        logs/nginx.pid;</span>\r\n\r\n<span class=\"hljs-section\">events</span> {\r\n    <span class=\"hljs-attribute\">worker_connections</span>  <span class=\"hljs-number\">1024</span>;\r\n}\r\n\r\n<span class=\"hljs-section\">http</span> {\r\n    <span class=\"hljs-attribute\">include</span>       mime.types;\r\n    <span class=\"hljs-attribute\">default_type</span>  application/octet-stream;\r\n\r\n    <span class=\"hljs-comment\">#log_format  main  \'$remote_addr - $remote_user [$time_local] \"$request\" \'</span>\r\n    <span class=\"hljs-comment\">#                  \'$status $body_bytes_sent \"$http_referer\" \'</span>\r\n    <span class=\"hljs-comment\">#                  \'\"$http_user_agent\" \"$http_x_forwarded_for\"\';</span>\r\n\r\n    <span class=\"hljs-comment\">#access_log  logs/access.log  main;</span>\r\n\r\n    <span class=\"hljs-attribute\">sendfile</span>        <span class=\"hljs-literal\">on</span>;\r\n    <span class=\"hljs-comment\">#tcp_nopush     on;</span>\r\n\r\n    <span class=\"hljs-comment\">#keepalive_timeout  0;</span>\r\n    <span class=\"hljs-attribute\">keepalive_timeout</span>  <span class=\"hljs-number\">65</span>;\r\n\r\n    <span class=\"hljs-comment\">#设定请求缓冲  </span>\r\n    <span class=\"hljs-attribute\">server_names_hash_bucket_size</span> <span class=\"hljs-number\">128</span>;  \r\n    <span class=\"hljs-attribute\">client_header_buffer_size</span> <span class=\"hljs-number\">32k</span>;  \r\n    <span class=\"hljs-attribute\">large_client_header_buffers</span> <span class=\"hljs-number\">4</span> <span class=\"hljs-number\">32k</span>;  \r\n    <span class=\"hljs-attribute\">client_max_body_size</span> <span class=\"hljs-number\">300m</span>;  \r\n    <span class=\"hljs-attribute\">tcp_nopush</span>     <span class=\"hljs-literal\">on</span>;  \r\n    <span class=\"hljs-attribute\">tcp_nodelay</span> <span class=\"hljs-literal\">on</span>;  \r\n    <span class=\"hljs-attribute\">server_tokens</span> <span class=\"hljs-literal\">off</span>;  \r\n    <span class=\"hljs-attribute\">client_body_buffer_size</span> <span class=\"hljs-number\">512k</span>;  \r\n    <span class=\"hljs-attribute\">proxy_connect_timeout</span>   <span class=\"hljs-number\">20</span>;  \r\n    <span class=\"hljs-attribute\">proxy_send_timeout</span>      <span class=\"hljs-number\">60</span>;  \r\n    <span class=\"hljs-attribute\">proxy_read_timeout</span>      <span class=\"hljs-number\">20</span>;  \r\n    <span class=\"hljs-attribute\">proxy_buffer_size</span>       <span class=\"hljs-number\">16k</span>;  \r\n    <span class=\"hljs-attribute\">proxy_buffers</span>           <span class=\"hljs-number\">4</span> <span class=\"hljs-number\">64k</span>;  \r\n    <span class=\"hljs-attribute\">proxy_busy_buffers_size</span> <span class=\"hljs-number\">128k</span>;  \r\n    <span class=\"hljs-attribute\">proxy_temp_file_write_size</span> <span class=\"hljs-number\">128k</span>;   \r\n    <span class=\"hljs-attribute\">client_header_timeout</span>  <span class=\"hljs-number\">3m</span>;  \r\n    <span class=\"hljs-attribute\">client_body_timeout</span>    <span class=\"hljs-number\">3m</span>;  \r\n    <span class=\"hljs-attribute\">send_timeout</span>           <span class=\"hljs-number\">3m</span>;  \r\n\r\n    <span class=\"hljs-attribute\">gzip</span> <span class=\"hljs-literal\">on</span>; <span class=\"hljs-comment\"># 开启gzip，节省带宽  </span>\r\n    <span class=\"hljs-attribute\">gzip_min_length</span>  <span class=\"hljs-number\">1100</span>;  \r\n    <span class=\"hljs-attribute\">gzip_buffers</span>     <span class=\"hljs-number\">4</span> <span class=\"hljs-number\">8k</span>;  \r\n    <span class=\"hljs-attribute\">gzip_types</span>       text/plain text/css application/x-javascript image/bmp application/javascript;     \r\n\r\n    <span class=\"hljs-attribute\">output_buffers</span>   <span class=\"hljs-number\">1</span> <span class=\"hljs-number\">32k</span>;  \r\n    <span class=\"hljs-attribute\">postpone_output</span>  <span class=\"hljs-number\">1460</span>;  \r\n\r\n    <span class=\"hljs-attribute\">limit_rate_after</span> <span class=\"hljs-number\">3m</span>; <span class=\"hljs-comment\"># 限速模块，前3M下载时不限速  </span>\r\n    <span class=\"hljs-attribute\">limit_rate</span> <span class=\"hljs-number\">512k</span>; <span class=\"hljs-comment\"># 限速模块   </span>\r\n\r\n<span class=\"hljs-attribute\">include</span> vhost/<span class=\"hljs-regexp\">*.conf</span>;\r\n\r\n}</code></pre>\r\n<pre><code class=\"language-bash hljs\">vim /usr/<span class=\"hljs-built_in\">local</span>/nginx/conf/vhost/storage.conf</code></pre>\r\n<p>内容：</p>\r\n<pre><code class=\"hljs cs\"><span class=\"hljs-meta\"># storage.conf</span>\r\nserver {\r\n    listen       <span class=\"hljs-number\">8080</span> ;\r\n    server_name  <span class=\"hljs-number\">172.30</span><span class=\"hljs-number\">.47</span><span class=\"hljs-number\">.156</span> ;\r\n\r\n    location / {\r\n        root   html;\r\n        index  index.html index.htm;\r\n    }\r\n\r\n    location ~/<span class=\"hljs-keyword\">group</span>[<span class=\"hljs-number\">0</span><span class=\"hljs-number\">-9</span>]/M00 {\r\n        <span class=\"hljs-keyword\">alias</span>   /opt/fastdfs/data/;\r\n        ngx_fastdfs_module;\r\n    }\r\n\r\n}</code></pre>\r\n<p>启动nginx：</p>\r\n<pre><code class=\"hljs bash\">/usr/<span class=\"hljs-built_in\">local</span>/nginx/sbin/nginx</code></pre>\r\n<p>然后访问上文件中生成的字符串拼接的url：<br><code>http://172.30.47.156:8080/group1/M00/00/00/rB4vnFpUPN-Adut0AANMVnJruQg458.png</code></p>\r\n<p>参考资料：<br>[1] <a href=\"http://www.ityouknow.com/fastdfs/2017/10/10/cluster-building-fastdfs.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\"></a><a href=\"http://www.ityouknow.com/fastdfs/2017/10/10/cluster-building-fastdfs.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">http://www.ityouknow.com/fastdfs/2017/10/10/cluster-building-fastdfs.html</a><br>[2] <a href=\"http://www.cnblogs.com/sunmmi/p/5798803.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\"></a><a href=\"http://www.cnblogs.com/sunmmi/p/5798803.html\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">http://www.cnblogs.com/sunmmi/p/5798803.html</a><br>[3] <a href=\"http://blog.csdn.net/u012453843/article/details/69055570\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\"></a><a href=\"http://blog.csdn.net/u012453843/article/details/69055570\" rel=\"nofollow\" style=\"color: rgb(66, 133, 244);\">http://blog.csdn.net/u012453843/article/details/69055570</a></p></div>\r\n</div>', '1', '2018-03-28 15:39:09','0','2');
  INSERT INTO `category` VALUES ('1', '生活记事', '2', '1', '2018-10-24 10:20:05');
  INSERT INTO `category` VALUES ('2', '技术折腾', '3', '1', '2018-10-24 10:20:34');
  INSERT INTO `background` VALUES ('1', '\\uploads\\20181024\\1b179fa86439c86731aa9845e1e0fc39.jpg', '\\uploads\\20181024\\685c236eedcead9479f13e50de7edd82.jpg', '1', '1', '2018-10-24 14:32:37');
  