您可以使用Thrift作为Cloud Foundry中应用程序之间的通信方式吗?

问题描述 投票:1回答:3

Cloud Foundry是否支持Thrift在应用程序之间进行交谈? 我找不到任何关于此的信息,似乎REST / HTTP或消息传递是应用程序间通信的首选机制。

有没有人试图在CF中使用Thrift提供服务? 是否有任何理由不支持Thrift; 或者有任何支持它的计划吗? 我更喜欢Thrift到REST进行跨语言通信,因为在Thrift中很容易生成API调用中使用的所有客户端类。 此外,它支持二进制数据传输,因此可能比REST更快。 另外我们已经有了Thrift API :)。

我猜 - 在理论上 - 客户端应用程序可以直接与另一个运行Thrift服务的CF应用程序实例对话; 但是你会失去CF目前为HTTP或消息传递提供的负载平衡优势。

rest thrift cloudfoundry
3个回答
2
投票

Cloud Foundry Router目前仅支持HTTP / HTTPS请求的路由。 正在努力创建一个TCP路由器来处理非CF流量到CF上运行的应用程序的路由。

有一个视频预览TCP路由器将提供的一些功能,以及一个包含TCP路由器的孵化版本 ,如果您通过BOSH部署自己的CF.

cf-dev邮件列表是一个讨论其他问题的好地方。

我猜 - 在理论上 - 客户端应用程序可以直接与运行Thrift服务的另一个CF应用程序实例对话

这是正确的 - 只要配置的安全组打开了正确的端口,在CF上运行的应用程序就可以使用任何协议相互通信。


1
投票

您是否可以通过HTTP和Thrift发送重要限制? 此外,我想更多地了解客户如何在您的服务上调用不同的方法。 您是否有一个通用的HTTP方法,或者您最终得到了一个类似REST的API,它反映了您的Thrift API的方法?

在处理传入请求的代码下方并返回结果。 这段代码是我前段时间为德国开发杂志撰写的文章的一部分。 整个包由一些JavaScript,一些C#和一些Delphi代码组成。 我可能会强调,我们也使用实际代码中显示的相同方法。

Delphi内置了对ISAPI的支持。 OnHandlerAction基本上是一个事件处理程序,可以分配给选定的URL端点,或捕获所有请求。 这也意味着,我们不需要关心线程管理,因为这就是IIS为我们所做的事情。

服务器端

我决定使用TJSONProtocol有两个原因。 首先,其中一个客户端是JavaScript部分,当时只能说JSON。 第二个目标是消除任何乱码数据的风险。 在这种情况下,我从未测试过TBinaryProtocolTCompactProtocol ,所以我不能对这种组合说多少。

procedure TSample.OnHandlerAction( Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
const GENERIC_ERROR_JSON = '[1,"TextToolIsapi",2,0,{"2":{"rec":{"1":{"str":"Internal error: %s"}}}}]';
var b : TBytes;
    s : string;
begin
  try
    Response.Content := TTextToolJsonServer.Process( Request.Content);
  except
    on e:Exception do begin
      b := ( SysUtils.TEncoding.UTF8.GetBytes(e.message));
      SetString( s, PAnsiChar(@b[0]), Length(b));
      Response.Content := Format( GENERIC_ERROR_JSON, [s]);
    end;
  end;
end;

剩下的部分是(de)序列化东西并为处理器提供信息的部分。 在此示例代码中,为每个调用创建一个处理器实例。 如果这不合适,可以考虑处理器实例池等。 在我们的例子中,特定于会话的数据保存在其他地方,因此处理器实际上非常轻量级。

class function TTextToolJsonServer.Process( const aRequest : string) : string;
var handler   : Samples.TTextTool.Iface;
    processor : IProcessor;
    protIn, protOut : IProtocol;
    stmIn, stmOut : TStringStream;
begin
  stmIn  := nil;
  stmOut := nil;
  try
    stmIn  := TStringStream.Create( aRequest);
    stmOut := TStringStream.Create;

    protIn  := TJSONProtocolImpl.Create(
                 TStreamTransportImpl.Create(
                   TThriftStreamAdapterDelphi.Create( stmIn, FALSE), nil));

    protOut := TJSONProtocolImpl.Create(
                 TStreamTransportImpl.Create(
                   nil, TThriftStreamAdapterDelphi.Create( stmOut, FALSE)));

    handler   := TTextToolHandler.Create;
    processor := Samples.TTextTool.TProcessorImpl.Create( handler);
    processor.Process( protIn, protOut);

    result := stmOut.DataString;

  finally
    stmIn.Free;
    stmOut.Free;
  end;
end;

这就是全部,其余的是标准的处理器/处理程序实现。

样本客户端

客户端对应方可以像这条JavaScript一样简单。 不幸的是,我手头没有Java示例,但它看起来非常相似。

  function MakeClient()
  {
    var transport = new Thrift.Transport("bin/TextToolSample.dll"); 
    var protocol  = new Thrift.Protocol(transport);
    var client = new Samples.TextToolClient(protocol);
    return client;
  }

  function CountWords() 
  {
    try
    {
      var client = MakeClient();
      var nCount = client.CountWords( document.EDITOR.textinput.value);
      alert("Text contains "+nCount.toString()+" words.");
    }
    catch (error) 
    {
      HandleError( error) 
    }
  }

0
投票

继@ JensG建议的解决方案后,我想找到一个使用Thrift / HTTP的解决方案。 如果您的CF管理员不想支持Thrift / TCP,这是一个后备,例如,如果您的CF部署中缺少.Net buildpack意味着Thrift服务必须在CF外部托管。 我在这里分享它是因为我不明白如何让Thrift / HTTP为C#服务实现工作。 整个使用节俭0.9.3。

示例Thrift IDL文件

namespace csharp AuthServiceGenCSharp
namespace * AuthServiceGenCSharp.thrift

struct Request
{
    1:string name
    2:i32 age
}

struct Result
{
    1:string reply
    2:bool permissionGranted
}

service AuthorizationService
{
    Result AskPermission(1:Request req)
}

使用Thrift编译器正常生成C#存根。 然后实现服务:

示例服务实现(C#)

using AuthServiceGenCSharp;

namespace AuthServiceImplementation
{
    /// <summary>
    /// Implementation of the Thrift interface.
    /// </summary>
    public class AuthorizationServiceImpl : AuthorizationService.Iface
    {
        public Result AskPermission(Request req)
        {
            Result result = new Result();
            result.Reply = "Hello " + req.Name;
            result.PermissionGranted = true;
            return result;
        }
    }
}

创建自定义HTTP处理程序

幸运的是,Thrift已经提供了一个实现IHttpHandler接口的类: Thrift.Transport.THttpHandler 。 您所要做的就是从THttpHandler派生您的处理程序,并传入Thrift编译器从您的IDL生成的处理器。 并指定JSON协议:

using AuthServiceGenCSharp;
using AuthServiceImplementation;
using Thrift.Protocol;
using Thrift.Transport;

// See also https://codealoc.wordpress.com/2012/04/06/thrift-over-http-with-iis/
namespace AuthServiceHTTPHandler.App_Code
{
    public class AuthServiceHandler : THttpHandler
    {
        public AuthServiceHandler()
            : base(CreateAuthProcessor(), CreateJSONFactory())
        {
            // We call the constructor for THttpHandler, passing in the processor we want to use (i.e., the one that
            // the Thrift compiler generated from our IDL) and the protocol factory for JSON in this case.
            // We can't use THttpHandler directly for 2 reasons. First, it doesn't have a no-arg constructor which
            // all proper handlers must have. (At runtime you'll get this error:
            // HTTP/1.1 500 Internal Server Error [MissingMethodException: Constructor on type &#39;Thrift.Transport.THttpHandler&#39; not found.])
            // Second, we need to tell THttpHandler which processor to use at the very least.
            // Maybe Thrift should make their THttpHandler class abstract to prevent people like me from trying to use it directly!?
        }

        private static AuthorizationService.Processor CreateAuthProcessor()
        {
            return new AuthorizationService.Processor(new AuthorizationServiceImpl());
        }

        private static TJSONProtocol.Factory CreateJSONFactory()
        {
            return new TJSONProtocol.Factory();
        }
    }
}

(在codealoc博客上给出了一个类似的例子。)将此处理程序放在ASP.Net Web应用程序的App_Code文件夹中。 在web.config中注册处理程序。 我在集成模式下使用IIS 7.5,所以我这样做:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="AuthServiceHandler"
           path="*."
           verb="*"
           type="AuthServiceHTTPHandler.App_Code.AuthServiceHandler"
           preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

示例Java客户端代码段

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TJSONProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.THttpClient;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import AuthServiceGenCSharp.thrift.AuthorizationService.Client;
import AuthServiceGenCSharp.thrift.Request;
import AuthServiceGenCSharp.thrift.Result;

...

TTransport transport = null;
try {
    transport = new THttpClient("http://localhost:9999");
} catch (TTransportException e) {
    e.printStackTrace();
}
TProtocol protocol = new TJSONProtocol(transport);
Client client = new Client(protocol);

try {
    transport.open();
    Request request = new Request("Fred", 32);
    Result result = client.AskPermission(request);
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(result);
    log.info("Response in JSON format: " + json);
    return json;
} catch (TException e) {
    e.printStackTrace();                
} catch (JsonProcessingException e) {                               
    e.printStackTrace();
} finally {
    if (transport != null && transport.isOpen()) {
        transport.close();
    }
}

当C#ASP.NET应用程序从Visual Studio 2010发布到IIS 7.5并且Java客户端指向它时,HTTP响应正文中的Thrift响应是:

[1,"AskPermission",2,1,{"0":{"rec":{"1":{"str":"Hello Fred"},"2":{"tf":1}}}}]

和Java日志输出:

Response in JSON format: {"reply":"Hello Fred","permissionGranted":true,"setPermissionGranted":true,"setReply":true}

我最初尝试实现自定义HTTP模块 。 但是,尽管在HTTP响应中返回了正确的Thrift响应,但HTTP标头始终为405: Method Not Allowed (Thrift客户端使用POST发送其请求)。 还有另外一篇关于此事的SO帖子 。 但是,使用HTTP处理程序可能比在长期运行中使用模块更好,因为您可以选择为长时间运行的请求创建异步处理程序

© www.soinside.com 2019 - 2024. All rights reserved.