【 .NET Core 3.0 】框架之二 || 后端项目搭建


前言


至于为什么要搭建.Net Core 平台,这个网上的解释以及铺天盖地,想了想,还是感觉重要的一点,跨平台,嗯!没错,而且比.Net 更容易搭建,速度也更快,所有的包均由Nuget提供,不再像以前的单纯引入组件,

640?wx_fmt=png

已经没有了之前的Assemblies和COM的引入,初次使用感觉会很别扭,不过使用多了,发现还是很方便的,所以你一定要会使用Nuget,真的很强大,这点儿设计思路感觉更像Linux了。

下边这三点,是先对 .net core  有一个初步的认识,看得懂或者看不懂都没有关系,以后大家肯定都会明白的:

 

1、.net core 框架性能测试

http://www.techempower.com/benchmarks/ 我们可以通过这个web框架性能测试来看看 aspcore 的性能

640?wx_fmt=png

640?wx_fmt=png

 

2、.net core 执行过程

640?wx_fmt=png

3、中间件执行过程

启动的时候先执行该中间件类的构造函数,然后一路 Next() ;下去,返回的时候,正好是反向的,执行的是该类的逻辑部分:

640?wx_fmt=png

 

4、AOP切面

640?wx_fmt=png

 

640?wx_fmt=png

 

 

5、整体框架结构与数据库表UML

 640?wx_fmt=png

 

 

640?wx_fmt=png

 

 

一、创建第一个Core

    说了从零开始,就得从零开始,老生常谈,开始。

1、SDK 安装

当然,前提是你得安装.Net Core 的 SDK 环境,这里只能使用 vs 2019 且版本在 16.3 以上。

 

下载 SDK 地址 :https://dotnet.microsoft.com/download


选择指定的平台即可安装:

640?wx_fmt=png

 

这里说下,SDK 和 RunTime 的区别:
1、SDK 是用来开发 NetCore 的,内部捆绑了 Runtime 运行时;
2、但是如果只想运行 NetCore 项目的话,只需要在服务器中安装 Runtime 运行时即可;

 

怎么判断安装成功了呢?直接运行命令,如果有结果证明成功了:

 

640?wx_fmt=png

 

 

2、新建项目

1、打开vs2019 ,创建一个新的项目,这里有很多模板,大家都可以试试:

640?wx_fmt=png

 

 

2、点击下一步 Next。



3、然后创建模板:

640?wx_fmt=png

 

这里要注意下,关于Https选项问题,有很多小伙伴在以后的接口调用中,勾选了这个,但是还是一直使用 http 协议去访问,导致找不到响应的接口地址。

640?wx_fmt=png


 

1、是你的项目创建的时候,勾选了 Https 选项,如果你还没有创建,那就可以不要勾选那个 HTTPS选项。

2、如果你的项目已经创建好了,每次访问都是HTTPS的,但是你不想这么做,可以在 launthSettings.json 文件中,把sslPort 端口号改成0即可
640?wx_fmt=png

 

3、删除IIS配置,默认使用 kestrel 服务器


 

640?wx_fmt=png


 

 

3、项目整体结构分析

接下来咱们看看这个项目都包含了哪些东西: 

640?wx_fmt=png

 

这里默认,有一个 WeatherForecastController.cs ,打开后:

1、当前控制器继承了 ControllerBase 基类;


2、有一个路由特性,可以配置当前路由规则,比如当前的是[Route("[controller]")],表示 Url 路径为 :localhost:5000/weacherforecast

   如果你配置 [Route("[controller]/[action]")] 表明 Url 路径为 :localhost:5000/weacherforecast/get


3、发现有一个默认的构造函数,里边已经注入了日志 ILogger,这个依赖注入相关内容,以后会讲到;

4、默认提供了一个 get 方法,随机生成了一个天气集合;


640?wx_fmt=png




640?wx_fmt=png

 

640?wx_fmt=png


接下来点开appsettings.json文件,这里就是整个系统app的配置地址,更类似以前的web.config,以后大家会用到。


 

 

继续往下,打开Startup.cs 文件这里是整个项目的启动文件,所有的启动相关的都会在这里配置,比如 依赖注入,跨域请求,Redis缓存等,更多详情在以后的文章中都会有所提起

 

640?wx_fmt=png


二、重要文件说明

1、Program.cs

