使用Javascript客户端访问Thrift Java服务器时出现OutOfMemoryError错误。

3

我昨天开始学习thrift。

经过不少努力,我成功地执行了Java教程。Java服务端和客户端完美运行。

但现在,我希望一个javascript客户端与Java Thrift服务器进行通信。

为此,我将所有JS文件移动到js/文件夹中。

并将index.html代码粘贴如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Thrift Javascript Bindings - Tutorial Example</title>

  <script src="js/thrift.js"  type="text/javascript"></script>
  <script src="js/tutorial_types.js"    type="text/javascript"></script>
  <script src="js/shared_types.js"      type="text/javascript"></script>
  <script src="js/SharedService.js"     type="text/javascript"></script>
  <script src="js/Calculator.js"        type="text/javascript"></script>

  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>


  <script type="text/javascript" charset="utf-8">
  //<![CDATA[
  $(document).ready(function(){
    // remove pseudo child required for valid xhtml strict
    $("#op").children().remove();
    // add operations to it's dropdown menu
    $.each(Operation, function(key, value) {
      $('#op').append($("<option></option>").attr("value",value).text(key)); 
    });

     $('table.calculator').attr('width', 500);
  });

  function calc() {
    var transport = new Thrift.Transport("http://localhost:9090");
    var protocol  = new Thrift.Protocol(transport);
    var client    = new CalculatorClient(protocol);

    var work = new Work()
    work.num1 = $("#num1").val();
    work.num2 = $("#num2").val();
    work.op = $("#op").val();

    try {
      result = client.calculate(1, work);
      $('#result').val(result);
      $('#result').css('color', 'black');
    } catch(ouch){
      $('#result').val(ouch.why);
      $('#result').css('color', 'red');
    }
  }

  function auto_calc() {
    if ($('#autoupdate:checked').val() !== undefined) {
      calc();
    }
  }
  //]]>
  </script>

</head>
<body>
  <h2>Thrift Javascript Bindings</h2>
  <form action="">
  <table class="calculator">
    <tr>
      <td>num1</td>
      <td><input type="text" id="num1" value="20" onkeyup="javascript:auto_calc();"/></td>
    </tr>
    <tr>
      <td>Operation</td>
      <td><select id="op" size="1" onchange="javascript:auto_calc();"><option></option></select></td>
    </tr>
    <tr>
      <td>num2</td>
      <td><input type="text" id="num2" value="5" onkeyup="javascript:auto_calc();"/></td></tr>
    <tr>
      <td>result</td>
      <td><input type="text" id="result" value=""/></td></tr>
    <tr>
      <td><input type="checkbox" id="autoupdate" checked="checked"/>autoupdate</td>
      <td><input type="button" id="calculate" value="calculate" onclick="javascript:calc();"/></td>
    </tr>
  </table>
  </form>

  <p>This Java Script example uses <a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;hb=HEAD">tutorial.thrift</a> and a Thrift server using JSON protocol and HTTP transport.
  </p>
    <p>
        <a href="http://validator.w3.org/check/referer"><img
            src="http://www.w3.org/Icons/valid-xhtml10"
            alt="Valid XHTML 1.0!" height="31" width="88" /></a>
    </p>
</body>
</html>

我替换了一行代码。
var transport = new Thrift.Transport("/thrift/service/tutorial/");

使用

var transport = new Thrift.Transport("http://localhost:9090");

我的服务器端口是9090。而/thrift/service/tutorial对我来说没有任何意义,也没有起作用。

当我打开我的页面时,Java thrift 服务器会崩溃,并显示以下错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at org.apache.thrift.protocol.TBinaryProtocol.readStringBody(TBinaryProtocol.java:339)
    at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:202)
    at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:27)
    at org.apache.thrift.server.TSimpleServer.serve(TSimpleServer.java:83)
    at thrift.server.CalculatorServer.main(CalculatorServer.java:23)

这里是CalculatorServer的Java类。
package thrift.server;

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;

import tutorial.Calculator;

public class CalculatorServer {

    public static void main(String[] args) {
        CalculatorHandler handler = new CalculatorHandler();
        Calculator.Processor<CalculatorHandler> processor = new Calculator.Processor<>(handler);        

        try {
            TServerTransport serverTransport = new TServerSocket(9090);
            TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));

            System.out.println("Starting the simple server...");
            server.serve();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }

}

其余代码来自Thrift教程。实际上,Java Thrift服务器与Java Thrift客户端完美配合。我认为Java服务器端没有任何问题。

有人能告诉我出了什么问题吗?

是否有JavaScript客户端的替代方案?

我正在使用Thrift在我的Java SE应用程序和本地计算机上的网站之间进行通信。这样,我就可以使用HTML + CSS + JS开发GUI,而不是使用Java Swing。


我们可以看到Java代码吗? - user180100
你应该使用更多的内存来运行服务器,例如 -Xmx1024m,然后再尝试一次。 - user180100
@RC 不好意思,还是同样的错误。 - Akshat
3个回答

2
我一直在寻找一种在Polymer JavaScript中轻松使用Thrift的方法。最终,在分析其他解决方案三天后,我找到了解决方案。它们都能够正常工作,但它们都需要从我的http://localhost:8088/view.html请求中读取view.html本地文件。由于我同时使用Google应用引擎和计算引擎,我发现这样做太昂贵了。我无法在应用引擎上定位本地目录,所以我做了以下处理。
  1. Write your java server pretty much like this.
  2. write your polymer element like this

    <dom-module id="thrift-client">
    <template>
    </template>
    <script>
        Polymer({
            is:'thrift-client',
            ready:function(){
                var transport = new Thrift.TXHRTransport("http://localhost:8088/service");
    
                var protocol  = new Thrift.TJSONProtocol(transport);
    
                var client = new NtvApiClient(protocol);
    
                var result = client.ping(); // ping the java server. custom
    
                console.log(result);
            }
    
            });
    </script>
    

  3. Note that the http://localhost can be changed to http://Your_server_ip_address.

  4. please make sure the java server has a check point exactly named as service

  5. bravo, we have all it takes to access the java server now from a javascript web client without providing any file path.

  6. Note that with this u can easily use in plain js. like this

                    var transport = new Thrift.TXHRTransport("http://localhost:8088/service");
                    var protocol  = new Thrift.TJSONProtocol(transport);
                    var client = new NtvApiClient(protocol);
                    var result = client.ping(); 
    

    Cheers.


1

默认的'TTransport'不是基于http协议的服务器。如果您想使用http作为通信协议,这似乎是客户端js唯一的选择,您应该使用基于http的'TTransport'。查看'org.apache.thrift.server.TServlet',它是在servlet中构建基于http的thrift服务器的简单方法。

您还应该在服务器端使用'TJSONProtocol'而不是'TBinaryProtocol',因为thrift js无法很好地处理二进制数据。这是我之前使用的代码片段。

public class CalculatorServlet extends TServlet 
{
   public CalculatorServlet() 
   {
      //'Calculator' is the generated class from thrift, 
      //'CalculatorHandler' is the implement class for thrift rpc
      super(new Calculator.Processor(
            new CalculatorHandler()),
            new TJSONProtocol.Factory());
  }
}

好的,你的意思是说我需要创建一个Servlet来与JS客户端进行通信? - Akshat
1
你的代码片段很好,但请详细说明并参照我的示例进行引用。这样我就可以更容易地理解它了。 - Akshat
1
但是,在创建Servlet实例之后,我该如何将其与服务器连接起来?这样,它就可以处理传入的请求了。 - Akshat
你应该在你的情况下为你的servlet嵌入一个jetty(servlet容器)。这里有一个教程https://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty。 - yinqiwen
好的,假设我已经完成了所有工作。但是,我的最终目的是JS客户端和Java服务器之间的通信(无论是在Jetty上作为servlet运行还是在本地JVM中运行)!这是否可能? - Akshat
显示剩余3条评论

0

据我所知,JavaScript仅支持JSON协议。这当然与二进制不兼容。

因此,解决方案是:在您的服务器上使用JSON协议而不是二进制协议

对于Thrift来说,一个好的经验法则是,在两端始终使用相同的传输/协议堆栈。在这种情况下,这意味着:

  • HTTP服务器
  • JSON协议
  • 没有额外的,如framed协议(缓冲区也可以工作)

(有一些例外,因为某些服务器类型本质上需要帧,但那是另一个故事,与您的问题无关)


我已经成功将Java Server协议设置为TJSONProtocol,但如何解决传输部分的问题? - Akshat
有两个类,TExtensibleServlet extends HttpServlet,似乎是正确的方法。这里还有更多的文档http://people.apache.org/~thejas/thrift-0.9/javadoc/org/apache/thrift/server/TExtensibleServlet.html我自己没有使用过。 - JensG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接