据用过阿里云、aws、vultr的朋友介绍,海外服务器现在比较推崇vultr,理由是按时计费合理,调用api创建/销毁/重启实例方便,每个实例可添加2个额外IP(适合爬虫等),售后服务不错。价格也可以,每月5刀那种配置能满足不少场景需求。
比较有经验的朋友会将vultr跟阿里云配合用,比如搞爬虫时,阿里云是调度、数据中心,vultr是提供资源干活的。开始用vultr源起于某段时间搞爬虫的痛点,各种被403/503,买了代理库的代理信息,但用着很不爽,可用率比较低,能用的没多久也down掉了。后来在知乎搜VPS用发现了vultr,开始试用。按小时计费,有比较完善的api,研究了下api用python写了管理脚本,批量创建、销毁实例十分方便,用起来实在太爽。跑过爬虫的应该知道IP的重要性,vultr干这个效率很高。每个实例可添加2个额外IP,不过额外收费,且需额外配置。
机房连接速度方面,如果用北京联通上网,一开始测了洛杉矶、日本的感觉日本的稍快些,用着也不错,过几天开第二个账号发现日本的各种连接问题,大致40%的实例创建后ping不通,开ticket跟工作人员沟通了很久,最终确认问题还是在我们这边,美国的也有类似问题;再后来发现悉尼的连接稳定性很好,且速度不错,用bypy往百度云传文件均速大约2M(不确定是我开的那台比较好还是普遍这样,后来没往百度云传过东西了),于是用api直接开了30台在悉尼,全部工作顺利。
python管理脚本,有意用的同学可以修改下用。我限制了只能在我阿里云机器的网段使用api,所以调用了代理(阿里云上的shadowsocks)访问api,再就是新建的实例会运行账号下的script脚本,脚本会完成环境配置、从阿里云上用git把代码clone下来、启动核心程序等工作。
script:
##### init setcp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime##### installapt-get update apt-get -y upgrade apt-get install -y gcc tmux vim git python-dev python-pip libxml2-dev libxslt1-dev libmysqld-dev pip install lxml beautifulsoup4 shadowsocks mysql-python pysocks netifaces pip install --upgrade requests##### dirscd /root##### ssh# pemwget http://example.com/skey.txt mv skey.txt id_rsa_1024_aliyun.pem chmod 0400 id_rsa_1024_aliyun.pem# configwget http://example.com/sshconfig.txt cat sshconfig.txt > ~/.ssh/config rm sshconfig.txt# known_hostswget http://example.com/knownhost.txt cat knownhost.txt > ~/.ssh/known_hosts rm knownhost.txt##### sswget http://example.com/sslocal.txt mv sslocal.txt sslocal.json sslocal -c sslocal.json &##### gitmkdir appcd app git clone ssh://aliyun/~/app/crawlercd crawler cp dat/cookie_tmpl.dat dat/cookie.dat##### workpython regHost.py reg python crawler.py 1 python regHost.py unreg
vultr.py
# coding: utf-8import sys, requests, socket# 自己写的日志类from Utils import loggingimport platformif platform.platform().startswith("Windows"): import win_inet_ptonclass VultrManager(): def __init__(self, account): self.name = socket.gethostname() self.proxies = {"http": "socks5://127.0.0.1:1081", "https": "socks5://127.0.0.1:1081"} if account == "account1": key = "key of account1" self.SSHKEYID = "57bbfc97ae887" self.SCRIPTID = 21252 elif account == "account2": key = "key of account2" self.SSHKEYID = "57c8e90240e81" self.SCRIPTID = 21554 self.api = {"API-KEY": key} def listServers(self): url = "https://api.vultr.com/v1/server/list" res = requests.get(url, headers = self.api, proxies = self.proxies) servers = res.json() return servers def getServerInfo(self, mid): servers = self.listServers() for server in servers: serverId = server hostname = servers[serverId]["label"] hostId = hostname.split("-")[-1] if hostId == mid: for info in servers[serverId]: print info + "\t" + str(servers[serverId][info]) def getServersInfo(self): infos = [] servers = self.listServers() for server in servers: serverId = server hostname = servers[serverId]["label"] ip = servers[serverId]["main_ip"] info = [serverId, hostname, ip] infos.append(info) print serverId + "\t" + hostname + "\t" + ip return infos def getOneId(self, mid): servers = self.listServers() for server in servers: serverId = server hostname = servers[serverId]["label"] hostId = hostname.split("-")[-1] if hostId == mid: return serverId, hostname return None, None def createOne(self, mids): if not type(mids) == list: mids = [mids] url = "https://api.vultr.com/v1/server/create" serverId = None for mid in mids: name = hostGroup + "-" + str(mid) argvs = { "DCID": 19, "OSID": 160, "VPSPLANID": 29, "SCRIPTID": self.SCRIPTID, "SSHKEYID": self.SSHKEYID, "hostname": name, "label": name } res = requests.post(url, headers = self.api, data = argvs, proxies = self.proxies) if res.status_code != 200: log = "create server " + name + " failed, " + res.text logging("e", log) else: serverId = res.json()["SUBID"] log = "server " + name + " created, its id is " + serverId logging("i", log) return serverId def createMany(self, start, end): for i in range(start, end+1): self.createOne(i) def destroyOne(self, mids): if not type(mids) == list: mids = [mids] result = None for mid in mids: serverId, hostname = self.getOneId(mid) url = "https://api.vultr.com/v1/server/destroy" data = {"SUBID": serverId} res = requests.post(url, headers = self.api, proxies = self.proxies, data = data) if res.status_code == 200: log = hostname + " destroyed" logging("i", log) result = True else: log = "Failed, status code: " + str(res.status_code) return result def rebootOne(self, mids): if not type(mids) == list: mids = [mids] result = None for mid in mids: serverId, hostname = self.getOneId(mid) url = "https://api.vultr.com/v1/server/reboot" data = {"SUBID": serverId} res = requests.post(url, headers = self.api, proxies = self.proxies, data = data) if res.status_code == 200: log = hostname + " rebooted" logging("i", log) result = True else: log = "Failed, status code: " + str(res.status_code) return result def destroyMe(self): hostId = self.name.split("-")[-1] serverId, hostname = self.getOneId(hostId) if not serverId: log = "can not find you, misson failed" logging("e", log) return else: sd = self.destroyOne(hostId) return sd def destroyAll(self): servers = self.getServersInfo() for server in servers: serverId, hostname, ip = server hostId = hostname.split("-")[-1] self.destroyOne(hostId) def rebootAll(self): servers = self.getServersInfo() for server in servers: serverId, hostname, ip = server hostId = hostname.split("-")[-1] self.rebootOne(hostId) def updateScript(self): url = "https://api.vultr.com/v1/startupscript/update" with open("vultr.sh", "r") as f: script = f.read() data = { "SCRIPTID": self.SCRIPTID, "name": "default", "script": script } res = requests.post(url, headers = self.api, proxies = self.proxies, data = data) if res.status_code == 200: log = str(self.SCRIPTID) + " updated" logging("i", log) else: print res.status_codeif __name__ == "__main__": hostGroup = "yourgroup" account = sys.argv[1] mode = sys.argv[2] vultrManager = VultrManager(account) if mode == "ia": vultrManager.getServersInfo() elif mode == "io": mid = sys.argv[3] vultrManager.getServerInfo(mid) elif mode == "co": mids = [] for i in range(len(sys.argv)-3): mid = sys.argv[i+3] mids.append(mid) vultrManager.createOne(mids) elif mode == "cm": mid_s = int(sys.argv[3]) mid_e = int(sys.argv[4]) vultrManager.createMany(mid_s, mid_e) elif mode == "do": mids = [] for i in range(len(sys.argv)-3): mid = sys.argv[i+3] mids.append(mid) vultrManager.destroyOne(mids) elif mode == "dm": vultrManager.destroyMe() elif mode == "da": vultrManager.destroyAll() elif mode == "ro": mids = [] for i in range(len(sys.argv)-3): mid = sys.argv[i+3] mids.append(mid) vultrManager.rebootOne(mids) elif mode == "ra": vultrManager.rebootAll() elif mode == "us": vultrManager.updateScript()