一、控制器层的更新、添加、删除

class AddKnowledgeAction extends CAction {
//add and update
public function actionPost() {
if ($_POST) { //如果是post操作
$res = array('code'=>,'message'=>'');
$kid = Yii::app()->request->getPost('kid'); //这里是知识主键id
$cid = Yii::app()->request->getPost('cid');
$title = Yii::app()->request->getPost('title');
$content = Yii::app()->request->getPost('content');
$auth_group = Yii::app()->request->getPost('auth_group');
$end_time = Yii::app()->request->getPost('end_time');
$keywords = Yii::app()->request->getPost('keywords'); if (empty($kid)) { //$kid不存在则说明是走add操作,否则是update
if ($kid = CallCenterService::addKnowledge($cid, $title, $content, $auth_group, $end_time, $keywords)) {
//这里表示添加成功
}
} else {
if (CallCenterService::updateKnowledge($kid, $cid, $title, $content, $auth_group, $end_time, $keywords)) {
//这里表示修改成功
}
}
}
} //delete
public function actionDelete (){
$kid = Yii::app()->request->getQuery('kid');
$action = Yii::app()->request->getQuery('action'); //action => ['delete' => '物理删除', 'Invalid' => '逻辑删除']if ($kid && $action) {
if (CallCenterService::delKnowledge($kid, $action)) {
//表示删除成功
}
}
}
}

二、服务层的更新、添加、删除

//服务层
class CallCenterService { private static $instance; public static $auth_group = null; public static function getInstance() {
if (empty(self::$instance)) {
self::$instance = new CallCenterService();
}
return self::$instance;
} /**
* 添加知识
*/
public static function addKnowledge($cid, $title, $content, $auth_group, $end_time, $keywords) {
$model = new Knowledgenew;
$operator = Yii::app()->user->id;
$created = date('Y-m-d H:i:s');
$model->attributes = array(
'cid' => $cid,
'title' => $title,
'content' => $content,
'operator' => $operator,
'created' => $created,
'auth_group' => $auth_group,
'end_time' => $end_time,
'keywords' => $keywords,
'updated' => $created
); if ($model->save()) {
$id = $model->id;
//异步添加索引到es
Knowledgenew::onKnowledgeChanged('add', array('id' => $id));
return $id;
} else {
}
return false;
} /**
* 编辑知识
*/
public static function updateKnowledge($kid, $cid, $title, $content , $auth_group, $end_time, $keywords) { $knowledge = Knowledgenew::getKnowledge($kid);
if ($knowledge) {
$model = new Knowledgenew;
$model->updateByPk($kid,
array(
'cid' => $cid,
'title' => $title,
'content' => $content,
'auth_group' => $auth_group,
'end_time' => isset($end_time) && !empty($end_time) ? $end_time : null,
'keywords' => $keywords,
'updated' => date('Y-m-d H:i:s')
)
);
Knowledgenew::onKnowledgeChanged('update', array('id' => $kid));
return true;
}
return false;
} /**删除一条知识
* @param $kid
* @param string $action Invalid => 逻辑删除 ,delete =>物理删除
* @return bool
*/
public static function delKnowledge($kid, $action = 'invalid') {
$knowledge = Knowledgenew::getKnowledge($kid); if ($knowledge) {
$model = new Knowledgenew;
if ($action == 'delete') {
$model->deleteByPk($kid);
} else {
$model->updateByPk($kid,array('status'=>Knowledgenew::STATUS_DEL));
}
//更新es
Knowledgenew::onKnowledgeChanged('delete', array('id' => $kid));
//删除收藏夹中的相关知识
KnowledgenewCollection::model()->deleteAll("kid = $kid");
return true;
}
return false;
} }

三、Model层的更新点击浏览次数场景及异步任务更新ES信息

