locked
Question on azure service fabric application design RRS feed

  • Question

  • Hi All,

    I have a below requirement in Micro-service architecture design.

    My project which is of type Azure Service Fabric stateless and stateful services in Dot Net Core.

    Total 3 stateless and 3 stateful services in that project.

    For Each stateful service we have created one stateless service as gateway to that.

    We will be storing data in stateful service and through stateless we will sending data and retrieving data.

    For communication purpose we will be using Service proxy(ie. IService implemented interface).

    I can easily call methods of stateful1 from stateless1,
     But I have requirement like I need data from stateful1 which is depended on the stateful 2 and stateful 3.

    I have some business logic in between each stateful service, 

    Currently am creating Service proxy on statful1 and gathering all the data of stateful 2 & 3 and after computing entire data will be sending to stateless.

    My question will be, Is it better to have one more layer called repository(Class library project used by the stateless) which will contact each stateful service and compute the business logic?

    Or If have entire business logic in stateful will impact on performance, instead of having business logic in stateless.

    I have taken simple example of 3 stateless and 3 stateful, But actually my project consists of more than 50+ services each one is having Gateway and stateful service.
    Between each stateful service I have more business need to write.

    Please suggest me better approach for doing this requirement.


    SrinivasReddyVelpula

    Wednesday, February 20, 2019 6:09 PM

Answers

  • Hi Srinivas. I wanted to make sure I got the best response I could for you on this so I forwarded the query to one of our Service Fabric Product Group Members. See the response below and let me know if you have follow up questions/ comments

    Note: You should always consider containerization of your services, and externalizing your state.

    The questions as I understand it are:

    Should microservices be built with hard failure condition dependencies with other services?

    Answer: No. “Microservice applications are composed of small, independently versioned, and scalable customer-focused services that communicate with each other over standard protocols with well defined interfaces”

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-overview-microservices#what-is-a-microservice

    When should your consider using stateful services?

    Answer: When externalizing you state doesn’t work for performance reasons (very uncommon for most users), and you have isolated units of state and logic;

    I.E. You are building a Database as a service like Azure SQL or Cosmos DB.

    Context:

    Scenarios for using containers

    Here are typical examples where a container is a good choice:

    • IIS lift and shift: You can put an existing ASP.NET MVC app in a container instead of migrating it to ASP.NET Core. These ASP.NET MVC apps depend on Internet Information Services (IIS). You can package these applications into container images from the precreated IIS image and deploy them with Service Fabric. See Container Images on Windows Server for information about Windows containers.
    • Mix containers and Service Fabric microservices: Use an existing container image for part of your application. For example, you might use the NGINX container for the web front end of your application and stateful services for the more intensive back-end computation.
    • Reduce impact of "noisy neighbors" services: You can use the resource governance ability of containers to restrict the resources that a service uses on a host. If services might consume many resources and affect the performance of others (such as a long-running, query-like operation), consider putting these services into containers that have resource governance.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-containers-overview

    If any of the following characterize your application service needs, then you should consider Reliable Services APIs:

    • You want your service's code (and optionally state) to be highly available and reliable
    • You need transactional guarantees across multiple units of state (for example, orders and order line items).
    • Your application’s state can be naturally modeled as Reliable Dictionaries and Queues.
    • Your applications code or state needs to be highly available with low latency reads and writes.
    • Your application needs to control the concurrency or granularity of transacted operations across one or more Reliable Collections.
    • You want to manage the communications or control the partitioning scheme for your service.
    • Your code needs a free-threaded runtime environment.
    • Your application needs to dynamically create or destroy Reliable Dictionaries or Queues or whole Services at runtime.
    • You need to programmatically control Service Fabric-provided backup and restore features for your service’s state.
    • Your application needs to maintain change history for its units of state.
    • You want to develop or consume third-party-developed, custom state providers.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-reliable-services-introduction#when-to-use-reliable-services-apis

    Although the actor design pattern can be a good fit to a number of distributed systems problems and scenarios, careful consideration of the constraints of the pattern and the framework implementing it must be made. As general guidance, consider the actor pattern to model your problem or scenario if:

    • Your problem space involves a large number (thousands or more) of small, independent, and isolated units of state and logic.
    • You want to work with single-threaded objects that do not require significant interaction from external components, including querying state across a set of actors.
    • Your actor instances won't block callers with unpredictable delays by issuing I/O operations.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-reliable-actors-introduction

    Given the context that you need to a service to pull state from multiple external sources; Actors should NOT be used for a service with that requirement.

    The common scenario for a Stateful Reliable Service, that pulls state from external sources, is when hydrating the Stateful Service state during disaster recovery fail over.

    I.E. You don’t appear to have a reason for stateful1 service in your solution; it sounds like you are attempting to use it to cache all of stateful2 and stateful3 data, perform some logic on it, and reply with the result.

    Why wouldn’t you just make stateful1 stateless, have it simply used queried data from stateful services, to compute a result?

    Commonly stateful services being a “cache” service, is when they are hydrating from an external store, what value would you get from hydrating from another internal stateful service?

    Thursday, February 21, 2019 1:04 AM

All replies

  • Hi Srinivas. I wanted to make sure I got the best response I could for you on this so I forwarded the query to one of our Service Fabric Product Group Members. See the response below and let me know if you have follow up questions/ comments

    Note: You should always consider containerization of your services, and externalizing your state.

    The questions as I understand it are:

    Should microservices be built with hard failure condition dependencies with other services?

    Answer: No. “Microservice applications are composed of small, independently versioned, and scalable customer-focused services that communicate with each other over standard protocols with well defined interfaces”

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-overview-microservices#what-is-a-microservice

    When should your consider using stateful services?

    Answer: When externalizing you state doesn’t work for performance reasons (very uncommon for most users), and you have isolated units of state and logic;

    I.E. You are building a Database as a service like Azure SQL or Cosmos DB.

    Context:

    Scenarios for using containers

    Here are typical examples where a container is a good choice:

    • IIS lift and shift: You can put an existing ASP.NET MVC app in a container instead of migrating it to ASP.NET Core. These ASP.NET MVC apps depend on Internet Information Services (IIS). You can package these applications into container images from the precreated IIS image and deploy them with Service Fabric. See Container Images on Windows Server for information about Windows containers.
    • Mix containers and Service Fabric microservices: Use an existing container image for part of your application. For example, you might use the NGINX container for the web front end of your application and stateful services for the more intensive back-end computation.
    • Reduce impact of "noisy neighbors" services: You can use the resource governance ability of containers to restrict the resources that a service uses on a host. If services might consume many resources and affect the performance of others (such as a long-running, query-like operation), consider putting these services into containers that have resource governance.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-containers-overview

    If any of the following characterize your application service needs, then you should consider Reliable Services APIs:

    • You want your service's code (and optionally state) to be highly available and reliable
    • You need transactional guarantees across multiple units of state (for example, orders and order line items).
    • Your application’s state can be naturally modeled as Reliable Dictionaries and Queues.
    • Your applications code or state needs to be highly available with low latency reads and writes.
    • Your application needs to control the concurrency or granularity of transacted operations across one or more Reliable Collections.
    • You want to manage the communications or control the partitioning scheme for your service.
    • Your code needs a free-threaded runtime environment.
    • Your application needs to dynamically create or destroy Reliable Dictionaries or Queues or whole Services at runtime.
    • You need to programmatically control Service Fabric-provided backup and restore features for your service’s state.
    • Your application needs to maintain change history for its units of state.
    • You want to develop or consume third-party-developed, custom state providers.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-reliable-services-introduction#when-to-use-reliable-services-apis

    Although the actor design pattern can be a good fit to a number of distributed systems problems and scenarios, careful consideration of the constraints of the pattern and the framework implementing it must be made. As general guidance, consider the actor pattern to model your problem or scenario if:

    • Your problem space involves a large number (thousands or more) of small, independent, and isolated units of state and logic.
    • You want to work with single-threaded objects that do not require significant interaction from external components, including querying state across a set of actors.
    • Your actor instances won't block callers with unpredictable delays by issuing I/O operations.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-reliable-actors-introduction

    Given the context that you need to a service to pull state from multiple external sources; Actors should NOT be used for a service with that requirement.

    The common scenario for a Stateful Reliable Service, that pulls state from external sources, is when hydrating the Stateful Service state during disaster recovery fail over.

    I.E. You don’t appear to have a reason for stateful1 service in your solution; it sounds like you are attempting to use it to cache all of stateful2 and stateful3 data, perform some logic on it, and reply with the result.

    Why wouldn’t you just make stateful1 stateless, have it simply used queried data from stateful services, to compute a result?

    Commonly stateful services being a “cache” service, is when they are hydrating from an external store, what value would you get from hydrating from another internal stateful service?

    Thursday, February 21, 2019 1:04 AM
  • Thanks, Micah. For the quick response and it is more informative.

    But, I think my question is not pretty straight forward which I mentioned earlier.

    The actual requirement is,

    I am using Stateful Reliable services, in that reliable dictionaries am using to store data.

     Currently, we will be using SQL Server to store data and our business is more and going to host in different regions so we want to move the existing to microservice architecture.

    So, We will be creating each table as one microservice and creating stateless service as a gateway. We will replace the database calls in the web application with stateless endpoints. For normal Create, Update, Delete, Get operations on the table we can create the endpoint for each and we can accomplish the requirement.

    In order to migrate all the views and Stored procedures in the database to service fabric stateful service, we need to communicate with other stateful services to perform join operations, need to get all the data from other services and need to compute the logic based on the get all endpoints of all other services.

    Currently, we will be using a Create service proxy in stateful services.

    Consider below example,

    I have three tables User, Role, UserRoles.I have created three stateful services for each table.

    I want to get all the users details for a particular role.

    For this Firstly, Need to get the role id for the role name and then get the user id's based on role id from user roles finally, we will get all users by user id.

    In my case, I am creating a service method in user service to get all user details for a particular role.

    I that method am creating the proxy for the Role and UserRoles to get all the data from roles and user roles to perform necessary joins.

    I have added all the computational logic(Ie Joins, or filtering data) in a stateful user service method.

    My question is if we add more computational logic and proxy calls to other services will impact on the performance. In my case nearly 100+ stored procs and 300+ views and functions.

    If we create service methods for each StoredProc or view is a huge computational logic in stateful service.

    For this, we have used IReliableIndexed dictionary to query the service fabric stateful service and getting the filtered data instead of iterating through all data in the dictionary. But we have some limitations indexed dictionary will not support nullable columns and some of the Linq operations.

    We thought of maintaining the cache in stateful service level, But we could not find any predefined cache mechanism in stateful reliable dictionaries. And also we want to maintain stateless repository in which will get required data from stateful services and computational logic we will do from here and return the computational result.

    Is this approach is better? or can you please suggest me a better.

    How to implement the cache in stateful service and stateless service?

    Or Can we join multiple reliable dictionaries directly? It is possible?


    SrinivasReddyVelpula


    Thursday, February 21, 2019 7:17 PM
  • Hi Srinivas. Response from the Service Fabric product team based on your last response: 

    You should externalize your state to Azure SQL or Cosmos DB, and build your services as containers.

    Building a Database Engine is not a trivial activity; your approach as you’ve described it, is not an effective means to re-implementing a solved problem, as Azure SQL offers Database as a Service.

    Your approach of redesigning your solution to internalize MS SQL eternized state, by building stateful services for tables/views/stored procedures/join operations, is not recommended.

        • The Service Fabric cluster resource in Azure is regional today, as are the virtual machine scale sets that the cluster is built on. This means that in the event of a regional failure you may lose the ability to manage the cluster via the Azure Resource Manager or the Azure portal. This can happen even though the cluster remains running and you'd be able to interact with it directly. In addition, Azure today does not offer the ability to have a single virtual network that is usable across regions. This means that a multi-region cluster in Azure requires either Public IP Addresses for each VM in the VM Scale Sets or Azure VPN Gateways. These networking choices have different impacts on costs, performance, and to some degree application design, so careful analysis and planning is required before standing up such an environment.
        • The maintenance, management, and monitoring of these machines can become complicated, especially when spanned across types of environments, such as between different cloud providers or between on-premises resources and Azure. Care must be taken to ensure that upgrades, monitoring, management, and diagnostics are understood for both the cluster and the applications before running production workloads in such an environment. If you already have experience solving these problems in Azure or within your own datacenters, then it is likely that those same solutions can be applied when building out or running your Service Fabric cluster.

    Ref:

    https://docs.microsoft.com/azure/service-fabric/service-fabric-common-questions

    E.G.

    Service Fabric in Azure is regional today, so why would you feel the requirement of hosting your solution in different regions, would imply you shouldn’t use Azure SQL or Cosmos DB?

    What value do you believe you will gain value from taking on the technical debt of building/managing all of those stateful services?

    The design of mapping SQL Server features to stateful services, is not an efficient means to build any microservices architected solution.

    I.E. Your scenario is Lift and Shift. So should leverage Azure SQL for your SQL Server state, and consider in order containers, stateless services, or guest executables (stateless is a last resort when external stores can not meet your technical requirements).

    If you are going to pursue a non-recommended approach, then please review Azure Support options, to acquire appropriate support to meet your development velocity (you sounds like your early in your design, and may benefit from a Primer Engineer whom can provide reference architectures and develop software for you):

    https://docs.microsoft.com/azure/service-fabric/service-fabric-support

    To address all your questions:

      1. Is this approach is better? Or can you please suggest me a better.
        1. No it not better, and yes I can suggest better (Please consider containerizing your services, and externalizing your state to Azure SQL).
      2. How to implement the cache in stateful service and stateless service?
        1. There is no caching in a stateful or stateless service. Please consider Azure Cache for Redis if you need a Cache: https://docs.microsoft.com/azure/azure-cache-for-redis/
      3. Or can we join multiple reliable dictionaries directly? It is possible?
        1. No.

    Lastly,

    Some statements to hopefully clarify a few things:

    Microservices is an architecture pattern, and stateful services are not required to develop a microservice architected solution.

    Stateful Services shouldn’t be built unless you have a technical requirement to do so, as the scale at which it becomes valuable is global Database as a Service scale, and smaller than that will nearly always be less efficient (Time to build, Resources to support, Specialized skill set to maintain, ect).

    Friday, February 22, 2019 1:49 AM
  • Sorry to hijack this thread, but @Micah are you saying that is it best practice to deploy your Microservices into containers running on Service Fabric rather than deploying the microservice directly to ServiceFabric.


    Tuesday, April 2, 2019 8:14 AM