优化 Workerman 检查主进程是否存活的逻辑

主要新增了判断进程是否为 Workerman 进程的逻辑,从而优化了确定主进程是否存活的准确性。

转载请注明来源地址:http://her-cat.com/posts/2021/03/17/optimize-workerman-to-check-whether-the-main-process-is-alive/

发现问题

年前逛 GitHub 的时候,发现 Workerman 有一个 2017 年打开的 Issue:already running,原文如下:

Where is the problem?! I reboot the server and it is the first time I want to run workerman

php index.php start -d
The result is

Workerman[index.php] start in DAEMON mode
Workerman[index.php] already running

大概意思就是重启服务器之后,第一次启动 Workerman 会提示已经在运行了,但实际上并没有运行。

因为重启服务器之后,保存 Workerman 主进程 PID 的文件仍保留在磁盘上。

正常情况下,Workerman 退出时会清理掉这个文件,但是该用户重启服务器后文件并没有被清理,导致 Workerman 误认为已经在运行中。

作者给出了一个补救方法:手动删除记录主进程 PID 的文件。虽然临时解决了问题,但是每次出现都要去手动处理一下,感觉不太友好。

要想解决这个问题,首先得弄清楚两个问题:

  • 为什么 Workerman 没有清理 PID 文件?
  • 为什么重启服务器后启动 Workerman 提示已经在运行中?

Workerman 判断是否已运行的逻辑

Workerman 在启动的时候会生成一个文件,用于记录主进程的 PID。

// Start file.
$backtrace        = \debug_backtrace();
static::$_startFile = $backtrace[\count($backtrace) - 1]['file'];

// 生成文件名
$unique_prefix = \str_replace('/', '_', static::$_startFile);

// 保存记录主进程 PID 的文件路径
if (empty(static::$pidFile)) {
    static::$pidFile = __DIR__ . "/../$unique_prefix.pid";
}

然后检查 Workerman 是否已经在运行中。

// 获取主进程的 PID,如果文件不存在或者不是一个正常的文件则返回 0
$master_pid      = \is_file(static::$pidFile) ? \file_get_contents(static::$pidFile) : 0;

// 如果 PID 存在就给它发送一个信号 `0`,信号量 `0` 类似于 ping,用于检测进程是否存活
// 然后判断当前进程 PID 是否不等于文件中记录的 PID(不相等说明 Workerman 已经在运行中,但是又再次执行命令了)
$master_is_alive = $master_pid && \posix_kill($master_pid, 0) && \posix_getpid() !== $master_pid;
if ($master_is_alive) {
    // 如果主进程存活并且执行的命令为 start,提示 Workerman 正在运行中并退出
    if ($command === 'start') {
        static::log("Workerman[$start_file] already running");
        exit;
    }
} elseif ($command !== 'start' && $command !== 'restart') {
    // 如果主进程未存活且执行的命令不是 start 或 restart,则提示 Workerman 未运行并退出
    static::log("Workerman[$start_file] not run");
    exit;
}

当一系列检查通过后,开始保存主进程的 PID。

protected static function saveMasterPid()
{
    // 非 Linux 系统不保存 PID
    if (static::$_OS !== \OS_TYPE_LINUX) {
        return;
    }

    // 获取主进程的 PID
    static::$_masterPid = \posix_getpid();

    // 将主进程的 PID 写入到文件中
    if (false === \file_put_contents(static::$pidFile, static::$_masterPid)) {
        throw new Exception('can not save pid to ' . static::$pidFile);
    }
}

当收到 SIGINTSIGTERMSIGHUP 等信号时,将进程状态设置为 STATUS_SHUTDOWN 并通知子进程退出。

如果主进程的状态为 STATUS_SHUTDOWN 并且所有子进程已经退出,就会去清除 PID 文件并退出。

protected static function exitAndClearAll()
{
    foreach (static::$_workers as $worker) {
        $socket_name = $worker->getSocketName();
        if ($worker->transport === 'unix' && $socket_name) {
            list(, $address) = \explode(':', $socket_name, 2);
            @\unlink($address);
        }
    }
    // 删除 PID 文件
    @\unlink(static::$pidFile);
    static::log("Workerman[" . \basename(static::$_startFile) . "] has been stopped");
    if (static::$onMasterStop) {
        \call_user_func(static::$onMasterStop);
    }
    // 退出进程
    exit(0);
}

