本文将以个人(开发)的角度,讲述如何从零开始,编写、搭建和部署一个基于Python的Web应用程序。

从最简单的出发点来剖析,一个web应用后端要完成的工作抽象出来无非就是3点:

  1. 接收和解析请求。
  2. 处理业务逻辑。
  3. 生产和返回响应。

对于初学者来说,我们关心的只需这些步骤就够了。要检验这三个步骤,最简单的方法是先写出一个hello world。

request->"hello world"->response

python有许多流行的web框架,我们该如何选择呢?试着考虑三个因素:

  • 易用:该框架是面对初学者友好的,而且具有健全的文档,灵活开发部署。例如flask,bottle。
  • 效率:该框架适合快速开发,拥有丰富的轮子,注重开发效率。例如django。
  • 性能:该框架能承载更大的请求压力,提高吞吐量。例如falcon,tornado,aiohttp,sanic。

根据场景使用合适的框架能少走许多弯路,当然,你还能自己写一个框架,这个下面再说。

对于缺乏经验的人来说,易用性无疑是排在第一位的,推荐用flask作为python web入门的第一个框架,另外也推荐django。

首先用virtualenv创建python的应用环境,为什么用virtualenv呢,virtualenv能创建一个纯净独立的python环境,避免污染全局环境。(顺便安利kennethreitz大神的pipenv)

mkdir todo
cd todo
virtualenv venv
source venv/bin/activate
pip install flask
touch server.py

代码未写,规范先行。在写代码之前要定义好一套良好代码规范,例如PEP8。这样才能使得你的代码变的更加可控。

心中默念The Zen of Python:

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

下面用flask来编写第一个程序:

from flask import Flask, jsonifyapp = Flask(__name__)@app.route('/index')
def index():return jsonify(msg='hello world')if __name__ == '__main__':app.run(host='0.0.0.0', port=8000)

在命令行输入python server.py

python server.py
* Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)

打开浏览器,访问http://127.0.0.1:8000/index,如无意外,会看到下面的响应。

{"msg": "hello world"
}

一个最简单的web程序就完成了!让我们看下过程中都发生了什么:

  1. 客户端(浏览器)根据输入的地址http://127.0.0.1:8000/index找到协议(http),主机(127.0.0.1),端口(8000)和路径(/index),与服务器(application server)建立三次握手,并发送一个http请求。

  2. 服务器(application server)把请求报文封装成请求对象,根据路由(router)找到/index这个路径所对应的视图函数,调用这个视图函数。

  3. 视图函数生成一个http响应,返回一个json数据给客户端。

    HTTP/1.0 200 OK
    Content-Type: application/json
    Content-Length: 27
    Server: Werkzeug/0.11.15 Python/3.5.2
    Date: Thu, 26 Jan 2017 05:14:36 GMT

当我们输入python server.py时,会建立一个服务器(也叫应用程序服务器,即application server)来监听请求,并把请求转给flask来处理。那么这个服务器是如何跟python程序打交道的呢?答案就是WSGI(Web Server Gateway Interface)接口,它是server端(服务器)与application端(应用程序)之间的一套约定俗成的规范,使我们只要编写一个统一的接口,就能应用到不同的wsgi server上。用图表示它们的关系,就是下面这样的:

只要application端(flask)和server端(flask内建的server)都遵循wsgi这个规范,那么他们就能够协同工作了,关于WSGI规范,可参阅Python官方的PEP 333里的说明。

目前为止,应用是下面这个样子的:

一切都很简单,现在我们要做一个Todo应用,提供添加todo,修改todo状态和删除todo的接口。

先不考虑数据库,可以迅速地写出下面的代码:

from flask import Flask, jsonify, request, abort, Response
from time import time
from uuid import uuid4
import jsonapp = Flask(__name__)class Todo(object):def __init__(self, content):self.id = str(uuid4())self.content = content #todo内容self.created_at = time() #创建时间self.is_finished = False #是否完成self.finished_at = None #完成时间def finish(self):self.is_finished = Trueself.finished_at = time()def json(self):return {'id': self.id,'content': self.content,'created_at': self.created_at,'is_finished': self.is_finished,'finished_at': self.finished_at}todos = {}
get_todo = lambda tid: todos.get(tid, False)@app.route('/todo')
def index():return jsonify(data=[todo.json() for todo in todos.values()])@app.route('/todo', methods=['POST'])
def add():content = request.form.get('content', None)if not content:abort(400)todo = Todo(content)todos[todo.id] = todoreturn Response() #200@app.route('/todo/<tid>/finish', methods=['PUT'])
def finish(tid):todo = get_todo(tid)if todo:todo.finish()todos[todo.id] = todoreturn Response()abort(404)@app.route('/todo/<tid>', methods=['DELETE'])
def delete(tid):todo = get_todo(tid)if todo:todos.pop(tid)return Response()abort(404)if __name__ == '__main__':app.run(host='0.0.0.0', port=8000)

