golang與java間的json-rpc跨語言調用


  關於如何使用golang進行json-rpc的調用,網上雖然有很多的帖子,但都僅僅是golang程序間通信,沒有牽涉到跨語言調用的問題。在使用golang開發服務端程序的時候,不可避免的要與其他語言的程序進行交互,特別是json-rpc這的協議,本身就應該是用在不同的平台間的調用上的(因為golang程序間的交流已經有了封閉的用gob編碼解碼的rpc包了,我們自然而言的會想到用json-rpc來提供對其他語言的支持)。本文就來詳細探究一下如何實現golang與java之間的json-rpc調用。轉載請注明出處:http://www.cnblogs.com/geomantic/p/4751859.html 

  •  首先,實現一個基於socket的java調用golang的樣例(這個方法不需要第三方golang庫,因為golang本身就有jsonrpc的支持庫,但是僅能通過tcp協議通信,並且有一些格式上的局限,直接與其他的語言交互會有些障礙。如果要通過http協議通信的話,必須自己寫一個或者用第三方的庫,后面會有介紹) 
package rpcz

// first we create a simple golang rpc server based on socket
import (
    "fmt"
    "net"
    "net/rpc"
    "net/rpc/jsonrpc"
)

type Counter struct {
    Sum int
}

func (this *Counter) Add(i int, r *int) error {
    this.Sum += i
    *r = this.Sum
    fmt.Printf("i: %v", i)
    return nil
}

func NewJsonRpcSocketServer() {

    rpc.Register(new(Counter))

    l, err := net.Listen("tcp", ":3333")
    if err != nil {
        fmt.Printf("Listener tcp err: %s", err)
        return
    }

    for {
        fmt.Println("wating...")
        conn, err := l.Accept()
        if err != nil {
            fmt.Sprintf("accept connection err: %s\n", conn)
        }
        go jsonrpc.ServeConn(conn)
    }

}

func NewJsonRpcSocketClient() {
    conn, err := net.DialTimeout("tcp", "127.0.0.1:3333", 1000*1000*1000*30)
    if err != nil {
        fmt.Printf("create client err:%s\n", err)
        return
    }
    defer conn.Close()

    client := jsonrpc.NewClient(conn)
    var reply int
    err = client.Call("Counter.Add", 10, &reply)

    fmt.Printf("reply: %s, err: %s\n", reply, err)

}

  上面的NewJsonRpcSocketServer()方法創建了一個基於tcp協議的json-rpc服務器,NewJsonRpcSocketClient()方法示范了golang端的簡單調用(注意是基於tcp,而不是http協議!稍后會給出調用"github.com/gorilla/rpc/json"實現的基於http協議的調用方法)。但這不是重點,下面看一下Java客戶端的調用,可以看出來,這也是一個基於socket的通信:

package cn;

import com.googlecode.jsonrpc4j.JsonRpcClient;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;

/**
 * Created by geomantic on 15/8/21.
 */
public class SocketClient {

    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 3333);
            JsonRpcClient client = new JsonRpcClient();

            InputStream ips = socket.getInputStream();
            OutputStream ops = socket.getOutputStream();

            int reply = client.invokeAndReadResponse("Counter.Add", new Object[]{1001}, int.class, ops, ips);

            System.out.println("reply: " + reply);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

    }
}

  上面的java代碼初步示范了如何異步調用golang服務端的兩個很重要的約束:

  1.  golang服務端的方法名注冊和調用保持一致,格式為: 結構體名.方法名, 如上面的Counter.Add。

  2. 能夠注冊的方法必須滿足指定的函數簽名:

       func (t *T) MethodName(argType T1, replyType *T2) error 。

   入參有且只有兩個,第一個是被調用函數的輸入參數,第二個是被調用函數的輸出參數。 返回值只有一個error類型。這三個參數一個都不能變。

  但是基於tcp的調用,對於用慣了http協議的人會感覺寫起來很蛋疼,可能更多的人還是習慣用http來解析。但是由於解決的方法有比較瑣碎的細節處理,而且牽涉到一些第三方庫的代碼修改,考慮到篇幅問題准備另起一篇,在下一篇中示范一下用http協議通信實現的rpc實現。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM