SongShuA

SongShuA

胸中梦黄粱,手握自在心 一个充满想法的网络安全从业人员 A person with dreams in their heart and the ability to control their own destiny, who is a creative professional in the field of cybersecurity.
github

近期项目知识随记

年初被迫接受了一个开发任务,自己从来没做过产品及开发只能硬着头皮上。一边百度一边 AI,终于最近有了些进展。随手记一下学到的知识点,比较细碎,记下来或许有用。

项目#

被安排的是开发一个网站可用性监测引擎。别的语言都不太擅长所以选用了 python。py 里自己最熟悉的框架又是 flask,所以便从这里开始。

python 的 post 数据#

flask 和很多 py 框架都有一些 “反人类”(也有可能是反我)的写法。
比如写一个路由

@app.post("/test/api/add")
def ch(request: Request):
      pass

比如这样写才能拿到 post 数据,普通访问只能 get。

并发#

刚开始写的时候只告诉我是个模块,后来又说是引擎,渐渐的越来越大,都快变成我一个人开发一个产品。
这个时候才知道我这个引擎到后面要接受整个公司所有项目的监测任务,目标保守估计几千个。大致估算了下并发估计能有 300 左右。
于是想到 flask 有没有可能扛不住这么大的并发,查一查到底怎么样。
于是查到 flask 是个开发引擎,不建议在生产环境使用。我寻思应该也是指高并发问题。然后又查到 fastapi 适合高并发场景,并且更适合作为 api “引擎”。就决定切换为 fastapi。

  1. 单纯的切换到 fastapi 其实起不到优化效果,需要将函数加上 async 关键词,使用异步才能优化。
  2. 接受数据的时候需要加 await 关键词,要不然会接受不到数据,不知道为什么。这个还要学习
  3. 所有函数都要加上 async,否则不但不优化,反而还有负优化
  4. 使用 fastapi 时需要另外安装 web 服务器,官方建议安装 uvicorn,但是在安装的时候是 uvicorn [xxxx] 的形式。这种格式表示安装 uvicorn 以及依赖。
  5. 使用异步时就不能再使用 requests 了,它不支持异步请求,我换了 aiohttp
  6. 也是最重要的一点。实测,fastapi 对并发优化其实和 flask 效果差不出太多

检测请求#

上游服务器给我任务,然后我要去监测。

所谓的监测就是 get 推送过来的 url。这里也有几个知识点

  1. 请求最好带上 UA 之类的东西,类似于爬虫的那些策略,防止被反爬系统干扰
  2. 监测网站时最好使用 GET 方法,有些网站限制了方法。我想过用 HEAD 但是产生了误报,推测可能是中间件或者安全设备配置的策略
  3. 当请求一个网站返回 200 时不一定就真的代表网站可访问,需要判断一下返回包的大小进一步确定。
  4. 超时时间长一点,有时候目标网络确实烂,也有时候请求过多我们自己的网络层会阻塞
  5. 奇怪的网络架构。举个例子,政府机构网站。县区级单位很多会选择把网站挂靠到上级的主机上。虽然一名不一样但是指向了一个主机。当对这个市区进行监测时在主机端看来我是高频请求,类 DDOS,所以就会直接拉黑。唯一的办法就是使用代理池,每个请求换一个代理。

整体架构#

最开始我想的只是写一个脚本了事,脚本不过几 K 大小。渐渐的我发现整个架构需要改变。

首先公司没有给我配代理池,只给了一个高频拨号服务器和一个公司出口服务器。所以我想尽量利用这两个机器,于是决定使用负载均衡。

其实之前只是一直听说并没有实际用过。毕竟我的主要工作是怎么打进去,至于负载均衡,只是多让我拿下一个权限而已。

负载均衡#

仔细学习了学习,发现负载均衡其实还是反代为基础。通过反代服务器进行请求转发。看了下和很久以前写的文章
初探单域名单端口多服务 web
很像。

那篇文章是说按照后缀转发到不同服务器,负载均衡则是按照某种算法进行转发。
以前我还以为是有什么专业的服务组件去完成,如果是反代为基础,那么 nginx 自然是最好用的。

配置文件大概是这么写的


worker_processes  4; //工作进程数,一般和主机核数相同

events {
    worker_connections  40960;//每个进程可跑的线程数,我这比较大因为直接用了phpstudy的参数
}

http {
    upstream web { //负载节点
        server 192.168.1.2:8000;
        server 192.168.1.3:8000;
    }

    server {
        listen 80;//反代服务器监听端口

        location / {
            proxy_pass http://web;//指定节点列表,这里的web就是upstream web中的web。平时这里是一个正常的url
        }
    }
}
docker 学习#

既然都这样了,单独在服务器上装一个 nginx 还挺麻烦的。所以我想到了 docker。以前用 docker 都是在使用别人的东西的时候按着人家给的命令执行,自己就知道一个docker ps docker images

这次自己换了方向,从使用者变成了开发者,于是学到了一些东西。

服务器系统是 centos7, yum install docker
然后还要安装 docker-compose(我终于记住这个单词了)

神奇的是 centos7 无法用 yum 直接安装,而是用 pip 进行 docker-compose 的安装。但是实测安装完成以后无法使用,可能是其他什么问题。于是按照官方文档直接用 wget 拉取了一个可执行文件。

sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose.yaml#

也学了学 docker-compose.yaml 的规则。毕竟节点架构就不能再用 sqlite 了。也得部署 mysql,俩组件加起来还是用 docker-compose 一键配置简单

version: '3'

services:
  nginx:
    image: nginx //镜像名
    ports:
      - "19100:80" //物理机端口:容器内服务端口
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro //文件覆盖到容器内


  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: web
    ports:
      - "3306:3306"
    volumes:
      - ./web.sql:/docker-entrypoint-initdb.d/web.sql //docker-entrypoint-initdb.d下的sql文件会自动导入到数据库

好了,暂时就想到了这些。遇到了很多问题,也学到了很多。果然应了那句话:你所承受的磨难终将成为日后的资本

写的有点对浏览器开始卡了,就这样吧。有哪些问题各位师傅请积极评论督促我进步学习。
最后其实还有一个问题,监测会有误报。把可用目标报成宕机,不知道为什么。同一个目标 py 脚本测不可用,curl 和 httpx 工具测都正常,想不通为什么。往大佬们指点。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。