Go开发生态 常用笔记

环境搭建

gvm 开发环境推荐使用版本管理脚本

你有同时使用多版本 Go 语言的需求吗,那就快使用多版本管理利器 GVM 吧!

环境准备:如何安装和配置一个基本的 Go 开发环境?

 工作区和GOPATH

软件生态

Go中文文档

开发工具

awesome-go

go的一些常用包

参考文章

为什么很多公司都转型go语言开发?Go语言能做什么

Go 语言的整洁架构之道 —— 一个使用 gRPC 的 Go 项目整洁架构例子

常用防火墙指南

iptables

运行在用户空间的应用软件,通过控制Linux内核netfilter模块,来管理网络数据包的处理和转发。iptables 支持内核2.4以上版本,旧版内核环境下则使用ipchains(于2.2版内核)或 ipwadm(于2.0版内核)完成类似的功能。2014年1月19日起发行的Linux内核3.13版则使用nftables取而代之,但仍然提供 iptables 命令做为兼容接口

CentOS 7.0默认使用的是firewall作为防火墙,启用iptable,

iptable需要先关闭firewall并禁止开启自启
service firewalld stop
systemctl disable firewalld.service #禁止firewall开机启动

#安装iptable
yum install iptables-services 
service iptables start #开启
systemctl enable iptables.service #设置防火墙开机启动




开放指定端口

删除已添加规则

查看已添加规则

应用场景


指令选项
iptables -L -F -A -D # list flush append delete

场景一
开放 tcp 10-22/80 端口 开放 icmp 其他未被允许的端口禁止访问
iptables -I INPUT -p tcp --dport 80 -j ACCEPT # 允许 tcp 80 端口
iptables -I INPUT -p tcp --dport 10:22 -j ACCEPT # 允许 tcp 10-22 端口
iptables -I INPUT -p icmp -j ACCEPT # 允许 icmp
iptables -A INPUT -j REJECT # 添加一条规则, 不允许所有

场景二
ftp: 默认被动模式(服务器产生随机端口告诉客户端, 客户端主动连接这个端口拉取数据) vsftpd: 使 ftp 支持主动模式(客户端产生随机端口通知服务器, 服务器主动连接这个端口发送数据)
iptables -I INPUT -i lo -j ACCEPT # 允许本机访问
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许访问外网
iptables -I INPUT -p tcp --dport 80 -s 10.10.188.233 -j ACCEPT # 只允许固定ip访问80

场景三
允许外网访问: web http -> 80/tcp; https -> 443/tcp mail smtp -> 25/tcp; smtps -> 465/tcp pop3 -> 110/tcp; pop3s -> 995/tcp imap -> 143/tcp
iptables -I INPUT -i lo -j ACCEPT # 允许本机访问
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # 允许访问外网
iptables -I INPUT -s 10.10.155.0/24 -j ACCEPT # 允许内网访问
iptables -I INPUT -p tcp -m multiport --dports 80,1723 -j ACCEPT # 允许端口, 80 -> http, 1723 -> vpn
iptables -A INPUT -j REJECT # 添加一条规则, 不允许所有
iptables-save # 保存设置到配置文件

场景四
nat 转发
iptables -t nat -L # 查看 nat 配置
iptables -t nat -A POST_ROUTING -s 10.10.177.0/24 -j SNAT --to 10.10.188.232 # SNAT
vi /etc/sysconfig/network # 配置网关
iptables -t nat -A POST_ROUTING -d 10.10.188.232 -p tcp --dport 80 -j DNAT --to 10.10.177.232:80 # DNAT

场景五
防CC攻击
iptables -I INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT # 限制并发连接访问数
iptables -I INPUT -m limit --limit 3/hour --limit-burst 10 -j ACCEPT # limit模块; --limit-burst 默认为5

相关文章

维基百科

iptables 详解

iptables命令

firewall

官方网站 维基百科

众所周知,在RHEL7系统中,firewalld防火墙取代了iptables防火墙。我们都知道iptables的防火墙策略是交由内核层面的netfilter网络过滤器来处理的,而firewalld则是交由内核层面的nftables包过滤框架来处理。

下面一张图,让大家明确的了解防火墙 Firewall 与 iptables 之间的关系与区别。

相较于iptables防火墙而言,firewalld支持动态更新技术并加入了区域(zone)的概念。简单来说,区域就是firewalld预先准备了几套防火墙策略集合(策略模板),用户可以根据生产场景的不同而选择合适的策略集合,从而实现防火墙策略之间的快速切换。

firewalld跟iptables比起来至少有两大好处:

  1. firewalld可以动态修改单条规则,而不需要像iptables那样,在修改了规则后必须得全部刷新才可以生效。
  2. firewalld在使用上要比iptables人性化很多,即使不明白“五张表五条链”而且对TCP/IP协议也不理解也可以实现大部分功能。

