Project Introduction
The silky framework is designed to help developers quickly build a microservice application development framework through simple code and configuration under the .net platform.It provides RPC communication and Microservice Governance Two key capabilities. This means that the microservices developed using silky will have mutual remote discovery and communication capabilities. At the same time, using the rich service governance capabilities provided by silky, service governance demands such as service discovery, load balancing, and traffic scheduling can be realized. At the same time, silky is highly extensible, and users can customize their own implementation at almost any function point to change the default behavior of the framework to meet their own business needs.
The silky microservice has the following advantages:
out of the box
- Simple and easy to use, use a general-purpose host or a web host to build (host) microservice applications.
- Ease of use is high, and the interface-oriented proxy feature can realize local transparent calls.
- Rich in functions, most of the microservice governance capabilities can be realized based on native libraries or lightweight extensions.
Ultra-large-scale microservice cluster practice
- A high-performance cross-process communication protocol, using the DotNetty communication framework to implement the RPC framework based on the interface proxy, providing high-performance proxy-based remote call capabilities, the service is based on the interface, and the underlying details of the remote call are shielded for developers.
- In terms of address discovery and traffic management, it can easily support large-scale cluster instances.
Enterprise-level microservice governance capabilities
- Through the service governance implemented by Polly, the fault tolerance of the service is improved.
- A variety of built-in load balancing strategies can intelligently perceive the health status of downstream nodes, significantly reduce call delays, and improve system throughput.
- Supports multiple registration center services, real-time perception of service instances going online and offline.
Guarantee of Data Consistency
- Use TCC distributed transactions to ensure the final consistency of data.
frame properties
service engine
- Responsible for the initialization process of the silky host
- Responsible for module parsing, dependency management and loading
- Service registration and resolution
Modular/plug-in design
- There are dependencies between modules
- Support plug-in loading module
- Support plug-in loading application services
RPC communication
- Use Dotnetty as the underlying communication component, use TCP as the communication protocol, and use long links to improve system throughput
- Interface-based dynamic proxy
- Support calling via template
- Support JSON codec
- Support cache interception during RPC communication to improve communication performance
- RPC call monitoring
Service Governance
- Service automatic registration and discovery, intelligent perception of service instances going online and offline
- RPC call failed retry
- Supports load balancing routing methods such as polling, random routing, and hash consistency, intelligently perceives the health status of downstream nodes, significantly reduces call delays, and improves system throughput.
- Support HTTP current limit and RPC call current limit
- Support fuse protection, when non-friendly exceptions occur n times, the fuse protection will be turned on
- Support monitoring of RPC calls
- Service degradation, called when the RPC call fails
Fabllback
The specified method achieves the purpose of service fault tolerance - Prohibit services from external access through configuration support
Build via .net host
- Build microservice applications using web hosting
- Build Microservices Applications Using a Generic Host
- Build microservice applications with websocket capabilities
- Build the gateway application
security design
- The gateway performs identity authentication and authentication in a unified manner
- The rpc token is used to protect the RPC communication, ensuring that the external cannot directly access the rpc service
- RPC communication supports ssl encryption
Various configuration methods
- Support Json format configuration file
- Support configuration files in Yaml format
- Support Apollo as a configuration service center
- use environment variables
link tracking
- HTTP request
- RPC call
- TCC distributed transaction
- Other (EFCore)…
Support for distributed transactions
- In the process of RPC communication, the final consistency of data is guaranteed through the TCC distributed framework
- Implemented using interceptor + TODO log
- Use Redis as TODO log storage warehouse
Support websocket communication
- Build websocket service through websocketsharp.core component
- Handshake and talk with the front end through the gateway agent
getting Started
sample project
Silky.Hero authority management system
quick start
Basic services
Recommended Usedocker-compose
Install and deploy basic services.
- Install and deploy Zookeeper, copy and save docker-compose.zookeeper.yml to the local, and then install the Zookeeper service through the following command:
docker-compose -f docker-compose.zookeeper.yml up -d
- Install and deploy the redis cache service, copy and save docker-compose.redis.yml locally, and then install the redis service through the following command:
docker-compose -f docker-compose.redis.yml up -d
create gateway
- CreateEmpty WebApplicationproject namedGateway,Install
Silky.Agent.Host
package, and inProgram.cs
The code for creating a managed gateway application host is added to the class;
using Gateway;
var hostBuilder = Host.CreateDefaultBuilder()
.ConfigureSilkyGatewayDefaults(webHostBuilder => webHostBuilder.UseStartup<Startup>());
await hostBuilder.Build().RunAsync();
- add
Startup.cs
class, and add the following code;
namespace Gateway;
public class Startup
{
public void ConfigureService(IServiceCollection services)
{
services.AddSilkyHttpServices()
.AddRouting()
.AddSwaggerDocuments()
.AddMiniProfiler();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseSwaggerDocuments();
app.UseMiniProfiler();
}
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapSilkyRpcServices(); });
}
}
- delete
.json
configuration file, and addappsetiings.yaml
configuration file, and add the following configuration:
rpc:
token: ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW
registrycenter:
type: Zookeeper
connectionStrings: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186
distributedCache:
redis:
isEnabled: true
configuration: 127.0.0.1:6379,defaultDatabase=0
- Run the gateway project, check the address where the http service runs (for example: https port is 7160), then open it through a browserhttps://127.0.0.1:7160/index.html swagger online documentation; when the application service is not added through business microservices, the swagger documentation does not have any interface:
Business Microservices
- Create a file namedDemoHostconsole project, install
Silky.Agent.Host
package, and inProgram.cs
The code to create a managed application host is added to the class;
using Microsoft.Extensions.Hosting;
var hostBuilder = Host.CreateDefaultBuilder().ConfigureSilkyGeneralHostDefaults();
await hostBuilder.Build().RunAsync();
- Add
appsettings.yaml
configuration file, and add the following configuration:
rpc:
token: ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW
port: 2200
registrycenter:
type: Zookeeper
connectionStrings: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183;127.0.0.1:2184,127.0.0.1:2185,127.0.0.1:2186
distributedCache:
redis:
isEnabled: true
configuration: 127.0.0.1:6379,defaultDatabase=0
- Add a sample service and add a new folderhelloand add
IHellAppService
interface:
[ServiceRoute]
public interface IHelloAppService
{
Task<string> SayHi([FromQuery]string name);
}
- Add to
HellAppService
class, and implementIHellAppService
interface:
public class HelloAppService : IHelloAppService
{
public Task<string> SayHi(string name)
{
return Task.FromResult($"Hello {name ?? "World"}");
}
}
- runDemoHostProject, and refresh the Swagger online document through the browser, you can see the following interface, and you can debug the webapi online through the swagger document:
How to call between services
- By referring to the application interface class library of other microservice applications (other microservices can package the application interface into a nuget package, and install the nuget package of the application interface of other microservice applications through the nuget package), by constructing the injected interface, directly Using the method defined by the interface, the dynamic proxy generated by the interface can realize RPC communication with the service provider:
Example: PermissionManager.cs in Silky.Hero project
public class PermissionManager : IPermissionManager, IScopedDependency
{
private readonly IUserAppService _userAppService;
private readonly IRoleAppService _roleAppService;
public PermissionManager(IUserAppService userAppService,
IRoleAppService roleAppService)
{
_userAppService = userAppService;
_roleAppService = roleAppService;
}
public async Task<ICollection<string>> GetUserRoleNamesAsync(long userId)
{
var userRoleOutput = await _userAppService.GetRolesAsync(userId);
return userRoleOutput.RoleNames;
}
public async Task<ICollection<long>> GetUserRoleIdsAsync(long userId)
{
var userRoleIds = await _userAppService.GetRoleIdsAsync(userId);
return userRoleIds;
}
public async Task<ICollection<string>> GetRolePermissionsAsync(long roleId)
{
var rolePermissions = await _roleAppService.GetPermissionsAsync(roleId);
return rolePermissions;
}
}
- Call the interface through the template
IInvokeTemplate
The provided API implements remote service calls, and the interface supports routing to specific service provider methods through service item Id or WebAPI;
For example: In the Silky.Hero project, the gateway’s authority authentication processor AuthorizationHandler passesIInvokeTemplate
Call the permission service provided by the permission application service to determine whether the currently requested interface has access permission:
public class AuthorizationHandler : SilkyAuthorizationHandlerBase
{
private readonly IInvokeTemplate _invokeTemplate;
private const string CheckPermissionServiceEntryId =
"Silky.Permission.Application.Contracts.Permission.IPermissionAppService.CheckPermissionAsync.permissionName_Get";
private const string CheckRoleServiceEntryId =
"Silky.Permission.Application.Contracts.Permission.IPermissionAppService.CheckRoleAsync.roleName_Get";
public AuthorizationHandler(IInvokeTemplate invokeTemplate)
{
_invokeTemplate = invokeTemplate;
}
protected override async Task<bool> PolicyPipelineAsync(AuthorizationHandlerContext context,
HttpContext httpContext,
IAuthorizationRequirement requirement)
{
if (requirement is PermissionRequirement permissionRequirement)
{
if (EngineContext.Current.HostEnvironment.EnvironmentName == SilkyHeroConsts.DemoEnvironment &&
httpContext.Request.Method != "GET")
{
throw new UserFriendlyException("演示环境不允许修改数据");
}
var serviceEntryDescriptor = httpContext.GetServiceEntryDescriptor();
if (serviceEntryDescriptor.GetMetadata<bool>("IsSilkyAppService"))
{
// todo
return true;
}
return await _invokeTemplate.InvokeForObjectByServiceEntryId<bool>(CheckPermissionServiceEntryId,
permissionRequirement.PermissionName);
}
return true;
}
protected override async Task<bool> PipelineAsync(AuthorizationHandlerContext context, HttpContext httpContext)
{
var serviceEntryDescriptor = httpContext.GetServiceEntryDescriptor();
var roles = serviceEntryDescriptor
.AuthorizeData
.Where(p => !p.Roles.IsNullOrEmpty())
.SelectMany(p => p.Roles?.Split(","))
.ToList();
foreach (var role in roles)
{
if (!await _invokeTemplate.InvokeForObjectByServiceEntryId<bool>(CheckRoleServiceEntryId, role))
{
return false;
}
}
return true;
}
}
Remark:
The advantage of using the template call method is that there is no need to refer to the application interface defined by other microservice applications between microservice applications, and the application and application are completely decoupled and independent of each other; the disadvantage is that it does not support the usage scenarios of distributed transactions;
Quickly create applications through project templates
silky provides templatessilky.app
Templates can quickly create applications, and developers can use modules to quickly create silky microservice applications after installing templates.
> dotnet new --install Silky.App.Template
Use project templates to create microservice applications.
PS> dotnet new silky.app -h
Silky App (C#)
作者: Liuhll
Usage:
dotnet new silky.app [options] [模板选项]
Options:
-n, --name <name> 正在创建的输出名称。如未指定名称,则使用输出目录的名称。
-o, --output <output> 要放置生成的输出的位置。
--dry-run 如果运行给定命令行将导致模板创建,则显示将发生情况的摘要。
--force 强制生成内容 (即使它会更改现有文件)。
--no-update-check 在实例化模板时,禁用对模板包更新的检查。
--project <project> 应用于上下文评估的项目。
-lang, --language <C#> 指定要实例化的模板语言。
--type <project> 指定要实例化的模板类型。
模板选项:
-t, --param:type <param:type> Set the silky host type, optional values: webhost, generalhost ,wshost, gateway
类型: string
默认: generalhost
-do, --dockersupport Add docker support for Silky
类型: bool
默认: true
-r, --rpcport <rpcport> Set the port for rpc listening
类型: int
默认: 2200
-in, --infrastr only include basic service orchestration files
类型: bool
默认: false
-e, --env <env> Set dotnet env
类型: string
默认: Development
-m, --module Is it a module project
类型: bool
默认: false
-p:i, --includeinfr Whether to include the basic orchestration service.
类型: bool
Example:
# 创建网关
> dotnet new silky.app -t gateway -n Silky.Gateway
# 创建业务微服务
> dotnet new silky.app -t generalhost -n Silky.Demo
contribute
- One of the easiest ways to contribute is to discuss issues. You can also contribute code changes by submitting Pull Requests.
#Silky #framework #designed #developers #quickly #build #microservice #development #framework #simple #code #configuration #net #platform