Based on the. net core microservice framework and the. netcore framework

Source: Internet
Author: User
Tags create domain intel core i7

Based on the. net core microservice framework and the. netcore framework
I. Preface

So far, we have been developing programming for 11 years, from VB6.0 and ASP to ASP. NET and then MVC. NET technology development, from the fearless ignorance of the young, to the current middle-aged uncle, from the ups and downs of the only I know. With the years of growth, the technology has also evolved from the original three-tier design to the current field-driven design, from the original Relational Database SQL 2000 to the current NOSQL (mongodb, couchbase, redis ), from the original SOAP-based web service to the current restful-based web api, wcf, and now the rpc microservice. The growth of technology has also brought traces of time.

Now Microsoft is out again. net core, in order to keep up with Microsoft's pace, I have studied it for nearly a year and read a lot of open source code, such as NetEscapades. configuration, eShopOnContainers, rabbit. RPC and so on. I have learned a lot from it and developed the distributed microservice framework surging with my own ideas. Open Source Address: Click to open the link. The following is an introduction in three articles:

Surging

1. Introduction and simple examples (Open Source) Based on. net core microservice framework-surging)

2. Analyze the architecture of surging

3. Subsequent architecture improvement of surging

2. What is surging?

Surging, in terms of translation, can also be translated into a surging landscape. What I hope is that. net core can become the most popular technology in I.

In terms of technology, surging is a distributed microservice framework based on the RPC protocol. The Framework relies on Netty for asynchronous communication and uses Zookeeper as the service registration center. It integrates hash, random and Round Robin as load balancing Algorithms

1. Basic Framework of service-oriented applications

The implementation process of the Framework is as follows:

1. Start the service provider and bind it to netty through the configured IP address and port according to the RPC protocol.

2. Store registration service information to Zookeeper

3. When the client CreateProxy calls the service, it obtains the valid service address of the last notification from the memory, selects the final called service address based on the routing information and load balancing mechanism, and initiates a call

2. Simple Example

Create IModuleServices

IUserService. cs:

[ServiceBundle] // service tag public interface IUserService {Task <string> GetUserName (int id); Task <bool> Exists (int id ); task <int> GetUserId (string userName); Task <DateTime> GetUserLastSignInTime (int id); Task <UserModel> GetUser (int id); Task <bool> Update (int id, userModel model); Task <IDictionary <string, string> GetDictionary (); Task TryThrowException ();}

Create a domain object

UserModel:

   [ProtoContract]    public class UserModel    {        [ProtoMember(1)]        public string Name { get; set; }        [ProtoMember(2)]        public int Age { get; set; }    }

 

AssemblyInfo. cs, extends AssemblyModuleType to identify the module, and registers reflection based on AssemblyModuleType.

[Assembly: AssemblyTitle ("Surging. IModuleServices. common ")] [assembly: AssemblyDescription (" Business Module Interface ")] [assembly: AssemblyModuleType (ModuleType. interFaceService)] // if this project is made public to COM, the following GUID is used for the Type Library ID [assembly: Guid ("2103624d-2bc2-4164-9aa5-1408daed9dee")]

 

Create Domain Service

PersonService. cs

[ModuleName ("Person")] // identifies the instantiation name public class PersonService: ServiceBase, IUserService {# region Implementation of IUserService private readonly UserRepository _ repository; public PersonService (UserRepository repository) {this. _ repository = repository;} public Task <string> GetUserName (int id) {return GetService <IUserService> ("User "). getUserName (id);} public Task <bool> Exists (int id) {return Ta Sk. fromResult (true);} public Task <int> GetUserId (string userName) {return Task. fromResult (1);} public Task <DateTime> GetUserLastSignInTime (int id) {return Task. fromResult (DateTime. now);} public Task <UserModel> GetUser (int id) {return Task. fromResult (new UserModel {Name = "fanly", Age = 18});} public Task <bool> Update (int id, UserModel model) {return Task. fromResult (true);} public Task <I Dictionary <string, string> GetDictionary () {return Task. fromResult <IDictionary <string, string> (new Dictionary <string, string >{{ "key", "value" }});} public async Task Try () {Console. writeLine ("start"); await Task. delay (5000); Console. writeLine ("end");} public Task TryThrowException () {throw new Exception ("the user ID is invalid! ") ;}# Endregion Implementation of IUserService }}