namespace blog.core.test3._0{    public class Program    {        public static void Main(string[] args)        {            CreateHostBuilder(args).Build().Run();        }
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }}


下边的内容,如果不理解,也无所谓,以后会慢慢懂的,至少要读几遍,知道相关概念。


这个Program是程序的入口, 看起来很眼熟, 是因为asp.net core application实际就是控制台程序(console application).


它是一个调用asp.net core 相关库的console application. 

Main方法里面的内容主要是用来配置和运行程序的。



因为我们的web程序需要一个宿主,所以CreateHostBuilder这个方法就创建了一个IHostBuilder. 而且我们还需要Web Server.


asp.net core 自带了两种http servers, 一个是WebListener, 它只能用于windows系统, 另一个是kestrel, 它是跨平台的.

kestrel是默认的web server, 就是通过UseKestrel()这个方法来启用的.

但是我们开发的时候使用的是IIS Express, 调用UseIISIntegration()这个方法是启用IIS Express, 它作为Kestrel的Reverse Proxy server来用.

640?wx_fmt=png

 

 

如果在windows服务器上部署的话, 就应该使用IIS作为Kestrel的反向代理服务器来管理和代理请求.

如果在linux上的话, 可以使用apache, nginx等等的作为kestrel的proxy server.

当然也可以单独使用kestrel作为web 服务器, 但是使用iis作为反向代理还是有很多有优点的: 例如,IIS可以过滤请求, 管理证书, 程序崩溃时自动重启等.

不过目前因为跨平台,所以使用较多的还是 nginx。


webBuilder.UseStartup<Startup>();, 这句话表示在程序启动的时候, 我们会调用Startup这个类.

Build()完之后返回一个实现了 IHost 接口的实例(IHostBuilder), 然后调用Run()就会运行Web程序, 并且阻止这个调用的线程, 直到程序关闭.

 

如果想要对AspNetCore源码进行研究,可以查看源码,这里提供两个方法:

1、F12,当然这个不能看到详细的,你需要安装一个组件,VS2017 Resharper

2、查看Github 开源源码 https://github.com/aspnet/MetaPackages/tree/master/src/Microsoft.AspNetCore 

640?wx_fmt=png

 

最后让大家看看我的 Blog.Core 项目最终的 Services :

640?wx_fmt=png




2、Startup.cs

    public class Startup    {        public Startup(IConfiguration configuration)        {            Configuration = configuration;        }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } }


其实Startup算是程序真正的切入点,是配置服务和中间件的启动类。

Startup 默认构造函数,注入了配置项 IConfiguration。


ConfigureServices方法是用来把services(各种服务, 例如identity, ef, mvc等等包括第三方的, 或者自己写的)加入(register)到container(asp.net core的容器)中去, 并配置这些services. 这个container是用来进行dependency injection的(依赖注入). 所有注入的services(此外还包括一些框架已经注册好的services) 在以后写代码的时候, 都可以将它们注入(inject)进去. 例如上面的Configure方法的参数, app, env, loggerFactory都是注入进去的services.

640?wx_fmt=png

 

Configure 方法是asp.net core程序用来具体指定如何处理每个http请求的, 例如我们可以让这个程序知道我使用mvc来处理http请求, 那就调用 app.UseEndpoints 这个方法就行,这个是一个短路中间件,表示 http 请求到了这里就不往下走了. 

640?wx_fmt=png

 

 

