Web开发从入门到放弃
1. Linux入门
1.1. 初始化
1.1.1. 测试环境(aliyun)
- 入门
- ECS
- RDS
- SLB
- NAS
-
- 创建VPC(192.168.0.0/16)
- 创建交换机(192.168.0.0/24)
- 交换机上创建ECS实例(购买ECS界面不要勾选弹性公网IP)
- 停止ECS实例
- 修改私网IP
- 申请弹性公网IP
- 绑定弹性公网IP
- 绑定域名(例如:zkbc.ddshell.com)
-
root@zkbc.ddshell.com
rpm -q --qf %{version} centos-release cat /etc/issue cat /etc/redhat-release cat /proc/version uname -r uname -a
-
格式化和挂载数据盘
-
DDOS/CC攻击
1.1.2. sudo配置
-
root@zkbc.ddshell.com
useradd zkbc passwd zkbc # 也可以使用visudo命令编辑全局配置 cat << EOF >/etc/sudoers.d/zkbc zkbc ALL=(ALL) ALL Defaults:zkbc !requiretty Defaults:zkbc timestamp_timeout=5,runaspw EOF
1.1.3. 免密登录
-
localhost
ssh-keygen # Linux系统可直接执行 ssh-copy-id zkbc@zkbc.ddshell.com cat ~/.ssh/id_zkbc.pub | ssh zkbc@zkbc.ddshell.com 'mkdir -p .ssh && cat - >> ~/.ssh/authorized_keys'
-
zkbc@zkbc.ddshell.com
#备份sshd配置文件 sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # 修改默认端口22为28317 sudo sed -i 's/#Port 22/Port 28317/' /etc/ssh/sshd_config # 开启端口转发 sudo sed -i 's/#GatewayPorts no/GatewayPorts yes/' /etc/ssh/sshd_config # 如果客户端公钥是通过ssh-copy-id命令上传的则无需执行 sudo chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh/ # 重启sshd服务 sudo service sshd restart
-
localhost
ssh -p28317 zkbc@zkbc.ddshell.com
1.2. SSH隧道
1.2.1. 反向代理
ssh -f -N -R 8888:localhost:9080 zkbc@zkbc.ddshell.com
1.2.2. 正向代理(翻墙)
ssh -f -N -D 0.0.0.0:7070 root@zkbc.ddshell.com
1.2.3. 穿内网
ssh -f -N -L 3307:192.168.0.101:3306 zkbc@zkbc.ddshell.com
mysql -h127.0.0.1 -P3307 -u -p
1.2.4. 压缩
-
localhost
mysqldump -uzkbc -pzkbc zkbc | ssh -C zkbc@zkbc.ddshell.com “mysql -uzkbc -pzkbc zkbc”
1.3. 程序部署
1.3.1. yum
-
更新为163源 (aliyun ECS有自己的源,不需要更新)
sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup wget http://mirrors.163.com/.help/CentOS6-Base-163.repo -O ~/CentOS6-Base-163.repo sudo mv ~/CentOS6-Base-163.repo /etc/yum.repos.d/
-
缓存安装包
sudo sed -i 's/keepcache=0/keepcache=1/' /etc/yum.conf
1.3.2. server-jre
-
安装 server-jre
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u91-b14/server-jre-8u91-linux-x64.tar.gz tar -xvf server-jre-8u91-linux-x64.tar.gz sudo mkdir /opt/java sudo mv jdk1.8.0_91 /opt/java/
-
jstack
/opt/java/jdk1.8.0_91/bin/jstack -l pid > ~/app.stack.txt
-
jmap
/opt/java/jdk1.8.0_91/bin/jmap -dump:format=b,file=~/app.heap.bin pid
-
jstatd & jvisualvm & jconsole
cat << EOF > ~/jstatd.all.policy grant codebase "file:${java.home}/../lib/tools.jar" { permission java.security.AllPermission; }; EOF nohup /opt/java/jdk1.8.0_91/bin/jstatd -J-Djava.security.policy=~/jstatd.all.policy -J-Djava.rmi.server.hostname=192.168.0.23 &
1.3.3. tomcat
-
安装 tomcat
wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.69/bin/apache-tomcat-7.0.69.tar.gz tar -xvf apache-tomcat-7.0.69.tar.gz sudo mkdir /opt/tomcat sudo mv apache-tomcat-7.0.69 /opt/tomcat/
-
安装 apr
sudo yum -y install gcc make apr-devel openssl-devel tar -xvzf /opt/tomcat/apache-tomcat-7.0.69/bin/tomcat-native.tar.gz -C /tmp cd /tmp/tomcat-native-1.1.33-src/jni/native ./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/opt/java/jdk1.8.0_91 make sudo make install cd ~
-
部署应用实例
sudo mkdir /opt/zkbc sudo chown -R zkbc /opt/zkbc cp -R /opt/tomcat/apache-tomcat-7.0.69 /opt/zkbc/app rm -rf /opt/zkbc/app/bin/* /opt/zkbc/app/lib/* /opt/zkbc/app/webapps/*
-
添加jdbc驱动
wget -T100 https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar mv mysql-connector-java-5.1.38.jar /opt/zkbc/app/lib/
-
修改应用实例最大线程数
sed -i '/Connector port="8080" protocol/{ n; n; s/"8443"/& \ acceptorThreadCount="2" \ acceptCount="1000" \ maxThreads="1000" \ URIEncoding="UTF-8"/; }' /opt/zkbc/app/conf/server.xml
-
修改日志配置
sed -i 's/<Context>/<Context swallowOutput="true">/' /opt/zkbc/app/conf/context.xml
-
/opt/zkbc/app/lib/log4j.properties
log4j.rootLogger = INFO, CATALINA # Define all the appenders log4j.appender.CATALINA = org.apache.log4j.DailyRollingFileAppender log4j.appender.CATALINA.File = ${catalina.base}/logs/catalina log4j.appender.CATALINA.Append = true log4j.appender.CATALINA.Encoding = UTF-8 # Roll-over the log once per day log4j.appender.CATALINA.DatePattern = '.'yyyy-MM-dd'.log' log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n log4j.appender.LOCALHOST = org.apache.log4j.DailyRollingFileAppender log4j.appender.LOCALHOST.File = ${catalina.base}/logs/localhost log4j.appender.LOCALHOST.Append = true log4j.appender.LOCALHOST.Encoding = UTF-8 log4j.appender.LOCALHOST.DatePattern = '.'yyyy-MM-dd'.log' log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n log4j.appender.MANAGER = org.apache.log4j.DailyRollingFileAppender log4j.appender.MANAGER.File = ${catalina.base}/logs/manager log4j.appender.MANAGER.Append = true log4j.appender.MANAGER.Encoding = UTF-8 log4j.appender.MANAGER.DatePattern = '.'yyyy-MM-dd'.log' log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n log4j.appender.HOST-MANAGER = org.apache.log4j.DailyRollingFileAppender log4j.appender.HOST-MANAGER.File = ${catalina.base}/logs/host-manager log4j.appender.HOST-MANAGER.Append = true log4j.appender.HOST-MANAGER.Encoding = UTF-8 log4j.appender.HOST-MANAGER.DatePattern = '.'yyyy-MM-dd'.log' log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Encoding = UTF-8 log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n # Configure which loggers log to which appenders log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost] = INFO, LOCALHOST log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager] =\ INFO, MANAGER log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager] =\ INFO, HOST-MANAGER
-
添加日志相关jar
wget -T100 https://repo1.maven.org/maven2/log4j/log4j/1.2.17/log4j-1.2.17.jar mv log4j-1.2.17.jar /opt/zkbc/app/lib/ wget -T100 http://www.apache.org/dist/tomcat/tomcat-7/v7.0.69/bin/extras/tomcat-juli.jar mv tomcat-juli.jar /opt/zkbc/app/bin/ wget -T100 http://www.apache.org/dist/tomcat/tomcat-7/v7.0.69/bin/extras/tomcat-juli-adapters.jar mv tomcat-juli-adapters.jar /opt/zkbc/app/lib/
-
删除原日志配置
rm -rf /opt/zkbc/app/conf/logging.properties
-
创建应用启动脚本
vi /opt/zkbc/app/bin/app-start.sh chmod +x /opt/zkbc/app/bin/*.sh
-
/opt/zkbc/app/bin/app-start.sh
#!/bin/sh JAVA_HOME=/opt/java/jdk1.8.0_91 JAVA_OPTS="-server -Xms1024M -Xmx1024M -Xss512k -XX:LargePageSizeInBytes=128m -XX:MaxTenuringThreshold=15 -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/zkbc/app.dump.bin -Djava.awt.headless=true" PRGDIR=`dirname "$0"` CATALINA_HOME=/opt/tomcat/apache-tomcat-7.0.69 CATALINA_BASE=`cd "$PRGDIR/.." >/dev/null; pwd` CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib" export JAVA_HOME JAVA_OPTS CATALINA_HOME CATALINA_BASE CATALINA_OPTS "$CATALINA_HOME"/bin/startup.sh
-
部署应用(模拟)
cp -R /opt/tomcat/apache-tomcat-7.0.69/webapps/ROOT /opt/zkbc/app/webapps
-
启动应用
/opt/zkbc/app/bin/app-start.sh
-
验证apr是否安装成功
grep APR /opt/zkbc/app/logs/catalina
1.3.4. mysql
-
安装
rpm -Uvh http://repo.mysql.com//mysql57-community-release-el6-8.noarch.rpm sudo yum clean metadata sudo yum makecache sudo yum update -y sudo yum install -y mysql-community-server
1.3.5. nginx
-
源码安装
wget http://nginx.org/download/nginx-1.10.0.tar.gz tar -xvf nginx-1.10.0.tar.gz wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz tar -xvf ngx_cache_purge-2.3.tar.gz groupadd -r nginx adduser -r -d /var/cache/nginx -s /sbin/nologin -g nginx nginx yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel PRGDIR=`pwd` cd nginx-1.10.0 ./configure \ --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --modules-path=/usr/lib/nginx/modules \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --pid-path=/run/nginx.pid \ --lock-path=/run/nginx.lock \ --http-client-body-temp-path=/var/cache/nginx/client_temp \ --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ --user=nginx \ --group=nginx \ --with-http_ssl_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_stub_status_module \ --with-http_auth_request_module \ --with-threads \ --with-stream \ --with-stream_ssl_module \ --with-http_slice_module \ --with-mail \ --with-mail_ssl_module \ --with-file-aio \ --with-http_v2_module \ --with-ipv6 \ --add-module=$PRGDIR/ngx_cache_purge-2.3 make sudo make install rm -rf /etc/nginx/html/ mkdir -p /etc/nginx/conf.d/ /usr/share/nginx/html/ install -m644 html/index.html /usr/share/nginx/html/ install -m644 html/50x.html /usr/share/nginx/html/
-
/etc/nginx/nginx.conf
user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } }
-
/etc/nginx/conf.d/app.ddshell.com.conf
proxy_cache_path /tmp/nginx_cache/cache2 levels=1:2 keys_zone=tmpcache:10m max_size=10g inactive=60m use_temp_path=off; add_header X-Cache $upstream_cache_status; upstream app { server 192.168.0.100:80; server zkbc.ddshell.com:80; } server { listen 80; server_name app.ddshell.com; access_log /var/log/nginx/app.access.log main; location ~ .(jpg|png|gif|css|js)$ { proxy_pass http://app; proxy_redirect off; proxy_set_header Host $host; proxy_cache tmpcache; proxy_cache_key $host$uri$is_args$args; proxy_cache_valid 200 304 10m; proxy_cache_valid 200 302 1h; proxy_cache_valid 301 1d; proxy_cache_valid any 1m; expires 30d; } location / { proxy_pass http://app; proxy_set_header Host $host; proxy_set_header Remote_Addr $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cookie_path / /; proxy_set_header Cookie $http_cookie; proxy_cache tmpcache; proxy_cache_key $uri$is_args$args; proxy_cache_purge PURGE from 127.0.0.1; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; } }
-
日志切割(/etc/logrotate.d/nginx)
/var/log/nginx/*log { create 0644 nginx nginx daily rotate 10 missingok notifempty compress sharedscripts postrotate /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true endscript }
-
静态缓存
- 故障转移
- 负载均衡
- https
1.3.6. nfs
-
安装服务 rpm -qa | grep "rpcbind" sudo yum -y install nfs-utils rpcbind
-
开机启动
chkconfig nfs on chkconfig rpcbind on
-
创建共享目录
mkdir -p /opt/zkbc/var/fs APP_SERVER=192.168.0.100 CORE_SERVER=192.168.0.101 cat << EOF >> ~/exports /opt/zkbc/var/fs $CORE_SERVER(rw,async,no_root_squash,no_subtree_check) /opt/zkbc/var/fs $MGT_SERVER(rw,async,no_root_squash,no_subtree_check) EOF sudo mv ~/exports /etc/
1.4. 日志分析
1.4.1. grep & cut & sort & uniq & wc & sed & awk
-
每秒访问数
cut -d ' ' -f 4 /opt/zkbc/app/logs/localhost_access_log.2016-05-11.txt|sort|uniq -c
-
每分访问数
cut -d : -f 2-3 /opt/zkbc/app/logs/localhost_access_log.2016-05-11.txt|sort|uniq -c
-
流量统计
sed -n 's/.*2016:\([^ ]*\) .* 200 \([0-9]*\)$/\1 \2/p' /opt/zkbc/app/logs/localhost_access_log.2016-05-11.txt | awk '{total[$1]+=$2}END{for(t in total)printf("%s %.4fM\n", t,total[t]/1024/1024)}'|sort -k2
1.5. 脚本样例
1.5.1. 应用健康检查
-
/home/zkbc/monitor.sh
#!/bin/sh CHKINTERVAL=60 touch /opt/zkbc/core/webapps/ROOT/check.html while true do CODE=`curl -o /dev/null --connect-timeout 30 --max-time 30 -s -w %{http_code} http://localhost:12080/check.html` if [ ${CODE} -ne 200 ] then CORE_PID=`ps -ef|grep "zkbc/core"|grep -v grep|awk '{print $2}'` /opt/java/jdk1.8.0_91/bin/jstack -l $CORE_PID > ~/core.stack.txt fi sleep ${CHKINTERVAL} done
-
后台运行脚本
nohup /home/zkbc/monitor.sh &
2. Java Web基础
2.1. gradle
2.2. springmvc
2.3. shiro
2.4. mybatis
2.5. slf4j/logback/log4j2
2.6. js/css/html
2.7. 微信端开发
2.8. jpda
3. Java Web进阶
3.1. spring-data-jpa
3.2. spring-data-redis
-
安装配置redis sudo groupadd -r redis sudo adduser -r -s /sbin/nologin -g redis redis mkdir -p /opt/redis/db chown -R redis:redis /opt/redis cd ~ wget http://download.redis.io/releases/redis-3.2.2.tar.gz tar -xzvf redis-3.2.2.tar.gz cd redis-3.2.2 make sudo make install sudo mkdir -p /usr/local/etc/redis sudo cp redis.conf /usr/local/etc/redis/ ipaddr=`ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -E '^(192|172|10)\.'` sudo sed -i "s/bind 127.0.0.1/bind 127.0.0.1 $ipaddr/" /usr/local/etc/redis/redis.conf nohup redis-server /usr/local/etc/redis/redis.conf &