UserService. cs

[ModuleName ("User")] // identifies the instantiation name public class UserService: IUserService {# region Implementation of IUserService private readonly UserRepository _ repository; public UserService (UserRepository repository) {this. _ repository = repository;} public Task <string> GetUserName (int id) {return Task. fromResult ($ "id: {id} is name fanly. ");} public Task <bool> Exists (int id) {return Task. fromResult (true);} pub Lic Task <int> GetUserId (string userName) {return Task. fromResult (1);} public Task <DateTime> GetUserLastSignInTime (int id) {return Task. fromResult (DateTime. now);} public Task <UserModel> GetUser (int id) {return Task. fromResult (new UserModel {Name = "fanly", Age = 18});} public Task <bool> Update (int id, UserModel model) {return Task. fromResult (true);} public Task <IDictionary <string, string>> GetDictionary () {return Task. fromResult <IDictionary <string, string> (new Dictionary <string, string >{{ "key", "value" }});} public async Task Try () {Console. writeLine ("start"); await Task. delay (5000); Console. writeLine ("end");} public Task TryThrowException () {throw new Exception ("the user ID is invalid! ") ;}# Endregion Implementation of IUserService }}

 

AssemblyInfo. cs, extends AssemblyModuleType to identify the module, and registers reflection based on AssemblyModuleType.

[ModuleName ("User")] // identifies the instantiation name public class UserService: IUserService {# region Implementation of IUserService private readonly UserRepository _ repository; public UserService (UserRepository repository) {this. _ repository = repository;} public Task <string> GetUserName (int id) {return Task. fromResult ($ "id: {id} is name fanly. ");} public Task <bool> Exists (int id) {return Task. fromResult (true);} pub Lic Task <int> GetUserId (string userName) {return Task. fromResult (1);} public Task <DateTime> GetUserLastSignInTime (int id) {return Task. fromResult (DateTime. now);} public Task <UserModel> GetUser (int id) {return Task. fromResult (new UserModel {Name = "fanly", Age = 18});} public Task <bool> Update (int id, UserModel model) {return Task. fromResult (true);} public Task <IDictionary <string, string>> GetDictionary () {return Task. fromResult <IDictionary <string, string> (new Dictionary <string, string >{{ "key", "value" }});} public async Task Try () {Console. writeLine ("start"); await Task. delay (5000); Console. writeLine ("end");} public Task TryThrowException () {throw new Exception ("the user ID is invalid! ") ;}# Endregion Implementation of IUserService }}

 

