為您解碼網(wǎng)站建設(shè)的點(diǎn)點(diǎn)滴滴
發(fā)表日期:2018-06 文章編輯:小燈 瀏覽次數(shù):2273
微信小程序后臺(tái)開(kāi)發(fā)
前言
微信小程序已經(jīng)是家喻戶曉了,最近和同學(xué)一起剛上線了一款應(yīng)用校園懶人邦,感興趣的朋友可以搜索一下,一款基于校園最后一百米的概念開(kāi)發(fā)的快遞&外賣配送平臺(tái),我是負(fù)責(zé)后臺(tái)開(kāi)發(fā)部分,這里給朋友們介紹下相關(guān)開(kāi)發(fā)經(jīng)驗(yàn),開(kāi)發(fā)框架和方式有很多,這里給大家介紹一些快捷高效的方法,大家少走彎路!
開(kāi)發(fā)環(huán)境
macOs 10.13.2
PyCharm 16.1
Python 2.7
vim 8.0
開(kāi)發(fā)流程
項(xiàng)目整體結(jié)構(gòu)
我們先來(lái)看下項(xiàng)目整體結(jié)構(gòu):
pjt: 整個(gè)項(xiàng)目的代碼文件
api: 項(xiàng)目的所有接口信息
conf: 項(xiàng)目所有的配置信息
dal/dao: 數(shù)據(jù)維護(hù)層,所有的操作數(shù)據(jù)庫(kù)的邏輯都要經(jīng)過(guò)這里
db: 第一版使用的自己設(shè)計(jì)的orm框架,第二版廢棄了
images: 圖片緩存區(qū),緩存存二維碼還有用戶頭像上傳七牛云
impl: 接口功能實(shí)現(xiàn)
key: 各種加密文件,微信支付,ssl證書(shū)等
log: 日志文件,目前天級(jí)別生成最新的一份
model: 數(shù)據(jù)模型, 第一版已廢棄
pjt_data: 第二版使用Django QuerySet的orm框架,比自己寫(xiě)的方便多了大力推薦,具體學(xué)習(xí)可以查看這里,內(nèi)部代碼就不當(dāng)做demo展示了,哈哈!
test_demo: 寫(xiě)一些功能的測(cè)試類,方便線上調(diào)試
接口開(kāi)發(fā)
整個(gè)接口開(kāi)發(fā)使用的是Flask框架,F(xiàn)lask是Python編寫(xiě)的輕量級(jí)Web應(yīng)用框架,用過(guò)的人都知道簡(jiǎn)單快捷, 馬上花一分鐘上手下:
安裝: sudo pip install flask
一個(gè)簡(jiǎn)單的demo:
from flask import Flaskapp = Flask(__name__)@app.route("/")def hi(): return "hi!"if __name__ == "__main__": app.run()123456789
運(yùn)行程序,瀏覽器輸入, 可以看到頁(yè)面返回了一個(gè)hi!,ok,這就可以了, 整個(gè)框架我們就搭建起來(lái)了,是不是很簡(jiǎn)單,后面我們來(lái)拓展一下!
http://127.0.0.1:5000/1
詳細(xì)的flask教程可以參考這里
項(xiàng)目部署
ip映射
個(gè)人選擇的服務(wù)器是阿里云,性能不錯(cuò),這里假設(shè)咱們的阿里云的Ip是1.2.3.4,那么首先我們要在服務(wù)器上建立映射關(guān)系,當(dāng)我訪問(wèn)http://1.2.3.4:5000/時(shí),不僅是本地能訪問(wèn),任何地方都行,這個(gè)很簡(jiǎn)單,只要你買(mǎi)了服務(wù)器,里面有一項(xiàng)配置你服務(wù)器的ip地址就行。
Nginx反向代理
現(xiàn)在我們可以使用http://1.2.3.4:5000/訪問(wèn)網(wǎng)站了,還缺少一些什么?當(dāng)然,微信小程序是不允許接口暴露ip地址的,你必須要用自己的域名和自定義的接口名稱,比如http://www.happypower.com/這樣才行,當(dāng)我訪問(wèn)這個(gè)網(wǎng)站時(shí)候,會(huì)先到阿里云服務(wù)器上做一下映射,確定我們的ip1.2.3.4,然后找到該Ip對(duì)應(yīng)的服務(wù)器,之后怎么辦? 我需要訪問(wèn)的是http://1.2.3.4:5000/這個(gè)啊,Nginx幫我們做了這個(gè)事,下面簡(jiǎn)單介紹下:
安裝:具體看這里
安裝完了之后咱們先配置下,詳細(xì)配置可以參考這里,這里我簡(jiǎn)單說(shuō)下我的配置,并給出具體demo:
進(jìn)入目錄/etc/nginx,每人安裝目錄可能不同,找到nginx.conf文件,vim進(jìn)行編輯,vim的操作如果不熟可以查看這里,不行可以先本地測(cè)好再到線上用,下面給出我配置的信息,大家可以仿造,應(yīng)該是比較精簡(jiǎn)的:
# For more information on configuration, see:# * Official English Documentation: http://nginx.org/en/docs/# * Official Russian Documentation: http://nginx.org/ru/docs/user nginx;worker_processes auto;error_log /var/log/nginx/error.log;pid /run/nginx.pid;# Load dynamic modules. See /usr/share/nginx/README.dynamic.include /usr/share/nginx/modules/*.conf;events { worker_connections 1024;}http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. #include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { return 404; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }# Settings for a TLS enabled server.## server {# listen 443 ssl http2 default_server;# listen [::]:443 ssl http2 default_server;# server_name _;# root /usr/share/nginx/html;## ssl_certificate "/etc/pki/nginx/server.crt";# ssl_certificate_key "/etc/pki/nginx/private/server.key";# ssl_session_cache shared:SSL:1m;# ssl_session_timeout 10m;# ssl_ciphers HIGH:!aNULL:!MD5;# ssl_prefer_server_ciphers on;## # Load configuration files for the default server block.# include /etc/nginx/default.d/*.conf;## location / {# }## error_page 404 /404.html;# location = /40x.html {# }## error_page 500 502 503 504 /50x.html;# location = /50x.html {# }# }# 自己主要要寫(xiě)的就下面這個(gè)serverserver { # 443是https監(jiān)聽(tīng)的端口,一般默認(rèn)就好 listen 443; # 自己接口的主域名,這就是當(dāng)我們?cè)L問(wèn)http://www.happypower.com時(shí)就會(huì)映射到這里 server_name www.happypower.com; ssl on; # 這是默認(rèn)主頁(yè),接口沒(méi)有主頁(yè)就注釋掉了 # root html; # index index.html index.htm; # 下面是阿里云下載的ssl證書(shū),后面會(huì)說(shuō)到ssl的配置,看不懂沒(méi)關(guān)系 ssl_certificate ./xxx.pem; ssl_certificate_key ./xxx.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location / { # 這里的意思是http://www.happypower.com會(huì)和http://0.0.0.0:8888做一個(gè)映射,這就解決了上面最開(kāi)始說(shuō)的那個(gè)問(wèn)題了,這一步很關(guān)鍵! proxy_pass http://0.0.0.0:8888; } # 日志文件路徑,有人訪問(wèn)你的網(wǎng)站時(shí)都會(huì)留下印記,有的話最好,不配置其實(shí)也行。 access_log /root/xxx/pjt/log/nginx.log;}}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
之后咱們啟動(dòng)nginx,就能通過(guò)http://www.happypower.com進(jìn)行訪問(wèn)了,成功的話會(huì)返回hi!
gunicorn+super多進(jìn)程開(kāi)啟服務(wù)+進(jìn)程監(jiān)控
這兩個(gè)很簡(jiǎn)單,其實(shí)就是幾條命令的事,主要說(shuō)下作用:
1 gunicorn 可以讓你的后臺(tái)服務(wù)多進(jìn)程方式開(kāi)啟,經(jīng)過(guò)測(cè)試可以提升一定的qps(每秒的請(qǐng)求數(shù)),簡(jiǎn)單來(lái)說(shuō)一定程度上防止你的服務(wù)器崩掉.
2 supervisor 的作用就是對(duì)你的進(jìn)程進(jìn)行監(jiān)控,該框架提供了一個(gè)可視化界面,可以通過(guò)這個(gè)界面去開(kāi)啟,暫停和關(guān)閉你的服務(wù)進(jìn)程,即使不動(dòng)代碼的人也能控制后臺(tái)服務(wù)。
3 具體配置沒(méi)啥好講的,學(xué)會(huì)幾個(gè)命令就行具體推薦看這里
ssl證書(shū)
由于小程序需要的接口都是需要https的連接,所以咱們還需要ssl證書(shū)才行,這里我使用的是阿里云服務(wù)器,具體配置可以先參考這里,可能有點(diǎn)難懂,下面簡(jiǎn)單說(shuō)下我的配置:
我選擇的是單域名免費(fèi)型 DV SSL,其實(shí)一般的應(yīng)用來(lái)說(shuō),單域名足夠了。
官網(wǎng)下載ssl證書(shū),一般是xxx.key和xxx.pem兩個(gè)文件,上面Nginx反向代理配置就需要用到這個(gè),可以返回上面的nginx.conf文件進(jìn)行查看!
管理證書(shū),這個(gè)就是配置問(wèn)題,官方文檔寫(xiě)的很詳細(xì)
配置成功后,可以使用https://127.0.0.1:5000/ 或者h(yuǎn)ttps://www.happypower.com來(lái)訪問(wèn)你的網(wǎng)站,然后返回hi!,當(dāng)然,也有可能訪問(wèn)不了,一般就是配置問(wèn)題,https其實(shí)也是在訪問(wèn)http,只是中間多了一個(gè)驗(yàn)證的過(guò)程,感興趣的可以到這里學(xué)習(xí)下http和https的區(qū)別。
ps.建議用什么服務(wù)器就用哪里的證書(shū),騰訊云和阿里云推薦,其他的真的難配,個(gè)人遇到了很多坑!
小程序常用功能
微信支付
有些小程序涉及到微信支付的,就比如校園懶人邦,這個(gè)其實(shí)很頭疼,做過(guò)就知道,難到不是很難,過(guò)程很繁瑣,官方文檔也很多坑,下面簡(jiǎn)單講解下:
首先一定要注冊(cè)公司,這個(gè)讓運(yùn)營(yíng)或者產(chǎn)品的同學(xué)去做會(huì)好一些
一般來(lái)說(shuō)支付都是單向的,也就是使用者對(duì)公司付款,如果是公司對(duì)使用者付款則需要9個(gè)月的申請(qǐng)時(shí)間才行,這個(gè)比較坑,當(dāng)然,退款是不需要等的.
具體細(xì)節(jié)可以先看文檔,這里面講的還是非常清楚的,包括一些接口說(shuō)明等.
這里我使用python寫(xiě)了個(gè)微信預(yù)支付的較為通用的類,大家改下參數(shù)拿去用就行,官方文檔一個(gè)個(gè)試出來(lái)的,簡(jiǎn)直坑:
class WeiXinPay(object): """微信支付,返回回客戶端需要參數(shù) """ def __init__(self, uu_id, open_id, spbill_create_ip, total_fee, out_trade_no): """ :param total_fee: 訂單金額 :param spbill_create_ip: 客戶端請(qǐng)求IP地址 """ self.params = { 'appid': '小程序的appid', 'attach': u'你的應(yīng)用名稱,我這里是(校園懶人邦)', 'body': u'校園懶人邦-代取費(fèi)', 'mch_id': '商戶id,你企業(yè)的id', 'nonce_str': '給個(gè)隨機(jī)數(shù),一般md5一下就好,時(shí)間戳啊或者別的什么', 'notify_url': 'http://www.happypower.com/result(這個(gè)就是通知地址,會(huì)異步返回信息給你),你寫(xiě)一個(gè)接口接收就行', 'openid': open_id, 'out_trade_no': out_trade_no, 'spbill_create_ip': spbill_create_ip, 'total_fee': str(total_fee), 'trade_type': 'JSAPI' } # 官方給的接口 self.url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' self.error = None def key_value_url(self, value): """將將鍵值對(duì)轉(zhuǎn)為 key1=value1&key2=value2 """ key_az = sorted(value.keys()) pair_array = [] for k in key_az: v = value.get(k, '').strip() v = v.encode('utf8') k = k.encode('utf8') pair_array.append('%s=%s' % (k, v)) tmp = '&'.join(pair_array) return tmp def get_sign(self, params): """生成sign """ stringA = self.key_value_url(params) stringSignTemp = stringA + '&key=' + 'xxx' # APIKEY, API密鑰,需要在商戶后臺(tái)設(shè)置 sign = (md5(stringSignTemp).hexdigest()).upper() params['sign'] = sign def get_req_xml(self): """拼接X(jué)ML """ self.get_sign(self.params) xml = "" for k, v in self.params.items(): v = v.encode('utf8') k = k.encode('utf8') xml += '<' + k + '>' + v + '' xml += "" print xml return xml def get_prepay_id(self): """ 請(qǐng)求獲取prepay_id """ xml = self.get_req_xml() headers = {'Content-Type': 'application/xml'} r = requests.post(self.url, data=xml, headers=headers) re_xml = ElementTree.fromstring(r.text.encode('utf8')) xml_status = re_xml.getiterator('result_code')[0].text if xml_status != 'SUCCESS': self.error = u"連接微信出錯(cuò)啦!" logging.error(u"連接微信出錯(cuò)啦!") return prepay_id = re_xml.getiterator('prepay_id')[0].text self.params['package'] = 'prepay_id=%s' % prepay_id self.params['timestamp'] = str(int(time.time())) def re_finall(self): self.get_prepay_id() if self.error: return sign_again_params = { 'appId': self.params['appid'], 'timeStamp': self.params['timestamp'], 'nonceStr': self.params['nonce_str'], 'package': self.params['package'], 'signType': 'MD5' } self.get_sign(sign_again_params) sign_again_params['paySign'] = sign_again_params['sign'] sign_again_params['total_fee'] = self.params['total_fee'] sign_again_params['notify_url'] = self.params['notify_url'] sign_again_params.pop('appId') sign_again_params.pop('sign') return json.dumps(sign_again_params)1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
5 這里最后返回的參數(shù)傳給前臺(tái)就能支付了,前臺(tái)會(huì)拿到你的prepay_id,然后就能按照指定金額支付了。
6 退款的話有些不同,首先也是具體先查看文檔,下面我也寫(xiě)了一個(gè)較為通用的類,大家覺(jué)得文檔麻煩直接用也行:
class WeiXinReturn(object): def __init__(self, out_trade_no, total_fee, refund_fee): self.params_mach = { # 申請(qǐng)商戶號(hào)的appid或商戶號(hào)綁定的appid 'appid': 'xxx', 'mch_id': 'xxx', 'nonce_str': '隨機(jī)數(shù)', 'out_trade_no': out_trade_no, 'out_refund_no': '微信訂單號(hào)', 'total_fee': str(total_fee), 'refund_fee': str(refund_fee), 'notify_url': 'http://www.happypower.com/pay_return/result(和支付一樣的意思,就是退款的通知地址,自己開(kāi)發(fā)一個(gè)接口就好)' } def pay_return(self): stringA = self.key_value_url(self.params_mach) stringSignTemp = stringA + '&key=' + 'xxx' # APIKEY, API密鑰,需要在商戶后臺(tái)設(shè)置 sign = (md5(stringSignTemp).hexdigest()).upper() self.params_mach['sign'] = sign xml = "" for k, v in self.params_mach.items(): v = v.encode('utf8') k = k.encode('utf8') xml += '<' + k + '>' + v + '' xml += "" headers = {'Content-Type': 'application/xml;charset=UTF-8'} # url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers' url = 'https://api.mch.weixin.qq.com/secapi/pay/refund' # 請(qǐng)求中需要帶有支付的證書(shū),沒(méi)有證書(shū)是無(wú)法申請(qǐng)的 r = requests.post(url, data=xml, headers=headers, cert=('xxx.pem', 'xxx.pem')) result = r.text re_xml = ElementTree.fromstring(r.text.encode('utf8')) xml_status = re_xml.getiterator('result_code')[0].text if xml_status == 'SUCCESS': return True return False def key_value_url(self, value): """將將鍵值對(duì)轉(zhuǎn)為 key1=value1&key2=value2 """ key_az = sorted(value.keys()) pair_array = [] for k in key_az: v = value.get(k, '').strip() v = v.encode('utf8') k = k.encode('utf8') pair_array.append('%s=%s' % (k, v)) tmp = '&'.join(pair_array) return tmp12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
ps.這里需要商戶證書(shū),具體怎么弄看這里
生成二維碼
這個(gè)功能比較常見(jiàn)了,同樣也是先看文檔,里面有三種二維碼接口,開(kāi)發(fā)階段建議使用接口B:https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN, 項(xiàng)目上線了用接口A會(huì)更加靈活,因?yàn)榭梢酝ㄟ^(guò)二維碼跳轉(zhuǎn)頁(yè)面且能夠攜帶參數(shù),校園懶人邦中的分享功能就是利用接口A進(jìn)行開(kāi)發(fā),主要接口A上線才好測(cè),而接口B開(kāi)發(fā)階段好測(cè)。
二維碼是圖片,涉及到存儲(chǔ)問(wèn)題,這里推薦七牛云,賬號(hào)免費(fèi)有10G的使用空間,很棒的,具體思路就是先到本地做一層緩存,然后本地上傳到七牛云,相關(guān)代碼可以參考下面的,基本已經(jīng)封裝好了:
def upload_img(self, local_path, upload_name, bucket_name, ttl=7200): """ 上傳圖片到七牛云 :param local_path: 本地文件路徑 :param upload_name: 上傳文件名 :param bucket_name: 七牛申請(qǐng)的存儲(chǔ)空間名稱 :param ttl: 過(guò)期時(shí)間 :return: 返回圖片地址 """ from qiniu import Auth, put_file import re q = Auth(access_key=conf_test.AccessKey, secret_key=conf_test.SecretKey) token = q.upload_token(bucket_name, upload_name, ttl) ret, info = put_file(token, upload_name, local_path) pat_status = 'status_code:(.*?),' status_code = re.compile(pat_status, re.S).findall(str(info)) if len(status_code) > 0: # 成功返回圖片外鏈名稱,失敗返回原因以及狀態(tài)碼 if int(status_code[0]) == 200: return {"msg":conf_test.qiniu_domain + upload_name, "status":1} return {"msg":"failed upload img failed", "status":-1}123456789101112131415161718192021
相關(guān)的sdk文檔可以參考這里
還有一個(gè)問(wèn)題就是微信小程序只能識(shí)別https的圖片外鏈地址,而剛開(kāi)始上傳七牛云生成的是http的鏈接圖片,因此這里需要到七牛云上面配置下,具體的可以查看這里
二維碼基本流程就是這么一套,當(dāng)然緩存怎么做方式很多,這里僅供參考。
推送消息
給用戶發(fā)送模板消息,提醒用戶做一些事也是經(jīng)常用到的功能,具體操作還是先查看文檔,當(dāng)然,微信規(guī)定了每天用戶只能最多收到三條消息,當(dāng)然還是有別的辦法可以給用戶多發(fā)一些消息,具體往下看.
看文檔可以知道,其實(shí)只需要有足夠的用戶form_id咱們就能對(duì)用戶無(wú)限制的發(fā)送消息,前提是用戶沒(méi)有屏蔽你的這個(gè)微信小程序,可以參考這里,當(dāng)然這里是用java寫(xiě)的,我按照這個(gè)封裝了一個(gè)python版本的,大家可以參考著用:
# 刷新用戶form_id 存入redis def fresh_formid(self, **kwargs): """ 接收前臺(tái)傳來(lái)的form_id存入redis :param kwargs: :return: """ uu_id = kwargs.get("uu_id", "") if not uu_id: return "failed: uu_id cannot be null" open_id = kwargs.get("open_id", "") if not open_id: return "failed: open_id cannot be null" form_id = kwargs.get("form_id", "") if not form_id: return "failed: form_id cannot be null" if "invalid code" in open_id: return "failed: get openid err" msg = {open_id: form_id} self.redis_cli.sadd(uu_id, json.dumps(msg)) return "success" # 發(fā)消息模板 def send_template_msg(self, **kwargs): uu_id = kwargs.get("uu_id", "") if not uu_id: return "failed: uu_id cannot be null" data = kwargs.get("data", "") if not data: return "failed: data can not be null" # 這個(gè)token可以從文檔中去查看怎么得到,內(nèi)部源碼不能提供 token = self.get_refresh_token() if not token: return "failed: cannot find a token" send_msg = {} # 從redis中取出用戶對(duì)應(yīng)的form_id redis_msg = self.redis_cli.spop(uu_id) if not redis_msg: return "failed: cannot find a open_id in redis" msg = json.loads(redis_msg.encode("utf8")) touser = msg.keys()[0] form_id = msg[touser] template_id = kwargs.get("template_id", "") if not template_id: return "failed: template_id cannot be null" # page是用戶點(diǎn)開(kāi)消息后跳轉(zhuǎn)到的頁(yè)面 page = kwargs.get("page", "") # 下面這些參數(shù)的含義在文檔中都能查到 emphasis_keyword = kwargs.get("emphasis_keyword", "") send_msg["touser"] = touser send_msg["template_id"] = template_id send_msg["page"] = page send_msg["form_id"] = form_id send_msg["data"] = data send_msg["emphasis_keyword"] = emphasis_keyword # 調(diào)起發(fā)送消息接口 api = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s" % token # post方式發(fā)起網(wǎng)絡(luò)請(qǐng)求 return self.get_html(url=api, data=send_msg)12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
測(cè)試
黑盒測(cè)試
應(yīng)用上線之前肯定要各種測(cè)試才行,功能上黑盒測(cè)試可以交給不太懂代碼的同學(xué),也就是按照流程走通一遍,中途出現(xiàn)的問(wèn)題記錄下來(lái)然后交給程序哥哥。
qps測(cè)試
我這里主要介紹下qps的測(cè)試,因?yàn)槲覀兪墙o用戶用的,我們必須估計(jì)一下我們的服務(wù)器能承載多少用戶同時(shí)在線,也就是平均來(lái)說(shuō)能承受多少用戶每秒的請(qǐng)求數(shù)量, 我們可以對(duì)最常用的幾個(gè)接口做一個(gè)極限測(cè)試,然后計(jì)算出大致的qps, 最簡(jiǎn)單的做法就是多線程瘋狂的call計(jì)算平均時(shí)間,這里給出一段測(cè)試代碼:
class PressTest(object): def __init__(self): pass def get_html(self, url, headers=conf_test.HEADERS, data=None): if data: data = json.dumps(data) req = urllib2.Request(url=url, headers=headers, data=data) response = urllib2.urlopen(req) html = response.read() return html def get_test(self, api_url): result = self.get_html(url=api_url) if not result: print "url %s result is none" %api_url return return def post_test(self, api_url, **kwargs): import time start_time = time.time() result = self.get_html(url=api_url, data=kwargs) print result if not result: print "url %s result is none" % api_url end_time = time.time() all = end_time - start_time print allif __name__ == '__main__': press_test = PressTest() print "requesting........." api_url = 'https://xxx接口1' api_url2 = 'https://xxx接口2' start = time.time() times = 400 for i in range(times): t1 = threading.Thread(target=press_test.get_test, args=(api_url,)) t2 = threading.Thread(target=press_test.get_test, args=(api_url2,)) t1.start() t2.start() t1.join() t2.join() end = time.time() ave = (end - start) / 800.0 print "count:%d, start_time :%s, now_time: %s, average_qps: %s" % (800, str(start), str(end), str(ave))12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
這里是開(kāi)了400個(gè)線程并發(fā)call這兩個(gè)常用接口,最后計(jì)算出qps(每秒的請(qǐng)求數(shù)),如果能達(dá)到100次/秒,基本上幾千人同時(shí)在線沒(méi)啥問(wèn)題,哈哈
歡迎加入Java高級(jí)架構(gòu)學(xué)習(xí)交流群:375989619
本群提供免費(fèi)的學(xué)習(xí)指導(dǎo) 架構(gòu)資料 以及免費(fèi)的解答
不懂得問(wèn)題都可以在本群提出來(lái) 之后還會(huì)有職業(yè)生涯規(guī)劃以及面試指導(dǎo) 進(jìn)群修改群備注:開(kāi)發(fā)年限-地區(qū)-經(jīng)驗(yàn) 方便架構(gòu)師解答問(wèn)題
免費(fèi)領(lǐng)取架構(gòu)師全套視頻?。。。。。。?!
日期:2018-04 瀏覽次數(shù):6790
日期:2017-02 瀏覽次數(shù):3472
日期:2017-09 瀏覽次數(shù):3690
日期:2017-12 瀏覽次數(shù):3557
日期:2018-12 瀏覽次數(shù):4857
日期:2016-12 瀏覽次數(shù):4608
日期:2017-07 瀏覽次數(shù):13667
日期:2017-12 瀏覽次數(shù):3538
日期:2018-06 瀏覽次數(shù):4292
日期:2018-05 瀏覽次數(shù):4477
日期:2017-12 瀏覽次數(shù):3582
日期:2017-06 瀏覽次數(shù):4007
日期:2018-01 瀏覽次數(shù):3969
日期:2016-12 瀏覽次數(shù):3933
日期:2018-08 瀏覽次數(shù):4450
日期:2017-12 瀏覽次數(shù):3749
日期:2016-09 瀏覽次數(shù):6480
日期:2018-07 瀏覽次數(shù):3238
日期:2016-12 瀏覽次數(shù):3253
日期:2018-10 瀏覽次數(shù):3407
日期:2018-10 瀏覽次數(shù):3514
日期:2018-09 瀏覽次數(shù):3601
日期:2018-02 瀏覽次數(shù):3622
日期:2015-05 瀏覽次數(shù):3549
日期:2018-09 瀏覽次數(shù):3333
日期:2018-06 瀏覽次數(shù):3460
日期:2017-02 瀏覽次數(shù):3895
日期:2018-02 瀏覽次數(shù):4356
日期:2018-02 瀏覽次數(shù):4215
日期:2016-12 瀏覽次數(shù):3599
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.