Varnish4 强制所有缓存过期

如果你正在使用Varnish 4, 使用Ban命令/参数可以使缓存强制过期

varnishadm命令行中使用ban命令

ban req.url ~ /foo
ban req.http.host ~ example.com && obj.http.content-type ~ text
ban.list

 

VCL文件中使用BAN参数

ban("req.url ~ /foo");

 

在VCL文件中增加BAN方法

sub vcl_recv {
    if (req.method == "BAN") {
        ban("req.http.host == " + req.http.host +
            " && req.url == " + req.url);
        # Throw a synthetic page so the request won't go to the backend.
        return(synth(200, "Ban added"));
    }
}

 

请注意:

Ban只能清除已经在缓存中的对象,例如ban并不能阻止新的对象加入缓存或者正在被处理. 已缓存的对象满足ban将被标记为过时的(obsolete). 过时的对象会被自动回收和其他 obj.ttl==0 的对象一样.

 

更多内容请参考官方文档: http://book.varnish-software.com/4.0/chapters/Cache_Invalidation.html#banning

Visual Studio中的Console Application不显示Debug窗口

打开*.sln之后,在项目的属性页,“配置属性”/“链接器”/“系统”中“子系统”选择“Windows(/SUBSYSTEM:WINDOWS)原先为“控制台(/SUBSYSTEM:CONSOLE)”

如果只修改这一项,重新编译的时候会报这样的错误:
MSVCRTD.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain@16,该符号在函数 ___tmainCRTStartup 中被引用

需要在“高级”选项中添加“入口点”:mainCRTStartup
再次编译就OK了。

Centos 7上配置Munin MySQL插件.

Munin自带的有MySQL插件,但是并不太好用,本文将介绍如何安装和配置第三方的Munin MySQL监控插件.
本文中所有操作都在Centos 7, MaraiDB 11.2下完成.

1.安装必要的Perl依赖

yum -y install perl-DBI perl-DBD-mysql perl-Module-Pluggable

2.下载,解压munin-mysql插件

wget https://github.com/kjellm/munin-mysql/archive/master.zip -O munin-mysql.zip
unzip munin-mysql.zip
cd munin-mysql-master

3.修改mysql.conf配置
修改 env.mysqlconnection DBI:mysql:mysql 为 env.mysqlconnection DBI:mysql:munin
修改env.mysqluser root 为 env.mysqluser munin
去掉env.mysqlpassword前面的#号,并把geheim修改成你将要使用监控MySQL账号的密码

4.编辑Makefile, 找到$(MUNIN_NODE) restart (大约45行),备注或者删除掉

5.安装, 在munin-mysql-master目录执行make install

6.配置MySQL,在phpmyadmin或者mysql -u root -p 下执行以下SQL

CREATE USER `munin` @`localhost` IDENTIFIED BY '0do8KxdWULQu'; #请自行把0do8KxdWULQu替换为你在mysql.conf里设置的密码
GRANT SUPER ON *.* TO `munin` @`localhost`;
GRANT PROCESS ON *.* TO `munin` @`localhost`;
CREATE DATABASE IF NOT EXISTS `munin`;
GRANT ALL PRIVILEGES ON `munin`.* TO 'munin'@'localhost';
FLUSH PRIVILEGES;

7.运行munin-run mysql,如果看到以下内容则安装成功.

multigraph mysql_bin_relay_log
Binlog_cache_disk_use.value 0
Binlog_cache_use.value 0
Binlog_stmt_cache_disk_use.value 0
Binlog_stmt_cache_use.value 0
ma_binlog_size.value 0
.....

7.重启munin-node,稍等片刻之后即可在Munin页面上看到MySQL的图表

systemctl restart munin-node

 

20160730163646

C++实现的一个Order-List有序链表 带迭代器 模板类(class)

使用方法: 在项目中导入头文件
MYLIB::OrderedList<int> lists;
MYLIB::OrderedList<double> dlists;

P.S: 迭代器有点小问题

//
// Author: Kotarou.
// Email: t.k@07.gs
// FileName: OrderedList.h
// Last modify: 28/05/2015
//

#ifndef __ORDEREDLIST_H__
#define __ORDEREDLIST_H__
#include 
namespace MYLIB
{
	template
	class OrderedList;
	
	template 
	class ListNode
	{
		friend class OrderedList;
		friend class OrderedList::iterator;
		