3. Server
Using Autofac; using Autofac. extensions. dependencyInjection; using Microsoft. extensions. configuration; using Microsoft. extensions. dependencyInjection; using Microsoft. extensions. logging; using Surging. core. caching. configurations; using Surging. core. CPlatform; using Surging. core. CPlatform. runtime. server; using Surging. core. dotNetty; using Surging. core. proxyGenerator. utilitys; using Surging. core. system. ioc; usi Ng Surging. core. zookeeper; using Surging. core. zookeeper. configurations; using System. net; using System. text; using System. threading. tasks; namespace Surging. services. server {public class Program {static void Main (string [] args) {Encoding. registerProvider (CodePagesEncodingProvider. instance); var services = new ServiceCollection (); var builder = new ContainerBuilder (); ConfigureLogging (ser Vices); builder. populate (services); ConfigureService (builder); ServiceLocator. current = builder. build (); ConfigureCache (); ServiceLocator. getService <ILoggerFactory> (). addConsole (c, l) => (int) l> = 3); StartService (); Console. readLine ();} /// <summary> /// configure related services /// </summary> /// <param name = "builder"> </param> /// <returns> </returns> private static void ConfigureService (ContainerBuilder builde R) {builder. initialize (); builder. registerServices (); builder. registerRepositories (); builder. registerModules (); builder. addCoreServce (). addServiceRuntime (). useSharedFileRouteManager ("c: \ routes.txt") // configure the local route file path. useDotNettyTransport () // configure Netty. useZooKeeperRouteManager (new ConfigInfo ("192.168.1.6: 2181", "/dotnet/unitTest/serviceRoutes"); // configure ZooKeeper builder. register (p => new CPlatformContai Ner (ServiceLocator. current ));} /// <summary> /// configure Log Service /// </summary> /// <param name = "services"> </param> public static void ConfigureLogging (IServiceCollection services) {services. addLogging () ;}/// <summary> /// configure the cache service /// </summary> public static void ConfigureCache () {new ConfigurationBuilder (). setBasePath (AppContext. baseDirectory ). addCacheFile ("cacheSettings. json ", optional: false );} /// <Summary> /// start the service /// </summary> public static void StartService () {var serviceHost = ServiceLocator. getService <IServiceHost> (); Task. factory. startNew (async () => {await serviceHost. startAsync (new IPEndPoint (IPAddress. parse ("127.0.0.1"), 98); Console. writeLine ($ "server started successfully, {DateTime. now }. ") ;}). Wait ();}}}

 

4. Client
Using Autofac; using Autofac. extensions. dependencyInjection; using Microsoft. extensions. dependencyInjection; using Microsoft. extensions. logging; using Surging. core. CPlatform; using Surging. core. dotNetty; using Surging. core. proxyGenerator; using Surging. core. proxyGenerator. utilitys; using Surging. core. system. ioc; using System. text; namespace Surging. services. client {public class Program {static void Main (string [] args) {Encoding. registerProvider (CodePagesEncodingProvider. instance); var services = new ServiceCollection (); var builder = new ContainerBuilder (); ConfigureLogging (services); builder. populate (services); ConfigureService (builder); ServiceLocator. current = builder. build (); ServiceLocator. getService <ILoggerFactory> (). addConsole (c, l) => (int) l> = 3 );} /// <summary> /// configure related services /// </summary> /// <param name = "builder"> </param> /// <returns> </returns> private static void ConfigureService (ContainerBuilder builder) {builder. initialize (); builder. registerServices (); builder. registerRepositories (); builder. registerModules (); var serviceBulider = builder. addClient (). useSharedFileRouteManager ("c: \ routes.txt "). useDotNettyTransport ();} /// <summary> /// configure Log Service /// </summary> /// <param name = "services"> </param> public static void ConfigureLogging (IServiceCollection services) {services. addLogging ();} /// <summary> /// configure the Service proxy /// </summary> /// <param name = "builder"> </param> /// <returns> </returns> public static IServiceProxyFactory RegisterServiceProx (ContainerBuilder builder) {var serviceProxyFactory = ServiceLocator. getService <IServiceProxyFactory> (); serviceProxyFactory. registerProxType (builder. getInterfaceService (). toArray (); return serviceProxyFactory ;}}}

 

Remote service call

ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key)

 

Local module and service call

ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key)

 

5. Server Load balancer

Surging provides three load balancing methods:

Random: Random. The larger the number of calls, the more evenly distributed. This method is used by default.

Polling

HashAlgorithm: consistent hash. requests with the same parameters are routed to a service provider.

6. Other functions

Surging also provides distributed caching, AOP data interception, subscription and release based on rabbitmq, and monitoring services. It will be explained later.

6. Performance Testing

Test Environment

CPU: Intel Core i7-4710MQ

Memory: 16 GB

Hard Disk: 1 tb ssd + 512 GB HDD

Network: Lan

The test results are as follows: 10 thousand calls, 2290 MS, and an average of 0.229 MS per time. The performance is good. 7. Summary The release of surging version 0.0.0.1 means that the distributed microservice has taken the first step and many work needs to be improved in the future. I will spend a lot of time improving it. If you have any questions or are interested, you can join the QQ group: 615562965

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.