HTTP请求头和响应头

1,HTTP请求的基本概念    TCP/UPD/HTTP  *2,

HTTP请求头和响应头的含义 请求头: 

Accept: text/html,image/*(浏览器可以接收的类型) 

Accept-Charset: ISO-8859-1(浏览器可以接收的编码类型) 

Accept-Encoding: gzip,compress(浏览器可以接收压缩编码类型) 

Accept-Language: en-us,zh-cn(浏览器可以接收的语言和国家类型) 

Host: www.it315.org:80(浏览器请求的主机和端口)

 If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT(某个页面缓存时间) 

Referer: http://www.it315.org/index.jsp(请求来自于哪个页面) 

User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)(浏览器相关信息) 

Cookie:(浏览器暂存服务器发送的信息) 

Connection: close(1.0)/Keep-Alive(1.1)(HTTP请求的版本的特点) 

Date: Tue, 11 Jul 2000 18:23:51 GMT(请求网站的时间)  

响应头: 

Location: http://www.it315.org/index.jsp(控制浏览器显示哪个页面) 

Server:apache tomcat(服务器的类型) 

Content-Encoding: gzip(服务器发送的压缩编码方式)

 Content-Length: 80(服务器发送显示的字节码长度) 

Content-Language: zh-cn(服务器发送内容的语言和国家名) 

Content-Type: image/jpeg; charset=UTF-8(服务器发送内容的类型和编码类型)

 Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT(服务器最后一次修改的时间) 

Refresh: 1;url=http://www.it315.org(控制浏览器1秒钟后转发URL所指向的页面) 

Content-Disposition: attachment; filename=aaa.jpg(服务器控制浏览器发下载方式打开文件)

 Transfer-Encoding: chunked(服务器分块传递数据到客户端)

 Set-Cookie:SS=Q0=5Lb_nQ; path=/search(服务器发送Cookie相关的信息) 

Expires: -1(服务器控制浏览器不要缓存网页,默认是缓存) 

Cache-Control: no-cache(服务器控制浏览器不要缓存网页)

 Pragma: no-cache(服务器控制浏览器不要缓存网页)   

Connection: close/Keep-Alive(HTTP请求的版本的特点)  

 Date: Tue, 11 Jul 2000 18:23:51 GMT(响应网站的时间) 

Centos7下添加开机自启动服务和脚本

添加开机自启脚本

在centos7中增加脚本有两种常用的方法,以脚本StartTomcat.sh为例:

#!/bin/bash
# description:开机自启脚本
/usr/local/tomcat/bin/startup.sh  #启动tomcat

方法一:

1、赋予脚本可执行权限(/opt/script/StartTomcat.sh是你的脚本路径)

# chmod +x /opt/script/StartTomcat.sh

2、打开/etc/rc.d/rc.local文件,在末尾增加如下内容

echo "/opt/script/StartTomcat.sh" >> /etc/rc.d/rc.local

3、在centos7中,/etc/rc.d/rc.local的权限被降低了,所以需要执行如下命令赋予其可执行权限

chmod +x /etc/rc.d/rc.local

方法二:

1、将脚本移动到/etc/rc.d/init.d目录下

# mv  /opt/script/StartTomcat.sh /etc/rc.d/init.d

2、增加脚本的可执行权限

chmod +x  /etc/rc.d/init.d/StartTomcat.sh

3、添加脚本到开机自动启动项目中

cd /etc/rc.d/init.d
chkconfig --add StartTomcat.sh
chkconfig StartTomcat.sh on

Specified key was too long; max key length is 1000 bytes

--
-- 表的结构 `ecs_goods_activity`
--

DROP TABLE IF EXISTS `ecs_goods_activity`;
CREATE TABLE `ecs_goods_activity` (
`act_id` mediumint(8) unsigned NOT NULL auto_increment,
`act_name` varchar(255) NOT NULL,
`act_desc` text NOT NULL,
`act_type` tinyint(3) unsigned NOT NULL,
`goods_id` mediumint(8) unsigned NOT NULL,
`product_id` mediumint(8) unsigned NOT NULL default '0',
`goods_name` varchar(255) NOT NULL,
`start_time` int(10) unsigned NOT NULL,
`end_time` int(10) unsigned NOT NULL,
`is_finished` tinyint(3) unsigned NOT NULL,
`ext_info` text NOT NULL,
PRIMARY KEY (`act_id`),
KEY `act_name` (`act_name`,`act_type`,`goods_id`)
) ENGINE=MyISAM;

关于FLUSH PRIVILEGES的使用

很多人在MySQL里面乱用FLUSH PRIVILEGES,你知道吗?包括从前的我,但是FLUSH PRIVILEGES你真的知道应该在什么场合使用么?

根据官方文档的如下链接内容可知:
https://dev.mysql.com/doc/refman/5.6/en/privilege-changes.html

当mysqld启动时,所有的权限都会被加载到内存中。
如果使用GRANT/REVOKE/SET PASSWORD/RENAME USER命令来更改数据库中的权限表,mysqld服务器将会注意到这些变化并立即加载更新后的权限表至内存中,即权限生效;
如果使用INSERT/UPDATE/DELETE语句更新权限表,则内存中的权限表不会感知到数据库中权限的更新,必须重启服务器或者使用FLUSH PRIVILEGES命令使更新的权限表加载到内存中,即权限需在重启服务器或者FLUSH PRIVILEGES之后方可生效。

权限生效的含义:
1、表级别/列级别的权限,当更新后的权限加载至内存表中,已存在的会话下一次请求时可使用该权限,在修改权限后的建立的会话则立即生效;
2、数据库级别的权限,当更新后的权限加载至内存表中,已存在会话下一次使用USE db_name后,可使用该权限,在修改权限后的建立的会话则立即生效;
3、全局权限或者修改密码,当更新后的权限加载至内存表中,需要在下一次登录mysqld后,可使用该权限或密码,对已存在会话不起作用。

MySQL复制表结构和内容到另一张表

复制表结构及数据到新表 

create table 新表 select * from 旧表

只复制表结构到新表

select table 新表
select * from 旧表 where 1=2

即:让where条件不成立.

方法二:(低版本的MySQL不支持,MySQL 4.0.25不支持,MySQL 5已经支持了)

create table 新表
like 旧表 

复制旧表的数据到新表(假设两个表结构一样)

insert into 新表
select * from 旧表 

复制旧表的数据到新表(假设两个表结构不一样)

insert into 新表(字段1,字段2,…….)
select 字段1,字段2,…… from 旧表

file_exist()和is_file()哪个性能更优?

今天浏览项目代码,在项目自动加载注册的路由方法发现前辈判断拼接的控制器文件是否存在时,用的是file_exists($file),而我个人风格更偏向于is_file(),为了弄清楚两个函数哪个性能更优,查阅了官方手册和一些博客文章。

PHP手册描述如下:

file_exists检查文件或目录是否存在

is_file判断给定文件名是否为一个正常的文件

由此我们知道,在功能上file_exists=is_file+is_dir,相当于后两者的集合,既可以判断文件是否存在,又可判断目录是否存在,那么这两个都可以判断文件是否存在的函数其性能哪个占优呢?

写程序验证一下(程序见附件):

分别执行1000次,记录所需时间。

文件存在(当前目录)
is_file:0.4570ms
file_exists:2.0640ms

文件存在(绝对路径3层/www/hx/a/)
is_file:0.4909ms
file_exists:3.3500ms

文件存在(绝对路径5层/www/hx/a/b/c/)
is_file:0.4961ms
file_exists:4.2100ms

文件不存在(当前目录)
is_file:2.0170ms
file_exists:1.9848ms

文件不存在(绝对路径5层/www/hx/a/b/c/)
is_file:4.1909ms
file_exists:4.1502ms

目录存在
file_exists:2.9271ms
is_dir:0.4601ms
目录不存在
file_exists:2.9719ms
is_dir:2.9359ms

is_file($file)
file_exists($file)
当$file是目录时,is_file返回false,file_exists返回true

文件存在的情况下,is_file比file_exists要快得多;
要检测文件所在的目录越深,速度差越多,但至少快4倍。

文件不存在的情况下,is_file比file_exists要慢一点点,但可以忽略不计。

目录存在的情况下,is_dir比file_exists要快得多;
目录不存在的情况下,is_dir比file_exists要慢一点点,但可以忽略不计。

结论:
如果要判断文件是否存在,用函数 is_file(),
如果要判断目录是否存在,用函数 is_dir(),
好像没地方需要用file_exists了,不确定传入的参数是文件还是目录的时候用。

—————————————-测试代码————————————————-

function runtime($t1){
return number_format((microtime(true) – $t1)*1000, 4).’ms’;
}
$times = 1000;

$t1 = microtime(true);
for($i=0;$i<$times;$i++){
is_file(‘/www/hx/www.9enjoy.com/config.php’);
}

echo ‘<br>is_file:’.runtime($t1);

$t2 = microtime(true);
for($i=0;$i<$times;$i++){
file_exists(‘/www/hx/www.9enjoy.com/config.php’);
}
echo ‘<br>file_exists:’.runtime($t2);

/*
$t3 = microtime(true);
for($i=0;$i<$times;$i++){
is_dir(‘/www/hx/www.9enjoy.com/’);
}
echo ‘<br>is_dir:’.runtime($t3);
*/