//model层
class Knowledgenew extends CActiveRecord
{
const STATUS_NORMAL = ;
const STATUS_DEL = ; //Invalid public function tableName()
{
return '{{knowledgenew}}';
} public static function model($className=__CLASS__)
{
return parent::model($className);
} /**
* 增加浏览数
*/
public static function addClickNum($kid) {
$model = self::model();
$model->updateCounters(array('click_num'=>),'id=:id',array(':id'=>$kid));
Knowledgenew::onKnowledgeChanged('update', array('id' => $kid));
return true;
} //更新es信息
public static function onKnowledgeChanged($action, $param){
//echo '更新知识库索引action='.$action.PHP_EOL;
EdjLog::info('更新知识库索引action='.$action);
$base_param = array('es_source' => 'Knowledgenew', 'es_action' => $action);
Queue::model()->putin( //异步
array(
'method'=>'synchronize_elasticsearch',
'params'=>array_merge($base_param, $param)
),
'synchronize_elasticsearch'
);
}
}

四、异步Job队列生产

<?php
/**
* 基于redis的queue队列
*/
class Queue {
private static $_models; public $queue_max_length = array(
); public static function model($className=__CLASS__) {
$model=null;
if (isset(self::$_models[$className]))
$model=self::$_models[$className];
else {
$model=self::$_models[$className]=new $className(null);
}
return $model;
} //确定redis
private function select_redis($type) {
return QueuePool::model()->get_zone($type);
} private function trim($queue_name) { $type = str_replace("queue_", "", $queue_name);
$max = ;
if (isset($this->queue_max_length[$type])) {
$max = intval($this->queue_max_length[$type]);
}
if ($max>) {
$zone = $this->select_redis($type);
if($zone) {
$zone['redis']->lTrim($queue_name, , $max-);
}
else {
EdjLog::error("can not find zone, queue name: " . $type);
return;
}
}
} /**
* 放入队列,统一队列对外暴露方法,增加类型默认放task队列,指定了就放对应的队列,同时如果不在指定类型内的,也放默认队列
*
* @param unknown_type $params
* @param unknown_type $type
* @return mixed
*/
public function putin($params=null, $type){
$type = empty($type) ? 'error' : strtolower($type); $base_qname = QNameManagerService::model()->get_base_qname($type); if(!empty($base_qname)) {
$this->queue_name = 'queue_'.$base_qname;
}else{
$this->queue_name = 'queue_error';
} if ($params===null) {
return $this->get();
} else {
return $this->add($params); //如果add替换为processTask方法,则同步
}
} /**
* 取一条队列数据,封装多个队列,统一调用方法
* @param string $type
* @return array
*/
public function getit($type='default')
{
$base_qname = QNameManagerService::model()->get_base_qname($type); if(!empty($base_qname)) {
$this->queue_name = 'queue_'.$base_qname;
}else{
return array();
} $zone = $this->select_redis($type);
if($zone) {
if($zone['brpop']) {
$json = '';
$result = $zone['redis']->brPop($this->queue_name, $zone['brpop']);
if(!empty($result) && isset($result[])) {
$json = $result[];
}
}
else {
$json = $zone['redis']->rPop($this->queue_name);
}
}
else {
EdjLog::error("can not find zone, queue name: " . $type);
return array();
} return json_decode($json, true);
} /**
* 返回队列接收的类型列表
* @return array
*/
public function getQueueTypeList()
{
$list = QNameManager::model()->findall();
if($list) {
return $list;
} EdjLog::error("Error: get queue list from database");
return array();
} /**
* 设置或者读取位置队列
* @param array $params
* @return mixed
*/
public function position($params=null) {
$this->queue_name='queue_position'; if ($params===null) {
return $this->get();
} else {
return $this->add($params);
}
} /**
* 心跳队列
* @param string $params
* @return mixed
*/
public function heartbeat($params=null) {
$this->queue_name='queue_heartbeat'; if ($params===null) {
return $this->get();
} else {
return $this->add($params);
}
} /**
* 最高优先级队列
* @param string $params
* @return mixed
*/
public function task($params=null) {
$this->queue_name='queue_task'; if ($params===null) {
return $this->get();
} else {
return $this->add($params);
}
} /**
* 保存日志到数据库
* @param string $params
* @return mixed
*/
public function dumplog($params=null) {
$this->queue_name='queue_dumplog'; if ($params===null) {
return $this->get();
} else {
return $this->add($params);
}
} /**
* 返回各个队列中的任务总数
*/
public function length() { $queue = $this->getQueueTypeList(); $queue_length=array();
$reg = "/P[0-9]+$/";
foreach($queue as $item) {
$base_qname = $item->base_qname;
$zone = $this->select_redis($base_qname);
$key = 'queue_'.$base_qname;
if($zone) {
$len = $zone['redis']->lLen($key);
if(isset($item->max) && $len > $item->max) {
$key = '!'.$key;
} $pkey = '';
if(preg_match($reg, $zone['name'])) {
$pkey = $key.'@'.$zone['name'];
}
else {
$pkey = $key.'@'.$zone['name']."_P".$item->level;
} $queue_length[$pkey] = $len;
}
else {
EdjLog::error("can not find zone, queue name: " . $key);
}
} return $queue_length;
} private function get() {
$type = str_replace("queue_", "", $this->queue_name);
$zone = $this->select_redis($type);
if($zone) {
if($zone['brpop']) {
$json = '';
$result = $zone['redis']->brPop($this->queue_name, $zone['brpop']);
if(!empty($result) && isset($result[])) {
$json = $result[];
}
}
else {
$json = $zone['redis']->rPop($this->queue_name);
}
}
else {
EdjLog::error("can not find zone, queue name: " . $type);
return array();
}
return json_decode($json, true);
} private function add($params) {
$json=json_encode($params);
$type = str_replace("queue_", "", $this->queue_name);
$zone = $this->select_redis($type);
$return = ;
if($zone) {
try {
$return = $zone['redis']->lPush($this->queue_name, $json);
} catch (Exception $e) {
EdjLog::error("write redis error,msg:".$e->getMessage());
//echo $e->getMessage();
}
}
else {
EdjLog::error("can not find zone, queue name: " . $type);
} return $return;
} //如果add 替换为此方法,则同步
public function processTask($task) {
if(!isset($task['method'], $task['params'])) {
$task_content = json_encode($task);
EdjLog::error("can not run task due to no 'method' or 'params' specified, task is $task_content");
return;
} $method=$task['method'];
$params=$task['params'];
$class = isset($task['class']) ? $task['class'] : "QueueProcess";
EdjLog::info("REDIS_QUEUE_OUT CLASS:$class METHOD:$method PARAMS:".json_encode($params));
try {
//throw new Exception("Value must be 1 or below");
$queue_process=new $class();
// check this method is exist, if not throw ReflectionException
new ReflectionMethod($queue_process, $method);
call_user_func_array(array($queue_process, $method), array($params));
} catch(Exception $e) {
$errmsg = $e->getMessage();
EdjLog::error("execption queue_run method:$method err: $errmsg");
}
} public function getLengthByType($type){
$type = empty($type) ? 'error' : strtolower($type);
$base_qname = QNameManagerService::model()->get_base_qname($type);
$zone = $this->select_redis($base_qname);
$key = 'queue_'.$base_qname;
$len = ;
if($zone) {
$len = $zone['redis']->lLen($key);
} else {
EdjLog::error("can not find zone, queue name: " . $base_qname);
}
return $len;
}
}

五、异步Job队列消费

<?php
/**
* 队列处理
*/
Yii::import("application.ecenter.service.HttpUtils");
class QueueProcess {
private static $_models;
private $message; public static function model($className=__CLASS__) {
$model=null;
if (isset(self::$_models[$className]))
$model=self::$_models[$className];
else {
$model=self::$_models[$className]=new $className(null);
}
return $model;
} public function synchronize_elasticsearch($param)
{
if (empty($param) || !isset($param['es_source'], $param['es_action'])) {
return false;
} $class_name = $param['es_source'].'Synchronizer';
$method_name = $param['es_action'];
if (class_exists($class_name) && method_exists($class_name, $method_name)) {
unset($param['es_source']);
unset($param['es_action']);
call_user_func(array($class_name, $method_name), $param);
} else {
EdjLog::error('synchronize method does not exist. class name '.$class_name.' method name '.$method_name);
}
} }

六、ES信息处理操作服务层

<?php
/**
* Created by PhpStorm.
*/ class KnowledgenewSynchronizer { static public $index = 'knowledge_index';
static public $type = 'knowledge';
static public $filed = ' id, keywords, title, content, auth_group, cid, operator, click_num, status, created, updated '; static public function add($param)
{
if (empty($param) || !isset($param['id'])) {
return false;
}
$id = $param['id'];
$sql = "select".self::$filed."from t_knowledgenew where id=:id";
$doc = Yii::app()->db->CreateCommand($sql)->queryRow(true,array('id'=>$id)); if (empty($doc)) {
EdjLog::error('cannot find knowledge with id: '.$id);
return false;
} return ElasticsearchSynchronizer::addDocument(self::$index, self::$type, $id, $doc);
} static public function delete($param)
{
if (empty($param) || !isset($param['id'])) {
return false;
}
$id = $param['id'];
return ElasticsearchSynchronizer::deleteDocument(self::$index, self::$type, $id);
} static public function update($param)
{
if (empty($param) || !isset($param['id'])) {
return false;
}
$id = $param['id']; $sql = "select".self::$filed."from t_knowledgenew where id=:id";
$doc = Yii::app()->db->CreateCommand($sql)->queryRow(true,array('id'=>$id)); if (empty($doc)) {
EdjLog::error('cannot find knowledge with id: '.$id);
return false;
} return ElasticsearchSynchronizer::updateDocument(self::$index, self::$type, $id, $doc);
} }

七、ES信息处理操作Model层

<?php

use Elastica\Client;
use Elastica\Query\QueryString;
use Elastica\Query;
use Elastica\Document; Class ElasticsearchSynchronizer
{//测试
//const ES_HOST='search.n.edaijia.cn';
//const ES_PORT=9200; static public function addDocument($index, $type, $id, $doc)
{
$client = new Client(array('host' => self::ES_HOST, self::ES_PORT));
$type = $client->getIndex($index)->getType($type);
try {
$response = $type->addDocument(new Document($id, $doc));
if ($response->isOk()) {
EdjLog::info("add document $id succeeded");
return true;
} else {
EdjLog::info("add document $id failed");
return false;
}
} catch (Exception $e) {
print_r($e);
EdjLog::error("add document $id failed with exception ".$e->getMessage());
return false;
}
} static public function updateDocument($index, $type, $id, $doc)
{
$client = new Client(array('host' => self::ES_HOST, 'port' => self::ES_PORT));
try {
$response = $client->getIndex($index)
->getType($type)
->updateDocument(new Document($id, $doc)); if ($response->isOk()) {
EdjLog::info("update document $id succeeded");
return true;
} else {
EdjLog::info("update document $id failed");
return false;
}
} catch (Exception $e) {
EdjLog::error("update document $id failed with exception ".$e->getMessage());
return false;
}
} static public function deleteDocument($index, $type, $id)
{
$client = new Client(array('host' => self::ES_HOST, 'port' => self::ES_PORT));
try {
$response = $client->getIndex($index)->getType($type)->deleteById($id);
if ($response->isOk()) {
EdjLog::info("delete document $id succeeded");
return true;
} else {
EdjLog::info("delete document $id failed");
return false;
}
} catch (Exception $e) {
EdjLog::error("delete document $id failed with exception ".$e->getMessage());
return false;
}
} }

八、查询

 /**
* @param $keyword
* @param int $page
* @param int $size
* @param str $search_type
* 搜索知识
* 搜索标题和内容,多个关键词是并且关系,空格分隔
*/
public static function searchKnowledge($keyword, $page = , $size = , $search_type = 'default') {
//对搜索关键词空格隔开
// $keywords = explode(' ',trim($keyword));
$start = $page * $size;
$client = new \Elastica\Client(array('host' => ElasticsearchSynchronizer::ES_HOST, 'port' => ElasticsearchSynchronizer::ES_PORT));//更改成线上主机和端口
$search = new \Elastica\Search($client);
$search ->addIndex(KnowledgenewSynchronizer::$index)->addType(KnowledgenewSynchronizer::$type);
// $query = new \Elastica\Query\Bool();
$query = new \Elastica\Query();
//设置必要查询
// foreach($keywords as $word) {
// if($word) {
// $knowledge_query = new \Elastica\Query\QueryString();
// $knowledge_query->setFields(array('title', 'content'));
// $knowledge_query->setQuery('"' . $word . '"');
// $query->addMust($knowledge_query);
// }
// }
$MultiMatch_obj = new \Elastica\Query\MultiMatch();
$MultiMatch_obj->setQuery($keyword);
if ($search_type == 'default') {
$MultiMatch_obj->setFields(array('keywords'));
} else {
$MultiMatch_obj->setTieBreaker(0.3);
$MultiMatch_obj->setType('best_fields');
$MultiMatch_obj->setFields(array('keywords^901209','content'));
$MultiMatch_obj->setOperator('or');
//这里是字符串,在es的扩展目录下 setMinimumShouldMatch方法把转int去掉//
//$this->setParam('minimum_should_match', (int)$minimumShouldMatch);
$MultiMatch_obj->setMinimumShouldMatch('30%'); }
$query->setQuery($MultiMatch_obj); //命中全部纪录
$query = \Elastica\Query::create($query);
$query->setSource(["id","cid","updated", "title", 'keywords',"content",'auth_group','status']);
// $query->setSort([
// 'click_num' => ['order' => 'desc']
// ]); //设置起始页
$query->setFrom($start);
$query->setSize($size);
//设置高亮显示
$query->setHighlight(array(
'pre_tags' => array('<span style="color: red">'),
'post_tags' => array('</span>'),
'fields' => array(
'title' => array(
'fragment_size' => ,//包含高亮词语,最多展示多少个
'number_of_fragments' => ,//分几段展示,这里一段就可以
),
'keywords' => array(
'fragment_size' => ,//包含高亮词语,最多展示多少个
'number_of_fragments' => ,//分几段展示,这里一段就可以
),
'content' => array(
'fragment_size' => ,//包含高亮词语,最多展示多少个
'number_of_fragments' => ,//分几段展示,这里一段就可以
),
),
)); $search->setQuery($query); $results = array();
$totalResults = ;
try {
$resultSet = $search->search();
$results = $resultSet->getResults();
$totalResults = $resultSet->getTotalHits();
} catch (Exception $e) {
EdjLog::error("query elasticsearch failed");
} if ($totalResults <= ) { return;
} $poi_result = array();
foreach ($results as $result) {
$highlight = $result->getHighlights();
$title_hightlight = isset($highlight['title'][])?$highlight['title'][]:'';
$content_hightlight = isset($highlight['content'][])?$highlight['content'][]:'';
$keywords_highlight = isset($highlight['keywords'][])?$highlight['keywords'][]:''; $poi_result[] = array(
'id' => $result->id,
'cid' => $result->cid,
'title' => $result->title,
'keywords' => $result->keywords,
'content' => $result->content,
'auth_group' => $result->auth_group,
'title_highlight'=>$title_hightlight, //高亮展示标题搜索关键词
'keywords_highlight'=>$keywords_highlight, //高亮展示标题搜索关键词
'content_highlight'=>$content_hightlight,//高亮展示内容搜索关键词
'updated'=>$result->updated,
'status' => $result->status,
);
} //这里过滤了用户非权限列表
$poi_result = self::filterNoAuthKnowledge($poi_result);
$totalResults = count($poi_result) ;
$info = array('totalNum'=>$totalResults,'data'=>$poi_result);
return json_encode($info);
}

九、源码包

链接:https://pan.baidu.com/s/1lVcrb50HSLrJh3zvBOdH5g
提取码:9c9c

ElasticSearch(九)e代驾使用Elasticsearch流程设计(Yii1版本)的更多相关文章

  1. Elasticsearch学习总结 (Centos7下Elasticsearch集群部署记录)

    一.  ElasticSearch简单介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticse ...

  2. 审核流(2)流程设计-SNF.WorkFlow功能使用说明--SNF快速开发平台3.1

    流程设计 图形化的流程设计,更方便.直观 1.打开“流程设计“程序,如上.点击”新建“如下: 2.红色部分为必填项,审批对象是选择要审批的程序菜单,单据名称是在审核流流转时用于提示的单据名称,还要选择 ...

  3. Elasticsearch入门教程(六):Elasticsearch查询(二)

    原文:Elasticsearch入门教程(六):Elasticsearch查询(二) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:h ...

  4. Atitit 修改密码的功能流程设计 attilax总结

    Atitit 修改密码的功能流程设计 attilax总结 1.1. 注意点1 1.2. 设计修改用户密码功能时把用户ID保存在哪里?1 1.3. Ui设计1 1.4. 功能设计源码1 1.5. Agt ...

  5. asp.net 微信企业号办公系统-表单及流程设计配置实例

    在环境搭建好之后,我们就来学习一下怎样快速创建一个流程,并执行和流转该流程(我们这里讲的只是入门,不涉及到具体流程参数设置). 创建一个流程步骤为:在数据库在创建表-->设计表单-->设置 ...

  6. asp.net 微信企业号办公系统-流程设计--保存与发布

    如果流程未设计完时可以先保存,以后再打开接着设计.点击工具栏上的保存按钮即可保存当前流程设计: 如果下次要接着设计,则可以打开该流程继续设计: 如果流程设计完成,可以点击安装按钮来发布流程,流程安装成 ...

  7. asp.net 微信企业号办公系统-流程设计--流程步骤设置-策略设置

    策略设置包括当前步骤的流转方式,处理人员,退回策略等设置. 流转类型:当前步骤后面有多个步骤时,此类型选择可以决定后续步骤的发送方式. 1.系统控制:由系统根据您在线上设置的流转条件来判断该发送到哪一 ...

  8. 三、activiti工作流-流程设计工具

    首先在diagrams下面新建一个文件夹 然后在这个文件夹下new一个Activiti Diagram new好后出现bpmn文件, 可以通过右键以xml方式打开bpmn文件查看源码 双击打开文件然后 ...

  9. Elasticsearch从入门到精通-Elasticsearch是什么

    作者其他ELK快速入门系列文章 logstash快速入门实战指南 Kibana从入门到精通 一.前言 驱动未来商业发展的最重要“能源”不是石油,而是数据.我们还来不及了解它,这个世界已经被它淹没.多年 ...

随机推荐

  1. 【转】Spring的IOC原理(通俗易懂)

    1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由Ñ个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 如果我们打开机械式手表的后盖,就会看到与上 ...

  2. python27期day01:变量、常量、注释、PEP8开发规范、数据类型、Python2和Python3的区别、用户输入、流程控制语句、作业题

    1.变量:将程序中运行的中间值临时存储起来,以便下次使用. 2.变量命名规范:数字.字母.下划线.建议驼峰体.变量名具有可描述性.不能使用中文和拼音.不能数字开头和使用关键字('and', 'as', ...

  3. 【问题篇四】SpringBoot的properties文件不能自动提示解决方法(1)

    一.Eclipse 解决方法:Eclipse中安装Spring Tools Suite(STS). 这里采用离线安装的方式. 1. 官网:https://spring.io/tools3/sts/al ...

  4. django之分页器、多对多关系、form校验组件

    批量插入数据 bulk_create # 1.往书籍表中插入数据 1000 # for i in range(1000): # 这种插入方式 效率极低 # models.Book.objects.cr ...

  5. css样式添加错误导致烦扰

    省厅和市州 两个ul 之间切换  分别能显示两者对应的内容 但是在做过程中,出现省厅界面有市州的内容… 找了半天,发现是css的问题   layui-show的多添加 算是把首页内容的任务解决了至于c ...

  6. ASP.NET Core 进程内(InProcess)托管

    ASP.NET Core 进程内(InProcess)托管 在 ASP.NET Core 中的进程内(InProcess)托管模型 什么是 Kestrel 服务器 当一个 ASP.NET Core 应 ...

  7. 8.10 NOIP模拟测试16 Blue+Weed+Drink

    T1 Blue 贪心,每次跳得时候跳能跳到的最远的地方,跳过的就把他设为0,每次二分找到位置,一直跳就行,如果能跳到的位置就是当前位置或比当前位置还小(数组里现在呆着的这一块石头,二分得到的就是当前位 ...

  8. [LeetCode] 15. 3Sum 三数之和

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  9. 使用IDEA+vue.js+easyUI的demo

    最近,随便写了几个开发的小例子,自己总结下,留个纪念. 例子1:使用EasyUI做了一个简单界面,服务器和客户端在一起. @Controller @RequestMapping("/demo ...

  10. uwsgi异常服务器内存cpu爆满

    记录线上服务器通过linux性能检测工具glances检测到 cpu.内存爆满,且是uwsgi进程占用,对于服务器内核,以及uwsgi配置优化 参考文章 https://blog.csdn.net/o ...