如何在Flask应用程序退出时停止Gunicorn

时间:2016-12-10 01:31:50

标签: python linux flask gunicorn

我正在使用gunicorn运行我的Flask应用程序,但是当Flask应用程序因错误而退出时,gunicorn将创建一个新的worker并且不会退出。

Flask应用示例:

$ vim app.py

# main file
import sys
import os
import logging
from flask import Flask

from views import views

def create_app():

    app = Flask(__name__)

    app_name = os.environ.get('FLASK_APP_NAME', None)
    if app_name is None:
        logging.error("Failed to load configuration")
        sys.exit(2)

    app.config['APP_NAME'] = app_name

    console = logging.StreamHandler(sys.stdout)
    logging.getLogger().addHandler(console)
    logging.getLogger().setLevel(logging.INFO)

    logging.info("Starting Flask application")

    app.register_blueprint(views)

    return app

app = create_app()

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, debug=False, threaded=True)


$ vim views.py

# views
from flask import request, jsonify, Blueprint
from flask import current_app as app

views = Blueprint('views', __name__)

@views.route("/", methods=["GET"])
def indexz():
    return jsonify(app=app.config['APP_NAME'], msg='OK'), 200

我尝试使用gunicorn的worker_exit服务器钩子:

$ vim gunicorn-config.py

import sys

workers = 2

def worker_exit(server, worker):
    sys.exit(2)
    # server.halt()

但这只会引发错误并继续产生工人:

# error when using sys.exit(2)
[2016-12-10 01:28:53 +0000] [11916] [INFO] Booting worker with pid: 11916
ERROR:root:Failed to load configuration
[2016-12-10 01:28:53 +0000] [11915] [INFO] Worker exiting (pid: 11915)
[2016-12-10 01:28:53 +0000] [11915] [WARNING] Exception during worker exit:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 576, in spawn_worker
    self.cfg.worker_exit(self, worker)
  File "gunicorn-config.py", line 6, in worker_exit
    sys.exit(2)
SystemExit: 2


# error when using server.halt()
[2016-12-10 01:30:15 +0000] [12202] [INFO] Booting worker with pid: 12202
ERROR:root:Failed to load configuration
[2016-12-10 01:30:15 +0000] [12197] [INFO] Worker exiting (pid: 12197)
[2016-12-10 01:30:15 +0000] [12197] [INFO] Shutting down: Master
[2016-12-10 01:30:15 +0000] [12197] [WARNING] Exception during worker exit:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 576, in spawn_worker
    self.cfg.worker_exit(self, worker)
  File "gunicorn-config.py", line 7, in worker_exit
    server.halt()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 331, in halt
    self.stop()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 378, in stop
    self.kill_workers(sig)
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 600, in kill_workers
    self.kill_worker(pid, sig)
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 616, in kill_worker
    self.cfg.worker_exit(self, worker)
  File "gunicorn-config.py", line 7, in worker_exit
    server.halt()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 338, in halt
    sys.exit(exit_status)
SystemExit: 0

修改:根据https://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L37将我的应用的退出代码修改为:sys.exit(4)。这次应用程序不会无限重启,但当有2个或更多工作程序时,会引发异常:

[2016-12-10 18:45:52 +0000] [22195] [INFO] Worker exiting (pid: 22195)
Traceback (most recent call last):
  File "/usr/bin/gunicorn", line 11, in <module>
    sys.exit(run())
  File "/usr/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 74, in run
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
  File "/usr/lib/python2.7/site-packages/gunicorn/app/base.py", line 192, in run
    super(Application, self).run()
  File "/usr/lib/python2.7/site-packages/gunicorn/app/base.py", line 72, in run
    Arbiter(self).run()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 218, in run
    self.halt(reason=inst.reason, exit_status=inst.exit_status)
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 331, in halt
    self.stop()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 381, in stop
    time.sleep(0.1)
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 231, in handle_chld
    self.reap_workers()
  File "/usr/lib/python2.7/site-packages/gunicorn/arbiter.py", line 506, in reap_workers
    raise HaltServer(reason, self.WORKER_BOOT_ERROR)
gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>

如何在不触发任何异常的情况下退出应用程序。

4 个答案:

答案 0 :(得分:4)

退出枪声:

private ViewClasses: (new (...args: any[]) => UnitView<{}>)[] = [
    TitleView
]

答案 1 :(得分:0)

查看gunicorn配置中的preload_app选项。这将在父级中加载您的应用程序。然后它应该能够引发异常并且gunicorn将无法启动。

答案 2 :(得分:0)

为完整起见,请使用标准errcodes: https://docs.python.org/3/library/errno.html#errno.EINTR

如此:

export default class Find extends Component {
constructor(props) {
    super(props);
    this.schools = ["Abubakar Tafawa Balewa University, Bauchi", "Ahmadu Bello University, Zaria", "Bayero University, Kano", "Federal University Gashua, Yobe", "Federal University of Petroleum Resources, Effurun", "Federal University of Technology, Akure", "Federal University of Technology, Minna", "Federal University of Technology, Owerri", "Federal University, Dutse, Jigawa State", "Federal University, Dutsin-Ma, Katsina", "Federal University, Kashere, Gombe State", "Federal University, Lafia, Nasarawa State", "Federal University, Lokoja, Kogi State", "Alex Ekweme University, Ndufu-Alike, Ebonyi State", "Federal University, Otuoke, Bayelsa", "Federal University, Oye-Ekiti, Ekiti State", "Federal University, Wukari, Taraba State", "Federal University, Birnin Kebbi", "Federal University, Gusau Zamfara", "Michael Okpara University of Agriculture, Umudike", "Modibbo Adama University of Technology, Yola", "National Open University of Nigeria, Lagos", "Nigeria Police Academy Wudil", "Nigerian Defence Academy Kaduna", "Nnamdi Azikiwe University, Awka", "Obafemi Awolowo University,Ile-Ife", "University of Abuja, Gwagwalada", "Federal University of Agriculture, Abeokuta", "University of Agriculture, Makurdi", "University of Benin", "University of Calabar", "University of Ibadan", "University of Ilorin", "University of Jos", "University of Lagos", "University of Maiduguri", "University of Nigeria, Nsukka", "University of Port-Harcourt", "University of Uyo", "Usumanu Danfodiyo University", "Nigerian Maritime University Okerenkoko, Delta State", "Abia State University, Uturu", "Adamawa State University Mubi", "Adekunle Ajasin University, Akungba", "Akwa Ibom State University, Ikot Akpaden", "Ambrose Alli University, Ekpoma", "Chukwuemeka Odumegwu Ojukwu University, Uli", "Bauchi State University, Gadau", "Benue State University, Makurdi", "Yobe State University, Damaturu", "Cross River State University of  Technology, Calabar", "Delta State University Abraka", "Ebonyi State University, Abakaliki", "Ekiti State University", "Enugu State University of Science and Technology, Enugu", "Gombe State Univeristy, Gombe", "Ibrahim Badamasi Babangida University, Lapai", "Ignatius Ajuru University of Education,Rumuolumeni", "Imo State University, Owerri", "Sule Lamido University, Kafin Hausa, Jigawa", "Kaduna State University, Kaduna", "Kano University of Science & Technology, Wudil", "Kebbi State University of Science and Technology, Aliero", "Kogi State University Anyigba", "Kwara State University, Ilorin", "Ladoke Akintola University of Technology, Ogbomoso", "Ondo State University of Science and Technology Okitipupa", "River State University of Science and Technology", "Olabisi Onabanjo University, Ago Iwoye", "Lagos State University, Ojo", "Niger Delta University Yenagoa", "Nasarawa State University Keffi", "Plateau State University Bokkos", "Tai Solarin University of Education Ijebu Ode", "Umar Musa Yar' Adua University Katsina", "Osun State University Osogbo", "Taraba State University, Jalingo", "Sokoto State University", "Yusuf Maitama Sule University Kano", "Oyo State Technical University Ibadan", "Ondo State University of Medical Sciences", "Edo University Iyamo", "Eastern Palm University Ogboko, Imo State", "University of Africa Toru Orua, Bayelsa State", "Bornu State University, Maiduguri", "Moshood Abiola University of Science and Technology Abeokuta", "Gombe State University of Science and Technology", "Zamfara State University", , "Achievers University, Owo", "Adeleke University, Ede", "Afe Babalola University, Ado-Ekiti - Ekiti State", "African University of Science & Technology, Abuja", "Ajayi Crowther University, Ibadan", "Al-Hikmah University, Ilorin", "Al-Qalam University, Katsina", "American University of Nigeria, Yola", "Augustine University", "Babcock University,Ilishan-Remo", "Baze University", "Bells University of Technology, Otta", "Benson Idahosa University, Benin City", "Bingham University, New Karu", "Bowen University, Iwo", "Caleb University, Lagos", "Caritas University, Enugu", "Chrisland University", "Covenant University Ota", "Crawford University Igbesa", "Crescent University", "Edwin Clark University, Kaigbodo", "Elizade University, Ilara-Mokin", "Evangel University, Akaeze", "Fountain Unveristy, Oshogbo", "Godfrey Okoye University, Ugwuomu-Nike - Enugu State", "Gregory University, Uturu", "Hallmark University, Ijebi Itele, Ogun", "Hezekiah University, Umudi", "Igbinedion University Okada", "Joseph Ayo Babalola University, Ikeji-Arakeji", "Kings University, Ode Omu", "Kwararafa University, Wukari", "Landmark University, Omu-Aran.", "Lead City University, Ibadan", "Madonna University, Okija", "Mcpherson University, Seriki Sotayo, Ajebo", "Micheal & Cecilia Ibru University", "Mountain Top University", "Nile University of Nigeria, Abuja", "Novena University, Ogume", "Obong University, Obong Ntak", "Oduduwa University, Ipetumodu - Osun State", "Pan-Atlantic University, Lagos", "Paul University, Awka - Anambra State", "Redeemer's University, Mowe", "Renaissance University, Enugu", "Rhema University, Obeama-Asa - Rivers State", "Ritman University, Ikot Ekpene, Akwa Ibom", "Salem University, Lokoja", "Samuel Adegboyega University, Ogwa.", "Southwestern University, Oku Owa", "Summit University", "Tansian University, Umunya", "University of Mkar, Mkar", "Veritas University, Abuja", "Wellspring University, Evbuobanosa - Edo State", "Wesley University. of Science & Technology, Ondo", "Western Delta University, Oghara Delta State", "Christopher University Mowe", "Kola Daisi University Ibadan, Oyo State", "Anchor University Ayobo Lagos State", "Dominican University Ibadan Oyo State", "Legacy University, Okija Anambra State", "Arthur Javis University Akpoyubo Cross river State", "Crown Hill University Eiyenkorin, Kwara State", "Coal City University Enugu State", "Clifford University Owerrinta Abia State", "Admiralty University, Ibusa Delta State", "Spiritan University, Nneochi Abia State", "Precious Cornerstone University, Oyo", "PAMO University of Medical Sciences, Portharcourt", "Atiba University Oyo", "Eko University of Medical and Health Sciences Ijanikin, Lagos", "Skyline University, Kano"];

    this.schools = this.schools.sort();
    this.state = {
        schools: this.schools,
        index: -1,
        text: '',
        loaded: false
    };

    this.handleChange = this.handleChange.bind(this);
    this.schoolChange = this.schoolChange.bind(this);
}
// this is where i set the state
componentDidMount()
{
this.setState({loaded: true})
}
static navigationOptions = {
    header: null,
    drawerLockMode: 'locked-closed'
};
 update(index){
   console.log(index);
 }
 handlePressedIn(){
     this.props.navigation.navigate('Land', {});
 }
handleIn(index){
    this.setState({index}, () => {this.update(this.state.index)})
}
 schoolChange(text){
     const schools = this.schools.filter(school => school.toUpperCase().includes(text.toUpperCase()));
     this.setState({
         schools,
     });
 }
 handleChange(text){
     this.setState({text}, () => {
         this.schoolChange(this.state.text)
     });
 }
render() {
    const schools = this.state.schools.map((school, index) =>
        <TouchableNativeFeedback
            onPressIn = {() => this.handleIn(index)}
            onPress={() => this.handlePressedIn(index)}
            key={index}>
            <View style={ this.state.index == index ? styles.hover : styles.minis}>
                <Text style={this.state.index == index ?styles.textHover: styles.text}>{school}</Text>
            </View></TouchableNativeFeedback>
    );
    const view = <TouchableNativeFeedback><ScrollView overScrollMode={'never'} keyboardShouldPersistTaps='always'>{schools}</ScrollView></TouchableNativeFeedback>;
    const shadowOpt = {
        color: "#000",
        border: 12,
        opacity: '0.08',
        radius: 12,
        x: 0,
        y: 1,
    };
    return (
        <View style={styles.container}>
            <StatusBar backgroundColor='#F2C490' translucent={true} barStyle='dark-content'/>
            <View style={styles.header}>
                <HideWithKeyboard style={{
                    flex: 1,
                    alignContent: 'center',
                    justifyContent: 'space-between',
                    marginLeft: 15,
                    marginRight: 15,
                    flexDirection: 'row'
                }}><Text style={styles.headerLeft}>sẹlẹ</Text>
                    <Text style={styles.headerRight}>Select Institute</Text></HideWithKeyboard>
            </View><View style={styles.search}>
                <View style={styles.subSearch}><MaterialIcons style={{
                    padding: 10,
                }} name="search" size={30} color="#535461"/>
                    <TextInput placeholder="Search for your Institute"
                               value={this.state.text}
                               onChangeText={(text) => this.handleChange(text)}
                               placeholderStyle={{fontSize: 16, fontFamily: 'mont'}}
                               placeholderTextColor="#615D5D"
                               underlineColorAndroid={'transparent'}
                               style={{
                                   flex: 1,
                                   paddingTop: 10,
                                   paddingRight: 10,
                                   paddingBottom: 10,
                                   width: '65%',
                                   paddingLeft: 0,
                                   padding: 4,
                                   backgroundColor: '#fff',
                                   fontSize: 16, fontFamily: 'mont', color: '#615D5D',
                               }}/></View>
            </View>
/*
THE ACTIVITY INDICATOR SHOWING BASED ON THE LOADED STATE RENDERING THE MAPPED ARRAY
*/
                <View style={{flex: 1}}>
                {this.state.loaded ? <View style={{flex: 1}}>{view}</View>
                    :<ActivityIndicator animating={true} size='large' color="#E5AC6C"/>
                    }
            </View>
        </View>
    );
}

答案 3 :(得分:0)

我正在使用(在 Gunicorn 配置文件中)...

server.halt(reason="DB Connection failed.", exit_status=4)

Sintaxis 在这里:https://github.com/benoitc/gunicorn/blob/1299ea9e967a61ae2edebe191082fd169b864c64/gunicorn/arbiter.py#L340

还有,这里是记录器:

<块引用>

[2021-07-08 17:16:09 -0400] [44647] [INFO] 原因:数据库连接失败。
[2021-07-08 17:16:09 -0400] [44647] [INFO] 大师 进程退出...

最后一行是从“on_exit()”生成的...

def on_exit(server):
    ...
    server.log.info("Master process exiting...")
    ...