复现问题

看到这有人肯定会问了,这不是有清理 PID 文件的机制吗?为什么还能从文件中获取到 PID?

我先在虚拟机中进行了测试,服务器在重启的时候会发送 SIGTERM 信号通知进程,Workerman 可以正常退出并且清理 PID 文件。

但是在云服务器中测试的时候,如果勾选了强制重启会导致 Workerman 收不到信号,也就不能够执行 exitAndClearAll() 里面的代码了。

来自服务器厂商的提醒:强制重启会导致云服务器中未保存的数据丢失,请谨慎操作。

为什么给 PID 文件中的进程发信号还会返回 true 呢?

服务器在重启后,另一个进程启动了,它的 PID 与 Workerman 的旧 PID 相同(没错,就是这么巧)。

所以在检查主进程是否存活时,还要判断该进程是否为 Workerman 的进程。

解决问题

Issue 中 @detain 给出了一个使用 shell 脚本的解决方法:

To check to see if its running and safely remove pid files can do something like:

if [ $(php start.php status 2>/dev/null|grep "PROCESS STATUS"|wc -l) -eq 0 ]; then
  # clean up old run, remove pid file or run a stop command?
  php start.php stop
  php start.php start -d
fi

先通过 php start.php status 命令获取 Workerman 的状态,然后统计 PROCESS STATUS 出现的次数(每个进程都会有一个 PROCESS STATUS),如果次数为 0 说明没有运行中的进程,就可以执行停止命令,再启动 Workerman。

受到这个方法启发,然后基于它改造了 Workerman 检查主进程是否存的逻辑,一顿复制粘贴之后就有了第一版的代码:

// Get master process PID.
$master_pid      = \is_file(static::$pidFile) ? \file_get_contents(static::$pidFile) : 0;
// Master is still alive?
if (static::checkMasterIsAlive($master_pid)) {
    if ($command === 'start') {
        static::log("Workerman[$start_file] already running");
        exit;
    }
}


/**
 * Check master process is alive
 *
 * @param $master_pid
 * @return bool
 */
protected static function checkMasterIsAlive($master_pid)
{
    if (empty($master_pid)) {
        return false;
    }

    $master_is_alive = $master_pid && \posix_kill($master_pid, 0) && \posix_getpid() !== $master_pid;
    if (!$master_is_alive) {
        return false;
    }

    // Master process will send SIGUSR2 signal to all child processes.
    \posix_kill($master_pid, SIGUSR2);
    // Sleep 1 second.
    \sleep(1);

    return stripos(static::formatStatusData(), 'PROCESS STATUS') !== false;
}

逻辑跟 shell 脚本差不多,就不再解释了。这个解决方法也有两个小问题:

  • 执行命令时会延迟一秒钟,因为执行一些命令的时候需要 sleep 一秒钟等待子进程写入状态信息。
  • 如果另一个进程的 PID 与 Workerman 的旧 PID 相同,它将接收 SIGUSR2 信号。

感觉在启动的时候慢一秒应该还能接受,只要处理请求的时候不慢就行了,于是就提交了 PR,并描述了这一段代码的作用及带来的问题。

Fixed: #125

There is a problem:
if another process starts and the pid is the same as the workerman's old pid, it will receive the SIGUSR2 signal.

没过多久作者便在 PR 下面回复了我:

Thank you for your pr.

There is a problem:
if another process starts and the pid is the same as the workerman's old pid, it will receive the SIGUSR2 signal.

If the PR is merged, some commands will be delayed by one second.
I think a better way is to read /proc/PID information to determine whether it is a PHP process or a workerman process.

先说了延迟一秒钟的问题,接着又给出了更好的解决方法:读取 /proc/PID 信息来确定它是其它进程还是 Workerman 进程。

搜索资料之后发现可以读取 /proc/PID/cmdline 得到启动进程时的命令。Workerman 在启动时会调用 Worker::setProcessTitle() 方法覆盖 cmdline 的内容,所以实际上得到的是 Workerman 的进程名称。

只需要判断 cmdline 是否包含 Worker::$processTitle 就可以知道该进程是否为 Workerman 进程。

因为进程名称可能会被截取掉,所以这里用的是包含而不是等于。

protected static function checkMasterIsAlive($master_pid)
{
    if (empty($master_pid)) {
        return false;
    }

    // 检查进程是否存活
    $master_is_alive = $master_pid && \posix_kill($master_pid, 0) && \posix_getpid() !== $master_pid;
    if (!$master_is_alive) {
        return false;
    }

    // 到了这里说明进程是存活的,但是不能保证这个进程是 Workerman 进程
    // 需要读取进程信息才能确定,有任何一个步骤导致不能获取进程信息都要返回 true
    // 因为根据上面的检测结果,进程是存活的

    $cmdline = "/proc/{$master_pid}/cmdline";

    // 进程信息不可读或设置的进程名为空
    if (!is_readable($cmdline) || empty(static::$processTitle)) {
        return true;
    }
    
    $content = file_get_contents($cmdline);
    // 未读取到进程信息
    if (empty($content)) {
        return true;
    }

    // 判断是否包含进程名称
    return stripos($content, static::$processTitle) !== false;
}

再次提交,没过多久就收到了代码被合并的邮件。

总结

回答一下上面提出的两个问题:

Q:为什么 Workerman 没有清理 PID 文件?

A:因为 Workerman 没有正常退出(强制关机、重启、断电)

Q:为什么重启服务器后启动 Workerman 提示已经在运行中?

A:因为服务器重启后,其他进程的 PID 与 Workerman 的旧 PID 相同,误认为是 Workerman 进程。

相关链接

  • already running
  • Optimize the logic of checking whether the master is alive
  • 优化 Workerman 检查主进程是否存活的逻辑
博客地址:她和她的猫,欢迎关注。
本文转载于网络 如有侵权请联系删除