in_array()踩坑记录

前几天写api,前端发过来的参数约定是数字1-3,按照开发文档,我写了如下代码,

if (!in_array($param, range(0, 3))) {
    $vo['error_code'] = 101;
    return $vo;
}

后来自己单元测试,发现发送模拟参数’1abc’和’abc’,居然没返回错误码(报错),经查阅PHP手册,得知该函数还有第三个参数,是否进行参数类型比较,默认为FALSE,这就导致字符串’1abc’在和整型int比较时,由于PHP是弱类型语言,会发生隐式类型转换,所以这里’1abc’转换为’1’,同理‘abc’转换为字符串类型’0’,从而返回true;

要避免这个坑,有以下两个方法

1.自行进行强制类型验证

if (!is_int($param) || !in_array($param, range(0, 3))) {
    $vo['error_code'] = 101;
    return $vo;
}

2.填充in_array()第三个参数为True,函数内部则会进一步检查类型是否相同

if (!in_array($param, range(1, 3),True)) {
    $vo['error_code'] = 101;
    return $vo;
}

 

PHP call_user_func_array 用法解释

主要用在函数名不确定,参数不确定的情况下,它体现了一种通过传递不同参数来调用不同方法的思想

1.直接调用方法

function say($word){
echo $word;
}
call_user_func_array(‘say’,array(‘Hello PHP’));
/*第一个参数为要调用的方法名,字符串形式,第二个参数为要传给方法的参数,数组形式*/
/*
*这如果say()方法不存在,通过call_user_func_array调用后只会返回false,
*而如果采用直接调用的形式:say(),则会直接报错
*/
2.调用对象中的方法

