Monthly Archives: January 2015

通过shell脚本在服务器上一键构建java应用并重新部署

1. 把代码从github等托管服务器上更新下来

2. 编译成war文件

3. 重启tomcat

第一次使用时,先手动地把代码拉到一个固定的目录中

cd /home/me/myappsite/code
git clone https://someuser@somesite/myapp.git

一键脚本:build-my.sh

#!/bin/sh
echo "pull and build"
cd /home/me/myappsite/code/myapp
git pull
mvn clean
mvn package -DskipTests

echo "shutting down the tomcat"
kill $(ps aux | grep 'java' | grep 'mytomcat'| awk '{print $2}')  #不要用shutdown.sh;这里需要同步杀死进程,shutdown.sh做不到同步杀

echo "clean existing war files and copy the new one"
rm -rf /home/me/mytomcat/webapps/ROOT  
cp /home/me/myappsite/code/myapp/target/myapp-x.x.war /home/me/myappsite/war/myapp.war   #tomcat的server.xml里请把root context path指向这个文件


echo "now start tomcat"
/home/me/mytomcat/bin/startup.sh

echo "get back"
cd /home/me




一个典型的centos + apache httpd + tomcat的配置

典型的java网站: 用centos做操作系统,用tomcat提供服务,用apache httpd做反向代理

apache httpd配置

引用

#一个IP多个域名

NameVirtualHost *:80

#禁止直接使用ip访问

<VirtualHost *:80>

        ServerName 11.11.11.11

        <Location />

           Order deny,allow

            Deny from all

        </Location>

</VirtualHost>

#顶级域名跳转到www域名

<VirtualHost *:80>

    ServerName my.com

    RewriteEngine on

    RewriteCond %{http_host} ^my.com [NC]

    RewriteRule ^(.*)$ http://www.my.com/$1 [L,R=301]

</VirtualHost>

#把对apache的访问指向tomcat

<VirtualHost *:80>

    ServerName www.my.com

    ProxyPass / http://localhost:8080/

    ProxyPassReverse / http://localhost:8080/

</VirtualHost>

tomcat配置(server.xml)

引用

<!–修改proxyName和proxyPort, 使得request.getServerName()和request.getServerPort()方法拿到的是用户请求的域名和端口–>

    <Connector port="8080" protocol="HTTP/1.1"

               connectionTimeout="20000"

               redirectPort="8443"

               proxyName="www.my.com"
               proxyPort="80"  
           

               />

注:这里的tomcat应用的contextPath是"/", 实际上也最好只有"/",而不是其它。否则当tomcat应用里执行  "redirect:/" 时会绕过httpd反向代理,除非你使用mod_proxy_html插件。

ec2中搭建服务后要编辑一下security group才能让外网访问

在aws ec2中搭建apache httpd或tomcat后,发现使用ec2 instance的public ip在浏览器里访问相关服务时失败。

这是因为防火墙未设置。对ec2来说,security group就相当于防火墙。

设置办法: 进入instance列表,在security group列中找到对应的group, 点击它,然后Actions => Edit Inbound Rules, 加入http, 即可允许80端口访问。

如果要打开8080的http端口,新增一个custom tcp rule.

innodb: 两个事务在binlog文件中不会交叉

在innodb的binlog文件中,如果一个事务从第m行开始,在第n行结束;那么从m到n之间只会记录本事务的操作,不会记录其他事务的行为。

这是因为innodb中binary log entries总是以事务为单位整体写入文件的。

引用

Within an uncommitted transaction, all updates (UPDATE, DELETE, or INSERT) that change transactional tables such as BDB or InnoDB tables are cached until a COMMIT statement is received by the server. At that point, mysqld writes the entire transaction to the binary log before the COMMIT is executed.

推论:

1. 只有事务完成了,相关记录才会进入binlog文件

2. 一个写事务不应该太长,否则当它被整体写入binlog文件时,会长时间占用binlog,导致其他事务在这段时间内无法写入binlog,因而无法提交,最终影响并发性能。

对InnoDb执行mysqldump时应该加上 –single-transaction参数

mysqldump默认情况下并不保证数据一致性。 在innodb中,可以这样:

mysqldump  --single-transaction mydb > mydb-backup.sql

如果有 –single-transaction参数,mysqldump会将整个数据的读取过程置于一个满足repeatable read的事务中,最后导出的数据也是相互一致的。

由于innodb的mvcc特性,使用 –single-transaction执行mysqldump, 不会阻塞其他进程的读写。

MySQL两种备份模式:Logical Backup 和 Raw Backup

Logical Backup 就是用诸如mysqldump这样的工具把数据导出为可视的sql文件或csv文件

Raw Backup 则是指直接备份数据库的数据文件

Raw Backup执行起来比Logical Backup快的多,因为它不需要消耗CPU/内存把数据变成sql或csv(顺便说一下,变csv比变sql要快很多)。

但Raw Backup有一个缺点:Raw File的跨平台能力比较弱。 一个windows下的文件在linux下可能就用不了,一个从mysql 5.1导出的文件可能无法被mysql 5.5识别。

Raw Backup还有一个严重的缺点: 如果Raw File是一个Corrupted File, 复制后产生的备份仍是一个Corrupted File; 这个备份就没有作用,因为你没法利用它来恢复数据。

innodb的binlog跟redo/undo log无关

mysql, 不管用的是不是innodb, 都有binlog. 这个binary log跟transaction没关系,它主要用于replication和backup. log文件会一直递增,不会循环使用(后面的记录不会覆盖前面的)

同时,innodb还有redo log/undo log. 它们用于transaction, 且会循环使用。

innodb中应该尽量把多条语句放在单个事务中执行

默认情况下,一个写操作就是一次事务

如果一次业务操作包含三次DB写操作,三个写操作就是三个事务,三个事务导致三次log flush(磁盘读写,代价较高):

引用
InnoDB must flush the log to disk at each transaction commit if that transaction made modifications to the database.

所以应该把这三次DB写操作合在一个事务里,这样只需要做一次flush disk。

MySQL Replication的基本架构

摘自High Performance MySQL

复制过程的核心是binlog

拓扑方面:

1. 一主一备最常见,可满足典型的读写分离需求

2. 一主多备也可以,但要注意备机太多可能导致主机负担过大。有个办法是主机只挂一个特殊的备机,其他备机再从这个特殊备机中同步数据(即把特殊备机当作主机),把主机的同步负担转移到特殊备机上。这个策略叫distribution master

3. 你可能会想用主主双活(Master-Master in Active-Active Mode)来同时分担读负担和写负担,即两台机分别是对方的备机,每台机都可以读和写,并互相数据同步。但这样做在数据一致性方面的问题非常多,严重不推荐。比如说,数据同步失效了,但两台机仍在提供写服务,怎么办?数据肯定不一致了。

4. 比较受推荐的模式是主主轮活(Master-Master in Active-Passive Mode),即在某一时刻总是一主一备,但必要时可以立即互换主备角色。这种模式在可用性方面(即无当机时间)很有帮助。比如,alter table可能会比较久,造成数据库不可用;但在主主轮活模式下,可以先去备机alter table, 然后切换一下角色,让原备机变成新主机提供服务,让原主机以新备机的角色同步alter table行为。这个过程中不会有down time.