这个程序基本实现了需要的接口,现在测试一下功能。

  • 添加一个todo
http -f POST http://127.0.0.1:8000/todo content=好好学习
HTTP/1.0 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Thu, 26 Jan 2017 06:45:37 GMT
Server: Werkzeug/0.11.15 Python/3.5.2
  • 查看todo列表
http http://127.0.0.1:8000/todo
HTTP/1.0 200 OK
Content-Length: 203
Content-Type: application/json
Date: Thu, 26 Jan 2017 06:46:16 GMT
Server: Werkzeug/0.11.15 Python/3.5.2{"data": ["{\"created_at\": 1485413137.305699, \"id\": \"6f2b28c4-1e83-45b2-8b86-20e28e21cd40\", \"is_finished\": false, \"finished_at\": null, \"content\": \"\\u597d\\u597d\\u5b66\\u4e60\"}"]
}
  • 修改todo状态
http -f PUT http://127.0.0.1:8000/todo/6f2b28c4-1e83-45b2-8b86-20e28e21cd40/finish
HTTP/1.0 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Thu, 26 Jan 2017 06:47:18 GMT
Server: Werkzeug/0.11.15 Python/3.5.2http http://127.0.0.1:8000/todo
HTTP/1.0 200 OK
Content-Length: 215
Content-Type: application/json
Date: Thu, 26 Jan 2017 06:47:22 GMT
Server: Werkzeug/0.11.15 Python/3.5.2{"data": ["{\"created_at\": 1485413137.305699, \"id\": \"6f2b28c4-1e83-45b2-8b86-20e28e21cd40\", \"is_finished\": true, \"finished_at\": 1485413238.650981, \"content\": \"\\u597d\\u597d\\u5b66\\u4e60\"}"]
}
  • 删除todo
http -f DELETE http://127.0.0.1:8000/todo/6f2b28c4-1e83-45b2-8b86-20e28e21cd40
HTTP/1.0 200 OK
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Thu, 26 Jan 2017 06:48:20 GMT
Server: Werkzeug/0.11.15 Python/3.5.2http http://127.0.0.1:8000/todo
HTTP/1.0 200 OK
Content-Length: 17
Content-Type: application/json
Date: Thu, 26 Jan 2017 06:48:22 GMT
Server: Werkzeug/0.11.15 Python/3.5.2{"data": []
}

但是这个的程序的数据都保存在内存里,只要服务一停止所有的数据就没办法保存下来了,因此,我们还需要一个数据库用于持久化数据。

那么,应该选择什么数据库呢?

  • 传统的rdbms,例如mysql,postgresql等,他们具有很高的稳定性和不俗的性能,结构化查询,支持事务,由ACID来保持数据的完整性。
  • nosql,例如mongodb,cassandra等,他们具有非结构化特性,易于横向扩展,实现数据的自动分片,拥有灵活的存储结构和强悍的读写性能。

这里使用mongodb作例子,使用mongodb改造后的代码是这样的:

from flask import Flask, jsonify, request, abort, Response
from time import time
from bson.objectid import ObjectId
from bson.json_util import dumps
import pymongoapp = Flask(__name__)mongo = pymongo.MongoClient('127.0.0.1', 27017)
db = mongo.todoclass Todo(object):@classmethoddef create_doc(cls, content):return {'content': content,'created_at': time(),'is_finished': False,'finished_at': None}@app.route('/todo')
def index():todos = db.todos.find({})return dumps(todos)@app.route('/todo', methods=['POST'])
def add():content = request.form.get('content', None)if not content:abort(400)db.todos.insert(Todo.create_doc(content))return Response() #200@app.route('/todo/<tid>/finish', methods=['PUT'])
def finish(tid):result = db.todos.update_one({'_id': ObjectId(tid)},{'$set': {'is_finished': True,'finished_at': time()}}    )if result.matched_count == :abort(404)return Response()@app.route('/todo/<tid>', methods=['DELETE'])
def delete(tid):result = db.todos.delete_one({'_id': ObjectId(tid)}  )if result.matched_count == :abort(404)return Response()if __name__ == '__main__':app.run(host='0.0.0.0', port=8000)

这样一来,应用的数据便能持久化到本地了。现在,整个应用看起来是下面这样的:

现在往mongodb插入1万条数据。

import requestsfor i in range(10000):requests.post('http://127.0.0.1:8000/todo', {'content': str(i)})

获取todo的接口目前是有问题的,因为它一次性把数据库的所有记录都返回了,当数据记录增长到一万条的时候,这个接口的请求就会变的非常慢,需要500ms后才能发出响应。现在对它进行如下的改造:

@app.route('/todo')
def index():start = request.args.get('start', '')start = int(start) if start.isdigit() else todos = db.todos.find().sort([('created_at', -1)]).limit(10).skip(start)return dumps(todos)

每次只取十条记录,按创建日期排序,先取最新的,用分页的方式获取以往记录。改造后的接口现在只需50ms便能返回响应。

现在对这个接口进行性能测试:

wrk -c 100 -t 12 -d 5s http://127.0.0.1:8000/todo
Running 5s test @ http://127.0.0.1:8000/todo12 threads and 100 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency     1.22s   618.29ms   1.90s    48.12%Req/Sec    14.64     10.68    40.00     57.94%220 requests in 5.09s, 338.38KB readSocket errors: connect 0, read 0, write 0, timeout 87
Requests/sec:     43.20
Transfer/sec:     66.45KB

rps只有43。我们继续进行改进,通过观察我们发现我们查询todo时需要通过created_at这个字段进行排序再过滤,这样以来每次查询都要先对10000条记录进行排序,效率自然变的很低,对于这个场景,可以对created_at这个字段做索引:

db.todos.ensureIndex({'created_at': -1})

通过explain我们轻易地看出mongo使用了索引做扫描

> db.todos.find().sort({'created_at': -1}).limit(10).explain()
/* 1 */
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "todo.todos","indexFilterSet" : false,"parsedQuery" : {},"winningPlan" : {"stage" : "LIMIT","limitAmount" : 10,"inputStage" : {"stage" : "FETCH","inputStage" : {"stage" : "IXSCAN","keyPattern" : {"created_at" : -1.0},"indexName" : "created_at_-1","isMultiKey" : false,"multiKeyPaths" : {"created_at" : []},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"created_at" : [ "[MaxKey, MinKey]"]}}}},"rejectedPlans" : []},"serverInfo" : {"host" : "841bf506b6ec","port" : 27017,"version" : "3.4.1","gitVersion" : "5e103c4f5583e2566a45d740225dc250baacfbd7"},"ok" : 1.0
}

现在再做一轮性能测试,有了索引之后就大大降低了排序的成本,rps提高到了298。

wrk -c 100 -t 12 -d 5s http://127.0.0.1:8000/todo
Running 5s test @ http://127.0.0.1:8000/todo12 threads and 100 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   310.32ms   47.51ms 357.47ms   94.57%Req/Sec    26.88     14.11    80.00     76.64%1511 requests in 5.06s, 2.27MB read
Requests/sec:    298.34
Transfer/sec:    458.87KB

再把重心放到app server上,目前我们使用flask内建的wsgi server,这个server由于是单进程单线程模型的,所以性能很差,一个请求不处理完的话服务器就会阻塞住其他请求,我们需要对这个server做替换。关于python web的app server选择,目前主流采用的有:

  • gunicorn
  • uWSGI

我们看gunicorn文档可以得知,gunicorn是一个python编写的高效的WSGI HTTP服务器,gunicorn使用pre-fork模型(一个master进程管理多个child子进程),使用gunicorn的方法十分简单:

gunicorn --workers=9 server:app --bind 127.0.0.1:8000

根据文档说明使用(2 * cpu核心数量)+1个worker,还要传入一个兼容wsgi app的start up方法,通过Flask的源码可以看到,Flask这个类实现了下面这个接口:

    def __call__(self, environ, start_response):"""Shortcut for :attr:`wsgi_app`."""return self.wsgi_app(environ, start_response)

也就是说我们只需把flask实例的名字传给gunicorn就ok了:

gunicorn --workers=9 server:app --bind 127.0.0.1:8000
[2017-01-27 11:20:01 +0800] [5855] [INFO] Starting gunicorn 19.6.0
[2017-01-27 11:20:01 +0800] [5855] [INFO] Listening at: http://127.0.0.1:8000 (5855)
[2017-01-27 11:20:01 +0800] [5855] [INFO] Using worker: sync
[2017-01-27 11:20:01 +0800] [5889] [INFO] Booting worker with pid: 5889
[2017-01-27 11:20:01 +0800] [5890] [INFO] Booting worker with pid: 5890
[2017-01-27 11:20:01 +0800] [5891] [INFO] Booting worker with pid: 5891
[2017-01-27 11:20:01 +0800] [5892] [INFO] Booting worker with pid: 5892
[2017-01-27 11:20:02 +0800] [5893] [INFO] Booting worker with pid: 5893
[2017-01-27 11:20:02 +0800] [5894] [INFO] Booting worker with pid: 5894
[2017-01-27 11:20:02 +0800] [5895] [INFO] Booting worker with pid: 5895
[2017-01-27 11:20:02 +0800] [5896] [INFO] Booting worker with pid: 5896
[2017-01-27 11:20:02 +0800] [5897] [INFO] Booting worker with pid: 5897

