Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于一个server有多个service,不能正常访问 #394

Open
longyn opened this issue Jun 26, 2024 · 9 comments
Open

关于一个server有多个service,不能正常访问 #394

longyn opened this issue Jun 26, 2024 · 9 comments

Comments

@longyn
Copy link

longyn commented Jun 26, 2024

1. DeviceStatus

service TDeviceStatus
{
  bool isRunning();
}

2. TPingService

service TPingService
{
  /** ping  */
  void ping();
}

3. Server

#include <string>
#include <memory>
#include <cstdio>
#include <signal.h>
#include <workflow/WFFacilities.h>
#include "TPingService.srpc.h"
#include "TDeviceStatus.srpc.h"

static WFFacilities::WaitGroup wait_group(1);

static void sig_handler(int signo) {
  wait_group.done();
}

class PingServiceImpl : public TPingService::Service {
private:
  static int mCallCount;

public:
  virtual void ping() {
    printf("ping %d\n", ++mCallCount);
  }
};

int PingServiceImpl::mCallCount = 0;

class DeviceStatusImpl : public TDeviceStatus::Service {
public:
  virtual bool isRunning() {
    printf("is running = true\n");
    return true;
  }
};

class PingAccess {
private:
  int mPort;

public:
  PingAccess()
      : mPort(9090) {
  }

  bool start() {
    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);

    srpc::ThriftServer server;
    PingServiceImpl    pingservice_impl;
    server.add_service(&pingservice_impl);

    DeviceStatusImpl devicestatus_impl;
    server.add_service(&devicestatus_impl);

    if (server.start(mPort) == 0) {
      printf("server start 0.0.0.0:%s ...\n", mPort);
      wait_group.wait();
      server.stop();
    } else {
      printf("error server start\n");
    }

    return true;
  }
};

int main(int argc, char const *argv[]) {
  PingAccess ping;
  ping.start();
  return 0;
}

Client

#include <string>
#include <memory>
#include <cstdio>

#include "TPingService.srpc.h"
#include "TDeviceStatus.srpc.h"

class PingAccess {
private:
  std::shared_ptr<TPingService::ThriftClient> mspTclient;
  std::shared_ptr<TDeviceStatus::ThriftClient> mspDeviceClient;
  std::string                                              mIp;
  int                                                      mPort;

public:
  PingAccess()
      : mIp("127.0.0.1")
      , mPort(9090) {
  }

  bool start() {
    mspTclient = std::make_shared<TPingService::ThriftClient>(mIp.c_str(), mPort);
    mspDeviceClient = std::make_shared<TDeviceStatus::ThriftClient>(mIp.c_str(), mPort);

    {
      mspTclient->ping();
      if (mspTclient->thrift_last_sync_success()) {
        printf("TService::ping => OK\n");
      } else {
        auto const &sync_ctx = mspTclient->thrift_last_sync_ctx();
        printf("TService::ping => error: %s\n", sync_ctx.errmsg);
      }

      mspDeviceClient->isRunning();
      if (mspDeviceClient->thrift_last_sync_success()) {
        printf("Status::isRunning=> OK\n");
      } else {
        auto const &sync_ctx = mspDeviceClient->thrift_last_sync_ctx();
        printf("Status::isRunning=> error: %s\n", sync_ctx.errmsg);
      }
    }

    return true;
  }
};

int main(int argc, char const *argv[]) {
  PingAccess ping;
  ping.start();
  return 0;
}

5. Client输出结果

TService::ping => OK
Status::isRunning=> error: TApplicationException: Wrong method name

我查看文档 docs-03-server.md中,有如下描述:
- 每一个Server可以拥有任意的Service,但在当前Server里ServiceName必须唯一, 已确认当ServiceName唯一,分别为"TPingService"和"TDeviceStatus"

如果只分别启动一个服务,都可以正常访问,同时启动2个服务,只能访问最前面一个服务的接口,请问下是那里没有使用正确吗?

@Barenboim
Copy link
Contributor

Barenboim commented Jun 26, 2024

你好。我们docs-03-server里的service,还不是thrift里的service。主要是在展示可以把thrift和protobuf两种不同的IDL生成的serivce,放到同一个server里,而不是支持thrift的多service。不支持的原因是,thrift的framed协议根本不支持多service,而我们主要只支持framed。

不过!我们的srpc::SRPCServer(非srpc::ThriftServer),是可以放入thrift idl生成的service的,这个在通讯中使用的并非thrift framed协议。你可以试一下用这个能不能支持(参考docs-03-server里的写法)。

@Barenboim
Copy link
Contributor

Barenboim commented Jun 26, 2024

我试过了,你这个代码里,把ThriftServer替换成SRPCServer,把TriftClient替换成SRPCClient(包括TPingService::SRPCClient和TDeviceStatus::SRPCClient),在SRPCServer里,加入两个service,是可以正常用的。通信协议是SRPC协议。

