大多数证券行情服务的SDK都是C++版本的最成熟,本文示例了使用证券行情的Linux C++ SDK调用封装了CloudEvents的Go SDK的C++动态库,实现向Knative Eventing平台提供行情事件。代码为Demo性质,最终交付为容器镜像形式。
以此方式,使用任何开发语言都可以直接消费实时证券行情数据,对于量化研究场景,可直接使用Python获取行情,并实现计算任务。但行情经过FaaS引擎传递一定会消耗时间,所以此方式不适合对行情时效有极限要求的场景。代码分为两部分:使用Go语言为开发的C++动态库、使用C++开发的行情服务。
WSL
中进行开发,所以首先依官方文档安装WSL(安装默认的Ubuntu即可)Ubuntu
应用程序,启动shell窗口,配置Go开发环境export GOPROXY=https://goproxy.cn,direct
sudo apt update
sudo apt install golang-go
mkdir cloudevents-sdk-cpp
cd cloudevents-sdk-cpp
vi event_sender.go
event_sender.go
package main
import (
"C"
"context"
"log"
cloudevents "github.com/cloudevents/sdk-go/v2"
uuid "github.com/satori/go.uuid"
)
import "os"
func main() {
Send("{a:1,b:2}")
}
//export Send
func Send(data string) bool {
bytedata := make([]byte, len(data))
copy(bytedata, data)
k_sink := os.Getenv("K_SINK")
if k_sink == "" {
log.Printf("failed to read sink address")
return false
}
p, err := cloudevents.NewHTTP(cloudevents.WithTarget(k_sink))
if err != nil {
log.Printf("failed to create http protocol: %s", err.Error())
return false
}
c, err := cloudevents.NewClient(p, cloudevents.WithUUIDs(), cloudevents.WithTimeNow())
if err != nil {
log.Printf("failed to create client: %s", err.Error())
return false
}
event := cloudevents.NewEvent("1.0")
event.SetType("com.quatation.data.received")
event.SetSource("https://quatation-service.io")
event.SetData(cloudevents.ApplicationJSON, bytedata)
event.SetID(uuid.NewV4().String())
log.Printf("sending cloudevent to %s", k_sink)
if res := c.Send(context.Background(), event); !cloudevents.IsACK(res) {
log.Printf("failed to send cloudevent: %v", res)
return false
}
return true
}
go mod init cloudevents-sdk-cpp
go get github.com/cloudevents/sdk-go/v2
go get github.com/satori/go.uuid
go build -o libevent_sender.so -buildmode=c-shared .
mv libevent_sender.h event_sender.h
Visual Studio 2022
,选择Visual C++开发
;创建新项目,选择CMake项目
,名字为quotation-service-in-knative
include
文件夹,放入rapidjson的头文件文件夹rapidjson,再放入上一步生成的event_sender.h
和行情服务提供的头文件lib
文件夹,放入上一步生成的libevent_sender.so
和行情服务提供的Linux C++ SDK的动态库文件quotation-service-in-knative.cpp
中,输入如下代码#include "quotation-service-in-knative.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "event_sender.h"
// 写入行情服务提供的头文件
#include ""
using namespace rapidjson;
using namespace std;
GoString BuildGoString(const char * p, size_t n) {
return { p, static_cast<ptrdiff_t>(n) };
}
string Serialize(const /*行情数据结构名*/ * pQuotation)
{
StringBuffer s;
Writer<StringBuffer> writer(s);
writer.StartObject();
writer.Key(""); //写入行情数据结构里的字段名
writer.Int(pQuotation->/*写入行情数据结构里的字段名*/);
writer.Key(""); //写入行情数据结构里的字段名
writer.String(pQuotation->/*写入行情数据结构里的字段名*/);
writer.Key(""); //写入行情数据结构里的字段名
writer.Double(pQuotation->/*写入行情数据结构里的字段名*/);
writer.Key(""); //写入行情数据结构里的字段名
writer.StartArray();
for (unsigned i = 0; i < 10; i++)
writer.Double(pQuotation->/*写入行情数据结构里的字段名*/[i]);
writer.EndArray();
writer.EndObject();
return s.GetString();
};
class CSQSPIInFaaS : public /*行情SDK数据处理接口类名*/
{
public:
void OnData(const /*行情数据结构名*/ * pQuotation)
{
string sData = Serialize(pQuotation);
cout << sData << endl;
Send(BuildGoString(sData.c_str(), sData.size()));
}
};
int main()
{
/*行情数据服务接口类*/ * iAPI = /*创建行情数据服务接口函数*/();
/*行情服务链接信息类*/ * iInit = new /*行情服务链接信息类*/();
// 需联系行情服务获取行情中心IP、端口、用户名和密码
strcpy(iInit ->host, "");
iInit ->port = 0;
strcpy(iInit ->userId, "");
strcpy(iInit ->password, "");
CSQSPIInFaaS * iCSQSPIInFaaS = new CSQSPIInFaaS();
/*行情订阅数据结构名*/ * iSubField = new /*行情订阅数据结构名*/();
// 需联系行情服务获取具体参数设置
strcpy(iSubField->strclass, "");
strcpy(iSubField->category, "");
strcpy(iSubField->exchId, "");
strcpy(iSubField->stkCode, "");
iAPI->Init(iInit);
iAPI->Set(iCSQSPIInFaaS);
iAPI->Start();
iAPI->Sub(iSubField);
char x;
cin >> x;
iAPI->Stop();
iAPI->UnInit();
delete iSubField;
delete iCSQSPIInFaaS;
delete iInit;
return 0;
}
目标系统
选择WSL:Ubuntu
,在CMakeLists.txt
中输入,然后按窗口上方提示,点击生成
按钮,生成Makefilecmake_minimum_required (VERSION 3.8)
project ("quotation-service-in-knative")
include_directories(include)
link_directories(lib)
add_executable (quotation-service-in-knative " .cpp" "quotation-service-in-knative.h")
target_link_libraries(quotation-service-in-knative /*行情服务动态库名称*/ event_sender)
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET quotation-service-in-knative PROPERTY CXX_STANDARD 20)
endif()
taikeguluer/ubuntu-4-cpp-and-go
docker run --name ubuntu_demo -itd ubuntu:20.04
ubuntu_demo
容器的CLIapt update
apt install golang-go
mkdir /home/app
WSL命令窗口
中,运行docker ps
获取ubuntu_demo容器的ID,如fd4fe6d147c9
,创建Docker imagedocker commit fd4fe6d147c9 taikeguluer/ubuntu-4-cpp-and-go
Dockerfile
文件,并输入如下代码,其中FROM后可以修改为上一步制作的镜像:FROM taikeguluer/ubuntu-4-cpp-and-go
ENV K_SINK 能接受CloudEvents格式事件的服务地址
WORKDIR /home/app
ADD ./lib/libCon.so /usr/lib
ADD ./lib/libCon2.so /usr/lib
ADD ./lib/libevent_sender.so /usr/lib
ADD ./lib/libQuotationAPI.so /usr/lib
ADD ./out/build/linux-debug/quotation-service-in-knative /home/app
CMD ./quotation-service-in-knative
F7
或从菜单选择全部生成
cd ~/.vs/quotation-service-in-knative
docker build -t your-docker-hub-id/quotation-service-in-knative .
docker run --name quotation-service-in-knative -itd your-docker-hub-id/quotation-service-in-knative