Write the Code. Change the World.

分类目录
4月 11

win10 系统,安装 docker,然后跑 php 项目,通常会很慢,一个最简单接口都可能要好几秒,真叫人肝疼。改变不了 win10,只能找解决方法。

处理方法

慢的原因网上有很多,怎么解决网上也很多,也实践过。不过,有一条是真的快。将代码放在 ubuntu 系统上跑,就是快。

步骤

  1. 先安装 Ubuntu。
  2. 再安装 docker。
  3. 设置 docker 。

设置 docker 如下图所示。

  1. win + r 输入 \\wsl$ 回车,打开 wsl 目录。或在资源管理器中打开 wsl 目录。这里要进入 Ubuntu 目录。然后将代码复制到 Ubuntu 系统中。比如将 docker-compose 相关的 service 放在 /docker-data 下。

  2. 进入 ubuntu 中。执行 docker-compose up -d,把服务跑起来。

这个时候再去请求 php 的接口就飞快。

4月 09

买了个 99 元的阿里云,最近经常卡死。通过 htop,可以看到是 /usr/bin/dnf makecache 占用 cpu 太高。

尝试处理

关闭 CentOS 的后台更新服务

systemctl stop dnf-makecache.timer

systemctl disable dnf-makecache.timer

后续

运行了许多天后,又卡死了。使用 htop 查看,发现是阿里云的监控煮助手。好吧,把监控助手也搞掉。

先干掉监控助手的守护进程。

# 停止云助手守护进程
/usr/local/share/assist-daemon/assist_daemon --stop

# 卸载云助手守护进程
/usr/local/share/assist-daemon/assist_daemon --delete

# 删除云助手守护进程目录
rm -rf /usr/local/share/assist-daemon

再来干掉监控助手。

# 查询您的ECS实例是否使用systemd初始化进程服务,有返回信息则表示使用的是systemd
strings /sbin/init | grep "/lib/system"

# 停止云助手Agent
systemctl stop aliyun.service

# 卸载云助手Agent
sudo rpm -qa | grep aliyun_assist | xargs sudo rpm -e

参考

https://blog.csdn.net/kunyus/article/details/106861400

https://help.aliyun.com/zh/ecs/user-guide/start-stop-or-uninstall-the-cloud-assistant-agent

https://help.aliyun.com/zh/ecs/user-guide/start-stop-or-uninstall-the-cloud-assistant-agent#section-ge4-ads-7ud

https://ivpsr.com/3914.html

4月 08

https://www.meilisearch.com/docs/learn/cookbooks/laravel_scout

构建 laravel 项目使用的工具不是 Sail 时。按照官方文档 https://laravel.com/docs/11.x/scout 来安装和使用 Scout 时,发现会报错。

cURL error 7: Failed to connect to 127.0.0.1 port 7700 after 0 ms: Couldn't connect to server (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for http://127.0.0.1:7700/indexes/resources/documents?primaryKey=id"

我这里使用的是 docker 环境。出现这个的原因是没有启动 meilisearch 服务。如果使用 sail 构建时,其会包含 meilisearch 服务。所以在这里,自己手动构建好 meilisearch 服务就可以了。docker-compose.yaml 配置如下:

  meilisearch:  
    image: getmeili/meilisearch:latest
    container_name: meilisearch_latest
    ports:  
      - "7700:7700"  
    environment:  
      - MEILI_MASTER_KEY=masterKey  
      - MEILI_NO_ANALYTICS=true  
    volumes:  
      - ./data/meilisearch:/var/lib/meilisearch  
    restart: always

其中,masterKey 为秘钥,可以自定义。

然后 laravel 的 .env 文件中,可以增加以下配置。

SCOUT_DRIVER=meilisearch  
MEILISEARCH_HOST=http://meilisearch:7700  
MEILISEARCH_KEY=masterKey

其他按照官方文档来就可以了。

1月 26

skynet 框架,在 skynet.start 方法中,对 skynet.newservice 进行 name 时候会报错 attempt to call a nil value (field 'name') 的处理。

使用 skynet.wait, 等待异步的完成就可以。下边给出示例。

local Service = '.Service'
skynet.start(function()
    local service = skynet.newservice('xxx')
    skynet.wait(service)
    skynet.name(Service, service)
end)
1月 24

在做自己的业务之前,尝试官方的样例是很有必要的。只需要一个装好 docker 的电脑,几步就可以完成测试。

官方 websocket 示例代码:
https://github.com/cloudwu/skynet/blob/master/examples/simplewebsocket.lua

