odoo17后台启动过程3——三种server

文件位置:odoo\service\server.py

1、三种server:

在这里插入图片描述

1.1、Threaded

这是Odoo默认的选项,线程模式,我们知道python的多线程并不是真正的多线程,所以,这种模式下,并发性能较低,也无法利用多核的优势。 优点是比较安全,兼容型号,如果对并发要求不高,这种模式是没有问题的。这也是odoo默认的模式。

1.2、Gevented

利用了python协程,需要预先安装Gevent库,提高了并发西性能,但是安全性和兼容性可能不太好,需要多做测试。
我尝试在windows下通过下列命令启动odoo,但是老是报错, 暂时不去管它了

python odoo-bin gevent -c odoo.conf

1.3、Prefork

可以充分利用多核处理器,它其实是一种多进程模式,由多个进程来处理web请求。

这三种网关有一个共同的父类CommonServer


class CommonServer(object):_on_stop_funcs = []def __init__(self, app):self.app = app# configself.interface = config['http_interface'] or '0.0.0.0'self.port = config['http_port']# runtimeself.pid = os.getpid()def close_socket(self, sock):""" Closes a socket instance cleanly:param sock: the network socket to close:type sock: socket.socket"""try:sock.shutdown(socket.SHUT_RDWR)except socket.error as e:if e.errno == errno.EBADF:# Werkzeug > 0.9.6 closes the socket itself (see commit# https://github.com/mitsuhiko/werkzeug/commit/4d8ca089)return# On OSX, socket shutdowns both sides if any side closes it# causing an error 57 'Socket is not connected' on shutdown# of the other side (or something), see# http://bugs.python.org/issue4397# note: stdlib fixed test, not behaviorif e.errno != errno.ENOTCONN or platform.system() not in ['Darwin', 'Windows']:raisesock.close()@classmethoddef on_stop(cls, func):""" Register a cleanup function to be executed when the server stops """cls._on_stop_funcs.append(func)def stop(self):for func in type(self)._on_stop_funcs:try:_logger.debug("on_close call %s", func)func()except Exception:_logger.warning("Exception in %s", func.__name__, exc_info=True)

1、构造函数需要传入一个app
2、提供了几个关闭服务的方法

2、start函数

这是一个入口函数,cli.server 就是通过调用这个函数来启动服务

odoo.service.server.start(preload=preload, stop=stop)

看看它的代码


def start(preload=None, stop=False):""" Start the odoo http server and cron processor."""global serverload_server_wide_modules()if odoo.evented:server = GeventServer(odoo.http.root)elif config['workers']:if config['test_enable'] or config['test_file']:_logger.warning("Unit testing in workers mode could fail; use --workers 0.")server = PreforkServer(odoo.http.root)# Workaround for Python issue24291, fixed in 3.6 (see Python issue26721)if sys.version_info[:2] == (3,5):# turn on buffering also for wfile, to avoid partial writes (Default buffer = 8k)werkzeug.serving.WSGIRequestHandler.wbufsize = -1else:if platform.system() == "Linux" and sys.maxsize > 2**32 and "MALLOC_ARENA_MAX" not in os.environ:# glibc's malloc() uses arenas [1] in order to efficiently handle memory allocation of multi-threaded# applications. This allows better memory allocation handling in case of multiple threads that# would be using malloc() concurrently [2].# Due to the python's GIL, this optimization have no effect on multithreaded python programs.# Unfortunately, a downside of creating one arena per cpu core is the increase of virtual memory# which Odoo is based upon in order to limit the memory usage for threaded workers.# On 32bit systems the default size of an arena is 512K while on 64bit systems it's 64M [3],# hence a threaded worker will quickly reach it's default memory soft limit upon concurrent requests.# We therefore set the maximum arenas allowed to 2 unless the MALLOC_ARENA_MAX env variable is set.# Note: Setting MALLOC_ARENA_MAX=0 allow to explicitly set the default glibs's malloc() behaviour.## [1] https://sourceware.org/glibc/wiki/MallocInternals#Arenas_and_Heaps# [2] https://www.gnu.org/software/libc/manual/html_node/The-GNU-Allocator.html# [3] https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=00ce48c;hb=0a8262a#l862try:import ctypeslibc = ctypes.CDLL("libc.so.6")M_ARENA_MAX = -8assert libc.mallopt(ctypes.c_int(M_ARENA_MAX), ctypes.c_int(2))except Exception:_logger.warning("Could not set ARENA_MAX through mallopt()")server = ThreadedServer(odoo.http.root)watcher = Noneif 'reload' in config['dev_mode'] and not odoo.evented:if inotify:watcher = FSWatcherInotify()watcher.start()elif watchdog:watcher = FSWatcherWatchdog()watcher.start()else:if os.name == 'posix' and platform.system() != 'Darwin':module = 'inotify'else:module = 'watchdog'_logger.warning("'%s' module not installed. Code autoreload feature is disabled", module)rc = server.run(preload, stop)if watcher:watcher.stop()# like the legend of the phoenix, all ends with beginningsif getattr(odoo, 'phoenix', False):_reexec()return rc if rc else 0

1、调用了load_server_wide_modules函数,实际上就是加载base和web两个模块。
2、根据配置和命令行参数来决定启动哪一种服务,并通过odoo.http.rootd对象来初始化server,三种网关都是用这个对象来初始化化

server = ThreadedServer(odoo.http.root)

3、调用server的run方法启动服务

rc = server.run(preload, stop)

3、class ThreadedServer(CommonServer)

先看看run这个入口方法:

    def run(self, preload=None, stop=False):""" Start the http server and the cron thread then wait for a signal.The first SIGINT or SIGTERM signal will initiate a graceful shutdown whilea second one if any will force an immediate exit."""self.start(stop=stop)

从注释中可以看出,该函数启动http server 和cron线程,然后就等待信号。

3.1 启动httpserver

在run方法中调用了 self.start(stop=stop) 来启动http服务。
在start方法中首先绑定了信号处理函数,然后调用了http_spawn 方法。

    def start(self, stop=False):_logger.debug("Setting signal handlers")set_limit_memory_hard()if os.name == 'posix':signal.signal(signal.SIGINT, self.signal_handler)signal.signal(signal.SIGTERM, self.signal_handler)signal.signal(signal.SIGCHLD, self.signal_handler)signal.signal(signal.SIGHUP, self.signal_handler)signal.signal(signal.SIGXCPU, self.signal_handler)signal.signal(signal.SIGQUIT, dumpstacks)signal.signal(signal.SIGUSR1, log_ormcache_stats)elif os.name == 'nt':import win32apiwin32api.SetConsoleCtrlHandler(lambda sig: self.signal_handler(sig, None), 1)test_mode = config['test_enable'] or config['test_file']if test_mode or (config['http_enable'] and not stop):# some tests need the http daemon to be available...self.http_spawn()

http_spawn启动了一个后台线程,线程的执行函数是http_thread,线程名称叫odoo.service.httpd

        t = threading.Thread(target=self.http_thread, name="odoo.service.httpd")t.daemon = Truet.start()

而http_thread 启动了一个ThreadedWSGIServerReloadable服务,并且调用了它的serve_forever方法,这估计是一个死循环,一直等待web请求。

    def http_thread(self):self.httpd = ThreadedWSGIServerReloadable(self.interface, self.port, self.app)self.httpd.serve_forever()

到这里http服务线程就启动好了.

3.2 启动cron线程

server的run方法中还需要启动后台服务线程,一般是2个

        self.cron_spawn()

这个代码比较简单,根据max_cron_threads 参数来启动后台任务线程。

    def cron_spawn(self):""" Start the above runner function in a daemon thread.The thread is a typical daemon thread: it will never quit and must beterminated when the main process exits - with no consequence (the processingthreads it spawns are not marked daemon)."""# Force call to strptime just before starting the cron thread# to prevent time.strptime AttributeError within the thread.# See: http://bugs.python.org/issue7980datetime.datetime.strptime('2012-01-01', '%Y-%m-%d')for i in range(odoo.tools.config['max_cron_threads']):def target():self.cron_thread(i)t = threading.Thread(target=target, name="odoo.service.cron.cron%d" % i)t.daemon = Truet.type = 'cron't.start()_logger.debug("cron%d started!" % i)

到这里,一个主线程,一个http服务线程和两个cron线程就启动好了
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/315672.html

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

相关文章

OCP NVME SSD规范解读-3.NVMe管理命令-part2

NVMe-AD-8:在某些情况下(如Sanitize命令、Format NVM命令或TCG Revert方法后数据被清除),设备应允许读取已清除的LBAs而不产生错误,并在最后一次清除完成后,对未写入LBAs的读取返回所有零值给主机 NVMe-AD…

如何在2024年编写Android应用程序

如何在2024年编写Android应用程序 本文将介绍以下内容: 针对性能进行优化的单活动多屏幕应用程序 🤫(没有片段)。应用程序架构和模块化 → 每个层面。Jetpack Compose 导航。Firestore。应用程序架构(模块化特征驱动…

x-cmd pkg | lazygit - git 命令的终端 UI

目录 简介首次用户功能特点类似工具与竞品进一步探索 简介 lazygit 由 Jesse Duffield 于 2018 年使用 Go 语言构建的 git 终端交互式命令行工具,旨在终端界面中便捷管理 git 存储库。 首次用户 使用 x lazygit 即可自动下载并使用 在终端运行 eval "$(curl …

JavaBean

学习目的与要求 熟练掌握<jsp:useBean>、<jsp:setProperty>、<jsp:getProperty>等JSP的操作指令。 本章主要内容 编写JavaBean在JSP中使用JavaBean 一个JSP页面通过使用HTML标记为用户显示数据&#xff08;静态部分&#xff09;&#xff0c;页面中变量的…

c语言:用指针输入两个数组|练习题

一、题目 利用指针&#xff0c;输入两个数组 如图&#xff1a; 二、代码截图【带注释】 三、源代码【带注释】 #include <stdio.h> int main() { int a[50]; int b[50]; int *paa,*pbb; //输入第一组数组 printf("请输入第一组5个数字&#xff1a;…

leetcode2975. 移除栅栏得到的正方形田地的最大面积

题目 有一个大型的 (m - 1) x (n - 1) 矩形田地&#xff0c;其两个对角分别是 (1, 1) 和 (m, n) &#xff0c;田地内部有一些水平栅栏和垂直栅栏&#xff0c;分别由数组 hFences 和 vFences 给出。 水平栅栏为坐标 (hFences[i], 1) 到 (hFences[i], n)&#xff0c;垂直栅栏为…

【VMware】Windows安装MySQL及网络配置---图文并茂详细介绍

目录 目录 一 安装MySQL ① 连接虚拟机传输MySQL压缩包 ②解压MySQL压缩包 ③ my文件拷贝mysql安装根目录下 ④ 修改my文件 ⑤ 5.7版本安装MySQL 5.1 注册mysql服务 5.2 初始化 5.3 启动MySQL 5.4 登入MySQL 5.5 修改默认密码 ⑥ 8版本安装MySQL 6.1 解压压缩包 …

透视屏幕有哪些优点

透视屏幕的优点有以下几个方面&#xff1a; 互动性强&#xff1a;透视屏幕可以实现人机互动&#xff0c;观众可以通过触摸屏幕或使用其他交互设备与屏幕进行互动&#xff0c;增强了观众的参与感和体验感。 多样化的展示方式&#xff1a;透视屏幕可以采用多种展示方式&#xff…

探究Chrome仿真模拟设备时Click区域不准确问题

一、开发环境 windows版本&#xff1a; windows 10 Chrome 版本&#xff1a; 116.0.5845.141 二、问题描述 在Chrome DevTools中开启仿真设备&#xff08;微信开发者工具也有类似问题&#xff09;&#xff0c;如果页面元素有绑定click时&#xff0c;实际点击事件响应区域会…

『番外篇九』SwiftUI 实战:打造一款“五脏俱全”的网络图片显示 App(上)

概览 俗话说得好:“读书破万卷,下笔如有神”。不过如果把这句话放到编程的学习上可就不那么贴切了。 要想熟练掌握一门编程语言,光看书是绝对不够的。我们还需尽可能的多撸码、早撸码,撸到无路可退、海枯石烂才有可能一窥门径。 在本篇和续篇博文中,我们将和小伙伴们一起…

DevC++ easyx实现视口编辑--像素绘图板与贴图系统

到了最终成果阶段了&#xff0c;虽然中间有一些代码讲起来没有意思&#xff0c;纯靠debug,1-1解决贴图网格不重合问题&#xff0c;这次是一个分支结束。 想着就是把瓦片贴进大地图里。 延续这几篇帖子&#xff0c;开发时间也从2023年的4月16到了6月2号&#xff0c;80小时基本…

设计模式之工厂设计模式【创造者模式】

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…