Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package.

High-performance PHP-to-Golang IPC bridge

Latest Stable Version GoDoc Linux macOS Windows Linters Go Report Card Codecov

PHPClasses Innovation Award

Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package. The library allows you to call Go service methods from PHP with a minimal footprint, structures and []byte support.
PHP source code can be found in this repository: goridge-php


See https://github.com/spiral/roadrunner - High-performance PHP application server, load-balancer and process manager written in Golang

Features

  • no external dependencies or services, drop-in (64bit PHP version required)
  • low message footprint (12 bytes over any binary payload), binary error detection
  • CRC32 header verification
  • sockets over TCP or Unix (ext-sockets is required), standard pipes
  • very fast (300k calls per second on Ryzen 1700X over 20 threads)
  • native net/rpc integration, ability to connect to existed application(s)
  • standalone protocol usage
  • structured data transfer using json
  • []byte transfer, including big payloads
  • service, message and transport level error handling
  • hackable
  • works on Windows
  • unix sockets powered (also on Windows)

Installation

GO111MODULE=on go get github.com/spiral/goridge/v3

Sample of usage

package main

import (
	"fmt"
	"net"
	"net/rpc"

	goridgeRpc "github.com/spiral/goridge/v3/pkg/rpc"
)

type App struct{}

func (s *App) Hi(name string, r *string) error {
	*r = fmt.Sprintf("Hello, %s!", name)
	return nil
}

func main() {
	ln, err := net.Listen("tcp", ":6001")
	if err != nil {
		panic(err)
	}

	_ = rpc.Register(new(App))

	for {
		conn, err := ln.Accept()
		if err != nil {
			continue
		}
		_ = conn
		go rpc.ServeCodec(goridgeRpc.NewCodec(conn))
	}
}

License

The MIT License (MIT). Please see LICENSE for more information.

