Guzzle使用经验总结

中文文档 英文文档

调用接口

主要功能,很多sdk都是使用该类库开发

写爬虫抓取页面

Laravel 下使用 Guzzle 编写多线程爬虫实战

项目中应用案例

java的古籍PC网站,该项目无人维护,无法提供书籍数据的接口。分析页面结构和接口使用guzzle库爬取书籍数据,完成数据对接。

在所用请求中共享cookie功能 文档

//创建客户端
$this->client = new Client([
    'base_uri' => $this->config['base_uri'],
    'timeout'  => 20.0,
    'cookies' => true, //共享cookie会话
);
//登录
protected function login()
{
    $response = $this->client->request('POST', 'XXX', [
            'headers' => [
                'Accept' => 'application/json'
            ],
            'form_params' => [
                'loginName' => $this->config['login_name'],
                'loginPassword' => $this->config['login_password']
            ]
        ]);

        $json = json_decode($response->getBody(), true);

        if (isset($json['operateMsg']) && $json['operateMsg'] !== '登录成功!') {
            throw new GujiException('原古籍系统账号故障');
        }
}

//请求接口数据
protected function request(string $pathUrl, array $param)
{
        $this->login(); //首先登录获取Cookies
        $response = $this->client->request('POST', $pathUrl, [
            'headers' => [
                'Accept' => 'application/json'
            ],
            'form_params' => $param
        ]);

        $contents = $response->getBody()->getContents();
        $json = json_decode($contents, true);

        if (json_last_error() === JSON_ERROR_NONE) {
            return $json;
        } elseif (json_last_error() == 10) {
            //解决json_decode错误Single unpaired UTF-16 surrogate in unicode escape
            $contents = \preg_replace('/(?<!\\\)\\\u[a-f0-9]{4}/iu', '', $contents);
            $json = \json_decode($contents, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                $json = $this->customJsonDecode($contents);
            }

            return $json;
        }
        {
            throw new GujiException("请求古籍系统接口失败");
        }
}

//抓取页面数据
protected function capture(string $pathUrl, array $param = [])
{
        $this->login(); //首先登录获取Cookies
        $response = $this->client->request('GET', $pathUrl, $param);

        if ($response->getStatusCode() == 200) {
            //获取页面内容
            return $response->getBody()->getContents();
        } else {
            throw new GujiException("古籍系统故障");
        }
}

跟随重定向

https://docs.guzzlephp.org/en/stable/faq.html#how-can-i-track-redirected-requests

https://docs.guzzlephp.org/en/stable/request-options.html#allow-redirects

调用非知名第三方支付系统,前后端分离架构,前端重定向到接口,接口调用第三方支付接口,成功后跟随响应到成功页面

use Illuminate\Support\Facades\Http;
use Psr\Http\Message\UriInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

//Http::withOptions laravel对guzzle的封装,详情看文档
$response = Http::withOptions([
            'allow_redirects' => [
                'max'             => 1,
                'on_redirect'     => function (
                    RequestInterface $request,
                    ResponseInterface $response,
                    UriInterface $uri
                ) use ($data) {

                    //自动跟随重定向响应
                    header('Location:' . $uri);
                },
            ]
        ])->asForm()->post($this->config['base_uri'] . '/multipay/h5.do', $data);

Composer使用经验总结

切换国内镜像 composer 加速扩展包—— hirak/prestissimo 中文文档

–ignore-platform-reqs:  忽略 phphhvmlib-* 和 ext-* 要求并强制安装,就算本地环境不完全要求。平台配置选项可见 platform 文档

举例说明,windows平台的php不支持pcntl扩展,安装laravel-horizon时需要用的该扩展,可以通过指令强制安装

–with-all-dependencies:(-W)

 添加所有白名单中的依赖到白名单,包括那些根依赖,

允许升级、降级和删除目前锁定在特定版本的软件包。

composer require packagename:*

不确定当前项目可以使用扩展的哪个版本的时,可以使用require xxx:* 来计算是否有任何版本可以安装

laravel5.5安装horizon示例

依赖冲突

比如package A 和 B依赖相同的package C,但是版本不同,需要通过github 或packagelist 的composer.json 找到A和B依赖的最低版本C然后卸载C 然后安装适合版本的A和B,这样会自动安装最适合版本C

laravel 如何覆盖composer的 vendor类文件? 适用于需要修改vendor代码的场景

项目和框架运行缓慢

基于composer构建的项目出现过,加载运行缓慢的问题。碰到过旧laravel项目运行php artisan -v 时,命令显示非常慢。运行php artisan server 访问页面响应也很慢。

具体原因未验证,可能是安装依赖时,和运行项目时的php版本不一致,使用低版本安装了依赖,切换了高版本的php。composer安装项目后,会在vendor/bin目录下生成命令文件和缓存之类的,

解决方法,将vendor目录完全删除,然后重新运行composer install ,项目在升级或切换composer版本和php版本之后保险起见需要重新安装依赖

引入本地包

laravel-devstart 本地包的名称,path指定目录 要用基于当前项目路的相对路径,适用于开发扩展包

//设置路径,本质是创建了一个系统软连接
composer config repositories.laravel-devstart path ../../package/laravel-devstart
//引入本地包的master分支
composer require yangliuan/laravel-devstart:dev-master

扩展包开发

安装 Package Builder 包结构创建工具
composer global require overtrue/package-builder 
安装项目需要的依赖

修改composer.json

编写异常

编写单元测试

测试扩展包

发布版本到github

发布第一个版本

自动化测试

使用 GitHub Actions 做自动化测试

使用 StyleCI 自动修复代码格式

参考教程

LX2 PHP 扩展包实战教程 – 从入门到发布

PHP回顾之创建自己的扩展包 概述

扩展包版本对应

Laravel旧版本和扩展包对应版本,方便维护旧项目时参考

Laravel版本扩展包版本
5.5“laravel/horizon”: “2.1”
5.5“barryvdh/laravel-ide-helper”: “2.4.1”
5.5“doctrine/dbal”: “^2.10”
5.5“laravel/passport”: “~4.0”
5.5“laravel/tinker”: “~1.0”
5.5“propaganistas/laravel-phone”: “^4.2”
5.5“barryvdh/laravel-debugbar”: “3.4”,
5.5“filp/whoops”: “~2.0”
5.5“friendsofphp/php-cs-fixer”: “^2.14” 配置文件为.php_cs.dist

Linux文件系统 FAQ

rm cannot remove xxx Read-only file system 无法删除文件

df dir 查看无法删除的目录所在的文件系统

df /snap/remmina/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/nvme0n1p2 479152840 195515620 259227828 43% /

fsck -y /   #执行修复文件系统 的挂载根目录 或者 有问题的文件所在的挂载目录;

shutdown -r now

再删除ubuntu系统中的snap应用文件时上述方法没有解决

使用df -h 查看 发现remmina中的 /snap/remmina/4978 的挂载点是/dev/loop12

sudo umount /dev/loop12 去掉挂载后,再删除就可以了 ,原因是磁盘的挂载目录无法直接被删除

阿里云在线扩容磁盘遇到的问题

按照官方文档扩容

输入growpart 命令时 没有查找一下该命令的参数和含义,照着文档以为是截图中的序号,结果报如下错误

NOCHANGE: partition 2 is size 0. it cannot be grown

growpart <DeviceName> <PartionNumber>

应该输入分区好,即截图中1,/dev/vdb 是设备名称 ,/dev/vdb1是设备名称+分区号,即设备分区

总结:
服务器运行不了解的命令一定要先查一下文档手册,看个大概,梳理一下操作的大概意思,然后在操作
完善一下文件系统的文档,复习一下文件系统的知识

参考

在线扩容云盘(Linux系统)

阿里云Linux服务器动态扩容(阿里云服务器扩容后磁盘空间无变化解决方法)

PHP知识框架

安装

编译安装php

安装php扩展

php运行模式

php优化配置指南

第三方脚本

oneinstack安装脚本

宝塔运维面板

lnmp一键安装包

phpbrew

语言参考

基础语法 变量 常量 数据类型 表达式 运算符

流程控制 自定义函数

面向对象相关 命名空间 枚举

错误和异常

纤程和生成器

注解

预定义变量 异常 接口

上下文(Context)选项和参数 支持协议和封装协议

安全和特点

session cookie

文件上传处理

连接处理 数据库持久连接

命令型模式

引用的解释 垃圾回收机制

内置函数和pecl扩展API

扩展函数参考文档

PHP调试

PHP debug 笔记

PHP开发生态

PHP开发生态 常用笔记

ubuntu简单美化

首先更新系统

sudo apt update && sudo apt upgrade

软件中心安装显卡驱动

Software && updates => Additional Drivers 一般N

如果没有合适的去官网下载,出现卡顿等问题也可以装一下显卡驱动试试

AMD Linux驱动 官方地址

NVIDIA官方驱动 NVIDIA安装驱动英文教程

sudo apt install nvidia-utils-530

安装N卡显示设置

sudo apt install nvidia-settings

切换显卡

更新驱动后可能会丢失这个选项 解决参考

可以通过指令切换 nvidia|intel|on-demand|query

sudo prime-select nvidia # select nvidia gpu
sudo prime-select intel  # select intel gpu
sudo prime-select on-demand  # on-demand 按需

安装tweaks

sudo apt install gnome-tweak-tool
#ubuntu22.04
sudo apt install gnome-tweaks
sudo apt install chrome-gnome-shell #需要安装chrome浏览器
sudo apt install gnome-shell-extensions

开启关闭gnome-shell-extensions

安装chrome-gnome-shell成功后

ubuntu20.04+ 已更新版本

安装dash to dock 和 TopIcons Plus 和 Drop Down Terminal

版本未更新时替代品

Dash to Dock for COSMIC (替代 dash to dock ) ddterm (替代Drop Down Terminal ) TopIconsFix (替代 TopIcons Plus)

https://extensions.gnome.org/

打开上述网站,搜索并安装扩展

设置为打开即可,如上图

dash to dock 配置截图

启用Dash To Dock 后 禁用ubuntu dock,否则会导致indicator-sysmonitor插件报错

dock尺寸

图标尺寸

isloate workspace 隔离工作空间 isloate monitors 隔离显示器

ddterm

Panel Icon : none 隐藏顶部栏图标

TopiconsFix

Tray horizontal alignment (托盘图标水平对齐) right

Ubuntu AppIndicators

Tray horizontal alignment left (托盘水平左对齐)可以解决一些应用菜单无法推出的情况

FAQ

gnome出现问题,可以尝试重新安装

sudo apt-get install --reinstall ubuntu-desktop

gnome控制中心设置失效可以重新安装

sudo apt install gnome-control-center 

Top命令参数相关系统知识总结

平均负载

平均负载是指单位时间内,系统处于可运行状态(R 状态 Running 或 Runnable)和不可中断状态(Uninterruptible Sleep,也称为 Disk Sleep) 的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系

进程状态

linux中断机制

参考

什么是中断机制?

操作系统需要管理外设,但是外设的速度远远低于CPU的速度,所以我们需要一种机制来弥补这种速度鸿沟,提高CPU的效率。

为此我们引入了中断机制,让外设在需要操作系统处理外设相关事件的时候,能够主动通知操作系统,即打断操作系统和应用的正常执行,让操作系统完成外设的相关处理,然后在恢复操作系统和应用的正常执行。

当CPU收到中断或者异常的事件时,它会暂停执行当前的程序或任务,通过一定的机制跳转到负责处理这个信号的相关处理例程中,在完成对这个事件的处理后再跳回到刚才被打断的程序或任务中

硬中断

由与系统相连的外设(比如网卡、硬盘)自动产生的。主要是用来通知操作系统系统外设状态的变化。比如当网卡收到数据包的时候,就会发出一个中断。我们通常所说的中断指的是硬中断(hardirq)。

软中断

为了满足实时系统的要求,中断处理应该是越快越好。linux为了实现这个特点,当中断发生的时候,硬中断处理那些短时间就可以完成的工作,而将那些处理事件比较长的工作,放到中断之后来完成,也就是软中断(softirq)来完成。

buff/cache

过高时会导致物理内存占用过高

Swap交换分区

Swap分区在系统的物理内存不够用的时候,把硬盘内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中

虚拟内存

虚拟内存计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。