服务端开发


服务端开发

本节内容介绍 VSOA 服务端使用 RPC 的方法。

开发须知

微服务对外提供 RPC 服务时,需要指定该 RPC 的 URL 资源标识并将该 URL 加入监听,同时需要指定 RPC 的回调函数用于处理 RPC 被调用时的逻辑。

常用接口

说明:

RPC 服务端的详细接口说明可参考以下手册:

开发示例

例如:将“灯光状态”定义为一个 /light 的 URL 资源标识,供调用 RPC 的客户端获取灯光状态。

向所创建的 VSOA 服务中增加一个 RPC 实现,需要指定当客户端调用 /light 时,将被执行的 RPC 回调函数。

说明:

VSOA vsoa_payload_t 结构体

在使用 C 语言开发过程中,需要特别注意 vsoa_payload_t 结构体的使用方法。该结构体中有 param 和 data 两个字段提供给用户以携带数据,长度分别为 param_len 和 data_len。其中: param 参数推荐用于字符串类型参数,data 参数用于二进制数据或者 base64 类型数据。如果用户没有用到该字段,需要将对应的字段置为 NULL 并将其长度置为 0

例如,如果只需要 param 参数不需要 data 参数,需要按照如下形式生成 payload:

vsoa_payload_t send;

send.data      = NULL;
send.data_len  = 0;
send.param     = "{\"light\": 1}";
send.param_len = strlen(send.param);

关于 vsoa_payload_t 的详细说明可见 VSOA Base Data Struct 中的 Payload 说明。

RPC GET/SET

如同定义函数时习惯区分函数的功能为“设置/获取”或“输入/输出”的概念,在 VSOA 的 RPC 中也可以通过读取 VSOA 报文头标志对 RPC 请求区分 GET 或 SET 操作。针对如下示例约定,当需要开启灯光时,向灯光控制微服务发送数据 "1";相反,当需要关闭灯光时,向灯光控制微服务发送数据 "0"。

并行 RPC

以上 RPC 使用方式中的所有回调函数都是串行执行的,VSOA 为 C 语言开发版本提供了并行处理 RPC 请求的功能,开发者可以通过并发 RPC 相关接口创建线程池并行处理 RPC 请求。

如下是将以上开发示例修改为并行 RPC 的示例:

/*
 * Application: light_server
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "vsoa_server.h"
#include "vsoa_platform.h"
#include "vsoa_plistener.h"

#define MY_SERVER_PASSWD "123456"

static vsoa_server_t *server;

/*
* /light Callback
*/
static void command_light (void *arg, vsoa_server_t *server, vsoa_cli_id_t cid,
                           vsoa_header_t *vsoa_hdr, vsoa_url_t *url, 
                           vsoa_payload_t *payload)
{
    vsoa_payload_t send;
    uint32_t seqno = vsoa_parser_get_seqno(vsoa_hdr);
   
    send.data      = NULL;
    send.data_len  = 0;
    send.param     = "{\"light\": 1}";
    send.param_len = strlen(send.param);

    vsoa_server_cli_reply(server, cid, 0, seqno, 0, &send);
}

int main (int argc, char **argv)
{
    int cnt, max_fd;
    fd_set fds;
    struct sockaddr_in addr;
    vsoa_url_t url;
    vsoa_plistener_t *pl;
    vsoa_plistener_handler_t handler;
    struct timespec timeout = { 1, 0 };

    bzero(&addr, sizeof(struct sockaddr_in));
    addr.sin_family      = AF_INET;
    addr.sin_port        = htons(3001);
    addr.sin_addr.s_addr = INADDR_ANY;

#ifdef VSOA_HAS_SIN_LEN
    addr.sin_len = sizeof(struct sockaddr_in);
#endif

    /*
    * Initialize server
    */
    server = vsoa_server_create("{\"name\":\"light_server\"}");
    if (!server) {
        fprintf(stderr, "Can not create VSOA server!\n");
        return  (-1);
    }

    /*
    * If need password
    */
    vsoa_server_passwd(server, MY_SERVER_PASSWD);

    /*
    * Create plistener
    */
    pl = vsoa_server_plistener_create(2);
    if (!pl) {
        vsoa_server_close(server);
        fprintf(stderr, "Can not create VSOA parallel server!\n");
        return  (-1);
    }

    /*
    * Add /light listener
    */
    url.url     = "/light";
    url.url_len = strlen(url.url);
    vsoa_server_add_listener(server, &url, command_light, NULL);

    /*
    * Add parallel listener
    */
    handler = vsoa_server_plistener_handler(pl, true, 0, command_light, NULL);
    vsoa_server_add_listener(server, &url, handler.callback, handler.arg);

    /*
    * Start server
    */
    if (!vsoa_server_start(server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
        vsoa_server_close(server);
        fprintf(stderr, "Can not start VSOA server!\n");
        return  (-1);
    }

    while (1) {
        FD_ZERO(&fds);
        max_fd = vsoa_server_fds(server, &fds);

        cnt = pselect(max_fd + 1, &fds, NULL, NULL, &timeout, NULL);
        if (cnt > 0) {
            vsoa_server_input_fds(server, &fds);
        }
    }

    return (0);
}

说明:

VSOA 并行 RPC 接口说明可参考 C 扩展编程手册

URL 匹配规则

URL 标识RPC 匹配规则
"/"默认监听所有事件
"/a/b/c"只处理 "/a/b/c" 标识的调用
"/a/b/c/"处理 "/a/b/c" 和 "/a/b/c/..." 标识的所有调用

注意:

如果 "/a/b/c" 和 "/a/b/c/" 的 RPC 监听处理同时存在,则客户端发起一个 "/a/b/c" 标识的 RPC 调用时, 系统将优先匹配 "/a/b/c",而非 "/a/b/c/"。

注意事项

C/C++ 服务端编译时需链接如下表所示的 VSOA 动态库,在 RealEvo-IDE 中配置时请参考 C/C++ 开发示例,Linux 下开发请参考 搭建 Linux 运行环境 提供的 C 语言范例进行配置。

库名称功能
libvsoa-json.so提供 JSON 功能
libvsoa-server.so提供服务端功能
libvsoa-parser.so提供参数解析功能