Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

questions/discussions #110

Open
vicpon opened this issue Nov 21, 2017 · 36 comments
Open

questions/discussions #110

vicpon opened this issue Nov 21, 2017 · 36 comments

Comments

@vicpon
Copy link

vicpon commented Nov 21, 2017

Where is the best place to ask about microdot?

@tsibelman
Copy link
Contributor

For now, this is the best place.

@vicpon
Copy link
Author

vicpon commented Nov 21, 2017

Okay. May I suggest gitter? https://gitter.im/

So my question is about documentation/support. I'm in the very early stages of implementing a microservices solution and am comparing different things: microdot, orleanka, or a more home grown solution like like the MS eShopOnContainerr sample (https://github.com/dotnet-architecture/eShopOnContainers).

I would really like to use microdot. It looks like you guys have done a great job of building this but I'm a bit wary because it's so new and there isn't much documentation to get started with. Is microdot used in production within gigya? What are the plans for microdot? How many contributors are there? Is it actively being developed or is it waiting for outside contributors to join or show interest?

Thanks

@tsibelman
Copy link
Contributor

Microdot is actively used in Gigya (now part of SAP ) it supports very high scale application in production with dozens of microservices developed on top of it, it constantly evolving you can check release history. We have some documentation in Wiki and we have samples repository you should take a look.

The code base is not very large and not very complex so even if you encounter some bug it would be easy for you to overcome it.

Ultimately you should make a decision that works best for you, you can use Microdot or you can just look at Microdot as a sample and source of ideas for your own solution.

@vicpon
Copy link
Author

vicpon commented Nov 21, 2017

Thanks for the response. I'll look into the code more and try to understand everything.

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Nov 21, 2017

Just wanted to add that Microdot is at the core of Gigya's solution and services built upon it are serving paying customers at this very moment. We make changes to Microdot on a daily basis and it is actively maintained.

As far as documentation, we're far behind where we'd like to be. Unfortunately, at this point we can't dedicate as much time as for documentation as it deserves (extremely time consuming task), but I'm hoping this changes in the near future. In any case, if you have any question or need guidance on any topic or subsystem of Microdot, we'll do our best to help you with it. Feel free to ask any questions you have, and mention the most critical parts of the documentation that are missing for you, so we can prioritize them.

@vicpon
Copy link
Author

vicpon commented Nov 21, 2017

Thank you gentlemen. I really appreciate the quick replies and am hoping microdot becomes widely popular. ++1

@vicpon
Copy link
Author

vicpon commented Nov 21, 2017

In the sample InventoryService project, the InventoryServiceHost is used as a console application so it uses Source="Local" as the service discovery method. I think the client service discovery would be a priority for me as I would like to implement a polyglot microservices architecture where some of the microservices may not be Orleans/Microdot services. I'm thinking that that this could be accomplished using an HTTP interface to the Microdot service(s).

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Nov 21, 2017

In order to support certain features such as distributed tracing, host overrides and certain C# language features (such as method overloading), the request to a service uses an "envelope" that contains more than just the parameters to the method, it also contains information about which method to call on which type, tracing and correlation information and more metadata. In order for a non-Microdot client to call methods on a Microdot service, they would have to know the method's metadata (otherwise obtained from the interface assembly that the service publishes to all its clients) and create a compatible envelope (which is not particularly difficult, its simple JSON). Method metadata can be obtained from a metadata endpoint that each Microdot service exposes, or you could write a tool to statically generate that metadata from the interface assembly into your target language and embed it into the client.

A trickier part would be exception serialization which heavily relies on .NET exception types, embedded in the $type JSON property that is used for polymorphism in Json.NET. You may be able to get away with simply deserializing those exceptions into simpler non-exception types on the other side.

At Gigya we do have a Java system that makes very specific calls to a certain Microdot-based service that has an extremely stable API surface, so it can be done. But you'll lose some of the features and the seamless experience which makes Microdot unique.

@vicpon
Copy link
Author

vicpon commented Nov 22, 2017

Thanks for the high level explanation of how Microdot works. It makes sense that the service API calls are more than the method contract defines given everything Microdot does for you out of the box. I may consider putting one ore more gateways in front of the Microdot services to abstract the envelope and provide simple HTTP contracts to my clients.

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Nov 22, 2017

At Gigya we have our own API gateway (based on ASP.NET Core) that handles all incoming API requests from the internet at large and translates them into Microdot service calls into our plethora of services. It uses a special feature of Microdot that allows dynamic discovery and dispatch of calls without needing to deploy a new version of the gateway every time a new service is used or its interface changes, instead it queries the aforementioned metadata endpoint of all the services to discover which URLs should be routed to which service methods, all at runtime and responding to any changes immediately without intervention. The metadata is generated by each of the services based on .NET attributes which you use to decorate certain methods in your service that you'd like to make callable through the API gateway.

