Develop Manual

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 64

开发记录
卷一
Dolphin
Copyright c
2017 Xiaoqiang Jiang
EDITED BY XIAOQIANG JIANG
http://jiangxiaoqiang.github.com/
All Rights Reserved.
Version 20:52, May 25, 2018
Contents
ITool
1Widgets ..................................................... 3
1.1 ssh(Secure Shell) 3
1.1.1 安全 ........................................................... 3
1.1.2 ssh 连接慢 (ConnectSlow) ........................................ 4
1.1.3 ssh 连接自动断开 ................................................. 5
1.1.4 Permission denied (publickey) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.5 Session 时间 .................................................... 6
1.1.6 代理转发 ....................................................... 7
1.1.7 ssh 查看日志 .................................................... 8
1.2 VisualVM 9
1.3 Tool Set 9
1.3.1 ECS(Elastic Compute Service) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.3.2 shadowsocks ................................................... 9
1.3.3 youtube-dl ..................................................... 9
1.3.4 Jenkins ....................................................... 10
1.3.5 OpenVPN ..................................................... 14
1.3.6 fastDFS ....................................................... 19
1.4 Nginx 19
1.4.1 X-Forwarded-For ............................................... 19
1.4.2 Nginx 获取真实 IP ............................................... 20
1.4.3 Nginx 并发 (Nginx Concurrent) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.4.4 URI 长度限制 ................................................... 24
1.4.5 开启 Gzip 压缩 ................................................. 25
1.4.6 Nginx 与爬虫 (Nginx Anti-Spider) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.4.7 Nginx 配置 .................................................... 26
1.4.8 负载均衡 (LoadBalance) ........................................ 27
1.4.9 阻止请求 ...................................................... 28
1.4.10 超时转发 ...................................................... 28
1.4.11 配置静态服务 ................................................... 28
1.4.12 指定首页 ...................................................... 29
1.4.13 常见问题 ...................................................... 29
2Gradle ..................................................... 33
2.1 基础 33
2.1.1 Wrapper ...................................................... 34
2.1.2 引用本地文件 ................................................... 34
2.1.3 Gradle Properties 支持 .......................................... 35
2.1.4 执行流程 ...................................................... 35
2.1.5 默认 JVM...................................................... 35
2.1.6 Repositories ................................................... 36
2.1.7 常见问题 ...................................................... 38
2.2 Gradle 对象 39
2.2.1 属性 (Properties) ............................................... 39
2.2.2 Task .......................................................... 40
II DB
3MariaDB .................................................... 45
3.1 常用操作 45
3.1.1 导入导出 ...................................................... 45
3.2 常见问题 46
3.2.1 mariadb 1045 (28000): Access denied for user ’root’@’localhost’ (using
password:YES) ................................................ 46
III 书籍记录应用
4DB .......................................................... 51
4.1 51
Bibliography ............................................... 53
Books 53
Articles 53
9
这里记录的是一些比较杂乱的笔记,绝大多数文字皆来源于网络,不是自己
的原创,这里没有高深的算法,没有宏伟的技术及系统架构,只是一些平时工作中
遇到的一些问题,和解决问题的思路以及所采用的方案。由于平时工作时还没有
遇到前人没有遇到过的问题需要自己发明方去解决 (其实真的遇到估计也是没辙)
所以绝大部分内容是为了避免再遇到同样的问题时,又需要到处去搜寻,索性将
之记录下来,以便于下次可以快刀斩乱麻,迅速解决问题。
I
1Widgets ............................ 3
1.1 ssh(Secure Shell)
1.2 VisualVM
1.3 Tool Set
1.4 Nginx
2Gradle ............................ 33
2.1 基础
2.2 Gradle 对象
Tool
1. Widgets
1.1 ssh(Secure Shell)
关闭不活动的 ssh ,使用 w命令来识别出不活动或者是空闲的 ssh 会话,
使用 pstree 命令来获取空闲会话的 PID,就是使用 kill 命令来关闭会话了。
1.1.1 安全
修改默认端口 (Change Default Port)
修改默认端口无法阻止专业的攻,因为修改 ssh 默认端口后,使用 nmap 工具
一样以识别出OpenSSH .但是修改认端为随机端后有点好处就
是可以避免被脚本自动扫描到来尝试登录 (爆破).
免密登陆 (Login Without Password)
SSH 服务如果在公网上,非常容易受到攻击,特别是弱口令扫描,字典扫描。
保护服务器免受攻击,可以使用 SSH 密钥,禁用口令认证,如果不能做到这一点,
务必使用强壮的密码。还可以设置登陆 IP 白名单。更改服务器 ssh 端口 (基本上没
有效果,调整了之后可以使用 nmap 轻松扫描到)使用 snortossec 等开源的入侵
检测设备保护服务器。免密登录需要注意的是,.ssh 文件夹下的 authorize_key 文件
的权限需要是 600。而.ssh 文件夹的权限需要是 700。调整/etc/ssh/sshd_config 配置
文件:
 
1RSAAuthentication yes
2PubkeyAuthentication yes
4Chapter 1. Widgets
3AuthorizedKeysFile .ssh/authorized_keys
 
拷贝公钥到服务器:
 
1ssh -p 22 pi@192.168.31.25 ’mkdir -p .ssh && cat >> .
ssh/authorized_keys’ < ~/.ssh/id_rsa.pub
2#如果本地没有生成过 ssh key
3#使用如下命令生成 ssh key
4ssh-keygen -t rsa -C "a@gmail.com"
 
调整文件夹权限:
 
1chmod 700 ~/.ssh
2chmod 600 ~/.ssh/authorized_keys
 
Mac OS X 中,有时自动登陆需要反复输入密码,解决问题的方法是可以配
Serria 记住密码:
 
1usekeychain yes
 
有时在 Ubuntu 下使用 ssh 也需要输入密码 (Enter passphrase for key id_rsa),
时也可以使用 keychain:
 
1#安装 keychain
2sudo apt install keychain
3/usr/bin/keychain ~/.ssh/id_rsa
 
keychain 会起一个 ssh-agent,后来登录的人通过设置环境变量使用同一个 ssh-
agent. 登录 Shell 时启动 keychain:
 
1#启动 keychain
2eval ‘keychain --eval id_rsa‘
 
1.1.2 ssh 连接慢 (Connect Slow)
在使SSH 时,每次连接建立都相当的慢啊,20 秒以上才能够登录上去,
严重影响工作效率。在服务端的/etc/ssh/sshd_config 文件中,修改配置,GSSAPI-
Authentication 默认设置为关闭即可,配置文件修改后需要重新启动 sshd 守护进程
配置才能够生效:
1.1 ssh(Secure Shell) 5
 
1GSSAPIAuthentication no
2#重启 sshd 守护进程
3sudo service sshd restart
 
GSSAPI ( Generic Security Services Application Programming Interface) 是一套
类似 Kerberos 5 的通网络系统口。该接对各同的户端
安全机制的封装,以消除安全接口的不同,降低编程难度。但该接口在目标机器
无域名解析时会有问题。使用 strace 查看后发现ssh key 后,
authentication gssapi-with-mic此时先去连接 DNS 服务器,在这之后会进行其他操
作。连接慢也可以关闭 DNS 反向解析,在 linux 中,默认就是开启了 SSH 的反向
DNS 解析,这个会消耗大量时间,因此需要关闭 [1]
 
1UseDNS=no
 
1.1.3 ssh 连接自动断开
ssh 连接总是自动断开,如果服务端没有权限配置,或者无法配置,可以配置
客户端 ssh,使客户端发起的所有会话都保持连接,客户端配置:
 
