switcherapiserver

package
v0.0.0-...-7258307 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2020 License: MIT Imports: 11 Imported by: 0

README

Switcher API Server

该进程用来修改 zookeeper 中的币种记录,以便控制 StratumSwitcher 进行币种切换。该进程一共有两种工作方式,一为通过定时任务拉取最新的用户币种信息,二为外部通过调用该进程提供的API来主动推送用户币种信息。

定时任务

在配置文件中设置 EnableCronJobtrue 即可开启定时任务,此后进程将每隔 CronIntervalSeconds 拉取一次 UserCoinMapURL,以获得最新的用户币种信息。

接口约定

假设 UserCoinMapURLhttp://127.0.0.1:8000/usercoin.php,则程序首次访问的实际URL为:

http://127.0.0.1:8000/usercoin.php?last_date=0

接口返回一个JSON字符串,包含所有用户及其正在挖的币种(无论是否进行过切换),形如:

{
    "err_no": 0,
    "data": {
        "user_coin": {
            "user1": "btc",
            "user2": "bcc",
            "user3": "bcc",
            "user4": "btc"
        },
        "now_date": 1513239055
    }
}

其中,user1user2user3为子账户名,btcbcc为币种,now_date为服务器的当前系统时间。

经过配置文件中设置的 CronIntervalSeconds 秒后,程序会再次访问如下URL:

http://127.0.0.1:8000/usercoin.php?last_date=1513239055

其中,1513239055为上次服务器返回的now_date

此时,服务器可根据程序提供的last_date进行判断,如果在last_date到现在这段时间内没有任何用户进行过切换,则返回空user_coin对象:

{
    "err_no": 0,
    "data": {
        "user_coin": {},
        "now_date": 1513239064
    }
}

注意:不可返回user_coin数组,如"user_coin":[],否则程序会在日志中产生警告。使用PHP数组实现接口时,在输出前请先将user_coin成员的类型强制转换为对象。

否则,返回在这段时间内进行切换的用户及切换后的币种:

{
    "err_no": 0,
    "data": {
        "user_coin": {
            "user1": "bcc",
            "user3": "btc"
        },
        "now_date": 1513239064
    }
}

备注:如果性能不受影响,服务器也可以忽略last_date参数,总是返回所有用户及其正在挖的币种,无论其是否或在什么时间进行过切换。

参考实现

UserCoinMapURL 的参考实现如下:

<?php
header('Content-Type: application/json');

$last_id = (int) $_GET['last_id'];

$coins = ["btc", "bcc"];

$users = [
    'hu60' => $coins[rand(0,1)],
    'YihaoTest' => $coins[rand(0,1)],
    'YihaoTest3' => $coins[rand(0,1)],
    'testpool' => $coins[rand(0,1)],
];

if ($last_id >= count($users)) {
    $users = [];
}

echo json_encode(
    [
        'err_no' => 0,
        'err_msg' => null,
        'data' => (object) $users,
    ]
);

API 文档

在配置文件中设置 EnableAPIServer 为 true 即可开启该API服务。外部在用户发起切换请求时可调用该API主动推送切换消息,以便 StratumSwitcher 第一时间进行币种切换。

目前共有两种调用方式:

单用户切换
认证方式

HTTP Basic 认证

请求URL

http://hostname:port/switch

请求方式

GET 或 POST

参数
名称 类型 含义
puname string 子账户名
coin string 币种
例子

子账户aaaa切换到btc:

curl -u admin:admin 'http://127.0.0.1:8082/switch?puname=aaaa&coin=btc'

子账户aaaa切换到bcc:

curl -u admin:admin 'http://10.0.0.12:8082/switch?puname=aaaa&coin=bcc'

该API的返回结果:

成功:

{"err_no":0, "err_msg":"", "success":true}

失败:

{"err_no":非0整数, "err_msg":"错误信息", "success":false}

例如

{"err_no":104,"err_msg":"coin is inexistent","success":false}
批量切换
认证方式

HTTP Basic 认证

请求URL
  • http://hostname:port/switch/multi-user
  • http://hostname:port/switch-multi-user
请求方式

POST

Content-Type: application/json

请求Body内容
{
    "usercoins": [
        {
            "coin": "币种1",
            "punames": [
                "用户1",
                "用户2",
                "用户3",
                ...
            ]
        },
        {
            "coin": "币种2",
            "punames": [
                "用户4",
                "用户5",
                ...
            ]
        },
        ...
    ]
}
例子

子账户a,b,c切换到btc,d,e切换到bcc:

curl -u admin:admin -d '{"usercoins":[{"coin":"btc","punames":["a","b","c"]},{"coin":"bcc","punames":["d","e"]}]}' 'http://127.0.0.1:8082/switch/multi-user'

该API的返回结果:

所有子账户均切换成功:

{"err_no":0, "err_msg":"", "success":true}

任一子账户切换失败:

{"err_no":非0整数, "err_msg":"错误信息", "success":false}

例如

{"err_no":108,"err_msg":"usercoins is empty","success":false}
获取子池Coinbase信息和爆块地址
认证方式

HTTP Basic 认证

请求URL
  • http://hostname:port/subpool/get-coinbase
  • http://hostname:port/subpool-get-coinbase
请求方式

POST

Content-Type: application/json

请求Body内容
{
	"coin": "币种",
	"subpool_name": "子池名称"
}
响应

成功:

{
	"success": true,
	"err_no": 0,
	"err_msg": "success",
	"subpool_name": "子池名称",
	"old": {
		"coinbase_info": "coinbase信息",
		"payout_addr": "爆块地址"
	}
}

失败:

{
	"err_no": 错误代码,
	"err_msg": "错误信息",
	"success": false
}

数据竞争(多个get-coinbase/update-coinbase同时调用时可能会出现,错开时间再试一次就可以成功):

{
	"err_no": 500,
	"err_msg": "data has been updated at query time",
	"success": false
}

例子:

curl -uadmin:admin -d'{"coin":"btc","subpool_name":"pool3"}' http://localhost:8080/subpool/get-coinbase
{
	"success": true,
	"err_no": 0,
	"err_msg": "success",
	"subpool_name": "pool3",
	"old": {
		"coinbase_info": "tigerxx",
		"payout_addr": "34woZDygXWqaVPnNxp5SUnbN6RNQ5koBt4"
	}
}

curl -uadmin:admin -d'{"coin":"bch","subpool_name":"pool3"}' http://localhost:8080/subpool/get-coinbase
{
	"err_no": 404,
	"err_msg": "subpool 'pool3' does not exist",
	"success": false
}

curl -uadmin:admin -d'{"coin":"bch","subpool_name":"pool3"}' http://localhost:8080/subpool/get-coinbase
{
	"err_no": 500,
	"err_msg": "data has been updated at query time",
	"success": false
}
更新子池Coinbase信息和爆块地址
认证方式

HTTP Basic 认证

请求URL
  • http://hostname:port/subpool/update-coinbase
  • http://hostname:port/subpool-update-coinbase
请求方式

POST

Content-Type: application/json

请求Body内容
{
	"coin": "币种",
	"subpool_name": "子池名称",
	"payout_addr": "爆块地址",
	"coinbase_info": "coinbase信息"
}
响应

成功:

{
	"success": true,
	"err_no": 0,
	"err_msg": "success",
	"subpool_name": "子池名称",
	"old": {
		"coinbase_info": "旧coinbase信息",
		"payout_addr": "旧爆块地址"
	},
	"new": {
		"coinbase_info": "新coinbase信息",
		"payout_addr": "新爆块地址"
	}
}

失败:

{
	"success": false,
	"err_no": 错误代码,
	"err_msg": "错误信息",
	"subpool_name": "子池名称",
	"old": {
		"coinbase_info": "旧coinbase信息",
		"payout_addr": "旧爆块地址"
	},
	"new": {
		"coinbase_info": "",
		"payout_addr": ""
	}
}

请求参数错误:

{
	"err_no": 错误代码,
	"err_msg": "错误信息",
	"success": false
}

例子:

curl -uadmin:admin -d'{"coin":"btc","subpool_name":"pool3","payout_addr":"bc1qjl8uwezzlech723lpnyuza0h2cdkvxvh54v3dn","coinbase_info":"tiger"}' http://localhost:8080/subpool/update-coinbase
{
	"success": true,
	"err_no": 0,
	"err_msg": "success",
	"subpool_name": "pool3",
	"old": {
		"coinbase_info": "hellobtc",
		"payout_addr": "34woZDygXWqaVPnNxp5SUnbN6RNQ5koBt4"
	},
	"new": {
		"coinbase_info": "tiger",
		"payout_addr": "bc1qjl8uwezzlech723lpnyuza0h2cdkvxvh54v3dn"
	}
}

curl -uadmin:admin -d'{"coin":"btc","subpool_name":"pool3","payout_addr":"bc0qjl8uwezzlech723lpnyuza0h2cdkvxvh54v3dn","coinbase_info":"tiger"}' http://localhost:8080/subpool/update-coinbase
{
	"success": false,
	"err_no": 500,
	"err_msg": "invalid payout address",
	"subpool_name": "pool3",
	"old": {
		"coinbase_info": "tiger",
		"payout_addr": "bc1qjl8uwezzlech723lpnyuza0h2cdkvxvh54v3dn"
	},
	"new": {
		"coinbase_info": "",
		"payout_addr": ""
	}
}

curl -uadmin:admin -d'{"coin":"btc","subpool_name":"pool4","payout_addr":"bc1qjl8uwezzlech723lpnyuza0h2cdkvxvh54v3dn","coinbase_info":"tiger"}' http://localhost:8080/subpool/update-coinbase
{
	"err_no": 404,
	"err_msg": "subpool 'pool4' does not exist",
	"success": false
}

构建 & 运行

安装golang

mkdir ~/source
cd ~/source
wget http://storage.googleapis.com/golang/go1.10.3.linux-amd64.tar.gz
cd /usr/local
tar zxf ~/source/go1.10.3.linux-amd64.tar.gz
ln -s /usr/local/go/bin/go /usr/local/bin/go

构建

mkdir -p /work/golang
export GOPATH=/work/golang
GIT_TERMINAL_PROMPT=1 go get github.com/btccom/btcpool-go-modules/switcherAPIServer

编辑配置文件

mkdir /work/golang/switcherAPIServer
mkdir /work/golang/switcherAPIServer/log
cp /work/golang/src/github.com/btccom/btcpool-go-modules/switcherAPIServer/config.default.json /work/golang/switcherAPIServer/config.json
vim /work/golang/switcherAPIServer/config.json

创建supervisor条目

vim /etc/supervisor/conf.d/switcher-api.conf
[program:switcher-api]
directory=/work/golang/switcherAPIServer
command=/work/golang/bin/switcherAPIServer -config=/work/golang/switcherAPIServer/config.json -log_dir=/work/golang/switcherAPIServer/log -v 2
autostart=true
autorestart=true
startsecs=6
startretries=20

redirect_stderr=true
stdout_logfile_backups=5
stdout_logfile=/work/golang/switcherAPIServer/log/stdout.log

运行

supervisorctl reread
supervisorctl update
supervisorctl status

更新

export GOPATH=/work/golang
GIT_TERMINAL_PROMPT=1 go get -u github.com/btccom/btcpool-go-modules/switcherAPIServer
diff /work/golang/src/github.com/btccom/btcpool-go-modules/switcherAPIServer/config.default.json /work/golang/switcherAPIServer/config.json

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// APIErrPunameIsEmpty puname为空
	APIErrPunameIsEmpty = NewAPIError(101, "puname is empty")
	// APIErrPunameInvalid puname不合法
	APIErrPunameInvalid = NewAPIError(102, "puname invalid")
	// APIErrCoinIsEmpty coin为空
	APIErrCoinIsEmpty = NewAPIError(103, "coin is empty")
	// APIErrCoinIsInexistent coin为空
	APIErrCoinIsInexistent = NewAPIError(104, "coin is inexistent")
	// APIErrReadRecordFailed 读取记录失败
	APIErrReadRecordFailed = NewAPIError(105, "read record failed")

	// APIErrWriteRecordFailed 写入记录失败
	APIErrWriteRecordFailed = NewAPIError(107, "write record failed")

	// APIErrUserCoinsEmpty 用户币种数组为空
	APIErrUserCoinsEmpty = NewAPIError(108, "usercoins is empty")
)

Functions

func Main

func Main(configFilePath string)

Main function

func RunCronJob

func RunCronJob()

RunCronJob 运行定时检测任务

Types

type APIError

type APIError struct {
	// 错误号
	ErrNo int
	// 错误信息
	ErrMsg string
}

APIError API错误结构

func NewAPIError

func NewAPIError(errNo int, errMsg string) *APIError

NewAPIError 新建一个APIError

func (*APIError) Error

func (apiErr *APIError) Error() string

type APIResponse

type APIResponse struct {
	ErrNo   int    `json:"err_no"`
	ErrMsg  string `json:"err_msg"`
	Success bool   `json:"success"`
}

APIResponse API响应数据结构

type ConfigData

type ConfigData struct {
	// 是否启用 API Server
	EnableAPIServer bool
	// API 用户名
	APIUser string
	// API 密码
	APIPassword string
	// API Server 的监听IP:端口
	ListenAddr string

	// AvailableCoins 可用币种,形如 {"btc", "bcc", ...}
	AvailableCoins []string

	// Zookeeper集群的IP:端口列表
	ZKBroker []string
	// ZKSwitcherWatchDir Switcher监控的Zookeeper路径,以斜杠结尾
	ZKSwitcherWatchDir string

	// 是否启用定时检测任务
	EnableCronJob bool
	// 定时检测间隔时间
	CronIntervalSeconds int
	// 用户:币种对应表的URL
	UserCoinMapURL string
	// 挖矿服务器对子账户名大小写不敏感,此时将总是写入小写的子账户名
	StratumServerCaseInsensitive bool
	//子池更新用的zookeeper根目录(注意,不应包括币种和子池名称),以斜杠结尾
	ZKSubPoolUpdateBaseDir string
	// 子池更新时jobmaker的应答超时时间,如果在该时间内jobmaker没有应答,则API返回错误
	ZKSubPoolUpdateAckTimeout int
}

ConfigData 配置数据

type HTTPRequestHandle

type HTTPRequestHandle func(http.ResponseWriter, *http.Request)

HTTPRequestHandle HTTP请求处理函数

type SubPoolCoinbase

type SubPoolCoinbase struct {
	Success     bool   `json:"success"`
	ErrNo       int    `json:"err_no"`
	ErrMsg      string `json:"err_msg"`
	SubPoolName string `json:"subpool_name"`
	Old         struct {
		CoinbaseInfo string `json:"coinbase_info"`
		PayoutAddr   string `json:"payout_addr"`
	} `json:"old"`
}

SubPoolCoinbase 子池Coinbase信息

type SubPoolUpdate

type SubPoolUpdate struct {
	Coin         string `json:"coin"`
	SubPoolName  string `json:"subpool_name"`
	CoinbaseInfo string `json:"coinbase_info"`
	PayoutAddr   string `json:"payout_addr"`
}

SubPoolUpdate 子池更新信息

type SubPoolUpdateAck

type SubPoolUpdateAck struct {
	SubPoolCoinbase
	New struct {
		CoinbaseInfo string `json:"coinbase_info"`
		PayoutAddr   string `json:"payout_addr"`
	} `json:"new"`
}

SubPoolUpdateAck 子池更新响应

type SubPoolUpdateAckInner

type SubPoolUpdateAckInner struct {
	SubPoolUpdateAck
	Host struct {
		HostName string `json:"hostname"`
	} `json:"host"`
}

SubPoolUpdateAckInner 子池更新响应(非公开)

type SwitchMultiUserRequest

type SwitchMultiUserRequest struct {
	UserCoins []SwitchUserCoins `json:"usercoins"`
}

SwitchMultiUserRequest 多用户切换请求数据结构

type SwitchUserCoins

type SwitchUserCoins struct {
	Coin    string   `json:"coin"`
	PUNames []string `json:"punames"`
}

SwitchUserCoins 欲切换的用户和币种

type UserCoinMapData

type UserCoinMapData struct {
	UserCoin map[string]string `json:"user_coin"`
	NowDate  int64             `json:"now_date"`
}

UserCoinMapData 用户币种列表接口响应的data字段数据结构

type UserCoinMapResponse

type UserCoinMapResponse struct {
	ErrNo  int             `json:"err_no"`
	ErrMsg string          `json:"err_msg"`
	Data   UserCoinMapData `json:"data"`
}

UserCoinMapResponse 用户币种列表接口响应的数据结构

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL