npm检查依赖最新版本并升级

使用 npm-check-updates 检查依赖并升级。

1.安装 npm-check-updates

1
$ npm install npm-check-updates -g

2.查看package.json中依赖的最新版本

1
$ ncu

执行结果:

1
2
3
4
5
6
7
8
9
10
11
Using /Users/xxx/package.json
⸨░░░░░░░░░░░░░░░░░░⸩ ⠸ :
mobx ^3.3.1 → ^5.5.0
mobx-react ^4.2.2 → ^5.2.8
The following dependencies are satisfied by their declared version range, but the installed versions are behind. You can install the latest versions without modifying your package file by using npm update. If you want to update the dependencies in your package file anyway, run ncu -a.
antd ^3.1.2 → ^3.10.1
node-sass ^4.6.1 → ^4.9.3
Run ncu with -u to upgrade package.json

3.更新package.json依赖到最新版本

1
$ ncu -a

4.执行npm install 完成新依赖安装升级

1
$ npm install

5.完成升级

注意前端发展日新月异,版本间有时差距较大,不建议做无准备的升级。

Linux系统用户权限命令小记

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建用户组 dev
$ groupadd dev
# root用户 添加 附加组dev
$ usermod -G dev root
# 指定目录或文件 删除其他人read权限
$ sudo chmod o-r config
# 指定目录或文件拥有组改为 dev
$ sudo chown dev account/
# 创建test用户并添加到 dev用户组
$ useradd -g dev test
# 更新test用户密码
$ passwd test

err_incomplete_chunked_encoding错误

问题

项目使用ajax请求json数据大量返回值下,浏览器可能会报 err_incomplete_chunked_encoding 错误。

解决

项目使用了nginx,在大量返回值的情况下,nginx需要使用到临时文件,有的时候上述错误是由 nginx权限不足导致的,可参考nginx日志配置对应目录权限。

本项目由于返回值过大,需更新nginx配置,proxy_max_temp_file_size设个合适的较大的值,或直接设为0,关闭硬盘缓冲。

1
2
3
server {
proxy_max_temp_file_size 0;
}

问题解决。

禁止Chrome强制Https跳转

问题

场景1:
网站原先使用了https证书,现在不再使用,chrome打开网站会进行https跳转,导致异常。

场景2:
主域名配置单个https证书,其二级域名未配置正式,chrome可能会对二级域名进行https跳转。

此时chrome会有如下提示:

https跳转提示您的连接不上私密连接

解决

chrome的地址栏输入:

1
chrome://net-internals/#hsts

Delete domain security policies 中输入 不想自动https跳转的地址,然后点击“delete”按钮,即可完成配置。

chrome删除https跳转

当然这个配置的前提是 网站原来就支持http且未开启https强制跳转,主要可以解决主域名有https证书但二级域名没有,访问二级域名自动跳转https的问题,像本站 blog.gelu.me,做了https强制跳转,就算删除后http请求也会再次重定向到https。

mysql性能优化-limit分页

问题

平台在主数据量不大的情况下遇到了MySQL limit较大偏移量分页查询极慢的情况。

分析解决

该查询语句存在的一些问题

问题1:

查询使用的 select ,虽然知道从性能角度来说应该用什么查什么,但项目非大数据类的项目,可见项目生命周期内也不会有超大量数据,因此为加快开发效率还是使用了select

问题2:

表中存在部分大字段,limit m, n 使得结果集查询了 m + n 的数据,并将 m 以前的数据抛弃。配合第一个问题,导致了 m 较大时查询非常慢。

实际项目中,这些字段当前也没有了使用需求,因此予以删除,基本解决了查询慢的问题。同时该表字段过多,近100个,会在后续的改版优化中进行拆分。

因为遇到了分页查询慢的问题,顺便整理收集了一下真正大量数据下的分页优化方案。

解决方案

1
select * from table_name inner join ( select id from table_name where xxx=yyy limit 200000,10) b using (id)

还有一些缩减查询范围 和 使用子查询的一些方法,有诸多限制,因此就没有记录。

当然有些时候大量数据查询场景可以避免,上家公司千万级的数据就通过归档数据减少数据库压力,也可以缩减业务查询范围避免大量数据查询。

Gitlab升级迁移小记

由于历史操作原因,Gitlab服务器与Jenkins服务器位于不同大区的ECS服务器中,拉取代码较慢,新服务器采购时正好做个迁移,将2个服务器配置在一个内网中。

原服务器系统CentOS,Gitlab版本 10.2.4,新服务器系统Ubuntu,Gitlab版本。

登录新服务器配置SSH,方便以后的登录。

可参考 SSH登录配置

在新服务器上安装Gitlab

参考 官网命令进行 新服务器Gitlab安装 https://about.gitlab.com/installation/#ubuntu?version=ce

1
2
3
4
5
6
7
8
9
apt update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://xxx.xxxx.com" apt-get install gitlab-ce

升级原服务器Gitlab版本。

由于Gitlab迁移要求 版本号相同,因此对于原服务器Gitlab需要做个升级。

下载新包

https://packages.gitlab.com/gitlab/gitlab-ce
https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-11.0.3-ce.0.el7.x86_64.rpm

关闭部分gitlab服务

1
2
3
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
gitlab-ctl stop nginx

Gitlab备份

1
gitlab-rake gitlab:backup:create

升级

1
2
3
4
5
6
7
8
rpm -Uvh gitlab-ce-11.0.3-ce.0.el7.x86_64.rpm
# 参考
# Ubuntu/Debian系统:
# sudo dpkg -i gitlab_x.x.x-omnibus.xxx.deb
# CentOS系统:
# sudo rpm -Uvh gitlab-x.x.x_xxx.rpm

gitlab跨版本升级错误

提示版本跨度过大无法升级,需按路径依次升级。

原Gitlab版本10.x,找了10版本下最大版本10.8.4,按照上面的升级流程重新走了一遍。

升级10成功。

Gitlab升级10.8.4成功

重新配置gitlab

1
gitlab-ctl reconfigure

重启gitlab

1
gitlab-ctl restart

启动以后500错误。

10.8.4 500错误

查看 日志 /var/log/gitlab/gitlab-rails/production.log

500日志错误

这个错误没有找到好的解决办法。

1
2
3
4
5
6
7
8
# 尝试直接修改表结构
$ gitlab-rails dbconsole
$ alter table issues add column deleted_at timestamp;
# 后续错误依次修改
$ alter table merge_requests add column deleted_at timestamp;
$ alter table namespaces add column deleted_at timestamp;

然后一般页面500错误消失,但退出登录会出现500错误,简直奔溃。

迁移还原

原服务器弄的不完美,直接将升完级的后再备份的文件转移至新服务器备份文件夹下,Gitlab备份文件夹目录/var/opt/gitlab/backups/,还原成功。

1
2
3
4
5
6
7
8
# 备份文件名 1531211711_2018_07_10_11.0.3_gitlab_backup.tar
$ cd /var/opt/gitlab/backups/
# 还原时出现 这个错误 tar: Error is not recoverable: exiting now,权限不足
$ chown git 1531211711_2018_07_10_11.0.3_gitlab_backup.tar
# 还原,还原成功。
$ sudo gitlab-rake gitlab:backup:restore BACKUP=1531211711_2018_07_10_11.0.3

建议谨慎升级,做好备份,实在不行还原到原版本,迁移的话也可以到同版本升级。

本次迁移的下下策是重新创建仓库、用户。因为用户及仓库数量也就十来个,不算多,也算有恃无恐。

Thymeleaf List指定数量循环

问题

项目使用Thymeleaf模板,后端查询10条数据,但根据不同页面可能会显示其中3条或5条。因此有了List指定数量循环的需求,数量由模板决定,而非后端。

解决

不知道是不是搜索关键字的问题还是问题太简单的原因,网上找到一些都是这种

1
${#numbers.sequence(0,3)}

通过Thymeleaf numbers函数进行截取的解决方案。此方案对本项目不适用,因为它要求传入的数据模型就是List,函数会直接截取该List,而项目使用的是更复杂的Map对象。
看了一下Thymeleaf文档,可以使用List的状态变量加以判断来解决这种问题。

1
2
3
4
<div th:text="${title}">标题</div>
<div class="column" th:each="item,itemStat : ${testList}" th:if="${itemStat.count}<=3">
<div th:text="${item.name}"></div>
</div>

以上代码使得无论testList实际有多长,最多只有前3个会被使用到。

其中th:each第二个变量就是迭代的状态变量,本文命名的是itemStat。状态变量有如下属性:
index: 当前迭代索引,从0开始。
count: 当前迭代索引,从1开始。
size: 迭代变量中的元素总数。
current: 每个迭代的iter变量, 和本文中的item一样。
even/odd: 当前迭代是偶数还是奇数,布尔值。
first: 在当前的迭代中是否是第一个,布尔值。
last: 在当前的迭代中是否是最后一个,布尔值。

使用 th:if 加 count比较 即可约束后续内容显示。

Thymeleaf相关链接:

Thymeleaf SAXParseException
Thymeleaf实现页面静态化
Thymeleaf TemplateProcessingException
Thymeleaf比较判断枚举类型

MyBatis查询无数据

问题

项目使用了Mybatis-PageHelper,项目有业务需要在指定范围(指定时间范围指定条数)内的数据里做查询,因此有了下面的Mybatis代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<select id="list" resultMap="TotalResultMap" parameterType="com.yl.dao.query.YlCaseListQuery">
select allData.* from (
select yce.*,yc.patient_id
from yl_a yce left join yl_c yc on yc.id = yce.case_id where 1=1
<if test="ctimeStart!=null">
and DATE_FORMAT(yce.ctime, '%Y-%m-%d') <![CDATA[>=]]> DATE_FORMAT(#{ctimeStart}, '%Y-%m-%d')
</if>
<if test="ctimeEnd!=null">
and DATE_FORMAT(yce.ctime, '%Y-%m-%d') <![CDATA[<=]]> DATE_FORMAT(#{ctimeEnd}, '%Y-%m-%d')
</if>
order by yce.ctime desc limit 200) as allData
<where>
<if test="patientId!=null">
and allData.patient_id = #{patientId}
</if>
</where>
</select>

当不使用patientId查询条件时没有问题,查询能正常查询出200条记录。
但添加查询条件后数据可能查询不出来。当时的情况是测试环境测试了一下可以查询,生产环境没有结果。

解决

当前看了好久没找到问题,后来打开生产环境的sql打印。发现mybatis-pagehelper在select count(0)查询时会默认将sql语句中的order by去掉,也就是count查询时上面的子查询没有order by排序但有limit 200, 有无排序的数据集是不一样的,此时查询出来的新的数据集确实没有包含对应patientId记录的话,count(0)值就是0。

因为查询前会count查询一下判断是否存在数据,再决定是否进行实际查询,count结果为0就直接导致了查询无数据。

查看Mybatis-PageHelper文档,在SQL中包含

1
/*keep orderby*/

注释时,count查询时不会移出order by。

因此更新代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<select id="list" resultMap="TotalResultMap" parameterType="com.yl.dao.query.YlCaseListQuery">
select allData.* from (
select yce.*,yc.patient_id
from yl_a yce left join yl_c yc on yc.id = yce.case_id where 1=1
<if test="ctimeStart!=null">
and DATE_FORMAT(yce.ctime, '%Y-%m-%d') <![CDATA[>=]]> DATE_FORMAT(#{ctimeStart}, '%Y-%m-%d')
</if>
<if test="ctimeEnd!=null">
and DATE_FORMAT(yce.ctime, '%Y-%m-%d') <![CDATA[<=]]> DATE_FORMAT(#{ctimeEnd}, '%Y-%m-%d')
</if>
order by yce.ctime desc limit 200) as allData /*keep orderby*/
<where>
<if test="patientId!=null">
and allData.patient_id = #{patientId}
</if>
</where>
</select>

此时,count查询是order by没被删除,根据patientId查询成功。

Thymeleaf异常-TemplateProcessingException Exception evaluating SpringEL expression - Property or field 'x' cannot be found on object of type 'java.util.HashMap'

问题

1
2
3
<div th:each="item:${list}">
<div th:text="${item.show}"></div>
</div>

thymeleaf 循环list时,若item里存在空值,即show为空时,可能会出现如下错误。

1
2
3
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "item.show" (template: "index" - line 37, col 82)
...
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'show' cannot be found on object of type 'java.util.HashMap' - maybe not public or not valid?

解决

使用map的方式获取值,即使用 ${item.get(‘show’)} 替换 ${item.show}。

1
2
3
<div th:each="item:${list}">
<div th:text="${item.get('show')}"></div>
</div>

成功渲染。

Thymeleaf相关链接:

Thymeleaf List指定数量循环
Thymeleaf SAXParseException
Thymeleaf实现页面静态化
Thymeleaf比较判断枚举类型

IOS The OSS Access Key Id you provided does not exist in our records

问题

IOS使用OSS上传提示403, InvalidAccessKeyId, The OSS Access Key Id you provided does not exist in our records。

解决

首先排除AccessKeyId出错的情况,Android及前端均能上传成功。

原因可能是服务端使用STS签名,返回相关凭证,如:

1
2
3
4
5
"StatusCode": "200",
"AccessKeyId": "STS.NJu2d79fYixPT5KmX8hF3GQ2A",
"AccessKeySecret": "FzskGbUNkiJn7BqMwfSPv1jkmAfLDyaEMiSAVnrnCLbn",
"SecurityToken": "CAISjQJ1q6Ft5B2yfSjIr4nAed6D1Ll43rq7VhP6iVhtZMkfqJSZozz2IH5Lf3RqAuEctP4xmmpQ6PoZlqp6U4cd7u9dwGY0vPpt6gqET9fria7ctM456vCMHWyUFGSMvqv7aPn4S9XwY+qkb0u++AZ43br9c0fNPTGiKobby+QkDLItUxK/cCBNCfpPOwJms7V6D3bKMuu3OROY5Qi1BUFz6A1nkjE9u+btgO/ks0OE0wSqmrJE+dmgesf1NPMBZskvD42Hu8VtbbfE3SJq7BxHybx7lqQs+02c4I7GXgMKsk/cabSKqIUxcFRjFaE+Gr9Zqv/njuF/ueHVmInxxgxEIeZPSSPbSZABOTdzsC5BXBqAAWOe5SUr5pZUDVrYtTLfpFnv030/ru2vxmINy3T8/ERQpnp92xDMXC/o1uozmN9GHBjh1qOvE6RRwjD0zewZYy9dHDbMSna43nJg988w0+vhciI1aswBrjwUlIqCmRosIVngmgIYe4zqqrYuTq1KF7jLmkciIORF8ZauwFakrln/",
"Expiration": "2018-07-02T02:04:59Z"

而IOS端当时的写法需要使用的是主AccessKey、Security,而非STS生成的凭证,因此也没有使用SecurityToken,因此导致上传出错。

如果仍然打算参数STS签名方式,可参考 IOS访问控制 https://help.aliyun.com/document_detail/32046.html 使用 OSSStsTokenCredentialProvider。