热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用Python搭建http服务器

DavidWheeler有一句名言:“计算机科学中的任何问题,都可以通过加上另一层间接的中间层解决。”为了提高Python网络服务的可移植性,Python社区在PE
David Wheeler有一句名言:“计算机科学中的任何问题,都可以通过加上另一层间接的中间层解决。”为了提高Python网络服务的可移植性,Python社区在PEP 333中提出了Web服务器网关接口(WSGI,Web Server Gateway Interface)。

为了提高Python网络服务的可移植性,Python社区在PEP 333中提出了Web服务器网关接口(WSGI,Web Server Gateway Interface)。
WSGL标准就是添加了一层中间层。通过这一个中间层,用Python编写的HTTP服务就能够与任何Web服务器进行交互了。现在,WSGI已经成为了使用Python进行HTTP操作的标准方法。
按照标准的定义,WSGI应用程序是可以被调用的,并且有两个输入参数。

1、WSGI

下面是第一段代码,第一个参数是environ,用于接收一个字典,字典中提供的键值对是旧式的CGI环境集合的拓展。第二个参数本身也是可以被调用的,习惯上会将其命名为start_response(),WSGI应用程序通过这个参数来声明响应头信息。
# 用WSGI应用形式编写的简单HTTP服务。

#!/usr/bin/env python3 
# A simple HTTP service built directly against the low-level WSGI spec. 
 
from pprint import pformat 
from wsgiref.simple_server import make_server 
 
def app(environ, start_response): 
    headers = {'Content-Type': 'text/plain; charset=utf-8'} 
    start_response('200 OK', list(headers.items())) 
    yield 'Here is the WSGI environment: 
 
'.encode('utf-8') 
    yield pformat(environ).encode('utf-8') 
 
if __name__ == '__main__': 
    httpd = make_server('', 8000, app) 
    host, port = httpd.socket.getsockname() 
    print('Serving on', host, 'port', port) 
    httpd.serve_forever()

上述只是一个简单的情况。但是在编写服务器程序时,复杂度就大大提升了。这是因为要完全考虑标准中的描述的许多注意点和边界情况。

2、前向代理与反向代理

无论前向代理还是反向代理,HTTP代理其实就是一个HTTP服务器,用于接收请求,然后对接收到的请求(至少是部分请求)进行转发。转发请求时代理会扮演客户端的角色,将转发的HTTP请求发送至真正的服务器,最后将从服务器接受到的响应发挥扮演客户端的角色,将转发的请求发送至真正的服务器,最后将从服务器接受到的响应发回给最初的客户端。
下面是前向代理和反向代理的简图。
使用Python搭建http服务器
反向代理已经广泛应用于大型的HTTP服务当中。反向代理是Web服务的一部分,对于HTTP客户端并不可见。

3、四种架构

架构师一般都使用很多种复杂的机制来将多个子模块组合建成一个HTTP服务。现在在Python社区中,已经形成了4种基本的模式。如果已经编写了用于生成动态内容的Python代码,并且已经选择了某个支持WSGI的API或框架,应该如何将HTTP服务部署到线上呢?

运行一个使用Python编写的服务器,服务器的代码中可以直接调用WSGI接口。现在最流行的是Green Unicorn(Gunicorn)服务器,不过也有其他已经可以用于生产环境的纯Python服务器。

配置mod_wsgi并运行Apache,在一个独立的WSFIDaemonProcess中运行Python代码,由mod_wsgi启动守护进程。

在后端运行一个类似于Gunicorn的Python HTTP服务器(或者支持所选异步框架的任何服务器),然后在前端运行一个既能返回静态文件,又能对Python编写的动态资源服务进行反向代理的Web服务器。

在最前端运行一个纯粹的反向代理(如Varnish),在该反向代理后端运行Apache或者nginx,在后端运行Python编写的HTTP服务器。这是一个三层的架构。这些反向代理可以分布在不同的地理位置,这样子就能够将离客户端最近的反向代理上的缓存资源返回给发送请求的客户端。

使用Python搭建http服务器
长期以来,对这4个架构的选择主要基于CPython的3个运行时的特性,即解释器占用内存大、解释器运行慢、全局解释器(GIL,Global Interpreter Lock)禁止多个线程同时运行Python字节码。但同时带来了内存中只能载入一定数量的Python实例。

4、平台即服务

这个概念的出现是因为现在的自动化部署、持续集成以及高性能大规模服务的相关技术的出现和处理有一些繁杂。所以有一些提供商提出了PaaS(Platform as a Service),现在只需关心应该如何打包自己的应用程序,以便将自己的应用部署到这些服务之上。
PaaS提供商会解决构建和运行HTTP服务中的出现的各种烦心事。不需要再关心服务器,或者是提供IP地址之类的事情。
PaaS会根据客户规模提供负载均衡器。只需要给PaaS提供商提供配置文件即可完成各种复杂的步骤。
现阶段比较常用的有Heroku和Docker。
大多数PaaS提供商不支持静态内容,除非我们在Python应用程序中实现了对静态内容的更多支持或者向容器中加入了Apache或ngnix。尽管我们可以将静态资源和动态页面的路径放在两个完全不同的URL空间内,但是许多架构师还是倾向于将两者放在同一个名字空间内。

5、不使用Web框架编写WSGI可调用对象

下面第一段代码是用于返回当前时间的原始WSGI可调用对象。

#!/usr/bin/env python3 
# A simple HTTP service built directly against the low-level WSGI spec. 
 
import time 
 
def app(environ, start_response): 
    host = environ.get('HTTP_HOST', '127.0.0.1') 
    path = environ.get('PATH_INFO', '/') 
    if ':' in host: 
        host, port = host.split(':', 1) 
    if '?' in path: 
        path, query = path.split('?', 1) 
    headers = [('Content-Type', 'text/plain; charset=utf-8')] 
    if environ['REQUEST_METHOD'] != 'GET': 
        start_response('01 Not Implemented', headers) 
        yield b'01 Not Implemented' 
    elif host != '127.0.0.1' or path != '/': 
        start_response('404 Not Found', headers) 
        yield b'404 Not Found' 
    else: 
        start_response('200 OK', headers) 
        yield time.ctime().encode('ascii')

第一段比较冗长。下面使用第三方库简化原始WGSI的模式方法。
第一个示例是使用WebOb编写的可调用对象返回当前时间。

#!/usr/bin/env python3 
# A WSGI callable built using webob. 
 
import time, webob 
 
def app(environ, start_response): 
    request = webob.Request(environ) 
    if environ['REQUEST_METHOD'] != 'GET': 
        response = webob.Response('501 Not Implemented', status=501) 
    elif request.domain != '127.0.0.1' or request.path != '/': 
        response = webob.Response('404 Not Found', status=404) 
    else: 
        response = webob.Response(time.ctime()) 
    return response(environ, start_response)

第二个是使用Werkzeug编写的WSGI可调用对象返回当前时间。

#!/usr/bin/env python3 
# A WSGI callable built using Werkzeug. 
 
import time 
from werkzeug.wrappers import Request, Response 
 
@Request.application 
def app(request): 
    host = request.host 
    if ':' in host: 
        host, port = host.split(':', 1) 
    if request.method != 'GET': 
        return Response('501 Not Implemented', status=501) 
    elif host != '127.0.0.1' or request.path != '/': 
        return Response('404 Not Found', status=404) 
    else: 
        return Response(time.ctime())

大家可以对比这两个库在简化操作时的不同之处,Werkzeug是Flask框架的基础。



推荐阅读
  • Python + Pytest 接口自动化测试中 Token 关联登录的实现方法
    本文将深入探讨 Python 和 Pytest 在接口自动化测试中如何实现 Token 关联登录,内容详尽、逻辑清晰,旨在帮助读者掌握这一关键技能。 ... [详细]
  • 本文探讨了为何相同的HTTP请求在两台不同操作系统(Windows与Ubuntu)的机器上会分别返回200 OK和429 Too Many Requests的状态码。我们将分析代码、环境差异及可能的影响因素。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • Symfony是一个功能强大的PHP框架,以其依赖注入(DI)特性著称。许多流行的PHP框架如Drupal和Laravel的核心组件都基于Symfony构建。本文将详细介绍Symfony的安装方法及其基本使用。 ... [详细]
  • 深入解析ESFramework中的AgileTcp组件
    本文详细介绍了ESFramework框架中AgileTcp组件的设计与实现。AgileTcp是ESFramework提供的ITcp接口的高效实现,旨在优化TCP通信的性能和结构清晰度。 ... [详细]
  • 目录一、salt-job管理#job存放数据目录#缓存时间设置#Others二、returns模块配置job数据入库#配置returns返回值信息#mysql安全设置#创建模块相关 ... [详细]
  • 深入解析Serverless架构模式
    本文将详细介绍Serverless架构模式的核心概念、工作原理及其优势。通过对比传统架构,探讨Serverless如何简化应用开发与运维流程,并介绍当前主流的Serverless平台。 ... [详细]
  • 在尝试使用C# Windows Forms客户端通过SignalR连接到ASP.NET服务器时,遇到了内部服务器错误(500)。本文将详细探讨问题的原因及解决方案。 ... [详细]
  • Python包管理工具pip的使用指南
    本文详细介绍了如何使用pip进行Python包的安装、管理和常见问题的解决方法,特别针对国内用户提供了优化建议。 ... [详细]
  • 微信小程序:授权登录与手机号绑定
    本文详细介绍了微信小程序中用户授权登录及绑定手机号的流程,结合官方指引和实际开发经验,提供了一套完整的实现方案,帮助开发者更好地理解和应用。 ... [详细]
  • 本文探讨了在 SQL Server 中使用 JDBC 插入数据时遇到的问题。通过详细分析代码和数据库配置,提供了解决方案并解释了潜在的原因。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文详细介绍了如何在 Android 中使用值动画(ValueAnimator)来动态调整 ImageView 的高度,并探讨了相关的关键属性和方法,包括图片填充后的高度、原始图片高度、动画变化因子以及布局重置等。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
  • 软件工程课堂测试2
    要做一个简单的保存网页界面,首先用jsp写出保存界面,本次界面比较简单,首先是三个提示语,后面是三个输入框,然 ... [详细]
author-avatar
mobiledu2502911457
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有