相关文章

firewalld防火墙详解
firewall-cmd

ufw

相关文章

UFW – Uncomplicated Firewall

簡易的防火牆 – UFW & GUFW

Linux编译安装程序操作篇

编译工具准备

GCC编译器 官网

通过apt yum dnf 等包管理工具安装

GCC原名为GNU C语言编译器(GNU C Compiler),只能处理C语言。但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Fortran、Pascal、Objective -C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection) [1] 

Make 文档

通过apt yum dnf 等包管理工具安装

GNU Make是一个可以自动运行shell命令并帮助执行重复任务的程序。它通常用于将文件转换成其他形式,例如将源代码文件编译成程序或库。

Make适用于构建小型C/ c++项目或库,这些项目或库将包含在另一个项目的构建系统中。大多数构建系统都有办法集成基于make的子项目。

对于较大的项目,您会发现更现代的构建系统更易于使用。

在以下情况下,我建议使用非Make的构建系统:

当正在构建的目标(或文件)数量为(或最终将为)数百时。 需要一个“配置”步骤,它设置和保存变量、目标定义和环境配置。 该项目将保持内部或私有,将不需要由终端用户构建。 您会发现调试是一项令人沮丧的工作。 您需要构建的是跨平台的,可以在macOS、Linux和Windows上构建。 在这些情况下,您可能会发现使用CMake、Bazel、Meson或其他现代构建系统是一种更愉快的体验。

一般情况下发布的linux源码包中包含了makefile文件

Autoconf 官网

帮助我软件开发者通过使用GNU m4语言在configure.ac中写出限定配置脚本行为的列表。Autoconf将configure.ac中的命令转化为对应特定平台的配置脚本。Autoconf本身并不具备编译能力,它仅仅用于产生通常附带在软件包中的配置脚本。生成configure脚本。

Automake

是一种编程工具,可以产生供make程序使用的Makefile,用来编译程序。它是自由软件基金会发起的GNU计划的其中一项,作为GNU构建系统的一部分。automake所产生的Makefile符合GNU编程标准。

automake是由Perl语言所写的,必须和GNU autoconf一并使用。

具体使用参考相关文章automake,autoconf使用详解

CMake 官网

跨平台的编译工具 ,一般情况下不用(c语言的程序),因为服务器软件大多跑在linux上。

可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。

安装流程

tar命令查询

configure配置

通过 –help可以查看命令选项

默认的通用参数 --prefix安装目录,不指定则安装到默认目录
./configure --prefix=/xxx/xxx/
其他配置项,需要看具体软件编译安装文档说明

make命令查询

make -j 线程数  加速编译  

参考文章 让Make编译速度加快(Make -j解析)

如何解决依赖问题

一下两个命令可以查看已安装程序的依赖

ldd 二进制程序文件 可以查看静态的二进制文件依赖的共享库

lsof -p PID 显示Linux系统当前已打开的所有文件列表,PID为进程数字

执行./configure 根据依赖报错来确定需要的依赖

更新动态链接库

安装后提示xxx.so.7: cannot open shared object file: No such file or directory

执行 ldconfig /usr/local/lib/ 更新动态库缓存

实战练习

编译安装php

Unix 系统下的安装 核心配置选项列表

编译安装ffmpeg

CompilationGuide

相关文章

Linux中编译安装软件的基本流程

Linux下源代码的编译安装入门

在Linux系统中编译安装软件的基本流程

GUN make 入门到精通

GUN Make指南

CMake 入门实战

automake,autoconf使用详解 

软件工程中的开发方法

瀑布开发

维基百科 百度百科

迭代式开发

维基百科 百度百科

敏捷开发

维基百科 百度百科

精益软件开发

维基百科 百度百科

由此衍生出的产品低代码平台,通过少量代码或图形界面操作来快速制作软件,无法解决定制需求

全面解析瀑布式开发和敏捷式开发

瀑布式开发和敏捷开发有什么关系?

服务端网络编程知识框架

进程的基础知识

线程基础知识

协程基础知识

进程线程协程的对比- 多任务:进程、线程与协程

Socket

unix socket tcp socket

五种 I/O 模型

阻塞 I/O

非阻塞 I/O

I/O 的多路复用(select 和 poll)

信号驱动的 I/O(SIGIO)

异步 I/O(POSIX 的 aio_functions)

Reactor模型

TCP粘包

[网络坦白局] TCP粘包 数据包:我只是犯了每个数据包都会犯的错 |硬核图解

惊群效应

网络通讯协议

Linux inotify

C10k问题

C10k文档

Libevent

event loop 事件循环

C/S 客户端->服务端 编程模型

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 去掉挂载后,再删除就可以了 ,原因是磁盘的挂载目录无法直接被删除