服务化了,有php代码,也有go代码,我们要相互调用,怎么办?走http,当然,这样子最简单,当并发高的时候,我们就可以走rpc了。
直接上代码,这样子可以好看一点,是吧
首先是golang的服务器

  1. // json_rpc_server project main.go
  2. package main
  3. import (
  4. "net/rpc"
  5. "net"
  6. "log"
  7. "net/rpc/jsonrpc"
  8. )
  9. //自己的数据类
  10. type MyMath struct{
  11. }
  12. //加法--只能两个参数
  13. func (mm *MyMath) Add(num map[string]float64,reply *float64) error {
  14. *reply = num["num1"] + num["num2"]
  15. return nil
  16. }
  17. //减法--只能两个参数
  18. func (mm *MyMath) Sub(num map[string]string,reply *string) error {
  19. *reply = num["num1"] + num["num2"]
  20. return nil
  21. }
  22. func main() {
  23. //注册MyMath类,以代客户端调用
  24. rpc.Register(new(MyMath))
  25. listener, err := net.Listen("tcp", ":1215")
  26. if err != nil {
  27. log.Fatal("listen error:", err)
  28. }
  29. for {
  30. conn, err := listener.Accept()
  31. if err != nil {
  32. continue
  33. }
  34. //新协程来处理--json
  35. go jsonrpc.ServeConn(conn)
  36. }
  37. }

然后是golang客户端调用服务器

  1. package main
  2. import (
  3. "net"
  4. //"net/rpc"
  5. "log"
  6. "fmt"
  7. "net/rpc/jsonrpc"
  8. )
  9. type Args struct {
  10. A, B int
  11. }
  12. type Arg struct {
  13. A, B string
  14. }
  15. type Quotient struct {
  16. Quo, Rem string
  17. }
  18. type MyMath struct{
  19. }
  20. type RpcObj struct {
  21. Id int `json:"id"` // struct标签, 如果指定,jsonrpc包会在序列化json时,将该聚合字段命名为指定的字符串
  22. Name string `json:"name"`
  23. }
  24. func main() {
  25. client, err := net.DialTimeout("tcp", "localhost:1215", 1000*1000*1000*30) // 30秒超时时间
  26. if err != nil {
  27. log.Fatal("client\t-", err.Error())
  28. }
  29. defer client.Close()
  30. m := map[string]int{"num1":2, "num2":3 }
  31. clientRpc := jsonrpc.NewClient(client)
  32. var reply interface{}
  33. // 请求数据,rpcObj对象会被填充
  34. err = clientRpc.Call("MyMath.Add", m, &reply)
  35. if err != nil {
  36. log.Fatal("MyMath error:", err)
  37. }
  38. fmt.Printf("MyMath: %d+%d=%f\n", m["num1"], m["num2"], reply)
  39. //当然,你也可以用协程来调用(Asynchronous Call),是不是很高大上
  40. m2 := map[string]int{"num1":4, "num2":3 }
  41. goCall := clientRpc.Go("MyMath.Add", m2, &reply, nil)
  42. replyCall := <-goCall.Done // will be equal to addCall
  43. fmt.Println(replyCall.Reply, reply)
  44. }

接下来是大家关心的php掉golang的:

  1. <?php
  2. class JsonRPC
  3. {
  4. private $conn;
  5. function __construct($host, $port) {
  6. $this->conn = fsockopen($host, $port, $errno, $errstr, 3);
  7. if (!$this->conn) {
  8. return false;
  9. }
  10. }
  11. public function Call($method, $params) {
  12. if ( !$this->conn ) {
  13. return false;
  14. }
  15. $err = fwrite($this->conn, json_encode(array(
  16. 'method' => $method,
  17. 'params' => array($params),
  18. 'id' => 0,
  19. ))."\n");
  20. if ($err === false)
  21. return false;
  22. stream_set_timeout($this->conn, 0, 3000);
  23. $line = fgets($this->conn);
  24. if ($line === false) {
  25. return NULL;
  26. }
  27. return json_decode($line,true);
  28. }
  29. }
  30. $client = new JsonRPC("127.0.0.1", 1215);
  31. $r = $client->Call("MyMath.Add",array('num1'=>1,'num2'=>2));
  32. print_r($r);
  33. $r = $client->Call("MyMath.Sub",array('num1'=>'1','num2'=>'2'));
  34. print_r($r);

这个只是展示了它们之间可以如何调用,当然我们最好的约定和种协议,我们现在自己约定为json协议,你也可用thrift来做一个约定。这样子也是可以的,都走thrift。

分类: web

标签:   php   golang