This API gateway is very Gigya-specific, performing specialized authentication and authorization, so it's not suitable to open-source it at this point (but we're thinking about it). Nevertheless, the dynamic discovery and dispatch is already in Microdot, and you might find it useful if you'll go down that path. Between services there is less of a need for dynamic dispatch, so we still use strongly- and statically-typed interfaces for ease of development allowing cross-service communication at a higher level of abstraction, without concerning yourself with the underlying protocol or serialization used (HTTP and JSON, currently) like you do in an API gateway.

@vicpon
Copy link
Author

vicpon commented Nov 22, 2017

I am really curious on the dynamic discovery and dispatch of calls feature of Microdot. Would it be possible to add a simple demo in the samples repo?

@daniel-lamberger
Copy link
Contributor

Victor, we've been meaning to open-source dynamic dispatching, we'll try to do so in the next couple of weeks, or at least to provide a code sample. I'll let you know.

@daniel-lamberger
Copy link
Contributor

@victor-ponce Sorry for not getting back to you, we didn't prioritize open-sourcing that part for now. Did you manage to get things going? Need assistance?

@vicpon
Copy link
Author

vicpon commented Dec 17, 2017

@daniel-lamberger. I took a look at the code but wasn't able to figure it out before I had to move on to something else. I'll have to wait until more examples and documentation area available. Thanks

@sabernar
Copy link

sabernar commented Jan 5, 2018

Would there be any difficulty using microdot with Docker?

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Jan 5, 2018

@sabernar: No, there shouldn't be any difficulty. In fact, before Docker was supported by Windows, we ran Microdot inside a Docker container with Linux and Mono, managed by Kubernetes. That is, until we found out the Mono GC tends to crash under certain high-load situations (this issue might have been resolved since), and so we returned to Windows. Our next attempt at Linux will be with .NET Core 2.0 when Orleans supports it in it's 2.0 version which is currently in beta.

@quinvit
Copy link

quinvit commented Jan 24, 2018

I am facing with HttpService and basePort issue. I have a multi tenants software, each tenant is a group of micro services. The first problem is I don't know which port is in used by other software or not. The second problem is how to manage and assign the port range for each group of micro services in a tenant in order they are not conflicted together. Do we have any best practice for this case?

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Jan 24, 2018

@quinvit, you can use the --BasePortOverride:1234 command line argument (see this wiki article) to assign base ports dynamically for each service in each group. So you could have the first group start at port 20000, and assign the services within it ports 20000, 20010, 20020, 20030, etc. Then you can have the next group of services use ports 21000, 21010, 21020, etc. This leaves room for 10 ports per service, and 100 services per groups, and you can have tens of groups per machine.

Then you'll either have to assign all of these statically and record them in the Discovery section of the configuration file, or you can use a service discovery mechanism such as Consul which is natively supported by Microdot (or write your own interface implementations to use a different mechanism).

@quinvit
Copy link

quinvit commented Jan 26, 2018

I am using a .NET Core 2 web app and a group of micro-services, can I use my web app as API Gateway, as Client to consume multiple micro-services with microdot directly via kernel.Get()? I tried but it doesn't work. It looks like a communication issue.

@Allon-Guralnek
Copy link
Contributor

@quinvit Could you please post the complete exception here?

@quinvit
Copy link

quinvit commented Jan 31, 2018

Sorry late reply. Because my .NET Core 2 Web App (target .netcore2.0) said that incompatible assembly issue so I give up without try to re-produce the exception. I used another standalone console app to host API Gateway with NancyFx. Where I can find out how to apply authentication between micro services using Microdot? Thank @Allon-Guralnek .

@quinvit
Copy link

quinvit commented Feb 3, 2018

Can I implement another logging module for microdot and create a PR for it? Serilog is my favorite one.

@Allon-Guralnek
Copy link
Contributor

@quinvit: Out of the box, Microdot only support authentication and encryption between services using HTTPS and both client and server certificates (which must be issued by the same CA, so they're effectively "pinned"). It involves a lot of certificate installing on the machines involved, and I'm not sure that's the kind of inter-service authentication you're looking for.

As for a new logging module, feel free to implement one for your favorite logger and we'll be happy to accept it as a PR!

@quinvit
Copy link

quinvit commented Apr 12, 2018

Is there anyway to override base port of [HttpService(8020, UseHttps = false)] for non Orleans service? I tried passing BasePortOverride via command line but it doesn't work for non Orleans service.

@daniellm
Copy link
Contributor

Make sure you're using this syntax: --BasePortOverride:1234

@quinvit
Copy link

quinvit commented Apr 12, 2018

Thank @daniellm and yes, I used that syntax. The service runs well under that port but at client code, it is still discovered under 8020 port. Is there anyway to set it to 8020 too at client code?

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <Discovery>
    <Services>
      <MyService Source="Local"  />
    </Services>
  </Discovery> 
    
</configuration>

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Apr 12, 2018

Try this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <Discovery>
    <Services>
      <MyService Source="Config" Hosts="localhost:8020" />
    </Services>
  </Discovery> 
</configuration>

If you want the HTTP call to be visible in Fiddler, use your machine name instead of localhost. Basically, Source="Local" is meant only for testing on the local machine with the default port.

@quinvit
Copy link

quinvit commented Apr 13, 2018

It works great. Thank @Allon-Guralnek .

@Cowraider
Copy link

Is there another way of calling a method in my ServiceInterface using the HttpServiceListener class?
I want to call my service and use the response in a WebClient.

When I do a POST call with the following data in the body

 { "Target" : 
    {
        "TypeName" : "SomeNamespace.Interface.IMyService",
        "MethodName" : "MyMethod"
    }  	
}

I get the results I want. Is there any other (easier) way to accomplish this?

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Jun 23, 2018

@Cowraider: Currently there is no other way. But we are accepting merge requests, so if you have another way you'd like to call methods, feel free to bounce the idea around and even submit some code.

@Cowraider
Copy link

@Allon-Guralnek Alright, thanks!

@Cowraider
Copy link

Cowraider commented Jun 24, 2018

I have another question regarding the HttpServiceListener. I always get a NullReferenceException in the GetParametersByName method when I am passing some arguments.
Following data is in the payload body:

{ 
"Target" : 
    {
        "TypeName" : "SomeNamespace.Interface.IMyService",
        "MethodName" : "Test",
        "Arguments" : { "param" : 42 } 
    } 
}

The Method signature in the IMyService interface looks like this:
Task<int> Test(int param);

Without passing arguments it works just fine but I am having troubles with arguments. Am I doing something wrong here?

@Allon-Guralnek
Copy link
Contributor

@Cowraider Could you post the stack trace of the exception?

@Cowraider
Copy link

here it is:

{
   "$type": "System.NullReferenceException:System.SystemException, mscorlib:mscorlib",
   "ClassName": "System.NullReferenceException",
   "Message": "Object reference not set to an instance of an object.",
   "Data": null,
   "InnerException": null,
   "HelpURL": null,
   "StackTraceString": "--- End of stack trace from MemberService v1.0.0.0 on Andreas-HP in global-dev ---\r\n  
	   at Gigya.Microdot.Hosting.HttpService.HttpServiceListener.<>c__DisplayClass63_0.<GetParametersByName>b__0(ParameterInfo p)\r\n   
		 at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()\r\n   
		 at System.Linq.Buffer`1..ctor(IEnumerable`1 source)\r\n   at
     System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)\r\n   
		 at Gigya.Microdot.Hosting.HttpService.HttpServiceListener.<GetResponse>d__62.MoveNext()\r\n   
		 at Gigya.Microdot.Hosting.HttpService.HttpServiceListener.<HandleRequest>d__54.MoveNext()",
   "RemoteStackTraceString": null,
   "RemoteStackIndex": 0,
   "ExceptionMethod": "8\n<GetParametersByName>b__0\nGigya.Microdot.Hosting, Version=1.10.5.841, Culture=neutral, PublicKeyToken=null\nGigya.Microdot.Hosting.HttpService.HttpServiceListener+<>c__DisplayClass63_0\nSystem.Object <GetParametersByName>b__0(System.Reflection.ParameterInfo)",
   "HResult": -2147467261,
   "Source": "Gigya.Microdot.Hosting",
   "WatsonBuckets": null
}

@Allon-Guralnek
Copy link
Contributor

Allon-Guralnek commented Jun 24, 2018

@Cowraider: Ah, Arguments needs to be outside Target, i.e. at the root of the JSON. Target can only contain TypeName, MethodName and ParameterTypes (which is used for overload resolution, not needed in your case since Test has no overloads).

You can see how the layout of the JSON needs to be by inspecting the HttpServiceRequest class.

@Cowraider
Copy link

@Allon-Guralnek oh wow, I inspected the HttpServiceRequest class but I must have overlooked it. Thank you very much. It's working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants