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

Overview

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.

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!

    B-performance 
    opened by swifft17 5
  • 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.

    B-missing feature A-network 
    opened by oakad 5
  • [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*
    
    A-network 
    opened by SerafimArts 4
  • 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.

    A-other 
    opened by tarampampam 4
  • 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

    E-needstest E-medium B-bug 
    opened by sikhlana 4
  • 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 =(

    B-bug 
    opened by tarampampam 4
  • 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.

    A-docs 
    opened by batyrmastyr 4
  • 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
    
    B-bug 
    opened by jrots 4
Releases(v3.6.1)
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
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.

Parca 2.7k Nov 19, 2022
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.

Zachary Yedidia 33 May 5, 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解析而产生的层层

Knownothing 1 Nov 10, 2021
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 (

Ivan 50 May 14, 2022
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

PAYFAZZ 0 Jan 7, 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

StreamingFast 1 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

syyong.x 1.5k Nov 25, 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

Mitchell Hashimoto 6.3k Nov 22, 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

Elliot Chance 1.2k Nov 25, 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

Ahmet Alp Balkan 3.2k Nov 22, 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

Ahmet Alp Balkan 3.2k Nov 22, 2022
Simple go package which converts roman strings to integer

romanparse Simple go package which converts roman strings

Caio Ribeiro Pereira 4 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

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

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

影浅 505 Nov 18, 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

diffme 11 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

null 15 Oct 16, 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

Bjørn Erik Pedersen 27 Sep 17, 2022
流媒体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无法下载脚

null 1.9k Nov 28, 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

Felipe Azevedo 0 Aug 2, 2022