@Barenboim
Copy link
Contributor

Server

#include <string>
#include <memory>
#include <cstdio>
#include <signal.h>
#include <workflow/WFFacilities.h>
#include "TPingService.srpc.h"
#include "TDeviceStatus.srpc.h"

static WFFacilities::WaitGroup wait_group(1);

static void sig_handler(int signo) {
  wait_group.done();
}

class PingServiceImpl : public TPingService::Service {
private:
  static int mCallCount;

public:
  virtual void ping() {
    printf("ping %d\n", ++mCallCount);
  }
};

int PingServiceImpl::mCallCount = 0;

class DeviceStatusImpl : public TDeviceStatus::Service {
public:
  virtual bool isRunning() {
    printf("is running = true\n");
    return true;
  }
};

class PingAccess {
private:
  int mPort;

public:
  PingAccess()
      : mPort(9090) {
  }

  bool start() {
    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);

    srpc::SRPCServer server;
    PingServiceImpl    pingservice_impl;
    server.add_service(&pingservice_impl);

    DeviceStatusImpl devicestatus_impl;
    server.add_service(&devicestatus_impl);

    if (server.start(mPort) == 0) {
      printf("server start 0.0.0.0:%d ...\n", mPort);
      wait_group.wait();
      server.stop();
    } else {
      printf("error server start\n");
    }

    return true;
  }
};

int main(int argc, char const *argv[]) {
  PingAccess ping;
  ping.start();
  return 0;
}

Client

#include <string>
#include <memory>
#include <cstdio>

#include "TPingService.srpc.h"
#include "TDeviceStatus.srpc.h"

class PingAccess {
private:
  std::shared_ptr<TPingService::SRPCClient> mspTclient;
  std::shared_ptr<TDeviceStatus::SRPCClient> mspDeviceClient;
  std::string                                              mIp;
  int                                                      mPort;

public:
  PingAccess()
      : mIp("127.0.0.1")
      , mPort(9090) {
  }

  bool start() {
    mspTclient = std::make_shared<TPingService::SRPCClient>(mIp.c_str(), mPort);
    mspDeviceClient = std::make_shared<TDeviceStatus::SRPCClient>(mIp.c_str(), mPort);

    {
      mspTclient->ping();
      if (mspTclient->thrift_last_sync_success()) {
        printf("TService::ping => OK\n");
      } else {
        auto const &sync_ctx = mspTclient->thrift_last_sync_ctx();
        printf("TService::ping => error: %s\n", sync_ctx.errmsg.c_str());
      }

      mspDeviceClient->isRunning();
      if (mspDeviceClient->thrift_last_sync_success()) {
        printf("Status::isRunning=> OK\n");
      } else {
        auto const &sync_ctx = mspDeviceClient->thrift_last_sync_ctx();
        printf("Status::isRunning=> error: %s\n", sync_ctx.errmsg.c_str());
      }
    }

    return true;
  }
};

int main(int argc, char const *argv[]) {
  PingAccess ping;
  ping.start();
  return 0;
}

用这个代码,就可以跑了。试一下。

@longyn
Copy link
Author

longyn commented Jun 26, 2024

好的,谢谢,明白了

@Barenboim
Copy link
Contributor

Barenboim commented Jun 26, 2024 via email

@longyn
Copy link
Author

longyn commented Jun 26, 2024

现在服务端的代码用的是muplexed protocol实现的,多路复用一个端口,一个server有多个服务,因为涉及到多种客户端,想考虑一下怎么在最小的代价下能够迁移到srpc。
所以首先还是想跟原生的thrift服务器通信。

@Barenboim
Copy link
Contributor

Barenboim commented Jun 26, 2024

嗯嗯,因为thrift本身就不是一种协议,出现新的功能需求从来不考虑协议兼容性,如果multiplexed protocol兼容一下framed,我们直接支持这个协议就可以了。

所以我们只能选一种最常用的协议来实现,也就是framed。理论上如果愿意改代码,我们也可以增加一种ThriftMultiplexedServer和Client来支持multiplexed protocol的通信,不影响现在的service书写。

你可以认为SRPCServer+thrift IDL是一种我们私有的thrift通讯协议,可以解决多service问题。

@longyn
Copy link
Author

longyn commented Jun 27, 2024

嗯好的,我先研究下,怎么加上ThriftMuplexedServer,这种应该修改代价比较小
使用SRPCServer + thrift IDL做为一个备选方案

@Barenboim
Copy link
Contributor

Barenboim commented Jun 28, 2024

关于thrift消息的解析,可以看这个地方:

static int thrift_parser_append_message(const void *buf, size_t *size,

这里解析了framed格式的thrift消息。

如果要支持multiplexed,需要再搞一套消息出来。其实也不难,SRPC里可以随意增加新的RPC通讯协议,甚至可以增加新的IDL格式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants