uwsgi 处理web 请求使用了多进程的模式,接收到web请求后可能由不同的进程去处理。
问题背景:
一、前段时间写了个api, 这个api 是在django项目中的,并且使用的是nginx+uwsgi的方式提供服务的。在api 中 使用了django 的 get_or_create来保证数据表的唯一性。
XXX.objects.get_or_create(custom_column_id=custom_column_id, l_id=l_id)
二、调用这个api 的客户端只有一个进程,并且使阻塞式的串行调用,只有在第一个接口返回后才进行下一次的请求。
三、结果经过长期的运行发现,数据表中多了很多重复的数据。
custom_column_id | l_id |
1 | 2 |
1 | 2 |
问题分析: 先查查get_or_create的源代码,发现其不是线程安全的。也就是说有两个进程或线程在同时执行的get_or_create的时候,可能会都进行Create,这样就会产生两条相同的数据。如下django 源码:
def get_or_create(self, defaults=None, **kwargs): """ Looks up an object with the given kwargs, creating one if necessary. Returns a tuple of (object, created), where created is a boolean specifying whether an object was created. """ lookup, params = self._extract_model_params(defaults, **kwargs) # The get() needs to be targeted at the write database in order # to avoid potential transaction consistency problems. self._for_write = True try: return self.get(**lookup), False except self.model.DoesNotExist: return self._create_object_from_params(lookup, params)
也就是说如果uwsgi 的多进程在同时并发处理请求时可能会导致这种重复的数据产生。但是疑惑的是,客户端是串行请求的。在一个请求完成后在发送另一个请求。仔细研究代码发现发送请求使用python的requests 库,并且加了timeout 限制,如下官方解释:
You can tell Requests to stop waiting for a response after a given number of seconds with the timeout parameter: requests.get('http://github.com', timeout=0.001) Traceback (most recent call last): File "<stdin>", line 1, in <module> requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
也就是在timeout范围内没有收到响应,客户端就会结束。虽然客户端停止了,但是服务端还没有结束,这时候再处理同样的请求就可能会并发的调用get_or_create方法,造成重复数据的问题。做一个实验来证明request 在timeout 后,客户端停止了。但是服务端依然在处理。如下图,客户端在timeout=3 s 后就自动返回,然而服务端依然在运行,知道uwsgi超时后自动重启。
图一、客户端超时返回错误
图二、服务端使用循环输出来验证
图三,服务端在超时后才退出
注:uwsgi 是使用进程池的方式处理http请求,也就是每次请求到来的请求可能是不同的进程去处理的。当然在uwsgi 中可以配置请求处理的超时时间,如果在超时时间内还没有处理完,主进程会把这个处理请求的进程重启。
解决思路:
一,调整调用api 时设置的超时时间,保证接受请求的api进程处理完毕。超时时间必须大于uwsgi进程的超时时间(目前使用该方法,观察了一个月没有数据重复的情况)。
二,如果能在数据库层面保证数据的唯一性是最好的。那样才能保证数据的唯一性。
相关推荐
查找mysql_pconnect时在mysql帮助文档上发现的,记在这里。 web server使用php生成一个web...一个多进程的web server通常有一个总的父进程协调一堆子进程来工作。当页面请求到达web server时,这个父进程把这个请求交
(牛客网C++课程)Linux 高并发Web服务器项目实战(带定时检测代码) 技术框架: 1. 线程池 + 非阻塞 socket + epoll + 事件处理的并发模型 2. 状态机解析HTTP请求 3. 心跳机制 4. 简易日志系统 主要内容: 1. ...
在Python实现web服务器入门学习笔记(3)——多进程、多线程实现并发HTTP服务器中,已经学习了如何通过多进程、多线程实现并发HTTP服务器,但当时是以实现功能为导向,并未使用面向对象的封装,本文记录一下如何对...
1.实现处理请求的Handler,该类继承自tornado.web.RequestHandler,实现用于处理请求的对应方法如:get、post等。返回内容用self.write方法输出。 2.实例化一个Application。构造函数的参数是一个Handlers列表,...
与其他传统的Web服务器不同的是当有连接请求到来时,它并不为每个连接单独创建进程,也不通过复制自身进程来处理多链接。而是通过建立HTTP请求列表来处理多路HTTP连接请求。同时它只为CGI程序创建新的进程,这样就...
Apache的WINDOWS版本是传统的Leader-Follow多进程模型,Nginx则 是多线程select模型(玩具?) * 配置文件采用JSON标准格式,简洁易写,而且支持行注释和块注释。Apache配置格式比较复杂,Nginx配置 格式多变怪异...
2020 年计算机二级《 Web 程序设计》练习题及答案 一、名词解释 1、 HTM:L hyper text markup language ,超文本标记语言 2、ASP: active server pages ,活动服务器网页 3、URL: uniform resorce locator ,统一...
SQL Server Express 是独立软件供应商 (ISV)、服务器用户、非专业开发人员、Web 应用程序开发人员、网站宿主以及客户端应用程序编程爱好者的理想之选。 未及时包括在本自述文件中的任何有关 SQL Server Express 的...
与其他传统的Web服务器不同的是当有连接请求到来时,它并不为每个连接单独创建进程,也不通过复制自身进程来处理多链接。而是通过建立HTTP请求列表来处理多路HTTP连接请求。同时它只为CGI程序创建新的进程,这样就在...
根据不同的webserver,也就是应用程序服务器,在处理应用请求的时候,有些是用多线程而非多进程的方式,那么由于线程会牵扯到共享寄存器和内存方面的,所以很容易出错(考虑c语言指针的情况),那么系统就需要时间和...
ASP.NET2.0内置的urlMappings和基于自定义HTTPModule的URL重写(使用NBear.Web中的UrlRewriteModule实现),并探讨URL重写中可能遇到的陷阱及处理办法。 需要手动为UrlRewriteWebSite目录添加一个到...
多个IP对应多个Web站点 如果本机已绑定了多个IP地址,想利用不同的IP地址得出不同的Web页面,则只需在“默认Web站点”处单击右键,选“新建→站点”,然后根据提示在“说明”处输入任意用于说明它的内容(比如为“我...
Web套接字服务器/客户端,在服务器上支持多进程和解析模板,并在客户端上发送/接收选项 图书馆有几个主要选择 服务器: 它是一个网络套接字服务器,用于多个连接,具有开箱即用的所有事件的解码/编码功能(带有...
这个请求被运行在Web服务器上的Servlet引擎处理,并返回响应到Servlet。Servlet通过HTTP将这个响应转发到客户端。 在功能上,Servlet与CGI、NSAPI有点类似,但是,与他们不同的是:Servlet具有平台无关性。 Java...
第七章 案例1通过委托实现异步调用 案例2使用定时器执行方法 案例3控制线程状态 案例4多线程同步的实现 案例5结束进程 案例6多线程资源共享与访问 案例7仅运行一个应用程序实例 案例7如何...
ASP.Net应用程序的多进程模型 NET委托:一个C#睡前故事 [推荐] - [原创] Microsoft .NET策略及框架概述 卸载Class? Web Form 窗体 如何实现web页面的提示保存功能 在ASP.Net中两种利用CSS实现多界面的方法 如何在...
请求Web服务971 26.8 异步使用Web服务973 26.9 小结976 第27章 配置977 27.1 配置概述977 27.1.1 服务器配置文件978 27.1.2 应用程序配置文件979 27.1.3 配置的应用979 27.1.4 检测配置文件的变化980 27.1.5 配置...
13.3.1 DOM的问题 438 13.3.2 XPath、XPathDocument和XmlDocument 438 13.4 DataSet 442 13.4.1 把DataSet保存到XML中 442 13.4.2 XmlDataDocument 443 13.5 XmlDataSource控件 445 13.6 XSLT 449 13.6.1 ...
概述PoolNoodle是一个基于 , 和的多进程HTTP Web服务器。 它管理子工作进程的多个池以处理应用程序请求,同时为父进程提供静态文件。 通过放入单个配置文件(或symlink),可以轻松添加应用程序,并且所有内容都...