		private:
			T Element;
			ListNode *prev;
			ListNode *next;
		public:
			ListNode() : next(NULL), prev(NULL) {};
	};
	
	template
	class OrderedList
	{
		private:
			ListNode *head;
			ListNode *tail;
		public:
			OrderedList() : head(NULL), tail(NULL) {};
			
			~OrderedList()
			{
				// delete all elements
				ListNode *temp = NULL;
				while(head)
				{
					temp = head->next;
					delete head;
					head = temp;
				}
			};
			
			// insertion sort
			void insert(const T &Element)
			{
				ListNode *temp = new ListNode;
				temp->Element = Element;
				
				if(!head && !tail)
				{
					head = temp;
					tail = temp;
				}
				else
				{
					//if the Element smaller than head, insert it before the head
					if(temp->Element <= head->Element)
					{
						temp->next = head;
						head->prev = temp;
						head = temp;
						return;
					}
					
					//if the Element greater than tail, insert it after the tail
					if(temp->Element >= tail->Element)
					{
						temp->prev = tail;
						tail->next = temp;
						tail = temp;
						return;
					}
					
					//find a position to insert
					ListNode *cur = head;
					while(cur)
					{
						if(temp->Element <= cur->Element)
						{
							temp->prev = cur->prev;
							cur->prev->next = temp;
							temp->next = cur;
							cur->prev = temp;
							break;
						}
						
						cur = cur->next;
					}
				}
			};
			
			class iterator
			{
				private:
					ListNode *node;
					bool done;
				public:
					iterator() : node(NULL), done(false) {};
					iterator(ListNode *in) : node(in), done(false){};
					
					T& operator*() // dereference
					{ 
						return node->Element; 
					};
					
					const T& operator*() const 
					{
						return node->Element; 
					};
					
					iterator& operator++() // prefix
					{
						node = node->next;
						return *this;
					};
					
					iterator operator++(int) // postfix
					{
						iterator temp = *this;
						++(*this);
						return temp;
					};
					
					iterator& operator--() // prefix
					{
						node = node->prev;
						return *this;
					};
					
					iterator operator--(int) // postfix
					{
						iterator temp = *this;
						--(*this);
						return temp;
					};
					
					bool operator==(const iterator& x) const
					{
						return (node == x.node);
					};
					
					bool operator!=(const iterator &rv)
					{
						if((node == rv.node && node) && done)
							return false;							
						
						if(node == rv.node && node)
							done = true;
						
						return ( node );
					};
			};
			
			iterator begin()
			{
				return iterator(head);
			};
			
			iterator end() 
			{
				return iterator(tail);
			};
	};
}
#endif


在Centos 7上使用Fail2ban来保护SSH服务

使用Fail2ban来保护SSH服务,减轻暴力攻击对安全性的影响.

1.Fail2ban with FirewallD

1.从EPEL库内安装Fail2ban

yum install -y epel-release
yum install -y fail2ban fail2ban-systemd

2.关闭SeLinux(如果开启)

setenforce 0
sed -i "s/SELINUX=.*/SELINUX=disabled/" /etc/selinux/config

3.配置Fail2ban, 我们选择使用Centos 7默认防火墙 FirewallD.

创建 /etc/fail2ban/jail.d/sshd.local 文件,并写入

[sshd]
enabled = true
port = ssh
#action = firewallcmd-ipset
logpath = %(sshd_log)s
maxretry = 5
bantime = 86400

4.启用Fail2ban

systemctl enable fail2ban
systemctl start fail2ban

2.Fail2ban with iptables-services

1.从EPEL库内安装Fail2ban

yum install -y epel-release
yum install -y fail2ban fail2ban-systemd

2.关闭SeLinux(如果开启)

setenforce 0
sed -i "s/SELINUX=.*/SELINUX=disabled/" /etc/selinux/config

3.设置Fail2ban, 在这里我们使用 iptables-services

yum -y install iptables-services
systemctl mask firewalld.service
systemctl enable iptables.service
systemctl enable ip6tables.service
systemctl stop firewalld.service
systemctl start iptables.service
systemctl start ip6tables.service

4.创建 /etc/fail2ban/jail.d/sshd.local 文件,并写入

[ssh-iptables]
enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
logpath  = %(sshd_log)s
maxretry = 5
bantime = 86400

5.启用Fail2ban

systemctl enable fail2ban
systemctl start fail2ban

