新部署的基本服务
最近发现好些应用,特别是贴近某些具体功能的镜像里普遍都使用了SO加密。还有些连系统账户的权限都限制了,实在懒得去破解root密码。
当然现在站在自己的角度,也认可这样的设置,共享不一定代表完全开源。有时候想做修改只是因为作者封装镜像的时候功能没考虑全,导致有些应用不太方便。
我觉得我的分享会比这种(连文件都无法拷贝出镜像)的开放一些,我只是避免函数的源码泄露,理论上,要把某些组件考出镜像自己再去用是没问题的。
既然大量的封装都涉及到制作SO文件,我想有必要做一个专门的服务来进行流水线处理。
Q1: 哪些文件需要打包?
A1: 主要是py文件,但也有可能是其他文件。
Q2: 如何避免重复打包?
A2: 根据哈希值进行真实的打包操作。
Q3: 如何获取打包后的文件?
A3: 提供文件的下载方式。
Q4: 如何上传要打包的文件?
A4: 可以使用接口,也可以采用文件上传形式。
file In so out
服务的工作机制很简单,收到用户发来的文件,或者字符,按照文件名和毫秒时间戳将其保存为文件(uploads); 保存后,读取文件的二进制字符,计算其哈希值 1 ◯ \text{\textcircled 1} 1◯。
用户、文件名、哈希、创建时间将会以日志方式存到数据库 2 ◯ \text{\textcircled 2} 2◯。
存储数据的时候,使用的是哈希码作为文件名(如果该哈希存在,则不会重复存储) 。 3 ◯ \text{\textcircled 3} 3◯程序会去查看转换文件目录(so_folder)是否已经有了该文件。如果没有,就进行转换。
4 ◯ \text{\textcircled 4} 4◯最后程序重定向请求到下载视图,将对应的so文件发给用户。
为了加快实施,现在做一些简化:该服务目前只接受可json的文件SO。用户通过接口将文件内容打包为字符串发过来,服务打包后直接返回一个附件。用户可以进行重命名。
so_pack最后的交付形态是镜像
免费的镜像仓库还是阿里比较大方,给了300个镜像的免费配额;腾讯就有点抠,只有100个。当然,不管是哪个其实都够用,目前我用阿里的感觉还不错。
一些简单的,通用的镜像我会存在公有云仓库;关于镜像有一些概念要明确:
假定启动的服务是多分身的
有些是Server,启动时会消耗端口资源。所以在设计的时候,一定会至少分为一个端口。为了便于记忆,这个端口会加到镜像的名称中。但是,最终分配多少端口用于分身会在「微服务运行表」中。Port如果是标量,那么就只有一个端口;如果是列表,那么就可以启动若干微服务。
更好的做法是,微服务分配的那个端口是发给nginx的,由nginx转发给其他分身(负载均衡)。
一个镜像对应多个微服务,一个微服务对应多个运行实例。
运行实例将会考虑运行的主机、端口列表(server类别);如果是worker类别会简单一些。
接下来转入具体的实现讨论。
git只做开发,具体的运行容器一定是基于镜像发布的(挂载必要的参数)
将一些常用的配置直接挂上,以后就不必挂
docker run -it \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone\
-e "LANG=C.UTF-8"\
-w /workspace\
someregistry/image:v108 bash
在开发时,挂载整个目录,这样便于调试(挂文件就不会随着git更新而检测变化了)
opt_path="/opt/xxx"
cur_port=24063
docker run -it \
--rm \
-v ${opt_path}:/workspace \
-p ${cur_port}:5555 \
IMAGE bash
开发完毕后,启动一个空容器,然后把文件考进去。这个服务比较基础,信息等级我觉得可以归于II级初等,所以我就没有对文件加密,而且也传到公网。如果我希望保密的话,这些文件都可以转为SO。
docker run -it \
IMAGE bash
docker cp ./XXX/static 276a5ef7cde0:/workspace/
docker cp ./XXX/config.py 276a5ef7cde0:/workspace/config.py
docker cp ./XXX/entry_py.py 276a5ef7cde0:/workspace/entry_py.py
docker cp ./XXX/so_transfer_setup.py 276a5ef7cde0:/workspace/so_transfer_setup.py
docker cp ./XXX/entry_sh.sh 276a5ef7cde0:/workspace/entry_sh.sh
docker commit 276a5ef7cde0 WORK_IMAGE:v1
docker push WORK_IMAGE:v1
这样,在启动工作容器时,只需要考虑一些个性化的配置,一般来说:
data_path="/data/"
cur_port=24063
image=WORK_IMAGE
docker run -d \
--name=xxx_m7_shard_0 \
--restart=always \
-e "LANG=C.UTF-8" \
-p ${cur_port}:5555 \
-v ${data_path}/original_files:/workspace/static/original_files \
-v ${data_path}/so_files:/workspace/static/so_files \
${image} \
sh -c "sh entry_sh.sh test"
这样只要指定了新的文件路径就可以了
/data/original_files /data/so_files
hello2_231b4c8b7edd6194c363bd7b096df96e.py
with open('hello.py','r') as f:
x = f.read()
x
"def hello():\n print('zzz')"
file_dict = {'name':'hello2.py', 'content':x}
the_so_resp = req.post(host_ip +'sotify_a_file/',json = file_dict)
if the_so_resp.ok:
print('ok')
the_headers = the_so_resp.headers['Content-Disposition']
the_file_name = the_headers[the_headers.find('filename=')+9:]
the_bin_content = the_so_resp.content
with open(the_file_name,'wb') as f:
print('Saving File %s' % the_file_name)
f.write(the_bin_content)
---
ok
Saving File hello2_231b4c8b7edd6194c363bd7b096df96e.so
总体上是达到了目标,也比预期花的时间多一些。比较奇怪的是,jupyter多次导入so内核会挂掉,我不知道为啥。