西维蜀黍

【HTTP】Web Server(Web 服务器)、Web Application Server(Web 应用服务器)和 CGI(Common Gateway Interface)的故事

Web Server(Web 服务器)

在网络刚刚盛行的年代(Web 1.0),绝大部分的 Web 资源都是静态的。这意味着,你访问 www.example.com/a.html,你就可以访问 a 页面,而如果访问 www.example.com/b.html,你就可以访问 b页面。显然,信息量是单向的,即网站上有什么,你就只能看什么,而不能修改网站的内容。我们通常把它称为静态网站

狭义的Web Server(Web 服务器)概念中,Web Server只能处理静态页面。

典型的Web Server的例子,就是 Apache HTTP Server,Nginx 还有 LightHttpd。

随着互联网的发展,我们更希望访问一个动态网站(Web 1.5),即可以根据用户传入的信息,动态地生成网页的内容。

这时候,我们就需要一个程序来帮忙处理动态请求(如返回特定用户的信息、获取当前时间等),而静态资源的请求,依然由Web Server来负责。

Web服务器程序会将动态请求转发给帮助程序(helper application),帮助程序处理后,返回处理后的静态结果给Web服务器程序。这样,就避免了 Web 服务器程序需要处理动态页面的问题,如下图:

  ...


【Python】WSGI(Web Server Gateway Interface)、uWSGI Server、uwsgi、WSGI Application 的故事

关于Web Server(Web 服务器)、Web Application Server(Web 应用服务器)和 CGI(Common Gateway Interface)的区别,可以访问【HTTP】Web Server(Web 服务器)、Web Application Server(Web 应用服务器)和 CGI(Common Gateway Interface)的故事

WSGI(Web Server Gateway Interface)

WSGI是 Web Server Gateway Interface 的缩写。

它不是服务器、Python模块、框架、API或者任何软件,而是一种描述 Web服务器(如Nginx)如何与Web application Server(Web应用程序,如用Django、Flask框架编写的程序)通信的规范。

因此,WSGI 是一种规范,或者说一种接口,或者说一种协议,equivalent 是 Java 世界中的 servlet。

WSGI是在 PEP 333 提出的,并在 PEP 3333 进行补充(主要是为了支持 Python3.x)。

这个协议旨在解决众多 Python Web 框架和Web server软件的兼容问题。有了WSGI,你再也不用因为使用特定的Web 应用框架而不得不选择特定的 Web server软件。

只要遵照了 WSGI 协议的的 Web 应用(Web application,我们称之为WSGI应用),都可以在任何遵照了WSGI协议的 Web server 软件(我们称之为 WSGI server,比如 uWSGI)上运行。

而对于WSGI 应用(WSGI Application),我们理论上可以完全自己从头编写一个 WSGI 应用,但是,我们通常会使用WSGI 应用框架(WSGI Application Framework),或者称为WSGI MiddleWare,比如Django,Flask等,因为框架已经帮我们封装了大量的底层逻辑,而让我们可以更好的专注于业务逻辑上。

为了更好的理解 WSGI 应用(WSGI Application),我们接下来会写一个非常原始的 WSGI 应用。

  ...


【Python】Error Handling

Error Return

If service can not handle request for internal error or upstream error, it should response proper error information to client.

Service should write log for every error return.

The error response structure should be consistent for all APIs in one service.

  • The error code should be either a short string code or an integer, defined by service. This is to help client understand the situation and choose different ways to handle the error.
  • The detailed error message is optional. This is to help client debug the issue.
  • The error code need to be categorized to 2 types, and allow client side easily identify the type of error.
    • Occasional error, such as upstream down, internal error, etc. This kind of errors means client can safely retry the request.
    • Logic error, such as invalid argument. Client can cached the result and should not directly retry the request.
  ...


【Design】Error Handling

Returned Errors

If service can not handle request for internal error or upstream error, it should response proper error information to client.

Service should write log for every error return.

The error response structure should be consistent for all APIs in one service.

  • The error code should be either a short string code or an integer, defined by service. This is to help client understand the situation and choose different ways to handle the error.
  • The detailed error message is optional. This is to help client debug the issue.
  • The error code need to be categorized to 2 types, and allow client side easily identify the type of error.
    • Occasional error, such as upstream down, internal error, etc. This kind of errors means client can safely retry the request.
    • Logic error, such as invalid argument. Client can cached the result and should not directly retry the request.

Error Codes

Google APIs must use the canonical error codes defined by google.rpc.Code. Individual APIs should avoid defining additional error codes, since developers are very unlikely to write logic to handle a large number of error codes. For reference, handling an average of 3 error codes per API call would mean most application logic would just be for error handling, which would not be a good developer experience.

  ...


【Design】API Design

HTTP REST APIs

URL

Example

The following sections present a few real world examples on how to apply resource-oriented API design to large scale services. You can find more examples in the Google APIs repository.

In these examples, the asterisk indicates one specific resource out of the list.

Gmail API

The Gmail API service implements the Gmail API and exposes most of Gmail functionality. It has the following resource model:

  • API service: gmail.googleapis.com

    • A collection of users:users/*. Each user has the following resources.
      • A collection of messages: users/*/messages/*.
      • A collection of threads: users/*/threads/*.
      • A collection of labels: users/*/labels/*.
      • A collection of change history: users/*/history/*.
      • A resource representing the user profile: users/*/profile.
      • A resource representing user settings: users/*/settings.

Cloud Pub/Sub API

The pubsub.googleapis.com service implements the Cloud Pub/Sub API, which defines the following resource model:

  • API service:pubsub.googleapis.com

    • A collection of topics: projects/*/topics/*.
  • A collection of subscriptions: projects/*/subscriptions/*.

NOTE: Other implementations of the Pub/Sub API may choose different resource naming schemes.

Cloud Spanner API

The spanner.googleapis.com service implements the Cloud Spanner API, which defines the following resource model:

  • API service:spanner.googleapis.com
    • A collection of instances:projects/*/instances/*.
      • A collection of instance operations: projects/*/instances/*/operations/*.
      • A collection of databases: projects/*/instances/*/databases/*.
      • A collection of database operations: projects/*/instances/*/databases/*/operations/*.
      • A collection of database sessions: projects/*/instances/*/databases/*/sessions/*.
  ...