0%

搭建 code-push-server

自己部署热更新主要有三个步骤要处理

1.code-push-server部署

2.修改react-native项目中react-native-code-push中的下载地址

3.部署监控的code-push-web

code-push-server部署

第一步 创建一个mysql数据库服务

我们将通过docker来启动mysql服务,docker在各个环境的安装可以到docker官网产看

参考MySQL

1
2
3
4
5
6
7
8
9
10
11
12
# 考虑到docker pool的镜像国内下载慢,因此mysql镜像采用daocloud.io的镜像
docker pull daocloud.io/library/mysql:5.7
# 我在宿主机(服务器)工作路径在 /home/michael 这个目录下面
# 在宿主机中创建mysql数据存放目录
mkdir /home/michael/storage

# 在使用挂载volume的时候,在SELinux 用户在这里可能会遇到一个问题,目前的解决方法是为你的配置文件指定相关的 SELinux 策略配置,那样容器才可以访问它:
chcon -Rt svirt_sandbox_file_t /home/michael/storage

# 启动mysql
docker run --name seerchat-code-push-mysql -v /home/michael/storage:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -p 4306:3306 -d daocloud.io/library/mysql:5.7

第二步 启动redis服务,做diff缓存以及用户登录验证。

1
2
3
4
5

docker pull daocloud.io/daocloud/dao-redis

docker run -d -p 6379:6379 -e REDIS_PASS="password" daocloud.io/daocloud/dao-redis:master-init

第三步 部署code-push-server

下载code-push-server代码到本地

1
2
3
4
5
6
7
cd /home/michael
mkdir code-push
# 下载
git clone https://github.com/lisong/code-push-server.git
cd code-push-server
# 安装npm包
yarn install

修改config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
db: {
username: process.env.RDS_USERNAME || "root",
password: process.env.RDS_PASSWORD || "password",
database: process.env.DATA_BASE || "codepush",
host: process.env.RDS_HOST || "localhost",
port: process.env.RDS_PORT || 4306,
dialect: "mysql",
logging: false
},
// ...
local: {
// Binary files storage dir, Do not use tmpdir and it's public download dir.
storageDir: process.env.STORAGE_DIR || "/home/michael/code-push/storage",
// Binary files download host address which Code Push Server listen to. the files storage in storageDir.
downloadUrl: process.env.LOCAL_DOWNLOAD_URL || "https://update.michaelxu.top/download",
// public static download spacename.
public: process.env.PUBLIC || '/download'
},

// ...
common: {
/*
* tryLoginTimes is control login error times to avoid force attack.
* if value is 0, no limit for login auth, it may not safe for account. when it's a number, it means you can
* try that times today. but it need config redis server.
*/
tryLoginTimes: 3,
// CodePush Web(https://github.com/lisong/code-push-web) login address.
//codePushWebUrl: "http://localhost:3001/login",
// create patch updates's number. default value is 3
diffNums: 3,
// data dir for caclulate diff files. it's optimization.
dataDir: process.env.DATA_DIR || "/home/michael/code-push/storage",
// storageType which is your binary package files store. options value is ("local" | "qiniu" | "s3")
storageType: process.env.STORAGE_TYPE || "local",
// options value is (true | false), when it's true, it will cache updateCheck results in redis.
updateCheckCache: true
},
// ...
// Config for redis (register module, tryLoginTimes module)
redis: {
default: {
host: "localhost",
port: 6379,
password: 'password',
retry_strategy: function (options) {
if (options.error.code === 'ECONNREFUSED') {
// End reconnecting on a specific error and flush all commands with a individual error
return new Error('The server refused the connection');
}
if (options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands with a individual error
return new Error('Retry time exhausted');
}
if (options.times_connected > 10) {
// End reconnecting with built in error
return undefined;
}
// reconnect after
return Math.max(options.attempt * 100, 3000);
}
}
}


1
2
# 启动mysql
./bin/db init --dbhost localhost --dbuser root --dbpassword password #初始化mysql数据库

第四步 pm2启动服务

全局安装pm2

1
sudo npm i -g pm2

编写pm2.json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"apps": [
{
"name": "code-push-server",
"max_memory_restart": "1024M",
"log_date_format": "YYYY-MM-DD HH:mm:ss SSS",
"script": "/home/michael/code-push/code-push-server/bin/www",
"out_file": "/home/michael/code-push/logs/app.log",
"error_file": "/home/michael/code-push/logs/err.log",
"port": "13001",
"env": {
"PORT": "13001",
"NODE_ENV": "production",
"HOST": "https://update.michaelxu.top"
}
}
]
}

启动程序

1
pm2 start pm2.json

第五部 配置nginx

安装nginx

配置https

通过certbot为网站生成https需要的ssl整数

1
2
./certbot-auto certonly --standalone --email michaelxu@michaelxu.top -d update.michaelxu.top

在/etc/nginx/conf.d/ 中新建一个文件名字为 update.michaelxu.top.conf 的文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
upstream update.michaelxu.top {
server localhost:13001 weight=1;
}
server {
listen 443;
server_name update.michaelxu.top;
root /home/xuqiaomin/seerline/bundle/programs/web.browser/app/;
ssl on;
ssl_certificate /etc/letsencrypt/live/update.michaelxu.top/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/update.michaelxu.top/privkey.pem;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
client_max_body_size 32m;
proxy_buffering off;
proxy_http_version 1.1;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_set_header Host $host:$server_port;
proxy_set_header Referer $http_referer;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
# NginxHttpRealIpModule
set_real_ip_from 127.0.0.1;
set_real_ip_from 10.10.10.10;
set_real_ip_from 192.168.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

location / {
# 如果code-push-web是需要跨域访问的化, 假设code-push-web访问的地址是
# http://manage.michaelxu.top 需要在以下加入跨域访问的语句
add_header Access-Control-Allow-Origin http://manage.michaelxu.top;
add_header Access-Control-Allow-Credentials true always;
if ($request_method = "OPTIONS") {
add_header 'Access-Control-Allow-Origin' http://manage.michaelxu.top always;
add_header 'Access-Control-Allow-Credentials' true always;
add_header 'Access-Control-Max-Age' 86400 always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PATCH' always;
add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type, x-requested-with, origin, authorization' always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain, charset=utf-8' always;
return 204;
}
client_max_body_size 100m;
proxy_pass http://update.michaelxu.top;
}
}

重启ngxin

1
nginx -s reload

配置react native项目

android

1
new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG)

替换成下面

1
new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG, 'https://update.michaelxu.top')

并且在android/src/build.grade中修改生成的新的deployment key

ios

在 info 中新增一个属性

1
CodePushServerURL: https://update.clchat.com

CodePushServerURL

code-push-web部署

第一步 下载程序

1
2
3
git clone https://github.com/lisong/code-push-web.git
cd code-push-web
yarn install

修改配置文件

1
vim ./src/config #change URL to production
1
2
3
4
5
6
7
export const common = {
api: {
URL: 'https://update.clchat.com', // production code-push-server address
devURL: 'https://update.clchat.com', // development code-push-server address
},
};

编写pm2_web.json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"apps": [
{
"name": "code-push-web",
"max_memory_restart": "1024M",
"log_date_format": "YYYY-MM-DD HH:mm:ss SSS",
"script": "/home/michael/code-push-web/build/server.js",
"out_file": "/home/michael/logs/app.log",
"error_file": "/home/michael/logs/err.log",
"port": "8080",
"env": {
"PORT": "8080",
"NODE_ENV": "production",
}
}
]
}

编写nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#设定负载均衡的服务器列表
upstream codepush.michaelxu.top {
#weigth参数表示权值,权值越高被分配到的几率越大
server 127.0.0.1:8080 weight=1;
}

#HTTP服务器
server {
#侦听80端口
listen 80;

#定义使用www.xx.com访问
server_name codepush.michaelxu.top;

#对所有请求进行负载均衡请求
location / {
root /home/xuqiaomin; #定义服务器的默认网站根目录位置
index index.html index.htm; #定义首页索引文件的名称
proxy_pass http://codepush.michaelxu.top ;#请求转向load_balance_server 定义的服务器列表

#以下是一些反向代理的配置(可选择性配置)
#proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Forwarded-For $remote_addr;
proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传

client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
}
}

启动程序

1
2
3
4
pm2 start pm2_web.json

# 重启nginx
nginx -s reload

为了方便后续的管理,编写一个脚本启动脚本来处理
其中code-push-web.tar.gz这个文件是我在开发环境中已经修改了配置等相应信息的压缩文件

1
2
3
4
5
6
7
8
9
10
11
ROOTPATH=/home/michael/code-push
PM2FILE=web_pm2.json


cd $ROOTPATH
rm -rf build
tar -zvxf code-push-web.tar.gz
cd $ROOTPATH/build
npm install
pm2 startOrRestart $ROOTPATH/$PM2FILE