Coder Social home page Coder Social logo

osexpert / goreremoting Goto Github PK

View Code? Open in Web Editor NEW

This project forked from therainbird/coreremoting

2.0 1.0 0.0 2.9 MB

Grpc Remoting library for migration from .NET Remoting

Home Page: https://www.nuget.org/packages/GoreRemoting

License: MIT License

C# 99.73% Batchfile 0.27%
dotnet-remoting grpc net6 dotnet-core remoting rpc binaryformatter messagepack system-text-json memorypack protobuf

goreremoting's Introduction

GoreRemoting

	public interface IService
	{
		Task<string> EchoAsync(string s);
	}
	public class Service : IService
	{
		public async Task<string> EchoAsync(string s)
		{
			await Task.Delay(10);
			return s;
		}
	}
	public Task Server()
	{
		var remServer = new RemotingServer(new ServerConfig(new BinaryFormatterAdapter());
		remServer.RegisterService<IService, Service>();

		var server = new Grpc.Core.Server()
		{
			Services =
			{
				ServerServiceDefinition.CreateBuilder()
					.AddMethod(remServer.DuplexCallDescriptor, remServer.DuplexCall)
					.Build()
			}
		};
		server.Ports.Add("0.0.0.0", 5000, ServerCredentials.Insecure);
		server.Start();
		// wait for shutdown
		return server.ShutdownTask;
	}
	public async Task Client()
	{
		var channel = new Channel("localhost", 5000, ChannelCredentials.Insecure);
		var client = new RemotingClient(channel.CreateCallInvoker(), new ClientConfig(new BinaryFormatterAdapter()));
		var proxy = client.CreateProxy<IService>();

		var echo = await proxy.EchoAsync("Hello world!");
	}

GoreRemoting is based on CoreRemoting https://github.com/theRainbird/CoreRemoting

GoreRemoting is (just like CoreRemoting) a way to migrate from .NET Remoting, but with Grpc instead of WebSockets\Sockets.

General

Services are always stateless\single call. If you need to store state, store in a session. You can send extra headers with every call from client to server, eg. a sessionId or a Token via BeforeMethodCall on client and CreateInstance on server (look in examples). Clients create proxies from service interfaces (typically in shared assembly). No support for MarshalByRef behaviour. Everything is by value. Currently there is a limit of 20 method parameters. It is possible to increase it, possibly can increated to 30 if demand. But more than 30 won't happen.

Callbacks from server to client

It is not possible to callback to clients directly, callbacks must happen during a call from client to server. The server can callback via a delegate argument (look in examples). Can have as many callback delegate arguments as you wish, but only one can return something from the client. Others must be void\Task\ValueTask and will be OneWay (no result or exception from client). If you need to have a permanent open stream from server to client, have the client call a method that awaits forever and keeps an open stream, and send callbacks via a delegate argument (look in examples).

Cancellation

Support CancellationToken (via Grpc itself)

IAsyncEnumerable

Does not support IEnumerable\IAsyncEnumerable as result. Has AsyncEnumerableAdapter to adapt to IAsyncEnumerable providers\consumers via delegate. But using delegate arguments may be just as easy\easier.

IProgress

Does not support IProgress as argument. Has ProgressAdapter to adapt to IProgress providers\consumers via delegate. But using delegates arguments may be just as easy\easier.

Serializers

Currently has serializers for BinaryFormatter, System.Text.Json, MessagePack, MemoryPack, Protobuf. Must set a default serializer. Can overide serializer per service\per method with SerializerAttribute. This way migration from BinaryFormatter to eg. System.Text.Json can happen method by method\service by service.

Exception handling

Exceptions thrown are marshalled based on a setting in ClientConfig\ServerConfig: ExceptionStrategy. The default for all serializers (except BinaryFormatter) are ExceptionStrategy.Clone. BinaryFormatter has its own ExceptionStrategy setting (override) and its default is ExceptionStrategy.BinaryFormatter.

Exception strategies (GoreRemoring)

public enum ExceptionStrategy
{
	/// <summary>
	/// Same type as original, but some pieces may be missing (best effort).
	/// Uses ISerializable.GetObjectData\ctor(SerializationInfo, StreamingContext).
	/// </summary>
	Clone = 1,
	/// <summary>
	/// Always type RemoteInvocationException.
	/// Uses ISerializable.GetObjectData\ctor(SerializationInfo, StreamingContext).
	/// </summary>
	RemoteInvocationException = 2
}

Exception strategies (BinaryFormatter)

public enum ExceptionStrategy
{
	/// <summary>
	/// Use ClientConfig\ServerConfig ExceptionStrategy setting
	/// </summary>
	Default = 0,

	/// <summary>
	/// BinaryFormatter used (if serializable, everything is preserved, else serialized as default)
	/// </summary>
	BinaryFormatter = 3
}

Compression

Has compressor for Lz4 and can also use GzipCompressionProvider that already exist in grpc-dotnet. Can set default compressor, and like for serializers, can overide per service\per method with CompressorAttribute. A NoCompressionProvider exist in case you want to use eg. Lz4 as default but want to override some methods\services to not use compression.

Task\async

Support Task\ValueTask in service methods result and in result from delegate arguments (but max one delegate with actual result).

Limitations

Method that return IEnumerable and yield (crashes)
Method that return IAsyncEnumerable and yield (crashes)

Removed from CoreRemoting

CoreRemoting use WebSockets while GoreRemoting is a rewrite (sort of) to use Grpc instead.
Encryption, authentication, session management, DependencyInjection, Linq expression arguments removed (maybe some can be added back if demand).

Delegate arguments

Delegates that return void, Task, ValueTask are all threated as OneWay. Then it will not wait for any result and any exceptions thrown are eaten. You can have max one delegate with result (eg. int, Task<int>, ValueTask<int>) else will get runtime exception. If you need to force a delegate to be non-OneWay, then just make it return something (eg. a bool or Task<bool>). But again, max one delegate with result.

Advanced streaming

StreamingFuncAttribute\StreamingDoneException can be used to make streaming from client to server faster. Normally there will be one delegate call from server to client for every delegate call that pull data from client. With StreamingFuncAttribute\StreamingDoneException there will only be one delegate call from server to client, to start the streaming. Streaming from server to client is always fast (one way delegate).

Methods

OneWay methods not supported. Methods always wait for result\exception.

Other Rpc framework maybe of interest

StreamJsonRpc (Json or MessagePack over streams & WebSockets) https://github.com/microsoft/vs-streamjsonrpc

ServiceModel.Grpc (code-first support, gRPC) https://github.com/max-ieremenko/ServiceModel.Grpc

protobuf-net.Grpc (code-first support, gRPC) https://github.com/protobuf-net/protobuf-net.Grpc

SignalR.Strong (strongly-typed hub methods) https://github.com/mehmetakbulut/SignalR.Strong

MagicOnion (RPC, gRPC) https://github.com/Cysharp/MagicOnion

SharpRemote (RPC, TCP/IP) https://github.com/Kittyfisto/SharpRemote

ServiceWire (RPC, Named Pipes or TCP/IP) https://github.com/tylerjensen/ServiceWire

AdvancedRpc (TCP and Named Pipes) https://github.com/fsdsabel/AdvancedRpc

SimpleRpc (gRPC) https://github.com/netcore-jroger/SimpleRpc

Examples

Client and Server in .NET Framework 4.8 using Grpc.Core. Client and Server in .NET 6.0 using grpc-dotnet.

BinaryFormatter interop

BinaryFormatter does not work well between .NET Framework and .NET because types are different, eg. string in .NET is "System.String,System.Private.CoreLib" while in .NET Framework "System.String,mscorlib"

There exists hacks (links may not be relevant): https://programmingflow.com/2020/02/18/could-not-load-system-private-corelib.html
https://stackoverflow.com/questions/50190568/net-standard-4-7-1-could-not-load-system-private-corelib-during-serialization/56184385#56184385

You will need to add some hacks yourself if using BinaryFormatter across .NET Framework and .NET

Performance

Performance (1MB package size): The file copy test: Grpc.Core .NET 4.8 server\client:
File sent to server and written by server: 18 seconds (why so slow?)
File read from server and written by client: 11 seconds

grpc-dotnet .NET 6.0 server\client:
File sent to server and written by server: 31 seconds (oh noes...)
File read from server and written by client: 13 seconds

Update, when using StreamingFuncAttribute\StreamingDoneException (but also using smaller package size, 8KB instead of 1MB): Grpc.Core .NET 6.0 server\client: File sent to server and written by server: 16 seconds (better) File read from server and written by client: 15 seconds

grpc-dotnet .NET 6.0 server\client: File sent to server and written by server: 22 seconds (grpc-dotnet still slower than Grpc.Core)
File read from server and written by client: 23 seconds (faster before...)

Grpc.Core .NET 4.8 server\client:
File sent to server and written by server: 15 seconds File read from server and written by client: 15 seconds

Conclusion: StreamingFuncAttribute\StreamingDoneException does even out the numbers from and to, but grpc-dotnet is still slower.

Grpc implementations

Can use both Grpc.Core https://grpc.io/blog/grpc-csharp-future/ and grpc-dotnet https://github.com/grpc/grpc-dotnet. But grpc-dotnet is only fully compatible with itself, so I would discourage mixing grpc-dotnet server and Grpc.Core clients. Mixing Grpc.Core server and grpc-dotnet clients may work better. But best to not mix grpc-dotnet with anything else. Reason: under stress will get errors, specifically ENHANCE_YOUR_CALM

grpc-dotnet problems

When calling the grpc-dotnet server too fast(?), I get ENHANCE_YOUR_CALM\RESOURCE_EXHAUSTED(ResourceExhausted)\RST_STREAM or similar: Bug filed: grpc/grpc-dotnet#2010 Workaround added: use a hangup sequence. But still, this only workaround the problem when grpc-dotnet is used as both server and client. If grpc-dotnet is mixed with Grpc.Core, the problem still exist, specially when using Grpc.Core client agains grpc-dotnet server.

goreremoting's People

Contributors

cornmarket avatar osexpert avatar therainbird avatar zii-dmg avatar

Stargazers

 avatar  avatar

Watchers

 avatar

goreremoting's Issues

Hi

@theRainbird Hi, i wonder if i need to change the license or copyright before i publish on nuget?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.