skynet 的 docker 环境构建
https://blog.vini123.com/1130

准备工作

  • docker 环境
  • 并按照上边链接里的方式构建出了 docker 镜像。

开始

docker images 看看构建的镜像是否存在,这个是前提。

# 以交互式的方式构建并进入容器
docker run -it --rm -p 9948:9948 skynet:1.7 bash

# 安装 vim (因为我们要修改下 config)文件
apk add vim

# 编辑 config 文件
vim examples/config

继续阅读

1月 24

skynet 最早就能提供 socket 服务。后来,也能提供 websocket 服务。这里,接着之前的代码,构建一个 websocket 服务。

https://github.com/cloudwu/skynet/blob/master/examples/simplewebsocket.lua

上边是官方 websocket 的一个示例。

开始

以官方为借鉴,这里先创建一个 websocket.lua 文件。完整的路径是 www/websocket/service/connect/websocket.lua

继续阅读

1月 11

skynet 常识

在写代码之前,先了解一些 api 和 组件。

skynet.manager

skynet.managerskynet 框架中的一个重要组件,它负责管理和调度所有的服务。其主要作用包括:

  • 服务注册与发现:skynet.manager 负责服务的注册与发现。当一个服务启动时,它会向 skynet.manager 注册自己,这样其他服务就可以通过 skynet.manager 找到并调用它。
  • 负载均衡:skynet.manager 提供了负载均衡的功能。当一个服务需要调用另一个服务时,skynet.manager 会根据其内部的算法选择一个合适的服务实例进行调用,确保服务的负载均衡和可用性。
  • 服务监控:skynet.manager 还提供了服务监控的功能。它可以收集每个服务实例的运行时信息,如 CPU 使用率、内存占用等,从而帮助开发者了解服务的性能和健康状况。
  • 服务路由:通过 skynet.manager,你可以定义自定义的路由规则,实现更灵活的服务调用逻辑。
  • 集群管理:在分布式环境下,skynet.manager 可以帮助管理整个集群的状态,包括服务的启动、停止、重启等操作。
  • 配置管理:skynet.manager 可以集中管理服务的配置信息,使得配置的修改更加方便和统一。

总的来说,skynet.manager 在 kynet 框架中扮演着中心协调者的角色,它使得服务的交互更加高效、可靠和灵活。

skynet.cluster

skynet.cluster 是一个用于实现集群功能的模块。它提供了一种机制,使得多个 skynet 节点可以形成一个集群,并实现节点间的通信和协作。其主要作用包括:

  • 节点间通信:skynet.cluster 提供了集群内节点间的通信机制。通过使用该模块,节点可以相互发送消息,进行数据交换和协调工作。
  • 集群管理:skynet.cluster 还提供了集群管理的功能。它可以管理集群中的节点,包括节点的加入、离开、故障检测等。此外,它还可以协调节点间的负载均衡,确保集群的高可用性和性能。
  • 服务发现:skynet.cluster 支持服务发现功能。通过该模块,节点可以发现集群中其他节点的服务,并与之进行交互。这有助于实现服务的动态发现和调用。
  • 配置管理:skynet.cluster还提供了配置管理功能。通过该模块,可以对集群进行统一的配置管理,包括节点间的通信参数、集群的拓扑结构等。这有助于简化集群的配置和维护工作。
  • skynet.cluster.reload 方法会重新加载节点的配置信息,但不会重启节点。要重启节点,必须得先试用 skynet.exit() 来停止节点,再通过 open 来启动节点。

总的来说,skynet.cluster 在 skynet 框架中提供了集群功能,使得多个 skynet 节点可以形成一个协同工作的整体,并实现高效、可靠的节点间通信和协调。它简化了分布式系统的构建和管理,使得开发者能够更轻松地构建高可用性、高性能的分布式应用程序。

然后,发现 skynet.manager 的作用和 skynet.cluster 的作用似乎有重合。又是怎么会事呢。

在 skynet 框架中,skynet.manager 和 skynet.cluster 虽然都涉及到了服务管理和集群的功能,但它们的作用和侧重点是有所不同的。

skynet.manager 更侧重于单个 skynet 节点内部的服务管理和调度。它主要负责在单个节点内部协调各个服务的运行,包括服务的注册、发现、负载均衡、监控等。skynet.manager 确保了单个节点内的服务能够高效、可靠地运行,并为其提供了一系列的管理和调度功能。