[C++]FCFS/RR/SJF/SRTF/RAND 调度算法模拟

一些进程调度算法的模拟.

输入参数:
./a.out 8 6 15 4

源代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
// some global value
int gMaxTimeInc, gMaxBurstTime;
int gNumProcesses, gTimeSlice;
struct Process
{
int ID;
int ArriveTime;
int WaitingTime;
int BurstTime;
int RunningTime;
int TurnAroundTime;
};
typedef deque dProcess;
void printResult(deque&, string*);
bool praseInput(int, const char**);
void getNextProcess(int&, int&);
bool isDigital(const char*);
char ganttChart(int);
dProcess generateJobQueue();
dProcess FCFS(dProcess, string&);
dProcess RR(dProcess, string&);
dProcess RAND(dProcess, string&);
dProcess SJF(dProcess, string&);
dProcess SRTF(dProcess, string&);
bool sortQueue (const Process &i,const Process &j) { return (i.ID list;
list.push_back(FCFS(Jobs,buffer[0]));
list.push_back(RR(Jobs,buffer[1]));
list.push_back(SJF(Jobs,buffer[2]));
list.push_back(SRTF(Jobs,buffer[3]));
list.push_back(RAND(Jobs,buffer[4]));
printResult(list, buffer);
}
else
{
cerr << "Invalid Argument, Try again.\n";
exit(EXIT_FAILURE);
}
return 0;
}
dProcess RAND(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for RAND.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
//make the readyqueue randomly
random_shuffle(ReadyQueue.begin(), ReadyQueue.end());
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
return EndQueue;
}
dProcess SRTF(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for SRTF.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
//sort the ready queue
sort(ReadyQueue.begin(), ReadyQueue.end(), sortForSRTF);
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
// check the ready queue.
if(!ReadyQueue.empty())
{
Process temp = ReadyQueue.front();
if(sortForSRTF(temp, *CPU))
{
ReadyQueue.push_back(*CPU);
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
}
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(), EndQueue.end(), sortQueue);
return EndQueue;
}
dProcess SJF(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for SJF.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
//sort the ready queue
sort(ReadyQueue.begin(), ReadyQueue.end(), sortForSJF);
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(), EndQueue.end(), sortQueue);
return EndQueue;
}
dProcess RR(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for FCFS.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// push process back to the readyqueue
if(CPU && CPU->RunningTime != CPU->BurstTime && CPU->RunningTime % gTimeSlice == 0)
{
ReadyQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
sort(EndQueue.begin(),EndQueue.end(),sortQueue);
return EndQueue;
}
dProcess FCFS(dProcess Jobs, string &chartBuffer)
{
unsigned long Time = 0;
bool done = false;
// get the job Queue.
dProcess ReadyQueue;
dProcess EndQueue;
Process* CPU = NULL;
//main loop for FCFS.
for(; !done; ++Time)
{
//check the job queue, move job to the ready queue
for(dProcess::iterator it = Jobs.begin(); it != Jobs.end();)
{
if(Time >= it->ArriveTime)
{
ReadyQueue.push_back(*it);
it = Jobs.erase(it);
}
else
++it;
}
// move finished process to EndQueue
if(CPU && CPU->RunningTime == CPU->BurstTime)
{
CPU->TurnAroundTime += Time;
EndQueue.push_back(*CPU);
CPU = NULL;
}
// if all job finished, set done to true, skip all code.
if(EndQueue.size() == gNumProcesses)
{
done = true;
continue;
}
// check the ReadyQueue, move the first Process into CPU
if(CPU == NULL)
{
// if nothing in readyQueue, print -
if(!ReadyQueue.empty())
{
CPU = &ReadyQueue.front();
ReadyQueue.pop_front();
}
else
{
chartBuffer += "-";
continue;
}
}
else
{
for(dProcess::iterator it = ReadyQueue.begin(); it != ReadyQueue.end(); ++it)
{
if(it->ArriveTime != Time)
++it->WaitingTime;
}
}
if(CPU->RunningTime != CPU->BurstTime)
{
++CPU->RunningTime;
chartBuffer += ganttChart(CPU->ID);
}
}
return EndQueue;
}
void getNextProcess(int &ArrivalTime, int &BurstTime)
{
static int PrevTime=-1;
if(PrevTime == -1)
PrevTime = ArrivalTime = 0;
else
ArrivalTime = PrevTime + 1 + rand() % gMaxTimeInc;
BurstTime = 1 + rand() % gMaxBurstTime;
PrevTime = ArrivalTime;
}
dProcess generateJobQueue()
{
dProcess JobQueue;
for(int i = 0; i < gNumProcesses; ++i)
{
Process temp;
temp.ID = i;
temp.WaitingTime = 0;
temp.RunningTime = 0;
getNextProcess(temp.ArriveTime, temp.BurstTime);
temp.TurnAroundTime = 0 - temp.ArriveTime;
JobQueue.push_back(temp);
}
return JobQueue;
}
bool praseInput(int num, const char **input)
{
if(num < 5)
return false;
if(isDigital(input[1]) && isDigital(input[2]) && isDigital(input[3]) && isDigital(input[4]))
{
gNumProcesses = atoi(input[1]);
gMaxTimeInc = atoi(input[2]);
gMaxBurstTime = atoi(input[3]);
gTimeSlice = atoi(input[4]);
return true;
}
return false;
}
bool isDigital(const char *num)
{
size_t len = strlen(num);
for(size_t i = 0; i < len; ++i)
{
if(!isdigit(num[i]))
return false;
}
return true;
}
char ganttChart(int index)
{
while(index >= 62)
index -= 62;
if(index >= 0 && index <= 9)
return 48 + index;
else if(index >= 10 && index <= 35)
return 55 + index;
else if(index >= 36 && index <= 61)
return 61 + index;
return 0;
}
void printResult(deque &Queue, string *ChartArray)
{
printf("%16s%11s%13s%12s%12s\n","FCFS", "RR", "SJF", "SRTF", "RAND");
printf("%8s%5s%5s%7s%5s%7s%5s%7s%5s%7s%5s\n", "BT", "WT", "TT", "WT", "TT", "WT", "TT", "WT", "TT", "WT", "TT");
int waiting[5] = {}, turn[5] = {};
dProcess dp[5];
for(int i = 0; i < 5; ++i)
{
dp[i] = Queue.front();
Queue.pop_front();
}
for(int i = 0; i < gNumProcesses; ++i)
{
printf("P%-5d", i);
Process ps;
for(int j = 0; j < 5; ++j)
{
ps = dp[j].front();
dp[j].pop_front();
waiting[j] += ps.WaitingTime;
turn[j] += ps.TurnAroundTime;
if(j == 0)
printf("%-5d", ps.BurstTime);
printf("%-5d%-7d", ps.WaitingTime, ps.TurnAroundTime);
}
printf("\n");
}
printf("%-11s", "Average:");
for(int i = 0; i < 5; ++i)
{
printf("%-5d%-7d", waiting[i] / gNumProcesses, turn[i] / gNumProcesses);
}
printf("\n\n%-6s%s\n", "FCFS:", ChartArray[0].c_str());
printf("%-6s%s\n", "RR:", ChartArray[1].c_str());
printf("%-6s%s\n", "SJF:", ChartArray[2].c_str());
printf("%-6s%s\n", "SRTF:", ChartArray[3].c_str());
printf("%-6s%s\n", "RAND:", ChartArray[4].c_str());
}

运行结果:
QQ20151008-1@2x

Centos 7更改Hostname

在把VPS上的系统升级到Centos 7之后,我尝试修改/etc/sysconfig/network来修改hostname, 但是没有用. 修改Centos 7的Hostname的方法和以前版本不同,希望本文能帮你来修改Hostname在Centos 7 / RHEL 7上.

使用hostnamectl来修改Hostname:

检查目前的Hostname

[root@vultr ~]# hostnamectl status
Static hostname: vultr.guest
Icon name: computer-vm
Chassis: vm
Machine ID: 19a12d5f5d824794a19caf165a9b3bca
Boot ID: 21c75ffe0718431d800fd8159be13d99
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-123.20.1.el7.x86_64
Architecture: x86_64

设置新的Hostname

[root@vultr ~]# hostnamectl set-hostname mysql.jzbk.org

检查当前Hostname

[root@vultr ~]# hostnamectl status
Static hostname: mysql.jzbk.org
Icon name: computer-vm
Chassis: vm
Machine ID: 19a12d5f5d824794a19caf165a9b3bca
Boot ID: 21c75ffe0718431d800fd8159be13d99
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-123.20.1.el7.x86_64
Architecture: x86_64