可以看到gunicorn启动了9个进程(其中1个父进程)监听请求。使用了二手QQ买号多进程的模型看起来是下面这样的:

继续进行性能测试,可以看到吞吐量又有了很大的提升:

wrk -c 100 -t 12 -d 5s http://127.0.0.1:8000/todo
Running 5s test @ http://127.0.0.1:8000/todo12 threads and 100 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   109.30ms   16.10ms 251.01ms   90.31%Req/Sec    72.47     10.48   100.00     78.89%4373 requests in 5.07s, 6.59MB read
Requests/sec:    863.35
Transfer/sec:      1.30MB

那么gunicorn还能再优化吗,答案是肯定的。回到之前我们发现了这一行:

[2017-01-27 11:20:01 +0800] [5855] [INFO] Using worker: sync

也就是说,gunicorn worker使用的是sync(同步)模式来处理请求,那么它支持async(异步)模式吗,再看gunicorn的文档有下面一段说明:

Async Workers
The asynchronous workers available are based on Greenlets (via Eventlet and Gevent). Greenlets are an implementation of cooperative multi-threading for Python. In general, an application should be able to make use of these worker classes with no changes.

gunicorn支持基于greenlet的异步的worker,它使得worker能够协作式地工作。当worker阻塞在外部调用的IO操作时,gunicorn会聪明地把执行调度给其他worker,挂起当前的worker,直至IO操作完成后,被挂起的worker又会重新加入到调度队列中,这样gunicorn便有能力处理大量的并发请求了。

gunicorn有两个不错的async worker:

  • meinheld
  • gevent

meinheld是一个基于picoev的异步WSGI Web服务器,它可以很轻松地集成到gunicorn中,处理wsgi请求。

gunicorn --workers=9 --worker-class="meinheld.gmeinheld.MeinheldWorker" server:app --bind 127.0.0.1:8000
[2017-01-27 11:47:01 +0800] [7497] [INFO] Starting gunicorn 19.6.0
[2017-01-27 11:47:01 +0800] [7497] [INFO] Listening at: http://127.0.0.1:8000 (7497)
[2017-01-27 11:47:01 +0800] [7497] [INFO] Using worker: meinheld.gmeinheld.MeinheldWorker
[2017-01-27 11:47:01 +0800] [7531] [INFO] Booting worker with pid: 7531
[2017-01-27 11:47:01 +0800] [7532] [INFO] Booting worker with pid: 7532
[2017-01-27 11:47:01 +0800] [7533] [INFO] Booting worker with pid: 7533
[2017-01-27 11:47:01 +0800] [7534] [INFO] Booting worker with pid: 7534
[2017-01-27 11:47:01 +0800] [7535] [INFO] Booting worker with pid: 7535
[2017-01-27 11:47:01 +0800] [7536] [INFO] Booting worker with pid: 7536
[2017-01-27 11:47:01 +0800] [7537] [INFO] Booting worker with pid: 7537
[2017-01-27 11:47:01 +0800] [7538] [INFO] Booting worker with pid: 7538
[2017-01-27 11:47:01 +0800] [7539] [INFO] Booting worker with pid: 7539

可以看到现在使用的是meinheld.gmeinheld.MeinheldWorker这个worker。再进行性能测试看看:

wrk -c 100 -t 12 -d 5s http://127.0.0.1:8000/todo
Running 5s test @ http://127.0.0.1:8000/todo12 threads and 100 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency    84.53ms   39.90ms 354.42ms   72.11%Req/Sec    94.52     20.84   150.00     70.28%5684 requests in 5.04s, 8.59MB read
Requests/sec:   1128.72
Transfer/sec:      1.71MB

果然提升了不少。

现在有了app server,那需要nginx之类的web server吗?看看nginx反向代理能带给我们什么好处:

  • 负载均衡,把请求平均地分到上游的app server进程。
  • 静态文件处理,静态文件的访问交给nginx来处理,降低了app server的压力。
  • 接收完客户端所有的TCP包,再一次交给上游的应用来处理,防止app server被慢请求干扰。
  • 访问控制和路由重写。
  • 强大的ngx_lua模块。
  • Proxy cache。
  • Gzip,SSL...

为了以后的扩展性,带上一个nginx是有必要的,但如果你的应用没大的需求,那么可加可不加。

想让nginx反向代理gunicorn,只需对nginx的配置文件加入几行配置,让nginx通过proxy_pass打到gunicorn监听的端口上就可以了:

      server {listen 8888;location / {proxy_pass http://127.0.0.1:8000;proxy_redirect     off;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}}

现在应用的结构是这样的:

但仅仅是这样还是不足以应对高并发下的请求的,洪水般的请求势必是对数据库的一个重大考验,把请求数提升到1000,出现了大量了timeout:

wrk -c 1000 -t 12 -d 5s http://127.0.0.1:8888/todo
Running 5s test @ http://127.0.0.1:8888/todo12 threads and 1000 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency   239.50ms  235.76ms   1.93s    91.13%Req/Sec    83.07     76.77   434.00     76.78%4548 requests in 5.10s, 6.52MB readSocket errors: connect 0, read 297, write 0, timeout 36Non-2xx or 3xx responses: 289
Requests/sec:    892.04
Transfer/sec:      1.28MB

阻止洪峰的方法有:

  • 限流(水桶算法)
  • 分流(负载均衡)
  • 缓存
  • 访问控制

等等..这里重点说缓存,缓存系统是每个web应用程序重要的一个模块,缓存的作用是把热点数据放入内存中,降低对数据库的压力。

下面用redis来对第一页的数据进行缓存:

rds = redis.StrictRedis('127.0.0.1', 6379)@app.route('/todo')
def index():start = request.args.get('start', '')start = int(start) if start.isdigit() else data = rds.get('todos')if data and start == :return datatodos = db.todos.find().sort([('created_at', -1)]).limit(10).skip(start)data = dumps(todos)rds.set('todos', data, 3600)return data

只有在第一次请求时接触到数据库,其余请求都会从缓存中读取,瞬间就提高了应用的rps。

wrk -c 1000 -t 12 -d 5s http://127.0.0.1:8888/todo
Running 5s test @ http://127.0.0.1:8888/todo12 threads and 1000 connectionsThread Stats   Avg      Stdev     Max   +/- StdevLatency    68.33ms   95.27ms   1.34s    93.69%Req/Sec   277.32    258.20     1.60k    77.33%15255 requests in 5.10s, 22.77MB readSocket errors: connect 0, read 382, write 0, timeout 0Non-2xx or 3xx responses: 207
Requests/sec:   2992.79
Transfer/sec:      4.47MB

上面的这个示例只展示了基础的缓存方式,并没有针对多用户的情况处理,在涉及到状态条件的影响下,应该使用更加复杂的缓存策略。

现在再来考虑使用缓存不当会造成几个问题,设置缓存的时间是3600秒,当3600秒过后缓存失效,而新缓存又没完成的中间时间内,如果有大量请求到来,就会蜂拥去查询数据库,这种现象称为缓存雪崩,针对这个情况,可以对数据库请求这个动作进行加锁,只允许第一个请求访问数据库,更新缓存后其他的请求都会访问缓存,第二种方法是做二级缓存,拷贝缓存比一级缓存设置更长的过期时间。还有缓存穿透缓存一致性等问题虽然这里没有体现,但也是缓存设计中值得思考的几个点。

下面是加入缓存后的系统结构:

目前为止还不能说完善,如果中间某个进程挂掉了,那么整个系统的稳定性就会土崩瓦解。为此,要在中间加入一个进程管理工具:supervisor来监控和重启应用进程。

首先要建立supervisor的配置文件:supervisord.conf

[program:gunicorn]
command=gunicorn --workers=9 --worker-class="meinheld.gmeinheld.MeinheldWorker" server:app --bind 127.0.0.1:8000
autostart=true
autorestart=true
stdout_logfile=access.log
stderr_logfile=error.log

然后启动supervisord作为后台进程。

supervisord -c supervisord.conf

虽然缓存可以有效地帮我们减轻数据库的压力,但如果系统遇到大量并发的耗时任务时,进程也会阻塞在任务的处理上,影响了其他普通请求的正常响应,严重时,系统很可能会出现假死现象,为了针对对耗时任务的处理,我们的应用还需要引入一个外部作业的处理系统,当程序接收到耗时任务的请求时,交给任务的工作进程池来处理,然后再通过异步回调或消息通知等方式来获得处理结果。

应用程序与任务进程的通信通常借助消息队列的方式来进行通信,简单来说,应用程序会把任务信息序列化为一条消息(message)放入(push)与特定任务进程之间的信道里(channel),消息的中间件(broker)负责把消息持久化到存储系统,此时任务进程再通过轮询的方式获取消息,处理任务,再把结果存储和返回。

显然,此时我们需要一个负责分发消息和与队列打交道的调度器和一个存储消息的中间件。

Celery是基于Python的一个分布式的消息队列调度系统,我们把Celery作为消息调度器,Redis作为消息存储器,那么应用看起来应该是这样的。

一般来说,这个结构已经满足大多数的小规模应用了,剩下做的就是代码和组件配置的调优了。

然后还有一个很重要的点就是:测试

虽然很多人不喜欢写测试(我也不喜欢),但良好的测试对调试和排错是有很大帮助的。这里指的测试不仅仅是单元测试,关于测试可以从几个方面入手:

  • 压力测试
    • wrk(请求)
    • htop(cpu和内存占用)
    • dstat(硬盘读写)
    • tcpdump(网络包)
    • iostat(io读写)
    • netstat(网络连接)
  • 代码测试
    • unittest(单元测试)
    • selenium(浏览器测试)
    • mock/stub
  • 黑盒测试
  • 功能测试
  • ...

还有另一个没提到的点就是:安全,主要注意几个点,其他奇形怪状的坑根据实际情况作相应的调整:

  • SQL注入
  • XSS攻击
  • CSRF攻击
  • 重要信息加密
  • HTTPS
  • 防火墙
  • 访问控制

面对系统日益复杂和增长的依赖,有什么好的方法来保持系统的高可用和稳定一致性呢?docker是应用隔离和自动化构建的最佳选择。docker提供了一个抽象层,虚拟化了操作系统环境,用容器技术为应用的部署提供了沙盒环境,使应用之间能灵活地组合部署。

将每个组件独立为一个docker容器:

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                                                NAMES
cdca11112543        nginx               "nginx -g 'daemon off"   2 days ago          Exited (128) 2 days ago                                                         nginx
83119f92104a        cassandra           "/docker-entrypoint.s"   2 days ago          Exited (0) 2 days ago                                                           cassandra
841bf506b6ec        mongo               "/entrypoint.sh mongo"   2 days ago          Exited (1) 2 minutes ago   0.0.0.0:27017->27017/tcp, 0.0.0.0:28017->28017/tcp   mongo
b110a4530c4a        python:latest       "python3"                2 days ago          Exited (0) 46 hours ago                                                         python
b522b2a8313b        phpfpm              "docker-php-entrypoin"   4 days ago          Exited (0) 4 days ago                                                           php-fpm
f8630d4b48d7        spotify/kafka       "supervisord -n"         2 weeks ago         Exited (0) 6 days ago                                                           kafka

关于docker的用法,可以了解官方文档。

当业务逐渐快速增长时,原有的架构很可能已经不能支撑大流量带来的访问压力了。

这时候就可以使用进一步的方法来优化应用:

  • 优化查询,用数据库工具做explain,记录慢查询日志。
  • 读写分离,主节点负责接收写,复制的从节点负责读,并保持与主节点同步数据。
  • 页面缓存,如果你的应用是面向页面的,可以对页面和数据片进行缓存。
  • 做冗余表,把一些小表合并成大表以减少对数据库的查询次数。
  • 编写C扩展,把性能痛点交给C来处理。
  • 提高机器配置,这也许是最简单粗暴地提升性能的方式了...
  • PyPy

不过即使再怎么优化,单机所能承载的压力毕竟是有限的,这时候就要引入更多的服务器,做LVS负载均衡,提供更大的负载能力。但多机器的优化带来了许多额外的问题,比如,机器之间怎么共享状态和数据,怎么通信,怎么保持一致性,所有的这些都迫使着原有的结构要更进一步,进化为一个分布式系统,使各个组件之间连接为一个互联网络。

这时候你需要解决的问题就更多了:

  • 集群的部署搭建
  • 单点问题
  • 分布式锁
  • 数据一致性
  • 数据可用性
  • 分区容忍性
  • 数据备份
  • 数据分片
  • 数据热启动
  • 数据丢失
  • 事务

分布式的应用的结构是下面这样的:


 

展开来说还有很多,服务架构,自动化运维,自动化部署,版本控制、前端,接口设计等,不过我认为到这里,作为后端的基本职责就算是完成了。除了基本功,帮你走得更远的是内功:操作系统、数据结构、计算机网络、设计模式、数据库这些能力能帮助你设计出更加完好的程序。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 矩阵乘法加速递推

    当获得一个递推式时&#xff0c;要求我们求第NNN项&#xff0c;但是这个N≤2109N \le 210^9N≤2109很大&#xff0c;单纯的O(n)O(n)O(n)递推无法解决。这个时候就需要用到矩阵乘法来加速递推 矩阵乘法&#xff1a; 设 AAA是n∗mn * mn∗m 矩阵&#xff0c;BBB是m∗pm * pm∗p矩…...

    2024/5/10 4:58:53
  2. 移民可以上网易新闻做推广吗?跑得效果怎么样啊

    移民可以上哪些平台做推广呢&#xff1f;跑得效果怎么样啊&#xff1f;成本跑得多少呢&#xff1f; 海外移民可以上的那些广告推广平台呢&#xff1f;海外移民还是比较具有局限性的&#xff0c;能上的平台不是很多&#xff0c;比如&#xff1a;知乎广告推广平台、网易广告推广…...

    2024/5/9 3:55:09
  3. Linux 最常用命令:解决 95% 以上的问题

    Linux是目前应用最广泛的服务器操作系统&#xff0c;基于Unix&#xff0c;开源免费&#xff0c;由于系统的稳定性和安全性&#xff0c;市场占有率很高&#xff0c;几乎成为程序代码运行的最佳系统环境。linux不仅可以长时间的运行我们编写的程序代码&#xff0c;还可以安装在各…...

    2024/5/9 6:55:55
  4. 隐马尔可夫模型(HMM)

    本文不是HMM的详细推导文章&#xff0c;是对HMM的一个小总结。详细的推导可参考李航统计学习方法第10章。本文目录如下&#xff1a; 隐马尔可夫模型简介 HMM可用于标注问题。隐马尔可夫模型是关于时序的概率模型&#xff0c;由一个隐藏的马尔可夫链随机生成不可观测的状态随机…...

    2024/5/8 19:19:29
  5. 深入浅出Visual C++动态链接库(DLL)编程

    转自&#xff1a;深入浅出Visual C动态链接库(DLL)编程(第二章vs2010篇)第二章&#xff1a;VC动态链接库编程之非MFCDLL2 1、一个简单的DLL第1 2节给出了以静态链接库方式提供add函数接口的方法&#xff0c;接下来我们来看看怎样用动态链接库实现一个同样功能的add函数。如图6&…...

    2024/5/8 13:05:27
  6. 图像质量评价指标

    本文目录一、均方误差&#xff08;Mean Square Error&#xff0c;MSE&#xff09;1. 简介2. 公式二、峰值信噪比&#xff08;Peak Signal Noise Ratio&#xff0c;PSNR&#xff09;1. 简介2. 计算(1) 灰度图像计算(2) RGB彩色图像计算三、结构相似性&#xff08;Structure Simi…...

    2024/5/8 23:05:34
  7. Django实践笔记

    本文以Python的Web框架Django为例&#xff0c;整理下做从零开始到一个成型的网站所涉及到内容&#xff0c;目的不是教你如何一步一步搭建项目&#xff0c;而是让你对Django的良好实践有个大概的了解。虽然很久没用Django&#xff0c;但还是想把以前整理的笔记分享给初学者&…...

    2024/5/8 20:41:37
  8. qss优先级设置

    录 一、简述 二、样式表语法 2.1 样式规则 2.2 选择器类型 2.3 子控件 2.4 伪选择器 2.5 解决冲突 2.6 级联效应 2.7 继承性 三、CSS常用样式 3.1 CSS文字属性 3.2 CSS背景样式&#xff1a; 3.3 CSS边框空白 3.4 CSS框线 3.5 CSS边界样式 回到顶部 一、简述 Qt样式表&#xf…...

    2024/5/2 21:53:04
  9. ResNet50《pytorch学习篇》

    引言&#xff1a;resNet50网络作为res网络家族中的一员&#xff0c;特别强调的是残差网络是何大神提出的&#xff0c;轰动世界的大江南北&#xff0c;主要是因为&#xff1a;当时的卷积神经网络主要通过不断地增加卷积层来提取图像的特征&#xff0c;但是这会引发一个问题-----…...

    2024/5/8 13:12:27
  10. N08020耐腐蚀合金硬度密度查询

    /(UNS N08020) /20号合金/alloy20/Ns143/ns1403/ CA20/ Carpenter 20Cb/0Cr20Ni35Mo3Cu3Nb NAS 335X、W.Nr.2.4660Nicrofer 3620 Nb-alloy20、ATI 20 国际通称&#xff1a;Alloy 20合金、UNS N08020、NS143、Inconel alloy20/NAS 335X、W.Nr.2.4460 Nicrofer 3620 Nb-alloy…...

    2024/5/8 11:31:08
  11. 3、CRUD

    3.1、namespace namespace中的包名要和Dao/mapper借口一致! 3.2、select 选择、查询语句;id: 就是对应namespace中的方法名resultType: sql语句执行的返回值 parameterType &#xff1a;参数的类型​ Mapper接口 //查询全部用户List<User> getUserList();//根据ID查…...

    2024/5/9 7:48:05
  12. 设计模式 行为型模式 -- 状态模式

    1. 状态模式 1.1 引入 1.2 定义 1.3 结构 1.3.1 典型的抽象状态类代码 1.3.2 典型的具体状态类代码 1.3.3 典型的环境类代码 1.4 状态转换的实现 1.4.1 第一种: 统一由环境类来负责状态之间的转换 1.4.2 第二种: 由具体状态类来负责状态之间的转换 1.5 电梯的案例 案例说明&…...

    2024/5/9 5:03:57
  13. Redis都要老了,你还在用什么古董客户端?

    前几日&#xff0c;Redis 创始人 Antirez 在他的个人博客上宣布将结束自己的 Redis 之旅&#xff01; 大神累了&#xff0c;Redis老了&#xff0c;但Redis依旧很火。 Redis的Java客户端有很多&#xff0c;比如jedis、redisson、lettuce等。 那大家都在用啥呢&#xff1f; 今…...

    2024/5/9 9:53:47
  14. k8s client-go中Leader选举实现

    文章目录介绍Kubernetes的leader选举代码深潜乐观锁定(并发控制)总结介绍 近年来&#xff0c;随着对可靠系统和基础设施的需求增加&#xff0c;"高可用性"一词越来越流行。在分布式系统中&#xff0c;高可用性通常涉及最大化正常运行时间和使系统容错。 在高可用性…...

    2024/5/9 6:49:42
  15. Incoloy20镍合金热处理固溶时效

    Incoloy 020 /(UNS N08020) /20号合金/alloy20/Ns143/ns1403/ CA20/ Carpenter 20Cb/0Cr20Ni35Mo3Cu3Nb NAS 335X、W.Nr.2.4660Nicrofer 3620 Nb-alloy20、ATI 20 国际通称&#xff1a;Alloy 20合金、UNS N08020、NS143、Inconel alloy20/NAS 335X、W.Nr.2.4460 Nicrofer 3…...

    2024/5/8 22:43:55
  16. 法律服务如何在百度投放广告?百度搜索广告是什么

    法律服务类广告想在百度上投放广告首先需要提供营业执照副本&#xff0c;只可公司类客户推广&#xff0c;从事法律咨询行业的客户无需提交律师事务所执业证书&#xff0c;需要提交营业执照&#xff0c;核定其经营范围&#xff0c;需要包含的社会法律咨询&#xff0c;法律文书代…...

    2024/5/8 21:15:22
  17. pycharm--显示 No module named ‘pygame‘

    错误显示如下 解决办法 直接下载对应模块即可 左上角 file 然后 setting 然后点击 project interpreter 右边 号 输入框输入 pygame 左下角安装即可...

    2024/5/9 0:33:11
  18. 1290.二进制链表转整数——记录(C++)

    class Solution { public:int getDecimalValue(ListNode* head) {vector<int>num;while(head){num.push_back(head->val);headhead->next;}int lnum.size();int m0;for(int xl-1;x>0;--x){mnum[x]*pow(2,l-1-x);}return m;} }; 开始五分钟写出了这一段代码&…...

    2024/5/2 21:52:23
  19. 万能的 JS(万字、基础、原理、面试、持续更新。。。)

    万能的 JS 心无杂念&#xff0c;行路也将势如破竹。万能的 JSJS&#xff08;JavaScript 轻量级动态脚本语言&#xff09;面向对象思想&#xff1a;作用域预解释 &#xff08;变量提声&#xff09; 浏览器天生自带JS 中内存的分类JS 数据类型检测数据类型类型转换null 和 undefi…...

    2024/5/8 17:38:47
  20. 时间管理专家的 Linux 工具

    无论你是需要帮助来保持专注、保持及时性&#xff0c;还是为了找到避免重复的捷径&#xff0c;这些 Linux 工具能够帮助你。生产力是一个主观术语&#xff0c;但从本质上讲&#xff0c;它是衡量特定任务完成效率的标准。每个人都有不同的方式来提高他们的生产力&#xff1a;有些…...

    2024/5/2 21:52:16

最新文章

  1. 初学者理解Transformer,本文is all you need

    要问现在AI领域哪个概念最热&#xff0c;必然是openAI推出chatGPT之后引发的大模型。然而这项技术的起源&#xff0c;都来自一篇google公司员工的神作“Attention Is All You Need”——本文标题也是一种致敬^_^&#xff0c;目前已有近12万的引用(还在增长)。 在“Attention Is…...

    2024/5/10 7:16:31
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/9 21:23:04
  3. 解决npm install安装node-sass包容易失败的问题

    具体问题如下&#xff1a; npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: XXX3.4.0 npm ERR! Found: webpack5.31.2 npm ERR! node_modules/webpack npm ERR! peer webpack”^4.0.0 || ^5.0.0″ from html-…...

    2024/5/9 7:01:56
  4. c++类的继承方式

    在 C 中&#xff0c;类的继承方式有三种&#xff1a;公有继承&#xff08;public inheritance&#xff09;、保护继承&#xff08;protected inheritance&#xff09;和私有继承&#xff08;private inheritance&#xff09;。这些继承方式决定了派生类对基类成员的访问权限。 …...

    2024/5/10 0:18:07
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/9 15:10:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/9 17:11:10
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57