1#客户端主动向服务端请求响应的间隔
2ServerAliveInterval 60
3ServerAliveCountMax 60
 
本地 ssh 每隔 30s server sshd 发送 keep-alive 包,如果发送 60 次,server
无回应断开连接。可以通过 Wireshark 抓包,看到每隔 30s 发送的数据包,如图1.1
(PS: 包的时间戳,可以通过“View»Time Display Format”设置时间显示格式).
1.1.4 Permission denied (publickey)
ssh 登陆机器时,提示 Permission denied (publickey)。可以尝试的方法,在
连接命令中加上-vvv 参数,观察详细的调试输出:
 
1ssh -p 2222 -vvv hldev@10.0.0.22
 
设置文件夹对应的权限:
 
1sudo chmod 700 .ssh
2sudo chmod 600 .ssh/authorized_keys
 
6Chapter 1. Widgets
Figure 1.1: ssh 心跳包
登陆服务器观察相应的日志输出:
 
1tail -f /var/log/auth.log
 
是不是服务器关闭了密码登陆?只能使用公钥认证登陆。后面检查确实如此,
务器端为了安全考虑,关闭了基于密码登录的方式,但是需要登录的主机并没有将
自己的公钥拷贝到服务器上。所以服务器直接提示了 Permission denied (publickey)
解决的办法就是在服务器端暂时开启密码登录,/etc/ssh/sshd_config 中调整配置:
 
1#允许使用基于密钥认证的方式登陆
2PubkeyAuthentication yes
 
1.1.5 Session 时间
在使用 ssh 的过程中,经常会遇到一会儿没有操作就自动断开了,不是非常方
便。
ClientAliveInterval
修改/etc/ssh/sshd_config 置文ClientAliveInterval 300(默认为 0,参数
是意思是每 5分钟,服务器向客户端发一个消息,用于保持连接,使用 service sshd
reload 让其修改后生效。如果发现还是有问题,可以试着把 300 设置小一点,例如
60
1.1 ssh(Secure Shell) 7
ClientAliveCountMax
另外,至于 ClientAliveCountMax, 使用默认值 3即可.ClientAliveCountMax 表示
服务器发出请求后客户端没有响应的次数达到一定值,就自动断开。
ControlPersist 4h
./ssh/config 中添加一行:
 
1ControlPersist 4h
 
When used in conjunction with ControlMaster, specifies that the master connection
should remain open in the background (waiting for future client connections) after the
initial client connection has been closed. If set to no, then the master connection will
not be placed into the background, and will close as soon as the initial client connection
is closed. If set to yes or 0, then the master connection will remain in the background
indefinitely (until killed or closed via a mechanism such as the ssh -O exit). If set
to a time in seconds, or a time in any of the formats documented in sshd_config, then the
backgrounded master connection will automatically terminate after it has remained idle
(with no client connections) for the specified time1.现在你每次通过 SSH 与服务器建
立连接之后,这条连接将被保持 4个小时,即使在你退出服务器之后,这条连接依
然可以重用,因此,在你下一次4小时之内)登录服务器时,你会发现连接以闪
电般的速度建立完成,这个选项对于通过 scp 拷贝多个文件提速尤其明显,因为你
不在需要为每个文件做单独的认证了。
1.1.6 代理转发
本地转发 Local Forward
将本(客户机)的某个端口转发到远端指定机器的指定端口.原理
这样的,本地机器上分配了一个 socket 侦听 port 端口,一旦这个端口上有了连接,
连接就经过安全通道转发出去,同时远程主机和 host hostport 端口建立连接.
以在配置文件中指定端口的转发.只有 root 转发口。应以参
??
 
1# Mac OS X 端口转发
2/usr/bin/ssh -g -L 2222:10.10.30.1:22222 127.0.0.1
3#接口服务器设置代理转发
4ssh -g -L 7805:192.168.250.100:7805 10.10.1.32
 
1http://man.openbsd.org/ssh_config.5
8Chapter 1. Widgets
有时在本地转发会遇到一些问题,比如 Connection Refused。首先要确定本地
要运行有 ssh 服务端,使用如下命令启动 sshd
 
1# Mac OS X 启动 sshd
2sudo /usr/bin/sshd
3# Ubuntu 启动 sshd
4sudo /etc/init.d/ssh
 
启动 SSHD 的时候系统提示:Could not load host key: /etc/ssh/ssh_ed25519_key
新版的 opensshd 中添加了 Ed25519 做签名验证,而之前系统里没这个算法的证书,
所以办法也很简单新生成下证书即可。
 
1sudo ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
2sudo ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
3sudo ssh-keygen -t ecdsa -f /etc/ssh/
ssh_host_ecdsa_key
4ssh-keygen -t ed25519 -f /etc/ssh/
ssh_host_ED25519_key
 
1.1.7 ssh 查看日志
如果需要查看 ssh 日志,可在/etc/ssh/sshd_config 配置日志输出:
 
1SysLogFacility LOCAL7
 
Facility: 设施,rsyslog 引入的概念,从功能或者程序上对日志进行分类,
由专门的工作负责记录相对应的信息,分类有:
auth(授权)authprivcron(定时任务)daemon(守护进程)kern(内核),lpr,mail(
件相关),mark,news,security(安全),syslog,user,uucp,local0,local7
多线程,多协议udp/tcp/ssl/tls/relpmysql,pgsql,oracle 等多种关系数据中,
大的过滤器,可实现过滤系统信息中的任意部分。自定义输出格式。适用于企业级
别日志记录需求。ssh 配置文件配置后,在/etc/rsyslog.conf 文件中作如下配置:
 
1LOCAL7.* /var/log/sshd.log
 
1.2 VisualVM 9
1.2 VisualVM
使用 nmap 扫描 1099 端口,看 jstatd 是否生效。
1.3 Tool Set
1.3.1 ECS(Elastic Compute Service)
配置ECS 端口规则,服务ECS–> 络和–> 全组–>
置规则–> 添加安全组规则.
1.3.2 shadowsocks
启动 ss 服务器:
 
1#可以查看启动日志
2ssserver -c /home/ec2-user/shadowsocks.json
3#后台启动
4ssserver -c /home/ec2-user/shadowsocks.json -d start
 
Shadowsocks 客户端操作:
 
1sudo apt-get install python-pip
2sudo apt-get install python-setuptools m2crypto
3#安装 Shadowsocks(Ubuntu/Fedora)
4pip install shadowsocks
5#前台启动
6#可以看到实时的日志输出
7#关闭终端后代理断开
8sslocal -c /etc/shadowsocks/shadowsocks.json
9#后台启动
10 sslocal -c /etc/shadowsocks/shadowsocks.json -d start
 
1.3.3 youtube-dl
YouTube 视频一般是不能下载的,但是是国内访问 YouTube 比较慢,经常卡,
所以可以使用 youtube-dl 工具下载 YouTube 视频:
 
1#下载默认的视频格式
10 Chapter 1. Widgets
2youtube-dl https://www.youtube.com/watch?v=
SnHxKQiXrFU
3#查看所有视频格式
4youtube-dl -F https://www.youtube.com/watch?v=
SnHxKQiXrFU
5#下载指定清晰度的视频
6#137 为指定视频格式的编码 format code
7youtube-dl -f 137 https://www.youtube.com/watch?v=
SnHxKQiXrFU
 