相关文章

  • 本体技术视点 | OpenKG区块链:构建可信开放的联邦知识图谱平台(上)

    论文摘要知识是有价值的,即使是权限可控的单一机构内部,知识来源也是多样化的,必定存在知识的价值量化、确权、溯源、隐私及可信等多方面问题。要在知识生产和消费闭环中平衡知识的责、权、利,并有效的激励众包,一种方法就是让知识上链,并构建知识的区块链系统。OpenKG作为新技术测试床,在相关方向努力做一些粗浅尝试,也希望为各企业机构建立知识图谱众包平台提供参考。在实践过程中,我们也发现很多问题和挑战,如细粒度知识确权带来的性能问题、细粒度知识众包的价值计算公平性问题、知识图谱的去中心化存储问题等,这些都需要更深入的研究和实践。本文介绍了OpenKG在区块链方向的一些实践和尝试。OpenKG初步完成了底层区块链平台测试,以及OpenKG.CN数据集、工具集和OpenBase细粒度知识众包的上链测试工作。在这个测试平台中,我们首次测试实现了OpenKG.CN和OpenBase平台的知识确权。通过OpenKG.CN发布的开放图谱和开源工具,以及通过OpenBase众包平台采集的三元组,OpenKG都在链上进行存证操作,并计算和分配产生的荣誉值。OpenKG希望通过这项工作为知识图谱社区提供更加可信、

  • 【多路径】CentOS7.7下使用Openfiler+Multipath+UDEV

    Openfiler是一款网络存储软件,在OracleRAC部署的时候,可以用来模拟共享存储,并实现多路径(Multipath)。多路径简单来说,就是连接磁盘的多条链路,避免单条链路中断导致的数据库不可用,另外多条链路间还能实现负载均衡。一、场景现在需要在VM虚拟机上搭建一套测试RAC集群(CentOS7.7+11.2.0.4),计划使用Openfiler软件模拟共享存储及实现多路径,共享磁盘的规划如下:磁盘名称说明大小数量+OCR集群注册表和表决磁盘3G1Gx3+DATA数据文件、controlfile、spfile、redolog20G1+FRA归档5G1Openfiler两块网卡IP:192.168.10.5510.10.10.15本篇客户端为CentOS7,操作均验证过二、Openfiler安装1.下载--下载地址,目前可下载到openfileresa-2.99.1-x86_64-disc1.iso https://www.openfiler.com/community/download复制2.安装使用VMware安装前配置:打开【VMwareWorkstation15Pro】点

  • 为Linux发行版安装中文字体

    前文提到博主为自己的ThinkPadE450安装了一款来自爱尔兰的Linux/GNU发行版作为主力系统使用。近期需要进行文字处理工作,安装了WPS2019Linux版,但是发现这款外来的Linux/GNU发行版并没有自带一些常用的中文字体,如宋体、仿宋、黑体等字体,经过一番检索,博主使用从Windows10家庭中文版中提取出中文字体导入,并在系统中刷新字体以使字体生效。下面就来讲讲详细步骤:字体资源准备方案一:字体可以自行从windows系统下进入C:\windows\Fonts文件夹,挑选常用的中文字体拷贝到U盘。方案二:为方便需要的人,博主已从windows系统中提取了常用中文字体并打包,放进博主的资源站(https://res.frytea.com/)开放下载,需要的伙伴可以从下列地址进入下载(若地址实效请自行进入资源站寻找或联系博主):直链地址:https://res.frytea.com/Others/Fonts/win_cn_fonts.zip资源来源详情: 系统版本:Windows10家庭中文版系统版本号:1903系统安装日期:2019/10/29操作系统版本:18362

  • [译] 在你学习 React 之前必备的 JavaScript 基础

    原文地址:JavaScriptBasicsBeforeYouLearnReact原文作者:NathanSebhastian写在前面为了不浪费大家的宝贵时间,在开头申明一下,这篇文章针对的阅读对象是:没有写过React或者刚刚才接触React并且对于ES6的语法不太了解的同学,这是一篇基础入门的文章,在一开始我并没有准备翻译一篇这样的基础文章,但是在阅读完全文之后,我想起自己刚开始学习React时的迷茫,ES6有那么多,我需要掌握多少呢?对于一个急于上手React写代码的人来说,这篇文章告诉你最基本要掌握的知识,让你快速的写起来。但是后期的提高,仍旧需要去夯实Javascript的基础。前言在理想的状态下,你可以在深入了解React之前了解JavaScript和Web开发的所有知识。不幸的是,我们生活在一个不完美的世界,所以在React之前把所有的JavaScript都咀嚼一遍只会让你举步维艰。如果你已经拥有一些JavaScript经验,那么在React之前你需要学习的只是实际用于开发React应用程序的JavaScript功能。在学习React之前你应该学会的JavaScript的知识

  • 深度强化学习调研概览及最新论文成果(一)RL base & DQN-DDPG-A3C introduction

    来源:https://zhuanlan.zhihu.com/p/25239682 过去的一段时间在深度强化学习领域投入了不少精力,工作中也在应用DRL解决业务问题。子曰:温故而知新,在进一步深入研究和应用DRL前,阶段性的整理下相关知识点。本文集中在DRL的model-free方法的Value-based和Policy-base方法,详细介绍下RL的基本概念和Value-basedDQN,Policy-basedDDPG两个主要算法,对目前state-of-art的算法(A3C)详细介绍,其他前沿算法的详细理解留待后续展开。一、RL:asimpleintroduction强化学习是机器学习的一个分支,相较于机器学习经典的有监督学习、无监督学习问题,强化学习最大的特点是在交互中学习(LearningfromInteraction)。Agent在与环境的交互中根据获得的奖励或惩罚不断的学习知识,更加适应环境。RL学习的范式非常类似于我们人类学习知识的过程,也正因此,RL被视为实现通用AI重要途径。1.1强化学习问题的基本设定:<A,S,R,P> Actionspace:A St

  • Python绘制带有中文标签和图例的图

    本文属于科学计算与可视化范畴,要点在于扩展库numpy、pylab、matplotlib的用法。importnumpyasnpimportpylabasplimportmatplotlib.font_managerasfm#设置字体myfont=fm.FontProperties(fname=r'C:\Windows\Fonts\STKAITI.ttf')#自变量取值范围t=np.arange(0.0,2.0*np.pi,0.01)#计算正弦函数值s=np.sin(t)#计算余弦函数值z=np.cos(t)pl.plot(t,s,label='正弦')pl.plot(t,z,label='余弦')#设置x标签pl.xlabel('x-变量',fontproperties='STKAITI',fontsize=24)pl.ylabel('y-正弦余弦函数值',fontproperties='STKAITI',fontsize=24)#图形标题pl.t

  • 新型3D打印汽车部件技术,能否改变汽车行业未来?

    据外媒报道,Divergent3D是一家致力于汽车配件3D打印业务的公司。几周前,它跟PSA集团(标致和雪铁龙)签订了一份合作协议。日前,它又跟工程公司Altran达成了合作关系。现在,Divergent3D将要开始研发一种能让OEM以更低成本、更低能源消耗量产汽车部件的技术。厂商在近几十年所用的汽车部件生产工艺似乎一直发生太大的改变,其所用的金属压印法不仅成本高昂而且还非常消耗能源。Divergent3D创始人兼CEOKevinCzinger在创办公司伊始就已经意识到这点。他告诉媒体,这种汽车零部件的生产工艺阻碍了汽车行业的发展。而Divergent3D的生产工艺则完全不同,他们使用了一种叫做直接金属激光烧结的工艺。该工艺能极为容易地将铝合金粉末烧结在一起,然后形成所需的部件或非金属部件模具。而传统的生产方式却不得不因部件的复杂形状而必须要先生产小块然后将其焊接在一起,显而易见,这种工艺显得麻烦得多。眼下,Divergent3D和它的合作伙伴们还只是在打造结构部件和悬挂部件,不过Czinger表示,未来他们将把这种工艺应用到气缸盖、引擎机体等更大的复杂结构部件生产中。据了解,Dive

  • 腾讯云主机安全删除恶意请求记录api接口

    1.接口描述接口请求域名:cwp.tencentcloudapi.com。 本接口(DeleteMaliciousRequests)用于删除恶意请求记录。 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DeleteMaliciousRequests。 Version 是 String 公共参数,本接口取值:2018-02-28。 Region 是 String 公共参数,详见产品支持的地域列表。 Ids.N 是 ArrayofInteger 恶意请求记录ID数组,(最大100条) 3.输出参数 参数名称 类型 描述 RequestId String 唯一请求ID,每次请求都会返回。定位问题时需要提供该次请求的Req

  • 明天去FDUSC报道了,GOD BLESS ALL OF US

    @lrb @tellmewtf @proverbs   没有人能阻止我前进的步伐,除了我自己!

  • 编译 curl with ssl

    安装openssh后,使用curl的./configure--with-ssl时,报错“找不到ssl”。因为curl在/usr/local/ssl的安装目录下找动态连接库。而ssl默认不生成动态连接库。解决办法是编译ssl时使用enable-shared生成动态连接库 ./configenable-shared  curlversion:    7.41.0 Hostsetup:      x86_64-unknown-linux-gnu Installprefix:  /usr/local Compiler:        gcc SSLsupport:     enabled(OpenSSL) SSHsupport:     n

  • JS实现单向链表、双向链表、循环链表

    https://cloud.tencent.com/developer/article/1114246   链表存储有序的元素的集合,但是和数组不同的是,链表中的元素在内存中的存储并不是连续的。每一个链表元素都包含了一个存储元素本身的节点和一个指向下一个元素的引用。看起来就像这样:   相对于传统的数组,链表的一个好处就是增删的时候无需移动其它元素,只要更改指针的指向就可以了。但是缺点就是如果想要访问链表中的元素,需要从头开始循环迭代到你想要的元素。 functionLinkedList(){ //Node辅助类,表示要加入列表的项,element是即将添加到列表的值,next是指向列表中下一个节点项的指针 letNode=function(element){ this.element=element this.next=null } letlength=0 lethead=null //向链表尾部追加元素 this.append=function(element){ letnode=newNode(element) letcurrent if(head===nu

  • git 命令行(三)-删除文件

    在Git中,删除也是一个修改操作,我们实战一下,有一个多余的文件:src/common/Util2.js 我们需要删除这个文件, 一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用 rm命令删了: 这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,gitstatus命令会立刻告诉你哪些文件被删除了: 现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令gitrm 删掉,并且gitcommit:   另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本: gitcheckout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

  • OpenStack概述、虚拟机部署OpenStack

      一、openstack概述 OpenStack是一个由美国国家航空航天局(NASA)和Rackspace合作研发并发起的开源项目。其中Rackspace贡献了Swift,NASA贡献了Nova项目,这两个子项目发展到现在的大大小小十多个项目。其宗旨在于:帮助组织运行为虚拟计算或存储服务的云,为公有云、私有云,也为大云、小云提供可扩展的、灵活的云计算。这些项目之间的关系是松耦合。可以独立的安装,启动和停止。 缺点是安装配置复杂; 优点是扩展性好,安全性高,不会存在单点故障。 总结:它是 Rackspace和NASA共同发起的开源项目。 是一系列开源软件项目的组合。 是基础设施资源的系统管理平台。(TaaS) 以Apache许可证为授权   openstack的组成 整个OpenStack是由控制节点,计算节点,网络节点,存储节点四大部分组成。(这四个节点也可以安装在一台机器上,单机部署) 其中: 控制节点负责对其余节点的控制,包含虚拟机建立,迁移,网络分配,存储分配等等 计算节点负责虚拟机运行 网络节点负责对外网络与内网络之间的通信 存储节点负责对虚拟

  • mysql 根据一张表更新另一张表

    updatetableaa,tablebbseta.bname=b.namewherea.bid=b.idanda.idbetween262and271复制 between是>=and<=,即包含两个边界   updatetableaainnerjointablebbona.bid=b.idseta.bname=b.namewherea.idbetween262and271复制   首页:   raindream GitHub:   https://github.com/rain-bjtu

  • java数据写入Excel

    正好最近公司要写一个对账的功能,后台用java从银行获得对账信息,数据是json类型的,然后写入excel中发送给一卡通中心的服务器上,网上找了很多代码,然后整合和改正,代码如下。 1importjava.io.File; 2importjxl.*; 3importjxl.write.*; 4importjxl.write.biff.RowsExceededException; 5importjava.sql.*; 6importjava.util.*; 7 8 9publicclassDBtoExcel{ 10 11 12/** 13*导出Excel表 14*@paramrs数据库结果集 15*@paramfilePath要保存的路径,文件名为fileName.xls 16*@paramsheetName工作簿名称工作簿名称,本方法目前只支持导出一个Excel工作簿 17*@paramcolumnName列名,类型为Vector 18*/ 19publicvoidWriteExcel(ResultSetrs,StringfilePath,StringsheetName,Vector

  • Altaro 物理服务器备份的系统要求是什么?

    备份支持的操作系统 WindowsServer2008R2(不支持UEFI[统一可扩展固件接口]版本)视窗服务器2012视窗服务器2012R2视窗服务器2016视窗服务器2019笔记: 不支持Hyper-V主机和客户端操作系统不支持核心操作系统不支持SBS2011不支持虚拟机(VM)进行备份,请使用AltaroVMBackup来备份VM 支持用于还原的Hyper-V主机操作系统 视窗服务器2012视窗服务器2012R2视窗服务器2016视窗服务器2019 所需的硬件规格 最低i5(或同等)处理器2GB内存1GB硬盘空间+15GB(用于备份操作期间创建的临时文件)每个卷上至少有10%的可用磁盘空间保存用于Microsoft卷影复制的实时数据被备份的分区必须:是NTFS或FAT32格式没有跨越/镜像卷是基本磁盘类型(非动态)磁盘类型为“LocalDisk” 软件先决条件 WindowsServer2012上的MS.NETFramework4.0/4.5和4.7(TLS1.2需要)Altaro管理控制台的最低屏幕分辨率:1280x800 通讯端口 35480:用户界面和Altaro物理服务器

  • [python]一些常用的python知识总结

    Pthon知识积累,遇到的各种python问题汇总 json.dumps()和json.loads()是json格式处理函数 json.dumps()函数是将一个Python数据类型列表进行json格式的编码(可以这么理解,json.dumps()函数是将字典转化为字符串) json.loads()函数是将json格式数据转换为字典(可以这么理解,json.loads()函数是将字符串转化为字典) https://www.json.cn/ json解析网站 python2与python3编码 python2默认以ASCII编码,python默认为utf-8 #--coding:utf-8--申明编码 字符串是由字符构成,字符在计算机硬件中通过二进制形式存储,这种二进制形式就是编码。如果直接使用“字符串↔️字符↔️二进制表示(编码)”,会增加不同类型编码之间转换的复杂性。所以引入了一个抽象层,“字符串↔️字符↔️与存储无关的表示↔️二进制表示(编码)”,这样,可以用一种与存储无关的形式表示字符,不同的编码之间转换时可以先转换到这个抽象层,然后再转换为其他编码形式。在这里,

  • 新Mvp

    Model层1 packagecom.example.mvpretrofit.Model; importjava.util.Map; /** *Createdby佘鑫海on2017/12/6. */ publicinterfaceIModel{ voidgetData(Map<String,String>map); } Model层2 packagecom.example.mvpretrofit.Model; importcom.example.mvpretrofit.Bean.MessageBean; importcom.example.mvpretrofit.Bean.NewBean; importcom.example.mvpretrofit.Presenter.NewsPresenter; importcom.example.mvpretrofit.Utils.RetrofitUtils; importjava.util.List; importjava.util.Map; importio.reactivex.Flowable; /**

  • centos 7 常用工具篇

    1、vmstat监控linux整体性能工具如查看命令:vmstat142、用netstat查看网络连接,接口等信息如:netstat-an 3、dig 或者nslookup跟踪yum解析过程先安装此软件包#yuminstallbind-utils常用命令:查看A级录  dig  baidu.com查看ns记录  dig baidu.com ns从根服务器追踪域名解析过程:dig www.baidu.com +trace 4、查看cpu情况cat/proc/cpuinfo 5、查看内存情况free-m6、查看硬盘分区情况fdisk-l7、查看文件占用磁盘情况df-h8、查看硬盘I/O性能iostat-d-x-k1109、查看平均负载uptime  10、查看系统有哪些用户,并占用了什么客户端w11、动态命令top12、finger命令查询用户详情信息需要安装:yum-y installfinger13、lsof查看端口占

  • 第6篇 Scrum 冲刺博客

    一、站立式会议 1.1会议照片 1.2成员完成情况 成员 昨天完成的任务 今天计划完成的任务 工作中的困难 郭沛 对团队计划增删改接口进行测试并添加了查看接口 将获取子任务接口与排序算法进行整合 接口文档不断地更新迭代较为麻烦 柴政 思考判断条件的设置 完成获取待排计划列表与排序后返回新列表的对接 好多实验算法要写 洪梓豪 修改之前的文档 编写消息推荐的模块 临近期末,其他作业也很多 王树干 完善个人计划静态页面 继续完善个人计划的编辑、添加页面 作业繁多,时间匆忙 黎其钻 修改了团队页面的数据流和样式 继续完善团队页面 ddl使我癫狂 简蕙兰 画了会议照片,对UI进行调整 修改了设置页面,修改了团队计划页面 脑子不大好使,记不住需求orz 二、项目燃尽图 三、成员代码/文档签入记录 3.1代码签入 后台: 前端: 3.2Issue链接 成员  Issue链接 郭沛 子任务排序接口对接 柴政

  • 「CSP-S-2022」来看这万千旧梦。

    来看这万千旧梦,在歌声中得到重生。 标题取自《视星等4.44》。 来,将灵魂拼合,把轨迹观测,从最初到最终 也许我们早已经共鸣在那约定之地 在诗人口中遥远的,最亮视星等 Fourandfourandfour 2022/09/18初赛。 今天是疯狂星期天,v我50,疯狂CSP。 没怎么复习就去考了,我觉得再差也不会差到哪里去吧。(然后你选择题开屏错了\(5\)题?) 下午考的,然后就翘掉数学课了。() 提前两小时到就进学校了,刚下车就碰到chen_03,然后他一直跟我说什么你先别急让我先急(?)。 不能进考场,在教学楼外面,好热啊,上次在这里挨晒还是中考的时候hhhh。 然后果然没人复习初赛,甚至有人在背英语。 周围好多小朋友,我已经是高二的老人了啊(奇妙感慨)。 进考场后,看了眼这个教室白板的作业,发现自己在的是一个文科班。 并没有什么事,发卷。 开屏雷击。有笨蛋刚复习完就忘了,然后寄了()。然后第二题看完还是不会,乐。 然后看到基排,我基排就写过SA。乐。但是这宇宙射线是什么鬼。到第\(9\)题的时候脑子一热想了几分钟。 第\(10\)题,啪的一下很快啊,我看完题目马上列了

相关推荐

推荐阅读