而 skynet.cluster 则更侧重于多个 skynet 节点之间的集群管理和通信。它主要负责实现多个节点间的通信、协调和管理,以形成一个协同工作的整体。skynet.cluster 提供了节点间消息传递、服务发现、集群管理等功能,使得多个节点可以形成一个分布式系统,并能够进行高效的节点间通信和协作。

虽然两者都涉及到了服务管理和集群的功能,但它们的关注点是不同的。skynet.manager 关注单个节点内部的服务管理,而 skynet.cluster 则关注多个节点间的集群管理和通信。在实际使用中,它们可以相互配合,共同实现分布式系统的构建和管理。

参考

https://blog.csdn.net/qq769651718/article/details/79432835

https://blog.csdn.net/linxinfa/article/details/120573016

1月 10

基础镜像构建好了之后,就可以使用镜像来构建容器,从而来进行服务。这里想创建一个 websocket 服务的项目。

这里可以有几个文章可以参考:

https://blog.csdn.net/linxinfa/article/details/120573016

https://github.com/Skycrab/skynet_websocket

[https://blog.csdn.net/u013617851/article/details/86712243][https://blog.csdn.net/u013617851/article/details/86712243]

创建基础文件夹和文件

按照 https://blog.csdn.net/linxinfa/article/details/120573016 的博客,对文件进行分类安排,创建基础文件夹和文件。如下所示:

│  .dockerignore
│  docker-compose.yaml
│
├─service
│  └─skynet
│          Dockerfile
│
└─www
    └─websocket
        │  main.lua
        │
        ├─etc
        │      cluster.lua
        │      config
        │
        ├─luaclib
        ├─lualib
        └─service

对于 skynet, config 文件会作为入口文件。而这个 config 文件可以是项目中任何位置,因为是由 skynet config 来明确指定的。不过,依照前人的约定习惯,把 config 文件放在 ./websocket/etc/ 下。

再来全局来看项目结构。最外层是 docker 相关的配置。 www 目录是项目的总和。这样是方便存放项目。今天存放一个 websocket 的项目,明天可能就会存放 socket.io 的项目。

在 websocket 项目中结果,还是遵循前人的约定习惯。

到此,仅可以看到创建的一些文件夹和两个文件:config 文件和 main.lua 文件。cluster.lua 暂时是空的。

config 文件你也可以命名为 config.lua 文件。

config

config.lua 作为入口文件,其地位当然是举足轻重的。来看看里边的内容。

-- 根目录
skynet_path = '/skynet'
service_path = '/www/websocket'

-- 节点名称
node = 'node_1'

-- 启用工作线程数 | c 编写的服务模块的位置 | 启动第一个服务
thread = 8
cpath = skynet_path .. '/cservice/?.so' 
bootstrap = 'snlua bootstrap'

-- 主程序入库 | 适用 cluster 的集群模式
start = 'main'
harbor = 0

-- lua 配置项
lualoader = skynet_path .. '/lualib/loader.lua'
luaservice = skynet_path .. "/service/?.lua;" .. service_path .. "/?.lua"
lua_path = skynet_path .. "/lualib/?.lua;" .. skynet_path .. "/lualib/?/init.lua;" .. service_path .. "/?.lua"
lua_cpath = skynet_path .. "/luaclib/?.so;" .. service_path .. "/luaclib/?.so"

skynet_path 配置的是 skynet 的安装的位置。

service_path 配置的是项目的位置。

这两个位置下边的配置会用到。

代码中,也加了一些注释说明。下边用表格的方式,再说明一次。

参数 描述
thread 启用的工作线程数量,一般配置为CPU核心数
harbor 主从节点模式。skynet 初期提供了 master/slave 集群模式,后来提供了更适用的 cluster 集群模式,建议使用 cluster 模式,配 0
cpath C 语言编写的服务模块的路径。cpath 配置项通常用于指定 C 模块的搜索路径。它不是必须的,但是如果你需要在你的服务中使用 C 编写的模块,那么你需要配置 cpath 来指定这些模块的位置。cpath 应该放在 bootstrap 配置之前,因为 bootstrap 会使用 cpath 指定的路径来加载 C 模块。如果你没有配置 cpath,那么你的服务将无法找到和加载C模块。因此,根据你的需求,你可能需要根据你的具体路径来配置 cpath
bootstrap 指定 skynet 启动时的第一个服务以及其启动参数。默认配置为 snlua bootstrap,即启动一个名为 bootstrap 的lua服务,通常指的是 service/bootstrap.lua 这段代码。这个服务是启动其他服务的入口点,并且会根据配置文件中的其他参数来加载和启动其他服务。因此,bootstrap 是用于引导 skynet 系统启动的重要配置选项。
start 主服务入口
luaservice 用于指定 Lua 服务的路径。它通常是一个字符串,包含了服务的名称或路径。在配置文件中,你可以指定多个服务,用分号(;)分隔。(包括 skynet 框架自带的一些服务和自己写的服务。)
lualoader lua 脚本加载器。用于配置调用哪一段Lua代码加载Lua服务。通常配置为lualib/loader.lua,由这段代码解析服务名称,进一步加载Lua代码。snlua会将核心配置项取出,放置在初始化好的Lua虚拟机的全局变量中。
lua_path lua_path用于指定Lua模块的搜索路径。它通常是一个字符串,包含了多个路径,用分号(;)分隔。
lua_cpath 用于指定C模块的搜索路径。它通常是一个字符串,包含了多个路径,用分号(;)分隔。

最后啰嗦一下。在 config 中配置的信息,在后续的逻辑中都可以通过 skynet.getenv 方法获取到。在这里,不需要使用 skynet.setenv 方法来明确设置。

skynet.setenv 有一个严格的问题,就是不能对已存在的变量进行设置。相对于一个 const 的行为。

虽然吧,在其他地方通过 skynet.getenv 方法获取到。但是也能通过 skynet.setenv 进行赋值一次。再第二次赋值就会报错。

从显现来看,虽然可以通过 skynet.getenv 方法获取到 config 中的参数,那似乎不是通过 skynet.setenv 的方式来传递的。

再来看 main.lua 中的代码。

local skynet = require 'skynet'

skynet.start(function()
    skynet.error('hello world')
    skynet.error(skynet.exit())
end)

就这么多。

代码都准备好了,最后在 docker-compose.yaml 文件中添加使用镜像,构建容器,启动服务的配置。

  …
  websocket:
    image: skynet:1.7
    container_name: websocket
    volumes:
      - ./www:/www
    command: /skynet/skynet /www/websocket/etc/config
    depends_on:
      - skynet

运行 docker-compose up 看看 。

(base) PS D:\Study\skynet\websocket> docker-compose up
[+] Building 0.0s (0/0)                                                                                                                                                                 docker:default 
[+] Running 2/0
 ✔ Container skynet1.7  Created                                                                                                                                                                   0.0s 
 ✔ Container websocket  Created                                                                                                                                                                   0.0s 
Attaching to skynet1.7, websocket
skynet1.7 exited with code 0
websocket  | [:00000002] LAUNCH snlua bootstrap
websocket  | [:00000003] LAUNCH snlua launcher   
websocket  | [:00000004] LAUNCH snlua cdummy     
websocket  | [:00000005] LAUNCH harbor 0 4       
websocket  | [:00000006] LAUNCH snlua datacenterd
websocket  | [:00000007] LAUNCH snlua service_mgr
websocket  | [:00000008] LAUNCH snlua main       
websocket  | [:00000008] hello world
websocket  | [:00000008] KILL self
websocket  | [:00000002] KILL self

是不是已经运行起来了,也达到了预期的效果了。

提交版本

git init -b main
git add .
git commit -m 'init skynet'
1月 10

用 docker 来部署和使用 skynet 其实也不错。

构建基础镜像

使用 docker init 命令创建基础的文件。将 Dockerfile 移动到 ./service/skynet/Dockerfile 这里。将 compose.yaml 文件重命名为 docker-compose.yaml

Dockerfile 文件中,做这些事情:使用一个基础镜像,安装 git,然后将 skynet 代码下下来,对代码进行编译。

Dockerfile

# syntax=docker/dockerfile:1

FROM alpine:latest

# 更新和安装 alpine 工具
RUN apk add --update alpine-sdk

RUN apk add --no-cache bash

RUN apk add readline-dev readline autoconf libgcc

# 安装 git
RUN apk add git

RUN git clone https://github.com/cloudwu/skynet.git /skynet

WORKDIR /skynet

RUN make linux

修改 compose.yaml 文件。

version: '3.9'
services:
  skynet: 
    build:
      context: ./service/skynet
    image: skynet:1.7
    container_name: skynet1.7

然后运行 docker-compose build 构建镜像。

为什么镜像的 tag 的版本号是 1.7 呢。因为 skynet 在 github 上最后的版本就是 1.7。