class S{
public function __construct(){

}
public static function say1($word){
echo $word;
}
public function say($word){
echo $word;
}
}
/*使用方式一:无需实例化调用类的静态方法*/
call_user_func_array(array(‘S’,’say1′),array(‘Hello PHP’));

/*使用方式二:不实例化调用类的非静态方法*/
call_user_func_array(array(‘S’,’say2′),array(‘Hello PHP’));
/*这里不会对自动实例化类,如果调用的方法中有$this语句,会报错,一般不这么用*/

/*使用方式三:实例化后调用类的非静态方法*/
$s = new S();

call_user_func_array(array($s,’say2′),array(‘Hello PHP’));
call_user_func_array(array(&$s,’say2′),array(‘Hello PHP’));/*&这个符号有或没有貌似没差别*/
call_user_func_array(array(new S(),’say2′),array(‘Hello PHP’));

[转载]缓存系列文章(三)缓存常用更新策略对比(一致性)。

转载出处:http://carlosfu.iteye.com/blog/2269678

 一、缓存的几种更新策略

 

从下面的表格看,缓存的更新策略大致分为三种,本文将从一致性和维护成本两个方面对于三种缓存更新策略进行简要说明,因为这些东西比较理论和抽象,如哪里说得不对,欢迎拍砖。

 

注:

(1) 一致性:缓存和真实数据源(例如mysql, hbase, elasticsearch等等)是否存在一段时间数据的不一致。

(2) 维护成本: 开发人员的开发和维护成本。

策略 一致性 维护成本
LRU/LIRS/FIFO算法剔除 最差
超时剔除 较差 较低
主动更新

 

二、LRU/LFU/FIFO算法剔除

 

1. 使用场景:

通常用于缓存使用量超过了预设的最大值时候(缓存空间不够),如何对现有的数据进行清理。例如FIFO会把最新进入缓存的数据清理出去, LRU会把最近最少使用的数据清理掉。

例如:Memcache使用的是LRU,具体Memcache如何实现的,这里就不在赘述了,网上资料多的是。

例如:Redis使用maxmemory-policy这个配置作为内存最大值后对于数据的更新策略。

配置名 含义 默认值
maxmemory 最大可用内存 不使用该配置,也就对内存使用无限制
maxmemory-policy 内存不够时,淘汰策略 volatile-lru
  • volatile-lru -> 用lru算法删除过期的键值
  • allkeys-lru -> 用lru算法删除所有键值
  • volatile-random -> 随机删除过期的键值
  • allkeys-random -> 随机删除任何键值
  • volatile-ttl -> 删除最近要到期的键值
  • noeviction -> 不删除键,只返回一个错误

 

2. 常用算法:

这里不再赘述,常用的算法有如下几种:

FIFO[first in first out]

LFU[Less Frequently Used]

LRU[Least Recently used]

 

 

3. 一致性

可以想象,要清理哪些数据,不是由开发者决定(只能决定大致方向:策略算法),数据的一致性是最差的。

 

4. 维护成本

这些算法不需要开发者自己来实现,通常只需要配置最大maxmemory和对应的策略即可。

开发者只需要有这个东西,知道是什么意思,选择自己需要的算法,算法的实现是由缓存服务器实现的。

 

 

三、超时剔除

 

1. 使用场景:

   就是我们通常做的缓存数据过期时间设置,例如redis和memcache都提供了expire这样的API,来设置K-V的过期时间。

一般来说业务可以容忍一段时间内(例如一个小时),缓存数据和真实数据(例如:mysql, hbase等等)数据不一致(一般来说,缓存可以提高访问速度降低后端负载),那么我们可以对一个数据设置一定时间的过期时间,在数据过期后,再从真实数据源获取数据,重新放到缓存中,继续设置过期时间。

例如: 一个视频的描述信息,我们可以容忍一个小时内数据不一致,但是涉及到钱的方面,如果不一致可想而知。

   

2. 一致性:

    一段时间内(取决于过期时间)存在数据一致性问题,即缓存数据和真实数据源数据不一致。

 

3. 维护成本

      用户的维护成本不是很高,只需要设置expire过期时间即可(前提是你的业务允许这段时间可能发生的数据不一致)。

 

四、主动更新

 

1. 使用背景:

   业务对于数据的一致性要求很高,需要在真实数据更新后,立即更新缓存数据。

具体做法:例如可以利用消息系统或者其他方式(比如数据库触发器,或者其他数据源的listener机制来完成)通知缓存更新。

 

2.  一致性:

   可以想象一致性最高(几乎接近强一致),但是有个问题:如果主动更新发生了问题,那么这条数据很可能很长时间不会更新了(所以可以结合超时剔除一起使用,下面最佳实践会说到)

 

3. 维护成本:

相当高,用户需要自己来完成更新(需要一定量的代码,从某种程度上加大了系统的复杂性),需要自己检查数据是否真的更新了之类的工作。

 

五、最佳实践

    其实最佳实践就是组合使用:

1. 一般来说我们都需要配置超过最大缓存后的更新策略(例如:LRU)以及最大内存,这样可以保证系统可以继续运行(例如redis可能存在OOM问题)(极端情况下除外,数据一致性要求极高)。

2. 一般来说我们需要把超时剔除和主动更新组合使用,那样即使主动更新出了问题,也能保证过期时间后,缓存就被清除了(不至于永远都是脏数据)。