2018年12月18日

.Net Core+Docker踩坑记录

作者 非鱼

新的项目基于.Net Core+Vue+iView开发,前后端完全分离。开发过程中没有什么问题,通过IIS Host Bundle部署在IIS上也没有太大问题。就是每次发布会比较麻烦,而且感觉性能似乎有点慢。

后来开通了阿里云的Docker服务做实验,本地通过一个脚本自动编译打包生成Docker镜像自动Push到阿里云然后通过CURL调用触发器链接来实现容器的自动更新,效果也很不错。但是过程中遇到了不少的坑。

1、阿里云的容器,通过同一个镜像创建dev和prod两个容器,想一个作为测试环境,测试没有问题的话,直接重新部署生产环境就可以了。这样用了很久,后来才发现,当使用触发器调用dev重新部署的时候,生产环境也一起被重新部署了。提工单沟通之后无解,只能将镜像分成两个不同的版本,在本地决定什么时候要Push到正式版本。

2、之前一直用听云来监测程序内部的运行效率,后来根据官方的安装说明想把它安装到docker里面,结果启动脚本的写法换了各种方法都一直不成功。最后发现不调用它的启动脚本,直接把它所需要的几个环境变量放在Docker的部署环境变量里就可以生效了。不过每次重启部署它都会认为是一个新的Host,对于免费版只允许3个Host的计费方式有些不友好。(但是影响不大,过期的Host半小时左右会自动删除。)

3、通过听云监控发现网站的性能一直很差,虽然页面上访问好像挺正常的,但很多监控会发现页面执行时间需要6秒以上,而其中最慢的过程居然是Redis访问。而且StackExchange.Redis库经常报Redis连接超时。后来发现应该是这个库本身的Bug,在.Net Core下面有问题,而且是多年的问题一直没有修复。全部清理掉换成CSRedisCore库,网站的性能有了质的提升,全部降为毫秒级返回。

4、Hangfire也是个必须的库,用来处理各种需要异步执行的任务非常好用。但是因为同时启动的任务比较多,全部使用同一个存储库的话,有时候会出现任务争用,而且有时候发布的版本不一样,有时候会出现测试的任务被正式环境抢过去执行,结果却因为没有这个方法造成失败,因此在几个测试环境里使用了Hangfire.MomeryStorage来使用内存存储。部署在IIS上的时候运行完全没有问题,结果迁移到Docker上就发现异步任务全部挂了,看日志发现Hangfire报OutOfMemory异常。应该是这个内存库对Linux环境兼容性有问题。本来想换成Redis版本的存储,但它的Redis版本又是依赖于StackExchange的,因此也只能放弃,回到SqlServer存储。

5、用户上传的文件在阿里云OSS里,使用官方.Net SDK进行上传下载,结果文件打开速度就特别慢,而且日志里也经常会出现下载文件500错误,有一个流已经关闭不可重复使用的异常,而这个异常发生在它的SDK里的方法GetObject里面,在外面对它返回的流做复制已经来不及了。无奈也只好不使用读出流的方式,改成生成加密URL的方式再跳转到它自身的访问URL上。不过有一个疑惑,在微信小程序里面访问这个URL的时候,居然不需要指定为安全域名就可以正常访问。