看一看我们项目的最后,Configure方法是如何配置的,这个现在看看就行,以后肯定会让大家都慢慢掌握:



 

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IBlogArticleServices _blogArticleServices)        {
#region ReuestResponseLog
if (Appsettings.app("AppSettings", "Middleware_RequestResponse", "Enabled").ObjToBool()) { app.UseReuestResponseLog();//记录请求与返回数据 }
#endregion
#region Environment if (env.IsDevelopment()) { // 在开发环境中,使用异常页面,这样可以暴露错误堆栈信息,所以不要放在生产环境。 app.UseDeveloperExceptionPage();
//app.Use(async (context, next) => //{ // //这里会多次调用,这里测试一下就行,不要打开注释 // //var blogs =await _blogArticleServices.GetBlogs(); // var processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; // Console.WriteLine(processName); // await next(); //}); } else { app.UseExceptionHandler("/Error"); // 在非开发环境中,使用HTTP严格安全传输(or HSTS) 对于保护web安全是非常重要的。 // 强制实施 HTTPS 在 ASP.NET Core,配合 app.UseHttpsRedirection //app.UseHsts();
} #endregion
#region Swagger app.UseSwagger(); app.UseSwaggerUI(c => { //根据版本名称倒序 遍历展示 typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version => { c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}"); }); // 将swagger首页,设置成我们自定义的页面,记得这个字符串的写法:解决方案名.index.html c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("Blog.Core.index.html");//这里是配合MiniProfiler进行性能监控的,《文章:完美基于AOP的接口性能分析》,如果你不需要,可以暂时先注释掉,不影响大局。 c.RoutePrefix = ""; //路径配置,设置为空,表示直接在根域名(localhost:8001)访问该文件,注意localhost:8001/swagger是访问不到的,去launchSettings.json把launchUrl去掉,如果你想换一个路径,直接写名字即可,比如直接写c.RoutePrefix = "doc"; }); #endregion
#region MiniProfiler app.UseMiniProfiler(); #endregion

#region CORS //跨域第二种方法,使用策略,详细策略信息在ConfigureService中 app.UseCors("LimitRequests");//将 CORS 中间件添加到 web 应用程序管线中, 以允许跨域请求。

#region 跨域第一种版本 //跨域第一种版本,请要ConfigureService中配置服务 services.AddCors(); // app.UseCors(options => options.WithOrigins("http://localhost:8021").AllowAnyHeader() //.AllowAnyMethod()); #endregion
#endregion

// 跳转https //app.UseHttpsRedirection(); // 使用静态文件 app.UseStaticFiles(); // 使用cookie app.UseCookiePolicy(); // 返回错误码 app.UseStatusCodePages();//把错误码返回前台,比如是404


app.UseRouting();
#region 第三步:开启认证中间件
//此授权认证方法已经放弃,请使用下边的官方验证方法。但是如果你还想传User的全局变量,还是可以继续使用中间件,第二种写法//app.UseMiddleware<JwtTokenAuth>(); //app.UseJwtTokenAuth();
//如果你想使用官方认证,必须在上边ConfigureService 中,配置JWT的认证服务 (.AddAuthentication 和 .AddJwtBearer 二者缺一不可) app.UseAuthentication(); #endregion
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapHub<ChatHub>("/api2/chatHub"); });

}


 

3、运行方法

.net core 调试的两种方法


1、通过IIS调试

640?wx_fmt=png

 

2、项目自带的Kestrel web应用调式

640?wx_fmt=png

 

 

 

三、注册并使用MVC


首先,在 ConfigureServices里添加控制器服务,因为我们这里是api项目,所以只需要添加 AddController() 即可,如果是 MVC,可以使用 AddControllersWithViews();


然后在 Configure 中,配置一下中间件:

 app.UseEndpoints(endpoints => {     endpoints.MapControllers(); });


这样就达到了目的,这个不仅仅是 mvc 的开发过程,其他的也都是这样的,以后我们开发其他的,都需要按照这个过程开发即可。


四、核心知识点

1、Routing 路由

路由有两种方式: Convention-based (按约定), attribute-based(基于路由属性配置的). 

其中convention-based (基于约定的) 主要用于MVC (返回View或者Razor Page那种的).

Web api 推荐使用attribute-based.

这种基于属性配置的路由可以配置Controller或者Action级别, uri会根据Http method然后被匹配到一个controller里具体的action上.

常用的Http Method有:

  • Get, 查询, Attribute: HttpGet, 例如: '/api/product', '/api/product/1'

  • POST, 创建, HttpPost, '/api/product'

  • PUT 整体修改更新 HttpPut, '/api/product/1'

  • PATCH 部分更新, HttpPatch, '/api/product/1'

  • DELETE 删除, HttpDelete, '/api/product/1

还有一个Route属性(attribute)也可以用于Controller层, 它可以控制action级的URI前缀.

//以下不是本系列教程,就看思路即可,不用敲代码namespace CoreBackend.Api.Controllers{    //[Route("api/product")]    [Route("api/[controller]")]    public class ProductController: Controller    {        [HttpGet]        public JsonResult GetProducts()        {            return new JsonResult(new List<Product>            {                new Product                {                    Id = 1,                    Name = "牛奶",                    Price = 2.5f                },                new Product                {                    Id = 2,                    Name = "面包",                    Price = 4.5f                }            });        }    }}


使用[Route("api/[controller]")], 它使得整个Controller下面所有action的uri前缀变成了"/api/product", 其中[controller]表示XxxController.cs中的Xxx(其实是小写).

也可以具体指定, [Route("api/product")], 这样做的好处是, 如果ProductController重构以后改名了, 只要不改Route里面的内容, 那么请求的地址不会发生变化.

然后在GetProducts方法上面, 写上HttpGet, 也可以写HttpGet(). 它里面还可以加参数,例如: HttpGet("all"), 那么这个Action的请求的地址就变成了 "/api/product/All".

 

2、内容协商 Content Negotiation

如果 web api提供了多种内容格式, 那么可以通过Accept Header来选择最好的内容返回格式: 例如:

application/json, application/xml等等

如果设定的格式在web api里面没有, 那么web api就会使用默认的格式.

asp.net core 默认提供的是json格式, 也可以配置xml等格式.

目前只考虑 Output formatter, 就是返回的内容格式.

 

如果想输出xml格式,就配置这里:

 640?wx_fmt=png

 

3、创建Post Action

以下不是本系列,就看思路即可,不用敲代码

//以下不是本系列教程,就看思路即可,不用敲代码    [Route("{id}", Name = "GetProduct")]        public IActionResult GetProduct(int id)        {            var product = ProductService...(x => x.Id == id);            if (product == null)            {                return NotFound();            }            return Ok(product);        }
[HttpPost] public IActionResult Post([FromBody] ProductCreation product) { if (product == null) { return BadRequest(); } var maxId = ProductService.Max(x => x.Id); var newProduct = new Product { Id = ++maxId, Name = product.Name, Price = product.Price }; ProductService.Add(newProduct);
return CreatedAtRoute("GetProduct", new { id = newProduct.Id }, newProduct); }


[HttpPost] 表示请求的谓词是Post. 加上Controller的Route前缀, 那么访问这个Action的地址就应该是: 'api/product'

后边也可以跟着自定义的路由地址, 例如 [HttpPost("create")], 那么这个Action的路由地址就应该是: 'api/product/create'.

[FromBody] , 请求的body里面包含着方法需要的实体数据, 方法需要把这个数据Deserialize成ProductCreation, [FromBody]就是干这些活的.

客户端程序可能会发起一个Bad的Request, 导致数据不能被Deserialize, 这时候参数product就会变成null. 所以这是一个客户端发生的错误, 程序为让客户端知道是它引起了错误, 就应该返回一个Bad Request 400 (Bad Request表示客户端引起的错误)的 Status Code.

传递进来的model类型是 ProductCreation, 而我们最终操作的类型是Product, 所以需要进行一个Map操作, 目前还是挨个属性写代码进行Map吧, 以后会改成Automapper.

返回 CreatedAtRoute: 对于POST, 建议的返回Status Code 是 201 (Created), 可以使用CreatedAtRoute这个内置的Helper Method. 它可以返回一个带有地址Header的Response, 这个Location Header将会包含一个URI, 通过这个URI可以找到我们新创建的实体数据. 这里就是指之前写的GetProduct(int id)这个方法. 但是这个Action必须有一个路由的名字才可以引用它, 所以在GetProduct方法上的Route这个attribute里面加上Name="GetProduct", 然后在CreatedAtRoute方法第一个参数写上这个名字就可以了, 尽管进行了引用, 但是Post方法走完的时候并不会调用GetProduct方法. CreatedAtRoute第二个参数就是对应着GetProduct的参数列表, 使用匿名类即可, 最后一个参数是我们刚刚创建的数据实体

运行程序试验一下, 注意需要在Headers里面设置Content-Type: application/json.

4、Validation 验证

针对上面的Post方法,  如果请求没有Body, 参数product就会是null, 这个我们已经判断了; 如果body里面的数据所包含的属性在product中不存在, 那么这个属性就会被忽略.

但是如果body数据的属性有问题, 比如说name没有填写, 或者name太长, 那么在执行action方法的时候就会报错, 这时候框架会自动抛出500异常, 表示是服务器的错误, 这是不对的. 这种错误是由客户端引起的, 所以需要返回400 Bad Request错误.

验证Model/实体, asp.net core 内置可以使用 Data Annotations进行: 

//以下不是本系列教程,就看思路即可,不用敲代码using System;using System.ComponentModel.DataAnnotations;
namespace CoreBackend.Api.Dtos{ public class ProductCreation { [Display(Name = "产品名称")] [Required(ErrorMessage = "{0}是必填项")] // [MinLength(2, ErrorMessage = "{0}的最小长度是{1}")] // [MaxLength(10, ErrorMessage = "{0}的长度不可以超过{1}")]     [StringLength(10, MinimumLength = 2, ErrorMessage = "{0}的长度应该不小于{2}, 不大于{1}")] public string Name { get; set; }
[Display(Name = "价格")] [Range(0, Double.MaxValue, ErrorMessage = "{0}的值必须大于{1}")] public float Price { get; set; } }}


这些Data Annotation (理解为用于验证的注解), 可以在System.ComponentModel.DataAnnotation找到, 例如[Required]表示必填, [MinLength]表示最小长度, [StringLength]可以同时验证最小和最大长度, [Range]表示数值的范围等等很多.

[Display(Name="xxx")]的用处是, 给属性起一个比较友好的名字.

其他的验证注解都有一个属性叫做 ErrorMessage (string), 表示如果验证失败, 就会把ErrorMessage的内容添加到错误结果里面去. 这个ErrorMessage可以使用参数, {0}表示Display的Name属性, {1}表示当前注解的第一个变量, {2}表示当前注解的第二个变量.

在Controller里面添加验证逻辑:

//以下不是本系列教程,就看思路即可,不用敲代码    [HttpPost]        public IActionResult Post([FromBody] ProductCreation product)        {            if (product == null)            {                return BadRequest();            }
if (!ModelState.IsValid) { return BadRequest(ModelState); }
var maxId = ProductService.Max(x => x.Id); var newProduct = new Product { Id = ++maxId, Name = product.Name, Price = product.Price }; ProductService.Add(newProduct);
return CreatedAtRoute("GetProduct", new { id = newProduct.Id }, newProduct); }


ModelState: 是一个Dictionary, 它里面是请求提交到Action的Name和Value的对们, 一个name对应着model的一个属性, 它也包含了一个针对每个提交的属性的错误信息的集合.

每次请求进到Action的时候, 我们在ProductCreationModel添加的那些注解的验证, 就会被检查. 只要其中有一个验证没通过, 那么ModelState.IsValid属性就是False. 可以设置断点查看ModelState里面都有哪些东西.

如果有错误的话, 我们可以把ModelState当作 Bad Request的参数一起返回到前台.

5、PUT请求

put应该用于对model进行完整的更新. 

首先最好还是单独为Put写一个Dto Model, 尽管属性可能都是一样的, 但是也建议这样写, 实在不想写也可以.

ProducModification.cs

    public class ProductModification    {        [Display(Name = "产品名称")]        [Required(ErrorMessage = "{0}是必填项")]        [StringLength(10, MinimumLength = 2, ErrorMessage = "{0}的长度应该不小于{2}, 不大于{1}")]        public string Name { get; set; }
[Display(Name = "价格")] [Range(0, Double.MaxValue, ErrorMessage = "{0}的值必须大于{1}")] public float Price { get; set; } }



然后编写Controller的方法:

//以下不是本系列教程,就看思路即可,不用敲代码    
[HttpPut("{id}")] public IActionResult Put(int id, [FromBody] ProductModification product) { if (product == null) { return BadRequest(); }
if (product.Name == "产品") { ModelState.AddModelError("Name", "产品的名称不可以是'产品'二字"); }
if (!ModelState.IsValid) { return BadRequest(ModelState); }
var model = ProductService.SingleOrDefault(x => x.Id == id); if (model == null) { return NotFound(); } model.Name = product.Name; model.Price = product.Price;
// return Ok(model); return NoContent(); }


按照Http Put的约定, 需要一个id这样的参数, 用于查找现有的model.

由于Put做的是完整的更新, 所以把ProducModification整个Model作为参数.

进来之后, 进行了一套和POST一模一样的验证, 这地方肯定可以改进, 如果验证逻辑比较复杂的话, 到处写同样验证逻辑肯定是不好的, 所以建议使用FluentValidation.

然后, 把ProductModification的属性都映射查询找到给Product, 这个以后用AutoMapper来映射.

返回: PUT建议返回NoContent(), 因为更新是客户端发起的, 客户端已经有了最新的值, 无须服务器再给它传递一次, 当然了, 如果有些值是在后台更新的, 那么也可以使用Ok(xxx)然后把更新后的model作为参数一起传到前台.

 

 

 


五、结语

    好啦,项目搭建就这么愉快的解决了,而且你也应该简单了解了.Net Core API是如何安装,创建,各个文件的意义以及如何运作,如何配置等,但是既然是接口,那一定是要前后端一起进行配置,使用,交流的平台,从上文看出,每次都特别麻烦,而且不直观,UI 不友好,怎么办呢?

    下一节我们就使用一个神器 Swagger,一个快速,轻量级的项目RESTFUL接口的文档在线自动生成+功能测试功能软件。

 

Github && Gitee

https://github.com/anjoy8/Blog.Core.git

 

NOTE

如何不会使用Git,可以参考

https://www.jianshu.com/p/2b666a08a3b5

 

一起学习,一起进步   QQ群:867095512

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样打造一个分布式数据库

本文来自&#xff1a;https://www.infoq.cn/article/how-to-build-a-distributed-database 文章写得很好&#xff0c;备份防丢失 在技术方面&#xff0c;我自己热衷于 Open Source&#xff0c;写了很多 Open Source 的东西&#xff0c;擅长的是 Infrastructure 领域。Infrastru…

向net core 3.0进击——Swagger的改变

前言十一小长假在不知不觉间可都没了&#xff0c;在这个小尾巴的空隙&#xff0c;把这两天鼓捣的net core 3.0升级过程记录一下&#xff0c;首先还是根据之前的顺序一个个补充进来&#xff0c;先从Swagger的变化说起&#xff08;新建工程什么的不多说了&#xff0c;就是选择的时…

Dubbo——面试问题集(1~3)

1、默认使用的是什么通信框架&#xff0c;还有别的选择吗? Dubbo默认使用netty&#xff0c;还支持mina, grizzy 配置方式&#xff1a; <dubbo:protocol name“dubbo” port“9090” server“netty” client“netty” codec“dubbo” serialization“hessian2” charset…

Dubbo——面试问题集(4~14)

4、默认使用什么序列化框架&#xff0c;你知道的还有哪些&#xff1f; 在Dubbo RPC中&#xff0c;同时支持多种序列化方式&#xff1a; dubbo序列化&#xff0c;阿里尚不成熟的java序列化实现。 hessian2序列化&#xff1a;hessian是一种跨语言的高效二进制的序列化方式&…

向net core 3.0进击——April.WebApi从2.2爬到3.0

前言在之前对Swagger的变化做了调整后&#xff0c;就开始想着要不把之前的工程升级得了&#xff0c;这样就还是个demo工程&#xff0c;来做各种测试&#xff08;当然还是因为懒&#xff09;&#xff0c;这就有了今天这个比较折腾的一步。升级之路首先&#xff0c;April.WebApi工…

共识与拜占庭将军问题

1、共识基础 人们对共识机制的研究其实由来已久&#xff0c;从上世纪70年代就开始了相关研究&#xff0c;其目的是为了解决分布式系统中的一致性问题。Fischer, Lynch 和 Patterson在1985年发表的论文中提出了可以说是最重要的分布式系统定理&#xff1a;FLP不可能定理&#x…

C#刷遍Leetcode面试题系列连载(2): No.38 - 报数

前言前文传送门&#xff1a;上篇文章中我们主要科普了刷 LeetCode 对大家的作用&#xff0c;今天咱们就正式进行 LeetCode 算法题分析。很多人都知道计算机中有种思想叫 递归&#xff0c;相应地也出现了很多算法。解决递归问题的要点有如下几个:找出递归的关系比如&#xff0c;…

Bumblebee微服务网关之负载策略

作为一个微服务网关&#xff0c;提供不同负载策略配置是一项非常重要的主要功能&#xff1b;在这方向Bumblebee提供了非常好的支持。Bumblebee可以针对不同路径制定各自的负载策略&#xff0c;更重要的是这些调整都可以在网关运行过程动态调整&#xff01;动态策略调整可以更好…

FastDFS分布式文件系统设计原理

FastDFS是一个开源的轻量级分布式文件系统&#xff0c;由跟踪服务器&#xff08;tracker server&#xff09;、存储服务器&#xff08;storage server&#xff09;和客户端&#xff08;client&#xff09;三个部分组成&#xff0c;主要解决了海量数据存储问题&#xff0c;特别适…

14年百度深度学习校招题目

一、简答题1.深度神经网络目前有哪些成功的应用&#xff1f;简述原因。(10分) 2.列举不同进程共享数据的方式&#xff08;至少三种&#xff09;。(10分) 3.对于N个样本&#xff0c;每个样本为D维向量&#xff0c;采用欧式距离使用KNN做类预测。(10分) 1).给出预测时间复杂度。 …

HDFS分布式文件系统设计原理

Hadoop分布式文件系统(HDFS)是一种被设计成适合运行在通用硬件上的分布式文件系统。HDFS是一个高度容错性的系统&#xff0c;适合部署在廉价的机器上。它能提供高吞吐量的数据访问&#xff0c;非常适合大规模数据集上的应用。要理解HDFS的内部工作原理&#xff0c;首先要理解什…

Magicodes.IE已支持导出Word、Pdf和Html

关于Magicodes.IE导入导出通用库&#xff0c;通过导入导出DTO模型来控制导入和导出&#xff0c;支持Excel、Word、Pdf和Html。GitHub地址&#xff1a;https://github.com/xin-lai/Magicodes.IE特点需配合相关导入导出的DTO模型使用&#xff0c;支持通过DTO以及相关特性控制导入…

AOP框架Dora.Interception 3.0 [1]: 编程体验

.NET Core正式发布之后&#xff0c;我为.NET Core度身定制的AOP框架Dora.Interception也升级到3.0。这个版本除了升级底层类库&#xff08;.NET Standard 2.1&#xff09;之外&#xff0c;我还对它进行大范围的重构甚至重新设计。这次重构大部分是在做减法&#xff0c;其目的在…

分布式缓存——一致性哈希算法

本文主要来自&#xff1a;http://www.zsythink.net/archives/1182 摘录防丢失 一致性哈希算法定义 一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希&#xff08;DHT&#xff09;实现算法&#xff0c;设计目标是为了解决因特网中的热点(Hot spot)问题&#xff0c;初…

H264学习_基本数据结构

&#xfeff;&#xfeff;原文地址:http://blog.csdn.net/yangzhongxuan/article/details/8003494 名词解释 场和帧 &#xff1a; 视频的一场或一帧可用来产生一个编码图像。在电视中&#xff0c;为减少大面积闪烁现象&#xff0c;把一帧分成两个隔行的场。 片&#xff1a…

【巴马火麻茶】调节三高、治疗失眠、排毒减肥,轻松get长寿的秘密!

水&#xff0c;无色无味&#xff0c;是人类的生命源泉对于长期坐办公室的程序员朋友来说每日都得喝水但又觉得寡淡的白开水缺少点乐趣于是&#xff0c;茶叶就成了大家泡水的首选今天&#xff0c;队长要为大家介绍一款养生好茶巴马火麻茶每天一杯&#xff0c;轻松get长寿的秘密火…

「合规」震惊!地图可视化竟能如此玩,零门槛,全免费,效果远胜主流作图工具!...

在数据可视化领域&#xff0c;早晚会遇上地图可视化的需求&#xff0c;一个高大上的地图可视化&#xff0c;瞬间拔高整个报告的层次。Excel催化剂有幸接触并将地图可视化完全落地于Excel中完成。相对主流Python、R、PowerBI等作图工具&#xff0c;在易用性、灵活性和功能的强大…

Opencv SVM demo

&#xfeff;&#xfeff;转载自http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html 支持向量机 (SVM) 是一个类分类器&#xff0c;正式的定义是一个能够将不同类样本在样本空间分隔的超平面。 换句话说&#xff…

BeetleX之FastHttpApi服务使用详解

BeetleX是一个轻量级高性能的开源TCP通讯应用框架&#xff0c;通过BeetleX可以轻松扩展不同场的TCP应用服务和客户端组件。框架开源地址:https://github.com/IKende/BeetleX组件特点高性能TCP通讯组件,轻易实现百万级RPS通讯交互提供完善的会话管理机制和协议分析规则提供简洁的…

康威定律

本文来自&#xff1a;http://www.dockone.io/article/2691 1、概述 微服务架构是一种非常流行的新概念&#xff0c;即便可供以借鉴的经验比较少&#xff0c;当然不能阻挡它成为热门话题与研究对象。 令人惊讶地是&#xff0c;其实微服务的概念早在五十多年前就已经被提出&…