Owner
Spiral Scout
Spiral Scout is a full-service digital agency, providing design, development and online marketing services to businesses around San Francisco and beyond.
Spiral Scout
Comments
  • Second call is too slow

    Second call is too slow

    Hi. I did: go get "github.com/spiral/goridge" composer require spiral/goridge cd ~/go/src/goridge/vendor/spiral/goridge/examples go run ./

    And ran the folowing script:

    `<?php use Spiral\Goridge; require "vendor/autoload.php";

    $t1 = microtime(true); $rpc = new Goridge\RPC( new Goridge\SocketRelay("127.0.0.1", 6001) ); echo $rpc->call("App.Hi", "Antony"); $t3 = (float)microtime(true) - (float)$t1;

    echo ": $t3 | "; $t1 = microtime(true); echo $rpc->call("App.Hi", "Antony"); $t2 = microtime(true); $t3 = (float)$t2 - (float)$t1; echo ": $t3" . PHP_EOL;`

    I got a result: Hello, Antony!: 0.00071406364440918 | Hello, Antony!: 0.041256904602051 Is it a bug? Or I made mistake?

    ** Thank for your job!

  • Allow Unix socket on Windows

    Allow Unix socket on Windows

    Windows 10 now supports basic functionality of AF_UNIX sockets. Consequently, restriction on Unix sockets on Windows was removed in Go and thus can be removed in goridge.

  • [BUG] RPC error message duplication

    [BUG] RPC error message duplication

    I tried this code:

    <?php
    
    use Spiral\Goridge\RPC\RPC;
    
    require __DIR__ . '/vendor/autoload.php';
    
    RPC::create('tcp://127.0.0.1:6001')
      ->call('unknown-method', null);
    

    I expected to see this happen:

    Error 'rpc: service/method request ill-formed: unknown-method' on tcp://127.0.0.1:6001
    

    Instead, this happened:

    Error 'rpc: service/method request ill-formed: unknown-method; rpc: service/method request ill-formed: unknown-method' on tcp://127.0.0.1:6001
    

    The version of RR used: 2.3.0 (stable)

    Errortrace, Backtrace or Panictrace

    *not required*
    
  • PHP code removed

    PHP code removed

    PHP code now located in spiral/goridge-php repository. So, current state in master branch can be a little bit cleared.

    Yes, I know about #91. But this iteration must be made anyway, I think.

  • Getting ErrorException when the worker is stopped

    Getting ErrorException when the worker is stopped

    In production whenever the worker is being terminated by Roadrunner normally or by stopping the main process, I am getting an ErrorException with the following message:

    unpack(): Type C: not enough input, need 1, have 0
    

    on line: https://github.com/spiral/goridge/blob/c522eec9d8215c6059eeb4647d37003a2726e346/src/StreamRelay.php#L152

    Goridge version: v2.4.4 Roadrunner version: v1.5.1

  • STDIN is not readable

    STDIN is not readable

    Since version 2.2.0 (after execution composer update) i'v got an error:

    resource `in` must be readable in /app/vendor/spiral/goridge/php-src/StreamRelay.php:43
    

    In my code, I create StreamRelay using the following code:

    new \Spiral\Goridge\StreamRelay(\STDIN, \STDOUT);
    

    And got an error, describet above. It happens because since version 2.2.0 this package uses next assert:

        /**
         * Checks if stream is readable.
         *
         * @param resource $stream
         *
         * @return bool
         */
        private function assertReadable($stream): bool
        {
            $meta = stream_get_meta_data($stream);
            return in_array($meta['mode'], ['r', 'r+', 'w+', 'a+', 'x+', 'c+'], true);
        }
    

    Previos checking method was better: $this->assertMode($in, 'r')

    But this method does not allows to use binary safe mode (b), which appended to the STDIN and STDOUT by default:

    $ docker run --rm php:7.3.0-alpine php -r 'var_dump(stream_get_meta_data(\STDIN)["mode"]);'
    string(2) "rb"
    
    $ docker run --rm php:7.2.0-alpine php -r 'var_dump(stream_get_meta_data(\STDIN)["mode"]);'
    string(2) "rb"
    

    So, my applications cannot be started after update =(

  • StreamRelay requires Sockets extension

    StreamRelay requires Sockets extension

    I tried to add metrics into my application and hit into following error:

    roadrunner_1  | WARN[0020] Error: Call to undefined function Spiral\Goridge\socket_create() in /www/vendor/spiral/goridge/php-src/SocketRelay.php:275 
    roadrunner_1  | WARN[0020] Stack trace:                                 
    roadrunner_1  | WARN[0020] #0 /www/vendor/spiral/goridge/php-src/SocketRelay.php(185): Spiral\Goridge\SocketRelay->createSocket() 
    roadrunner_1  | WARN[0020] #1 /www/vendor/spiral/goridge/php-src/SocketRelay.php(88): Spiral\Goridge\SocketRelay->connect() 
    roadrunner_1  | WARN[0020] #2 /www/vendor/spiral/goridge/php-src/RPC.php(47): Spiral\Goridge\SocketRelay->send('metrics.Add\x00\x00\x00\x00...', 20) 
    roadrunner_1  | WARN[0020] #3 /www/vendor/spiral/roadrunner/src/Metrics.php(44): Spiral\Goridge\RPC->call('metrics.Add', Array) 
    roadrunner_1  | WARN[0020] #4 /www/psr-worker.php(29): Spiral\RoadRunner\Metrics->add('app_metric_coun...', 1) 
    roadrunner_1  | WARN[0020] #5 {main}                                    
    

    RR version is 1.4.7. The reason is inexisting Sockets extension.

    Suggestion: to require it in composer.json as "ext/sockets" OR to mention it in documentation and to throw exception if (!extension_loaded('sockets')) in createSocket

    P.S. There are also some json_encode in Spiral\Goridge\RPC, so it's better to add ext/json to require too.

  • Make slice error

    Make slice error

    got a weird error for a service that was already running for a week: when looking at the code it can only be triggered if leftBytes is negative? is that possible?

    data = make([]byte, 0, leftBytes)

    panic: runtime error: makeslice: cap out of range
    goroutine 89191655 [running]:
    github.com/spiral/goridge.(*SocketRelay).Receive(0xc420142330, 0x0, 0x0, 0x0, 0x28, 0xc42047bda0, 0x0, 0x0)
            /Users/jayme/Documents/projects/go/src/github.com/spiral/goridge/socket.go:54 +0x20e
    github.com/spiral/goridge.(*Codec).ReadRequestBody(0xc420346000, 0x0, 0x0, 0x0, 0x0)
            /Users/jayme/Documents/projects/go/src/github.com/spiral/goridge/codec.go:48 +0x48
    net/rpc.(*Server).readRequest(0xc4201360a0, 0x93b520, 0xc420346000, 0x725fc0, 0x992af8, 0x93b520, 0xc420346000, 0x79a91f, 0x28, 0x0, ...)
            /usr/local/Cellar/go/1.9/libexec/src/net/rpc/server.go:547 +0xe1
    net/rpc.(*Server).ServeCodec(0xc4201360a0, 0x93b520, 0xc420346000)
            /usr/local/Cellar/go/1.9/libexec/src/net/rpc/server.go:460 +0x77
    net/rpc.ServeCodec(0x93b520, 0xc420346000)
            /usr/local/Cellar/go/1.9/libexec/src/net/rpc/server.go:669 +0x41
    created by main.main
    
Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.
Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.

Continuous profiling for analysis of CPU, memory usage over time, and down to the line number. Saving infrastructure cost, improving performance, and increasing reliability.

Jan 2, 2023
Perforator is a tool for recording performance metrics over subregions of a program using the Linux "perf" interface.

Perforator Perforator is a tool for recording performance metrics over subregions of a program (e.g., functions) using the Linux "perf" interface.

Dec 15, 2022
A data parser lib for Go with pythonic grammar sugar and as concern as possible for high performance

mapinterface - A data parser lib for Go with pythonic grammar sugar and as concern as possible for high performance mapinterface 旨在消灭对map/list解析而产生的层层

Nov 10, 2021
Utility to restrict which package is allowed to import another package.

go-import-rules Utility to restrict which package is allowed to import another package. This tool will read import-rules.yaml or import-rules.yml in t

Jan 7, 2022
efaceconv - Code generation tool for high performance conversion from interface{} to immutable type without allocations.

efaceconv High performance conversion from interface{} to immutable types without additional allocations This is tool for go generate and common lib (

May 14, 2022
Go library to interface with NEAR nodes' JSON-RPC interface

StreamingFast Solana library for Go Go library to interface with NEAR nodes' JSON-RPC interface Contributing Issues and PR in this repo related strict

Nov 9, 2021
Use Golang to implement PHP's common built-in functions.

PHP2Go Use Golang to implement PHP's common built-in functions. About 140+ functions have been implemented. Install go get github.com/syyongx/php2go R

Dec 28, 2022
Go library for decoding generic map values into native Go structures and vice versa.

mapstructure mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. This l

Dec 28, 2022
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.

?? github.com/elliotchance/pie Enjoy a slice! pie is a library of utility functions for common operations on slices and maps. Quick Start FAQ What are

Dec 30, 2022
.NET LINQ capabilities in Go

go-linq A powerful language integrated query (LINQ) library for Go. Written in vanilla Go, no dependencies! Complete lazy evaluation with iterator pat

Jan 7, 2023
.NET LINQ capabilities in Go

go-linq A powerful language integrated query (LINQ) library for Go. Written in vanilla Go, no dependencies! Complete lazy evaluation with iterator pat

Jan 7, 2023
Simple go package which converts roman strings to integer

romanparse Simple go package which converts roman strings

Aug 11, 2022
Distributed Lab 2: RPC in Go

Distributed Lab 2: RPC in Go Using the lab sheet There are two ways to use the lab sheet, you can either: create a new repo from this template - this

Oct 22, 2021
Easy to use, light enough, good performance Golang library
 Easy to use, light enough, good performance Golang library

指令使用 特性 简单易用、足够轻量,避免过多的外部依赖,最低兼容 Window 7 等老系统 快速上手 安装 $ go get github.com/sohaha/zlsgo HTTP 服务 // main.go

Dec 29, 2022
A simple API for computing diffs of your documents over the time built on a scalable technology stack.

Diffme API WIP - this is an API to compute diffs between documents. It serves as a way to easily create audit logs for documents in your system, think

Sep 8, 2021
Go Parrot Twap will execute buy or sell orders over a specific time interval.

Go Parrot Twap Go Parrot Twap will execute buy or sell orders over a specific time interval. Getting started Firstly copy the .env.example to .env and

Dec 13, 2022
Go API backed by the native Dart Sass Embedded executable.

This is a Go API backed by the native Dart Sass Embedded executable. The primary motivation for this project is to provide SCSS support to Hugo. I wel

Jan 5, 2023
流媒体NetFlix解锁检测脚本 / A script used to determine whether your network can watch native Netflix movies or not
流媒体NetFlix解锁检测脚本 / A script used to determine whether your network can watch native Netflix movies or not

netflix-verify 流媒体NetFlix解锁检测脚本,使用Go语言编写 在VPS网络正常的情况下,哪怕是双栈网络也可在几秒内快速完成IPv4/IPv6的解锁判断 鸣谢 感谢 @CoiaPrant 指出对于地域检测更简便的方法 感谢 @XmJwit 解决了IPV6 Only VPS无法下载脚

Dec 29, 2022
Cpu-profiling - Basic example of CPU Profiling in Golang which shows the bottlenecks and how much time is spent per function

cpu-profiling Basic example of CPU Profiling in Golang which shows the bottlenec

Aug 2, 2022