High-performance PHP-to-Golang IPC bridge

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
    
PHP bindings for the Go programming language (Golang)

PHP bindings for Go This package implements support for executing PHP scripts, exporting Go variables for use in PHP contexts, attaching Go method rec

Jan 1, 2023
PHP parser written in Go
PHP parser written in Go

PHP Parser written in Go This project uses goyacc and ragel tools to create PHP parser. It parses source code into AST. It can be used to write static

Dec 25, 2022
Transpiling fortran code to golang code

f4go Example of use > # Install golang > # Compile f4go > go get -u github.com/Konstantin8105/f4go > cd $GOPATH/src/github.com/Konstantin8105/f4go > g

Sep 26, 2022
Golang->Haxe->CPP/CSharp/Java/JavaScript transpiler

TARDIS Go -> Haxe transpiler Haxe -> C++ / C# / Java / JavaScript Project status: a non-working curiosity, development currently on-ice The advent of

Dec 30, 2022
A JavaScript interpreter in Go (golang)

otto -- import "github.com/robertkrimen/otto" Package otto is a JavaScript parser and interpreter written natively in Go. http://godoc.org/github.com/

Jan 2, 2023
A BASIC interpreter written in golang.
A BASIC interpreter written in golang.

05 PRINT "Index" 10 PRINT "GOBASIC!" 20 PRINT "Limitations" Arrays Line Numbers IF Statement DATA / READ Statements Builtin Functions Types 30 PRINT "

Dec 24, 2022
Expression evaluation in golang
Expression evaluation in golang

Gval Gval (Go eVALuate) provides support for evaluating arbitrary expressions, in particular Go-like expressions. Evaluate Gval can evaluate expressio

Dec 27, 2022
golang AST matcher

goastch (GO AST matCH) Introduction Inspired by ast matcher. There are four different basic categories of matchers: Node Matchers: Matchers that match

Nov 11, 2022
Scriptable interpreter written in golang
Scriptable interpreter written in golang

Anko Anko is a scriptable interpreter written in Go. (Picture licensed under CC BY-SA 3.0, photo by Ocdp) Usage Example - Embedded package main impor

Dec 23, 2022
Arbitrary expression evaluation for golang

govaluate Provides support for evaluating arbitrary C-like artithmetic/string expressions. Why can't you just write these expressions in code? Sometim

Jan 2, 2023
hotbuild - a cross platform hot compilation tool for golang
hotbuild - a cross platform hot compilation tool for golang

hotbuild A cross platform hot compilation tool By monitoring the modification of the project directory file, the recompilation and running are automat

Dec 12, 2022
The golang tool of the zig compiler automatically compiles different targets according to the GOOS GOARCH environment variable. You need to install zig.

The golang tool of the zig compiler automatically compiles different targets according to the GOOS GOARCH environment variable. You need to install zig.

Nov 18, 2022
Tgo - Test Helpers for Standard Golang Packages

Test Helpers for Standard Golang Packages see example_test.go go test --- FAIL:

Apr 26, 2022
Logexp - Logical expression compiler for golang

Logical Expression Compiler Functions: - Compile(exp string) - Match(text string

Jan 24, 2022
Runcmd - just golang binary that runs commands from url or local file and logs output

runcmd just golang binary that runs commands from url or local file and logs out

Feb 2, 2022
A compiler for the ReCT programming language written in Golang

ReCT-Go-Compiler A compiler for the ReCT programming language written in Golang

Nov 30, 2022
🧙 High-performance PHP-to-Golang IPC/RPC bridge

High-performance PHP-to-Golang IPC bridge Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/r

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

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.

Dec 28, 2022
Bridge Chrome "native messages" to Discord's IPC socket

chrome-discord-bridge This code bridges Chrome "native messages" to Discord's IPC socket. It's written in Go with no third-party dependencies. It's in

Nov 18, 2022
PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. You can use PHP like functions in your app, module etc. when you add this module to your project.

PHP Functions for Golang - phpfuncs PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. Y

Dec 30, 2022