查看 YouTube 所有格式视频输出效果如图所示:
Figure 1.2: 查看所有格式视频
1.3.4 Jenkins
启动 Jenkins 提示 Job for jenkins.service failed because the control process exited
with error code. See "systemctl status jenkins.service" and "journalctl -xe" for details
半是由于 Java 未安装或者安装后未指定 Java 路径。打开文件:
 
1#配置文件中指定 Java 路径
2vim /etc/rc.d/init.d/jenkins
3#启动 Jenkins
4service jenkins start
 
配置文件中指定 Java 路径如图所示。
修改默认的端口号:
 
1.3 Tool Set 11
Figure 1.3: 指定 Jenkins Java 路径
1vim /etc/sysconfig/jenkins
2service jenkins restart
 
默认密码路径:
 
1#密码默认路径
2vim /var/lib/jenkins/secrets/initialAdminPassword
3vim {$home}/.jenkins/secrets/initialAdminPassword
 
忘记登录密码
忘记 Jenkins 登录密码,可以先禁用登录认证,进入 Jenkins 修改密码后,使用
新密码登录,打开配置文件:
 
1vim /var/lib/jenkins/jenkins.config
 
删除与登录认证相关的配置:
 
1<useSecurity>true</useSecurity>
2<authorizationStrategy class="hudson.security.
FullControlOnceLoggedInAuthorizationStrategy"
>
3<denyAnonymousReadAccess>true</
denyAnonymousReadAccess>
4</authorizationStrategy>
5<securityRealm class="hudson.security.
HudsonPrivateSecurityRealm">
6<disableSignup>true</disableSignup>
7<enableCaptcha>false</enableCaptcha>
12 Chapter 1. Widgets
8</securityRealm>
 
1. 重启 Jenkins 服务;
2. 进入首页 >“系统管理”>Configure Global Security
3. 勾选“启用安全”
4. 点选“Jenkins 专有用户数据库”,并点击“保存”
5. 重新点击首页 >“系统管理”,发现此时出现“管理用户”
6. 点击进入展示“用户列表”
7. 点击右侧进入修改密码页面,修改后即可重新登录。
Jenkins Gradle 版本
Jenkins 中使gradlew 时,Gradle 版本始终是某一个,但是 build.gradle
Jenkins 中指定的却是另一个版本。
 
1#查看 gradlew 版本
2./gradlew -v
3#更新版本
4gradle wrapper
 
Jenkins Gradle 配置
Jenkins Gradle 需要添加全局变量 GRADLE_USER_HOME, Jenkins->
管理-> -> ,全局GRADLE_USER_HOME
要保证 Jenkins 用户有写入的权限,如图1.4所示.
Figure 1.4: 指定 Jenkins Gradle 用户路径
1.3 Tool Set 13
Jenkins 运行脚本
Jenkins 后台运行脚本时,需要使用 setsid 和设置 BUILD_ID=dontKillMe2.如下
命令所示:
 
1count=‘ps -ef | grep dolphin-web-${VERSION} | grep -v
"grep" | wc -l‘
2if [ $count -lt 1 ]; then
3#使用 setsid 启动 app
4#setsid 在一个新的会话中运行命令
5#从而可以避开当前终端发出的 HUP 信号
6setsid ${JAVA_HOME}/bin/java -Xmx512M -Xms256M \
7-jar -Xdebug -Xrunjdwp:transport=dt_socket,
suspend=n,server=y,address=5005 \
8${APP_PATH}/dolphin-web-${VERSION}.jar \
9--spring.config.location=${APP_PATH}/application.
properties>/dev/null &
10 else
11 echo "process aready exists!"
12 fi
 
也可以在 Jenkins 系统环境变量中设置 BUILD_ID 变量,如图1.5所示。
Figure 1.5: Jeknins 全局变量
Jenkins 系统中添加执行脚本的时候,有一些命令是需要 sudo 权限和来执行的,
可以在 root 权限下添加一下 Jenkins 账号的权限。如下命令所示:
2https://wiki.jenkins.io/display/JENKINS/ProcessTreeKiller
14 Chapter 1. Widgets
 
1#打开 sudoers 文件
2vim /etc/sudoers
 
/etc/sudoers 文件中添加如下内容:
 
1#可以不用输入密码
2#直接以超级管理员权限执行 ps 命令和 kill 命令
3jenkins ALL=NOPASSWD:/usr/bin/ps,/usr/bin/kill
 
1.3.5 OpenVPN
OpenVPN 2001 年开始开发,使用的是 C语言。此处使用的 OpenVPN 版本
2.4.1。如果使用 Mac brew 工具安装,则 OpenVPN 录在:/usr/local/Cel-
lar/openvpn/2.4.1OpenVPN 的配置文件在:/usr/local/etc/openvpn目前 OpenVPN
能在 SolarisLinuxOpenBSDFreeBSDNetBSDMac OS X Microsoft Win-
dows 以及 Android iOS 上运行,并包含了许多安全性的功能。此处的服务器使
用的是 CentOS 7.3,客户端包含 Fedora 24Ubuntu 14.04Ubuntu 16.04Window
7Windows 10。在 OpenVPN 网络中查看存活的主机:
 
1nmap -A -T4 10.0.0.*
 
安装 (Install)
安装基础包:
 
1sudo yum -y install openssl openssl-devel lzo openvpn
easy-rsa --allowerasing
2#手动安装
3wget -c https://swupdate.openvpn.org/community/
releases/openvpn-2.4.1.tar.gz
4tar -zxvf openvpn-2.4.1.tar.gz
5./configure
6make && make install
 
LZO 是致力于解压速度的一种数据压缩算法,LZO Lempel-Ziv-Oberhumer
的缩写。这个算法是无损算法,参考实现程序是线程安全的。实现它的一个自由
软件工具是 lzop。最初的库是用 ANSI C 编写、并且遵GNU 通用公共许可证发
1.3 Tool Set 15
布的。现在 LZO 有用于 PerlPython 以及 Java 的各种版本。代码版权的所有者是
Markus F. X. J. Oberhumer。如果没有安装 easyrsa 工具,使用如下命令安装:
 
1#下载 easy-rsa 源码
2wget -c https://github.com/OpenVPN/easy-rsa/archive/
master.zip
3#目录/etc/openvpn/easy-rsa/easyrsa3 下拷贝默认配置
4cp var.example vars
 
调整配置
修改证书生成的配置文件:
 
1set_var EASYRSA_REQ_COUNTRY "CN"
2set_var EASYRSA_REQ_PROVINCE "Chongqing"
3set_var EASYRSA_REQ_CITY "Chongqing"
4set_var EASYRSA_REQ_ORG "Three people"
5set_var EASYRSA_REQ_EMAIL "jiangtingqiang@gmail
.com"
6set_var EASYRSA_REQ_OU "My Organizational"
7
8set_var EASYRSA_KEY_SIZE 2048
 
生成根证书
生成 OpenVPN 的根证书:
 
1#清除之前生成的证书,重新生成;
2./easyrsa clean-all
3#生成 root 根证书
4#证书路径:/etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt
5./easyrsa build-ca
 
生成服务器端证书
生成服务器端证书命令如下:
 
1#指定服务端证书的文件名为 server, 可以任意改动
2./easyrsa build-server-full server
 
16 Chapter 1. Widgets
生成客户端证书
生成客户端证书端步骤如下:
 
1./easyrsa build-client-full jiangxiaoqiang
 
PKIPublic Key Infrastructure 公钥基础设施。生成请求:
 
1./easyrsa gen-req dolphinfedora
 
PEM 码。PEM - Privacy Enhanced Mail, ,"—–
BEGIN..." 开头, "—–END..." 结尾,内容是 BASE64 编码。Apache *NIX 服务器偏
向于使用这种编码格式.签约:
 
1#切换到服务端生成 rsa 的目录
2#导入 req
3./easyrsa import-req ~/client/easyrsa/easy-rsa-master
/easyrsa3/pki/reqs/dolphinfedora.req
dolphinfedora
4#用户签约,根据提示输入服务端的 ca 密码
5./easyrsa sign client dolphinfedora
 
PKIPublic Key Infrastructure 公钥基础设施。输入 PEM 码。PEM - Pri-
vacy Enhanced Mail, 打开文本,"—–BEGIN..." , "—–END..." ,
容是 BASE64 编码.查看 PEM 格式证书的信息:openssl x509 -in certificate.pem -text
-nooutApache *NIX 服务器偏向于使用这种编码格式.服务端生成的文件有:
文件名称 说明 (Purpose) 位置
ca.crt 根证(Root CA certificate)
Server+All Clients
reqs/server.req
reqs/dolphin.req
private/ca.key 根证书私钥 (Root CA key) key signing machine only
private/server.key
issued/server.crt Server Certifi-
cate
server only
issued/dolphin.crt
dh.pem Diffie Hellman parameters server only
客户端生成的文件有:
1.3 Tool Set 17
序号 名称
private/dolphinclient.key
reqs/sdolphinclient.req
拷贝出客户端证书文件:
 
1cp easyrsa/easy-rsa-master/easyrsa3/pki/ca.crt ~/
dolphinfedora/
2cp easyrsa/easy-rsa-master/easyrsa3/pki/issued/
dolphinfedora.crt ~/dolphinfedora/
3cp ~/client/easyrsa/easy-rsa-master/easyrsa3/pki/
private/dolphinfedora.key ~/dolphinfedora/
 
启动 OpenVPN
 
1sudo openvpn server.conf
2# Mac 下启动 OpenVPN
3sudo /usr/local/Cellar/openvpn/2.4.1/sbin/openvpn /
usr/local/etc/openvpn/client.conf
4#需要以后台交互方式启动时
5screen sudo openvpn client.conf
 
客户端端配置如下:
 
1client #指定当前 VPN 是客户端
2dev tun #必须与服务器端的保持一致
3proto udp #必须与服务器端的保持一致
4#指定连接的远程服务器的实际 IP 地址和端口号
5remote 192.168.1.106 1194
6#断线自动重新连接
7#在网络不稳定的情况下 (例如:笔记本电脑无线网络)非常
有用
8resolv-retry infinite
9nobind #不绑定特定的本地端口号
10 persist-key
11 persist-tun
12 ca ca.crt #指定 CA 证书的文件路径
13 cert client1.crt #指定当前客户端的证书文件路径
14 key client1.key #指定当前客户端的私钥文件路径
18 Chapter 1. Widgets
15 ns-cert-type server #指定采用服务器校验方式
16 #如果服务器设置了防御 DoS 等攻击的 ta.key
17 #则必须每个客户端开启;如果未设置,则注释掉这一行;
18 tls-auth ta.key 1
19 comp-lzo #与服务器保持一致
20 #指定日志文件的记录详细级别,可选 0-9,等级越高日志内
容越详细
21 verb 3
 
ns-cert-type(Netscape Cert Type) 指定为 server 主要是防止中间人攻击
(Man-in-the-Middle Attack)。在服务端做如下配置:
 
1nsCertType server
 
生成 Diffle Hellman 参数
生成 Diffle Hellman 参数命令如下:
 
1./easyrsa gen-dh
 
初始化配置文件
初始化配置文件如下:
 
1#拷贝示例配置到配置目录
2cp /usr/share/doc/openvpn-2.4.4/sample/sample-config-
files/server.conf /etc/openvpn
 
拷贝 server.crt/ca.cert 等文件到配置目录.
生成 ta.key
使用如下命令生成 ta.key:
 
1openvpn --genkey --secret ta.key
 
启动服务端:
 
1openvpn --config /etc/openvpn/server.conf
 
1.4 Nginx 19
拷贝客户端文件
将服务器生成的客户端文件拷贝到客户端:
 
 
1.3.6 fastDFS
启动 tracker server:
 
1/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
 
启动 storaged server:
 
1/usr/bin/fdfs_storaged /etc/fdfs/storage.conf
 
1.4 Nginx
安装配置好 nginx 服务器后默认目录是/usr/share/nginx/htmlnginx 模块一般被
分成三大类:handlerfilter upstreamMac Nginx 配置文件的路径为:/usr/lo-
cal/etc/nginx/nginx.conf
1.4.1 X-Forwarded-For
X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1RFC 2616协议并没有对
它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真
IP如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广
泛使用,并被写入 RFC 7239Forwarded HTTP Extension标准之中。在默认情况下,
Nginx 并不会对 X-Forwarded-For 头做任何的处理,除非用户使用 proxy_set_header
参数设置:
 
1proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
 
X-Forwarded-For 请求头格式:
 
1X-Forwarded-For: IP0, IP1, IP2
 
XFF 的内容由「英文逗号 +空格」隔开的多个部分组成,最开始的是离服务
端最远的设备 IP,然后是每一级代理设备的 IP
20 Chapter 1. Widgets
1.4.2 Nginx 获取真实 IP
Nginx 作为 HTTP 代理转发前端时,后端服务无法获知前端访问客户的 IP
址。要获取客户端 IP,需要将 http_realip_module 编译进入 Nginx 中。查看 Nginx
安装了哪些模块,使用如下命令:
 
1nginx -V
 
在命令的输出结果中,可以看到 Nginx 的版本,Nginx 的编译参数,和 Nginx
已经包含有哪些模块。此处显示已经编译了 http_realip_module 模块。在服务器上
的项目中使用的 tengine经过查看是没有编译 http_realip_module 模块,tengine
官网上下载好源码,输入如下命令进行编译:
 
1#Ubuntu 14.04 LTS 下安装 pcre 依赖
2# pcre:Perl Compatible Regular Expressions
3sudo apt-get install libpcre3 libpcre3-dev
4#指定预编译参数,仅仅指定路径
5sudo ./configure --prefix=/opt/tengine
6#realip 模块编译进入
7sudo ./configure --prefix=/opt/tengine --with-
http_realip_module
8#编译
9sudo make
10 #安装
11 sudo make install
12 ./configure --prefix=/usr/local/tengine-2.1.2 --with-
openssl=/Users/dolphin/source/openssl
 
不指定 prefix则可执行文件默认放在/usr/local/bin库文件默认放在/usr/local/lib
配置文件默认放在/usr/local/etc。其它的资源文件放在/usr /local/share。你要卸载这
个程序,要么在原来的 make 目录下用一次 make uninstall(前提是 make 文件指定
uninstall,要么去上述目录里面把相关的文件一个个手工删掉。指定 prefix
接删掉一个文件夹就够了,这也是制定 prefix 一个比较方便的地方。在编译时,
需要指定 pcre 的版本,因为 Ubuntu 16.04 LTS 里有时安装有 pcre 3而部署的电脑
上不一定安装有 pcre 3,而且 pcre 3 的源码不容易找到。所以编译命令如下:
 
1#realip 模块编译进入,并指定 pcre
2sudo ./configure --prefix=/opt/tengine --with-
1.4 Nginx 21
http_realip_module --with-pcre=/root/software
/pcre-8.40 --with-openssl=/root/software/
openssl-OpenSSL_1_1_0e --without-
http_gzip_module
3
4./configure --prefix=/opt/tengine --with-
http_realip_module --with-pcre=/root/software
/pcre-8.40 --without-http_gzip_module
5
6#本机编译(不成功)
7./configure --prefix=/opt/tengine --with-
http_realip_module --with-pcre=/home/hldev/
Downloads/pcre-8.40 --with-openssl=/home/
hldev/Downloads/openssl-OpenSSL_1_0_1e --
without-http_gzip_module
8
9#本机编译(成功)
10 -prefix=/opt/tengine --with-http_realip_module --with
-pcre=/home/hldev/Downloads/pcre-8.40 --with-
openssl=/home/hldev/software/openssl-
OpenSSL_1_0_2g --without-http_gzip_module
11
12 #构建程序
13 make
14
15 #安装程序
16 make install
17
18 #服务器
19 ./configure --prefix=/opt/tengine
20
21 ./configure: error: SSL modules require the OpenSSL
library.
22 You can either do not enable the modules, or install
the OpenSSL library
23 into the system, or build the OpenSSL library
22 Chapter 1. Widgets
statically from the source
24 with nginx by using --with-openssl=<path> option.
 
–with-pcre pcre(Perl Compatible Regular Expressions) 的源代码目录
在编译时,还需要注openssl 的版本,本地电脑版本是 1.0.2g,服务端的版本是
1.0.1e。服务器端编译 Nginx 的一个命令:
 
1./configure --prefix=/opt/tengine --with-openssl=/usr
/local/src/openssl-OpenSSL_1_0_2g/ --without-
http_gzip_module --with-pcre=/usr/local/src/
pcre-8.40/
 
这里编译的时候有一个小细节需要注意,需要将源码包存放到/usr/local/src
录下。一直没有编译成功也许是这个小小的细节,开始时是将源码包随意存放的一
个目录。以上编译的命令没有包含 Zlib,也没有包含 http_realip_module 块。最
终的编译命令如下:
 
1./configure --prefix=/opt/tengine --with-openssl=/usr
/local/src/openssl-OpenSSL_1_0_2g/ --with-
pcre=/usr/local/src/pcre-8.40/ --with-zlib=/
usr/local/src/zlib-1.2.11 --with-
http_realip_module
 
编译完毕之后,输入如下命令:
 
1#查看 Tengine 版本、模块信息,编译时所使用的参数
2./nginx -V
 
即可看到 http_realip_module 已经编译到 Nginx 中了。Nginx http realip mod-
ule 等于 Apache mod_rpaf用于接受前端发来的 IP head 信息,从获取到真实的
用户 IP。将获取真实 IP 的模块编译进入 Nginx 后,还需要在对应的 httpserver
location 中加入以下参数:
 
1#指令是告诉 nginx10.10.1.11 是我们的反向代服务器
2#不是真实的用户 IP
3set_real_ip_from 10.10.1.11;
4#告诉 nginx 真正的用户 IP 是存在
5#X-Forwarded-For 请求头中
1.4 Nginx 23
6real_ip_header X-Real-IP;
 
其中 set_real_ip_from 可以指定某个网段。这个指令指定信任的代理 IP,它们
将会以精确的替换 IP 转发。0.8.22 后可以指定 Unix socketsreal_ip_header 设置需
要使用哪个头来确定替换IP 地址。由于项目中使用的 Nginx 作为反向代理,所
以配置如下:
 
1location /inapi {
2proxy_pass http://localhost:28080;
3proxy_set_header X-Real-IP $remote_addr;
4proxy_redirect off;
5}
 
在另一台电脑上访问服务端,在后端根据新添加的 Header 获取到的 IP 地址如
1.6所示:
Figure 1.6: Nginx 获取用户真实访问 IP
此处获取到的 IP 是用户的真实 IP,而不是反向代理服务器的 IP
1.4.3 Nginx 并发 (Nginx Concurrent)
如何设置能限制某个 IP 某一时间段的访问次数是一个让人头疼的问题,特别
面对恶意的 ddos 攻击的时候。其中 CC 攻击(Challenge Collapsar)是 DDOS(分
布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或
者肉鸡向向受害主机不停地发大量数据包,造成对方服务器资源耗尽,一直到宕
机崩溃。
cc 攻击一般就是使用有限的 ip 务器到攻的,
Nginx 以通HttpLimitReqModule HttpLimitZoneModule ip
一时间段的访问次数来防 cc 攻击。
HttpLimitReqModule 用来限制连单位时间内连接数的模块,使用 limit_req_zone
limit_req 指令配合使用来达到限制。一旦并发连接超过指定数量,就会返回 503
24 Chapter 1. Widgets
错误。limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法
leaky bucket
 
1http {
2limit_conn_log_level error;
3limit_conn_status 503;
4#Zone=one allips 表示设置了
5#名为“one”或“allips”的存储区
6#大小为 10 兆字节
7limit_conn_zone $binary_remote_addr zone=one:10m;
8limit_conn_zone $server_name zone=perserver:10m;
9#rate=1000r/s 的意思是允许 1秒钟不超过 1000 个请
10 limit_req_zone $binary_remote_addr zone=allips
:100m rate=1000r/s;
11 #限制每分钟不超过 600 个请求
12 limit_req_zone $binary_remote_addr zone=allips
:100m rate=600r/m;
13 server {
14 limit_conn one 100;
15 limit_conn perserver 3000;
16 limit_req zone=allips burst=5 nodelay;
17 }
18 }
 
HttpLimitConnModule 用来限制单个 ip 的并发连接数,使用 limit_zone limit_conn
指令,这两个模块的区别前一个是对一段时间内的连接数限制,后者是对同一时
刻的连接数限制。
1.4.4 URI 长度限制
Http1.1 协议中并没有提出针对 URL 的长度进行限制,RFC 协议里面是这
样描述的,HTTP 协议并不对 URI 的长度做任何的限制,服务器端必须能够处理
任何它们所提供服务多能接受的 URI,并且能够处理无限长度的 URI, 如果服务器
不能处理过长的 URI, 那么应该返回 414 状态码。接触的最多的服务器类型就是
Nginx Tomcat, 对于 url 的长度限制,它们都是通过控制 http 请求头的长度来进
行限制的,nginx 的配置参数为 large_client_header_bufferstomcat 的请求配置参数
maxHttpHeaderSize
1.4 Nginx 25
 
1# Nginx 配置 HTTP 请求头长度
2client_header_buffer_size 2048k;
 
项目采用 Spring Boot所使用的 Tomcat 为内嵌的 Tomcatapplication.properties
中,增加如下配置:
 
1#单位为 KB, 如果没有指定,默认为 8192(8KB)
2server.max-http-header-size=1024
 
奇怪的是,在本机设置的 1024KB 可以查询,部署到服务器上,参数必须再调
大才能够查询,否则提示请求头太大的错误。真的遇到鬼了。在不同的操作系统上
单位不一样吗?见鬼
1.4.5 开启 Gzip 压缩
Nginx 开启 Gzip 压缩配置如下:
 
1gzip on;
2gzip_min_length 1k;
3gzip_buffers 4 16k;
4gzip_comp_level 2;
5gzip_types application/javascript application/json
text/plain application/x-javascript text/css
application/xml text/javascript application/x
-httpd-php image/jpeg image/gif image/png;
6gzip_vary off;
7gzip_disable "MSIE [1-6]";
 
curl 测试是否开启了压缩:
 
1curl -I -H "Accept-Encoding: gzip, deflate" "http://
creditsystem.test/main"
2curl -I -H "Accept-Encoding: gzip, deflate" "http
://10.10.1.11/main"
 
-I 选项与-header 选项是等价的,表示只打印出 HTTP 头部。开启压缩成功后,
可以看到一句:Content-Encoding: gzip
26 Chapter 1. Widgets
1.4.6 Nginx 与爬虫 (Nginx Anti-Spider)
Nginx 限制统一 IP 每分钟访问的次数:
 
1limit_req_zone $binary_remote_addr zone=one:3m rate=1
r/s;
2limit_req_zone $binary_remote_addr $uri zone=two:3m
rate=1r/s;
3limit_req_zone $binary_remote_addr $request_uri zone=
thre:3m rate=1r/s;
 
可以根据客户端的 user-agents 首部字段来阻止指定的爬虫爬取我们的网站.
1.4.7 Nginx 配置
简单的配置:
 
1user www-data;
2worker_processes 4;
3pid /run/nginx.pid;
4
5events {
6worker_connections 768;
7}
8
9http {
10 server{
11 listen 80;
12 #定义网站默认根目录
13 root /opt/dolphin/frontend/dist;
14
15 location /api {
16 proxy_pass http://localhost:8011;
17 }
18
19 location / {
20 root /opt/dolphin/frontend/dist;
21 index index.html;
22 }
1.4 Nginx 27
23 }
24 }
 
Nginx 部署 React 项目的简单配置如图1.7所示。
Figure 1.7: Nginx React 简单配置
0.7 以后的版本中加入了一个 try_files 指令,配合命名 location可以部分替
代原本常用的 rewrite 配置方式。其作用是按顺序检查文件是否存在,返回第一个
找到的文件或文件夹 (结尾加斜线表示为文件夹),如果所有的文件或文件夹都找
不到,会进行一个内部重定向到最后一个参数。此处配置如果 $url 不存在,则
部重定向到 @fallback
1.4.8 负载均衡 (Load Balance)
Nginx 的负载均衡配置,在主机 (10.10.1.12) 出现问题时,Nginx 会自动切换到
备机 (10.10.1.13),当主机恢复服务后,Nginx 会自动切换回主机:
 
1upstream backend{
2server 10.10.1.12:28080;
3server 10.10.1.13:28080 backup;
4}
 
而反向代理实际意义就是把请求转发,使用的时候用 proxy_pass 实现.反向代
理与正向代理都是用 proxy_pass 来实现的,使用起来没有太大的区别,本质上都是
转发网络请求.反向代理一般指服务器将请求转发到内部网络,这样可以防范外网
直接请求内网带来的网络风险。
28 Chapter 1. Widgets
1.4.9 阻止请求
项目中有一个张表有 700W+ 数据,是采用 like 匹配,like 匹配无法利用索引,
只能全表扫描,有时会有爬虫不断的请求此接口,导致数据库压力不断增大。为了
临时应对,临时限制此接口的请求。如下代码片段所示:
 
1location /dolphin/api {
2#匹配类似于/dolphin/api/test/reg?id=1 url
3#不阻止形如/dolphin/api/test/reg 请求
4if ( $args ~ id= ) {
5return 403;
6}
7proxy_pass http://localhost:8011;
8proxy_redirect off;
9}
 
1.4.10 超时转发
当一个请求到达后端机器,后端机器因某些原因load 高等等)响应变慢导致超
时的时候,Nginx 会把这个请求转发到另外的后端机器上.The proxy_next_upstream
directive is a configuration directive to control re-request from a group of upstream servers
by a proxy_pass if request to one of them fails.
 
1server {
2location / {
3proxy_pass http://backends;
4proxy_next_upstream error timeout http_404;
5}
6}
 
proxy_next_upstream nginx 中是默认打开的。参数值 timeout这个参数代表
如果超时,则尝试其他节点。
1.4.11 配置静态服务
静态文件单独配置一个服务:
 
1server {
2server_name creditstatic;
1.4 Nginx 29
3listen 8088;
4
5root /opt/app/static;
6index index.html index.htm;
7
8location / {
9try_files $uri $uri/ =404;
10 }
11 }
 
1.4.12 指定首页
Nginx 中指定默认首页:
 
1server {
2location / {
3root /opt/app/frontend-v1.3/dist;
4index /main/index.html;
5}
6}
 
1.4.13 常见问题
open() "/opt/tengine/conf/nginx.conf" failed (2: No such file or directory)
以上的路径是编译时 Nginx 配置文件的路径,如果在启动时不指定配置文件
和日文件路径,Nginx 默认使用的编译的文路径,但是这里
经将编译文件移动到另外的文件夹里面了,所以需要显示的指定配置文件的路径:
 
1#启动 Nginx(测试环境)
2/opt/app/local/tengine/sbin/nginx -c /opt/app/local/
tengine/conf/nginx.conf -p /opt/app/local/
tengine
3#启动 Nginx(正式环境)
4/home/app/local/tengine/sbin/nginx -c /home/app/
local/tengine/conf/nginx.conf -p /home/app/
local/tengine
 
30 Chapter 1. Widgets
也可以指定 prefix 文件目录,这样就会更改默认的 Nginx 主目录了:
 
1#重新加载配置 (测试环境)
2/opt/app/local/tengine/sbin/nginx -s reload -p /opt/
app/local/tengine
3/opt/app/local/tengine/sbin/nginx -c /opt/app/local/
tengine/conf/nginx.conf -p /opt/app/local/
tengine
4/opt/home/local/tengine/sbin/nginx -c /home/app/
local/tengine/conf/nginx.conf -p /home/app/
local/tengine
 
其中 opt 目录是编译时指定的目录,/opt/app/local 是新的目录,用 p参数指定
新目录即可。同理,在刷新配置的时候也需要显示的指定 Nginx 的主目录:
 
1#重新加载配置 (正式环境 Nginx Reload)
2/home/app/local/tengine/sbin/nginx -p /home/app/
local/tengine -s reload
3./nginx -p /home/app/local/tengine -V
 
4C:CC:6A:7C:C3:CF D8:CB:8A:8A:CD:15
error while loading shared libraries: libpcre.so.3: cannot open shared object file
找不到 libpcre.so.3 文件,在本机搜索了之后,发现文件在目录下:
 
1/lib/i386-linux-gnu/libpcre.so.3
2/lib/x86_64-linux-gnu/libpcre.so.3
 
error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file
有可能是由于 openssl 库的位置不对导致的,可以尝试创建软链接解决:
 
1ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/
libssl.so.1.1
2ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/
libcrypto.so.1.1
 
.so 为共享库,shared object, 用于动态连接的,dll 差不多。openssl多用途
的命令行工具,各功能分别使用子命令实现,libcrypto公共加密库(存放了各种加
1.4 Nginx 31
密算法)libsslssl 协议的实现。Ubuntu 下可以通过如下命令安装 libssl.so.1.0.0:
 
1sudo apt-get install libssl1.0.0:amd64
2sudo apt-get install libssl1.0.0 libssl-dev
3
4#查看 OpenSSL 版本
5openssl version
6
7#查看系统中对 libssl
8find -name libssl.s0*
9
10 #列出 openssl
11 yum list \*openssl\*
 
不过此处不能通过命令安装,只能通过源码编译安装。这里有包https://
pkgs.org/download/libssl1.0.0。查看当前操作系统支持的 openssl
 
1yum --showduplicates list openssl
 
寻找包含 libssl.so.1.0.0 的安装包:
 
1yum provides */libssl.so.1.0.0
 
http://rpm.pbone.net/上搜索 openssl1-1.0.0 , 搜到 openssl1-1.0.0-4.fc24.x86_64.rpm
2. Gradle
一般Mac Gradle 的安装路径为:/usr/local/Cellar/gradle/3.2.1/libexec
Mac Intellij Idea 指定 Gradle 路径时,即用此路径。
 
1${PROGRAM_DEVELOP_PATH_BACKEND}/gradlew -p ${
PROGRAM_DEVELOP_PATH_BACKEND}/cc-web-boot -x
test build --info
 
info 参数会输出详细的 log 信息,便于问题定位.
2.1 基础
Gradle 使用的 Groovy 语言,Groovy 语言字符串的表示形式很多,有一些细微
的区别:
 
1def a = ’单引号形式
2def b = "双引号形式,${v}"
3def c = ’’’三个单引号形式
4支持多行
5不支持占位符’’’
6def d = """三个双引号形式
7支持多行
8支持占位符,${v}"""
34 Chapter 2. Gradle
9def e = /反斜杠形式
10 支持多行
11 支持占位符,${v}/
12 def f = $/美刀反斜杠形式
13 支持多行
14 支持占位符,${v}/$
 
建议使用"两种形式。单引’’ 中的内容严格对应 Java String,不
$符号进行转义。双引号"" 的内容则和脚本语言的处理有点像,如果字符中有 $
号的话,则它会 $表达式先求值。三个引号”’xxx”’ 中的字符串支持随意换行。
2.1.1 Wrapper
如果项目文件夹下没有 gradlew 文件,可以通过如下命令生成:
 
1gradle wrapper
 
其本质是调用 build.gradle 中的 wrapper  task:
 
1task wrapper(type: Wrapper) {
2description = ’Generates gradlew[.bat] scripts’
3gradleVersion = ’3.2.1’
4}
 
2.1.2 引用本地文件
有时候项目依赖的可能不是公布在网络上的一个公共库,可能只是一个闭源
jar 包,只是一个本地文件而已。Gradle 中引用本地文件写法如下:
 
1def ccDataLibs = fileTree(dir: "$rootDir/cc-data/lib"
, include: ’*.jar’)
2
3dependencies {
4compile ccDataLibs
5}
 
dir 表示文件所在目录,include 表示包含哪些文件。
2.1 基础 35
2.1.3 Gradle Properties 支持
Gradle 支持三种 Properties, 这三种 Properties 的作用域和初始化阶段都不一样:
System Properties可通过 gradle.properties 文件,环境变量或命令行-D 参数
设置,可在 setting.gradle build.gradle 中动态修改,在 setting.gradle 中的修改对
buildscript block 可见;所有工程可见,不建议在 build.gradle 中修改。多子工程项
目中,子工程的 gradle.properties 会被忽略掉,只有 root 工程的 gradle.properties
效。
Project Properties通过 gradle.properties 文件,环境变量或命令行-P 参数
设置,优先级是:可在 build.gradle 中动态修改,但引用不存在project properties
会立即抛错,动态修改过的 project properties buildscript block 中不可见。
Project ext properties可在项目的 build.gradle 中声明和使用,本工程和子工
程可见,不能在 setting.gradle 中访问,如果有多处设置,加载次序如下(注意:gradle
2.0 是这样的, 1.10 1.12 bug,后面的覆盖前面的设置。
from gradle.properties located in project build dir.
from gradle.properties located in gradle user home.
from system properties, e.g. when -Dsome.property is used in the command line.
setting.gradle
build.gradle
2.1.4 执行流程
There is a one-to-one relationship between a Project and a "build.gradle" file. Dur-
ing build initialisation, Gradle assembles a Project object for each project which is to
participate in the build, as follows:
Create a Settings instance for the build. Evaluate the "settings.gradle" script, if
present, against the Settings object to configure it. Use the configured Settings object
to create the hierarchy of Project instances. Finally, evaluate each Project by executing its
"build.gradle" file, if present, against the project. The projects are evaluated in breadth-
wise order, such that a project is evaluated before its child projects. This order can be
overridden by calling evaluationDependsOnChildren() or by adding an explicit evaluation
dependency using evaluationDependsOn(String).
2.1.5 默认 JVM
Intellij Idea 中首次导入 Gradle 时,Gradle JVM
时在项目初始选择页面选择 Configure > Project Defaults > Project Structure,在项目
Structure 中设置 JVM 即可。
36 Chapter 2. Gradle
2.1.6 Repositories
Gradle 默认每次编译或者刷新 (Refresh) 都会 Resolve Dependencies,每次都会
去进行网络请求。可以通过 Wireshark 抓包来验证是否有网络请求以及请求的具
体地址,从图中可以看出 Gradle Resolve 时的请求地址,如果没有调整请求地址
Gradle 会使用默认的 Maven 仓库的地址或 JCenter 地址,众所周知,国访问 Maven
仓库非常慢,导致 Gralde 一直卡在 Resolve Dependencies 阶段,具体如图2.1所示。
Figure 2.1: Wireshark 查看 Gradle Resolve 请求
如果访问 JCenter 很慢,光是这个步骤说不定就要十几分钟。解决方法是在
Project Preferences Gradle Offline work。注意这样之后当你添加了新
dependencies它是不会去自动下载的,也就是说报错。需要进入项目目录运行
gradlew 手动同步,或是临时在 Preferences 那里禁用 Offline work也可以设置国内
的源,在 home .gradle 文件夹中新建 init.gradle 文件,并在文件中输入如下内
容,指定默认的国内源的地址,加速依赖包下载速度:
 
1allprojects{
2repositories {
3def ALIYUN_REPOSITORY_URL = ’http://maven.
aliyun.com/nexus/content/groups/public’
4def ALIYUN_JCENTER_URL = ’http://maven.aliyun
.com/nexus/content/repositories/jcenter’
5all { ArtifactRepository repo ->
6if(repo instanceof
MavenArtifactRepository){
7def url = repo.url.toString()
2.1 基础 37
8if (url.startsWith(’https://repo1.maven.
org/maven2’)) {
9project.logger.lifecycle "Repository
${repo.url} replaced by $
ALIYUN_REPOSITORY_URL."
10 remove repo
11 }
12 if (url.startsWith(’https://jcenter.
bintray.com/’)) {
13 project.logger.lifecycle "Repository
${repo.url} replaced by $ALIYUN_JCENTER_URL."
14 remove repo
15 }
16 }
17 }
18 maven {
19 url ALIYUN_REPOSITORY_URL
20 url ALIYUN_JCENTER_URL
21 }
22 }
23 }
 
Gradle 构建标本 build.gradle 里,经常会看到如下脚本:
 
1repositories {
2maven {
3url ’http://www.eveoh.nl/files/maven2’
4}
5maven {
6url ’http://repox.gtan.com:8078’
7}
8mavenCentral()
9jcenter()
10 maven {
11 url ’http://repo.spring.io/plugins-release’
12 }
38 Chapter 2. Gradle
13 }
 
总的来说,只有两个标准的 Android library 文件服务器:JCenter Maven Cen-
tral初,Android Studio Maven Central 作为默认仓库。如果你使用老版
本的 Android Studio 创建一个新项目,mavenCentral() 会自动的定义在 build.gradle
中。但Maven Central 的最大问题是对开发者不够友好。上传 library 异常困难。
上传上去的开发者都是某种程度的极客。同时还因为诸如安全方面的其他原因
Android Studio 团队决定把默认的仓库替换成 JCenter。正如你看到的,一旦使用
最新版本的 Android Studio 创建一个项目JCenter() 自动被定义,而不是 maven-
Central()mavenCentral() Central Maven 2 的,
址是https://repo1.maven.org/maven2JCenter 表示依赖是从 Bintarys JCenter
Maven 仓库中获取的,仓库的地址是https://jcenter.bintray.comBintray 是一
家提供全球企业软件开发包托管的商业公司。
2.1.7 常见问题
could not find method compile()
gradle 项目配置中引用 java 插件。
Could not find or load main class org.gradle.wrapper.GradleWrapperMain
运行 gradlew 脚本时,出现错误:Could not find or load main class org.gradle.wrapper.GradleWrapperMain
安装 gradle 后运改 gradle wrapper 命令修复。
Gradle 找不到 Tasks
有时在使用 Gradle 命令编译时找不到相应到任务 (Tasks)。比如在部署脚本在
project/script/deploy 目录下,当在此目录下运行脚本时,会提示在项目目录 deploy
下找不到任务。命令如下:
 
1${PROGRAM_DEVELOP_PATH_BACKEND}/gradlew copyTask -x
test
 
此时就需要指定项目的路径,将命令调整为:
 
1${PROGRAM_DEVELOP_PATH_BACKEND}/gradlew -p ${
PROGRAM_DEVELOP_PATH_BACKEND} copyTask -x
test
 
p参数指定项目的路径。在不同目录下面执行 gradle tasks 命令,可以看到不同
的任务,当/project/script/deploy 目录下执行 gradle tasks 命令时,是看不到 copy-
2.2 Gradle 对象 39
Task 命令的,但是在项目的根目录下执行是可以看到 copyTasks 任务,如图2.2
示。
Figure 2.2: Gradle 查看 Tasks
2.2 Gradle 对象
2.2.1 属性 (Properties)
Extra Properties
extra 属性用于量,All extra properties1must be defined through the
"ext" namespace. Once an extra property has been defined, it is available directly on the
owning object (in the below case the Project, Task, and sub-projects respectively) and can
be read and updated. Only the initial declaration that needs to be done via the namespace.
 
1buildscript {
2ext {
3springBootVersion = ’1.4.5.RELEASE’
4jacksonVersion = ’2.8.7’
5springfoxVersion = ’2.6.1’
6poiVersion = "3.14"
7aspectjVersion = ’1.7.4’
8}
9}
 
Reading extra properties is done through the "ext" or through the owning object.
ext.isSnapshot = version.endsWith("-SNAPSHOT") if (isSnapshot) // do snapshot
stuff
1https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#
extraproperties
40 Chapter 2. Gradle
定义目标 jar 包名
有时在构建后需要定义目标 jar 包的名称。
 
1project(":web"){
2description = "web"
3jar{
4baseName = "dolphin-web"
5}
6}
 
编译打包后的 jar 包名称即为 dolphin-web.jar
2.2.2 Task
对于 build.gradle 配置文件,当运行 Gradle <Task> 时,Gradle 会为我们创建一
Project 象,build.gradle 中的容。呢,Task
范畴的代码,Gradle 会创建一个 Script 的对象,来执行这些代码;对Task
定义,Gradle 会创Task 对象,并将它会作为 project 的属性存在 (际上是通过
getTaskName 完成的)
拷贝文件
在项目中需要根据不同的用途生成不同的文件,比如 api 需要单独打包,平台
需要单独打包,但是 api 和平台的代码都是一套代码,只是配置不同罢了。此时需
Gradle 在构建之后根据不同的用途生成不同的包名称,使用 copy 功能来实现。
首先定义项目的动态属性:
 
1buildscript {
2ext {
3projectVersion = ’1.1.11’
4}
5}
 
然后在 task 中使用此属性即可。
 
1task copyfile(){
2println(projectVersion)
3}
 
2.2 Gradle 对象 41
一个简单的拷贝任务,在生成完毕文件后,目的文件拷贝一个接口部署包副
本,接口与应用程序单独部署,并重新命名。
 
1def ccCommonBuildScript = file("$rootDir/gradle/
common.gradle")
2apply from: ccCommonBuildScript
3/**
4*复制一份接口的部署包
5*接口与平台单独部署,避免互相影响
6*/
7task copyTask(type: Copy) {
8from ’build/libs/credit-system-web-boot-’ +
version + ’.jar’
9into ’build/libs/api’
10 rename ’credit-system-web-boot-’ + version + ’.
jar’,’credit-system-web-api-’ + version + ’.
jar’
11 }
12
13 /**
14 *复制一份接口的部署包
15 *接口与平台单独部署,避免互相影响
16 *指定路径
17 */
18 task copyTask(type: Copy) {
19 from "$projectDir/build/libs/credit-system-web-
boot-${version}.jar"
20 into "$projectDir/build/libs/api"
21 rename "credit-system-web-boot-${version}.jar","
credit-system-web-api-${version}.jar"
22 }
 
在这里,version 变量是来自另外一个 gradle 文件。version 变量在 common.gradle
中定义,在 build.gradle 文件中使用。
II
3MariaDB ........................... 45
3.1 常用操作
3.2 常见问题
DB
3. MariaDB
3.1 常用操作
CentOS 下启动 MariaDB:
 
1systemctl start mariadb.service
 
3.1.1 导入导出
导出整个库结构和数据:
 
1mysqldump -h localhost -uroot -p123456 database >
dump.sql
 
启动 MariaDB 时注意是否带了–skip-networking 参数,否则会出现数据库启动
了,但是端口没有监听的情况。
允许远程登录
首先以 root 用户登陆 MariaDB 服务器:
 
1--允许用户名为‘dolphin‘的用户从任意ip以密码为123456访
问所有数据库
2grant all PRIVILEGES on *.* to dolphin@’%’ identified
by ’123456’;
46 Chapter 3. MariaDB
3--使其生效
4flush privileges;
 
修改数据库密码
修改数据库密码如下:
 
1#登录 SQL
2mysql -uroot -p
3use mysql;
4UPDATE user SET password=password(’newpassword’)
WHERE user=’root’;
5flush privileges;
6exit;
 
3.2 常见问题
3.2.1 mariadb 1045 (28000): Access denied for user ’root’@’localhost’ (using
password: YES)
在使用命令登录时,出现错误.依次执行如下语句即可:
 
1#停止 MariaDB
2systemctl stop mariadb.service
3#登录
4mysqld_safe --user=mysql --skip-grant-tables --skip-
networking &
5mysql -u root mysql
6#设置新密码
7UPDATE user SET Password=PASSWORD(’123123’) where
USER=’root’;
8FLUSH PRIVILEGES;
9quit
10 #启动 MariaDB
11 systemctl start mariadb.service
 
修改后,登录数据库:
 
3.2 常见问题 47
1mysql -u root -p123123
 
III
4DB ................................. 51
4.1
Bibliography ...................... 53
Books
Articles
书籍记录应用
4. DB
4.1
字典表用户存储系统字典,如国家字典等,出版社不存储到字典里.在新增数据
,使用户选择数据而不是手工填写.
Table 4.1: 常见数据库连接池
表名称 表说明 备注
book 书籍表 存放所有书籍
shelf 书架表 存放每个用户的书籍信息
user 用户表 存放用户信息
dictionary 字典表 存放系统字典
author 作者表 存放作者信息,包括译者等等
publisher 出版社表 存储出版社信息
Bibliography
Books
[1] .Wireshark 网络分析的艺术. 1st ed. 人民邮电出版社, 2016, pp. 3–6.
ISBN: 978-7-115-41021-4.
Articles

Navigation menu