如鹏网net微服务课件_第1页
如鹏网net微服务课件_第2页
如鹏网net微服务课件_第3页
如鹏网net微服务课件_第4页
如鹏网net微服务课件_第5页
免费预览已结束,剩余67页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

网《.NetCore微服务》本课件为网《.Net微服务》课程的配套资料,课件可以在不修改内容的情况下自由。课件著作权归“信息科技”所有,授权用于等目的。配套课程 网本次课程的将会全部捐献给.NetCore微服务相关开源社区讲的可能都是错的,欢迎讨论,谩骂。2、本课程适合哪些人ASP.NetMVC项目开发但是不熟悉微服务的开发者,特别是如果您还是.Net初学者或者没有项目开发经验,请报名就业4、本课程不讲什么本课程主要目的是全面讲解“微服务”,会讲解涉及到的.NetCore基础,即使您不熟悉.NetCore也可以学习,但是不会深入讲解.NetCore细节。网.Net提高班系统讲解了.NetCore等技术。dentityServer的其他内容。最佳用法、Ocelot+Consul你根据需要写到配置中即可;没有对参数做校验等。8、开发工具:VS2017+,安装.NetCore2.1+插件(https:/ .NetCore微服务选 .NetCore基 一 .Net跨平台历 二 三 四 五 六 一 二 .NetCore连接 三 四 服务Consul及注 五 一 二 Polly简 三 Polly简单使 四 五 六 七 八 Polly的异步用 九 AOP框架基 十 十一 十二 Ocelot网 一 Ocelot基本配 二 三 JWT算 一 JWT简 二 .Net中使用JWT算 一 二 三 四 五 一 二 三 四 五 什么是微服务架构?第一代微服务:Dubbo(Java)、Orleans(.Net)等;第二代微服务:SpringCloud等;第三代微服务:ServiceMesh(ServiceFabric、Istio、Conduit等)。第一代微服务和语言绑定紧密;第.NetCore用来实现微服务更方便,而且.NetCore可以跨平台。是开发体验没有JavaJavaZuul等的时候还可能需要写一些Java代码。也可以使用Java开发。但是目前开源的版本还不太适合普通厂商使用(难度;跨平台;通果想搭建SF私有云,慎用。如果选择.NetCore技术栈的第二代微服务框架,推荐使用腾讯(支付网关)在使用架构:Consul+Ocelot+.NetCore+Polly+……。注意腾讯只是一部分系统是使用.NetCore腾讯的.Net大队长张善友把腾讯的架构实战整理出一个开源项目 供我们参考,所以我这次课就是参考NanoFabric帮大家自己搭建其中最的部分。SpringCloud中:EurekaServer做服务治理和服务发现、Hystrix做熔断降级、Zuul做NanoFabric中:Consul做服务治理和服务发现、Polly做熔断降级、Ocelot做网关;强。技术有Thrift、gRPC等。.NetCore一、.Njava一样跨平台的,.netframeworkwindows下运行的,大部分类是可以兼容移植到linux下的,但是没人做这个工作。2001年为Gnome寻找桌面开发技术,在研究了微软的.netframeworkmononovell公司ios游戏的技术)的基础。2016monoxamarinmono,还要搞出来一个.netcoremono完全兼容.netframework,架构太陈旧,不有利于现在云计算、集群等现在新的架构理念。因此微软重写了.netframework、.netcore、framework、.netcore、xamarin有通用的类,也有特有的。为了保证代码通用,微软定义了公共的.NetStandardLibrary(.net标准库,像FileStream、List等这些),按照.NetStandardLibrary编写的代码可以在几个平台下通用。如何判断dll是否支持.netcore,举例:、.netcoreWindows在开发环境发布,然后把发布包上传到服务器,然后到下执行“dotnetdll”即可。.Netcore时代“命令行”才是正道,不要还是想着“傻瓜化图形化界面”3、https是保证在不安全网络环境下通讯安全的必要的步骤。从.Netcore2.1开始默认启用ASP.NetCore令行指定Web应用的端口(默认5000)可以通过设置临时环境变量ASPNETCORE_URLS来改变默认的端口、,也就是执行修改配置文件、server.urls等其他方式,但是这种方式启动多个实例更方便。如果需要在程序中端口、(后续服务治理会用到),用ASPNETCORE_URLS环{return}{Stringip=config["ip"];Stringport=config["port"];}.NetCoreIIS运行了。后续课程中统一用.NetCore内置WebAPIWebAPIRestfuljson格式,虽然请求也可以是表单格式,json(contenttype=application/json)的方法体:和.NetFrameworkWeb不一样,如果[HttpPost]、[HttpGet]等标记不加参数,则表示匹正确:publicvoidSend_HW(SendSMSRequestmodel)3)错误:publicvoidSend_LX(stringphoneNum,stringmsg)usingusing{publicclassController:{publicvoidSend_ Request{}{}publicvoidSend_ Request{}}publicclassSend{publicstring {get;set;}publicstringTitle{get;set;}publicstringBody{get;set;}}} {{{publicclassSMSController:{{ ine($"通过小米接口向{model.phoneNum} }{ ine($"通过联想接口向{model.PhoneNum} }{ ine($"通过接口向{model.PhoneNum} }}publicclass{publicstringPhoneNum{get;set;}publicstringMsg{get;set;}}}usingSystem.Linq;using{publicclassProductController:privatestaticList<ProductproductsnewList<Product>();staticProductController(){products.Add(newProductId=1,Name="T430笔记本",Price=8888,Description="CPUi7标products.Add(newProduct{Id=2,Name="Mate10",Price=3888,Description="大猩猩屏幕,多点触摸"});products.Add(newProductId3,Name天梭手表Price9888,Description经典款,可好了}{return}publicProductGet(int{varproduct=products.SingleOrDefault(p=>p.Id==id);{}return}publicvoidAdd(Product{{}}publicvoidDelete(intid)varproduct=products.SingleOrDefault(p=>p.Id==id);if(product!=null){}}}}usingusingSystem.Linq;using{publicclass{publiclongId{get;set;}publicstringName{get;set;}publicdoublePrice{get;set;publicstringDescription{get;set;}}六、.NetCore 网.NetConsul服务治理发现Consul([ˈkɒnsl],康搜)是中心,服务提供者、服务消费者等都要到一、consulconsul地址consul.exeagent-dev开发环境中consul重启后数据就会丢失。.NetCore三、Rest再提供一个HealthController.cs{{return}}四、服务Consul及注publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv,IApplicationLifetime{if{}stringip=intport=stringserviceName=stringserviceId=serviceName+Guid.NewGuid();using(varclient=newConsulClient(ConsulConfig)){{ID=serviceId,//服务,不能重复,用Guid最简Address=ip,//ip地址(可以被其他应用的地址,本地测试可以Port=port,//端口Check=new{DeregisterCriticalServiceAfter=TimeSpan.FromSeconds(5),//=HTTP$"http://{ip}:{port}/api/health",//健康检查地址Timeout=TimeSpan.FromSeconds(5)}}//程序正常退出的时候从Consul//要通过方法参数注入IApplicationLifetimeusing(varclient=new{}}{ enter=}是服务名字、ip地址、端,具体服务怎么实现、怎么调用Consul不管。注意不同实例一定要用不同的Id,即使是相同服务的不同实例也要用不同的Id,上面GuidIdName。Address、Port是供服务消是正常的。服务正常结束(Ctrl+C)会触发ApplicationStopped,正常注销。即使结束也没关系,Consul健康检查过一会发现服务器死掉后也会主动注销。服务只会ip、端口,consul只会保存服务名、ip、端口这些信息,至于服务提供什么接口、方法、参数,consul不管,需要消费者知道服务的这些细节。{varservices=consulClient.Agent.Services().Result.Response;foreach(varserviceinservices.Values){}}{varservices=.Where(s=>s.Service.Equals("MsgService", {}{

}} 地址: Nuget地址:usingusing{//////publicclass{/////////publicHttpStatusCodeStatusCode{get;set;//////响应的报文///publicHttpResponseHeadersHeaders{get;set;}}{/// //////<typeparam{//////响应报文体json反序列化的///publicTBody{get;set;}}usingSystem;usingSystem.Linq;usingSystem.Threading.Tasks;{//////按照客户端负载均衡算法解析为这样的真///publicclass{publicStringConsulServerUrl{get;set;}="";privateHttpClienthttpClient;{}////////////<param///<param///{ {varservices=(await if{例}}

}{}

thrownewArgumentException($"找不到服务{serviceName} return$"{service.Address}:{service.Port}";//把转换为privateasynk<String>ResolveUrlAsync(String{Uriuri=newStringserviceName=StringrealRootUrl=awaitResolveRootUrlAsync(serviceNamereturnuri.Scheme+"://"+realRootUrl+uri.PathAndQuery;}//////Get////// HttpRequestHeadersrequestHeaders=null){{{foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); }}

//////Post//////<paramname="body">请求数据,将会被json///public {{{foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); }}//////Post//////publicasynk<RestResponse>PostAsync(Stringurl,objectbody=null,HttpRequestHeadersrequestHeaders=null){{{foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); varresp=awaidAsync(requestMsg);returnresp;}}

//////Put//////<paramname="body">请求数据,将会被json///public {{if(requestHeaders!={foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); }}

//////Put//////<paramname="body">请求数据,将会被json/// {{{foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); varresp=awaidAsync(requestMsg);returnresp;}}//////Delete//////publicasyn k<RestResponseWithBody<T>>DeleteForEntityAsync<T>(Stringurl,HttpRequestHeadersrequestHeaders=null){{{foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url)); }}//////Delete///}}/// requestHeaders=null){{if(requestHeaders!={foreach(varheaderin{}}//转换为requestMsg.RequestUri=newUri(awaitResolveUrlAsync(url));varresp=awaidAsync(requestMsg);return}}//////Http////// SendForEntityAsync<T>(HttpRequestMessagerequestMsg){varresult=awaithttpCliendAsync(requestMsg);RestResponseWithBody<T>respEntity=newRestResponseWithBody<T>();respEntity.StatusCode=result.StatusCode;{}//////Http//////{varresult=awaithttpCliendAsync(requestMsg);RestResponseresponse=newRestResponse();response.StatusCode=result.StatusCode;response.Headers=result.Headers;}}}usingRestTemplateCore;usingSystem;using{class{staticvoidMain(string[]{using(HttpClienthttpClient=new{RestTemplaterest=new varret1={foreach(varpin{} ProductnewP=newProduct();newP.Id=888;newP.Name辛增";newP.Price=88.8;varret=rest.PostAsync("",newP).Result;}}class{publiclongId{get;set;}publicstringName{get;set;}publicdoublePrice{get;set;publicstringDescription{get;set;}}}1).NetCore2.1中新增的管理HttpClient实例的 html后面综合应用中再使用熔断、降级等二、Polly.NetCore中有一个被.Net认可的库Polly,可以用来简化熔断降级的处理。主要 Install-PackagePolly-Version6.0.1作”包括FallBack(降级)、重试(Retry)、熔断(Circuit-breaker)等。Polly也支持请求缓存“数据不变化则不重复自行代码”,但是和新版本兼容不好,而三、PollyPolicypolicy=.HandleArgumentException{thrownewArgumentException("oworld!"); Policypolicy=.Handle<ArgumentException>()//故{},ex=> policy.Execute(()thrownewArgumentException("oworld!"); Policy<string>policy=.Handle<Exception>()//故{

return"降级的值";stringvalue=policy.Execute((){Console.Wriine("开始任务");thrownewException("oworld!");return"正常的值";四、重试处理Policypolicy=policy.Execute(()=>{if(DateTime.Now.Second%10!={thrownewException("出错}Retry()是重试最多一次;Retry(n)五 短路保护CircuitPolicypolicy={{policy.Execute(()thrownewException("出错"); }{}}六、策略封装policy3=七、超时处理Policypolicy=.Fallback(()=>{Console.Wriine("执行出错");});//这样不行policy.Execute(()=>{thrownewArgumentException("oworld!"); PolicypolicyPolicy.Timeout(3TimeoutStrategy.Pessimistic创建一个3秒钟(注意Policypolicy= .Fallback((){policy=policy.Wrap(Policy.Timeout(2,TimeoutStrategy.Pessimistic));policy.Execute(()=>{

Policypolicy=policy=policy.Wrap(Policy.Timeout(3,TimeoutStrategy.Pessimistic));policy.Execute(()=>{ 八、PollyPolicy<byte[]>policy=.FallbackAsync(asynccreturnnewbyte[0];},asyncr=> policy=policy.WrapAsync(Policy.TimeoutAsync(20,TimeoutStrategy.Pessimistic,async(context,timespan,task)=>{varbytes=awaitpolicy.ExecuteAsync(async(){Console.Wriine("开始任务");HttpClienthttpClientnewHttpClient();varresult=await returnresult;Policypolicy=.FallbackAsync(asyncc policy=policy.WrapAsync(Policy.TimeoutAsync(3,TimeoutStrategy.Pessimistic,async(context,timespan,task)=>{awaitpolicy.ExecuteAsync(async()九、AOPAspectCore(国产,动态织入),其他要不就是不支持.NetCore,要不就是不支持对异步方法。MVC Install-PackageAspectCore.Core1、编写器 publicclassCustomInterceptorAttribute {publicasyncoverrideTaskInvoke(AspectContextcontext,AspectDelegate{{}

Console.Wriine("Beforeservicecall");awaitnext(context);//执行被 catch{Console.Wriine("Servicethrewanexception!");}{}}}publicclass{publicvirtualvoidSay(string{Console.Wriine("service}}3、通过AspectCore创建对ProxyGeneratorBuilderproxyGeneratorBuilder=newProxyGeneratorBuilder();using(IProxyGeneratorproxyGenerator=proxyGeneratorBuilder.Build()){p=proxyGenerator.CreateClassProxy<>(); }注意p指向的对象是AspectCore生成的的动态子类的对象,直接new是无法publicclass{ publicvirtualasynk<string>oAsync(string{return"ok";}public k<string>oFallBackAsync(string{return"fail";}}当oAsync执行出错的时候执行oFallBackAsync方法 usingAspectCore.DynamicProxy;usingSystem;usingnamespace{public mandAttribute { {this.FallBackMethod=}publicstringFallBackMethod{get;set;publicoverrideasynkInvoke(AspectContextcontext,AspectDelegate{{}

awaitnext(context);//执行 catch(Exception{//context.Implementation实际执行的对象//context.Parameters方法参数//如果执行失败,则执行 ObjectfallBackResult=fallBackMethod.Invoke(context.Implementation,context.ReturnValue=}}}}publicclass//需要public{ publicvirtualasynk<string>oAsync(stringname)//需要是虚方{Strings=null;//s.ToString();return"ok";}publicasynk<string>oFallBackAsync(string{return"fail";} publicvirtualintAdd(inti,intj){Strings=//s.ToArray();returni+}publicintAddFall(inti,int{return}}ProxyGeneratorBuilderproxyGeneratorBuilder=newProxyGeneratorBuilder();using(IProxyGeneratorproxyGenerator=proxyGeneratorBuilder.Build()){p=proxyGenerator.CreateClassProxy<>();Console.Wriine(p.Add(1,2));} mand]并且 public //需要public{ publicvirtual k<string>oAsync(stringname)//需要是虚方{ o"+name);Strings=null;return"ok";} publicvirtualasynk<string>o1FallBackAsync(string{ o降级1"+name);Strings=null;return"fail_1";}publicvirtualasynk<string>o2FallBackAsync(string{ ine("o降级2"+return} publicvirtualintAdd(inti,intj){Strings=null;returni+j;}publicintAddFall(inti,int{return}}十一、细化框架 Nuget地址:现允许错误几次,MillisecondsOfBreak表示熔断多长时间(毫秒);超时:TimeOutMilliseconds执行超过多少毫秒则认为超时(0表示测超时Install-Package.Extensions.Caching.MemoryusingusingAspectCore.DynamicProxy;usingSystem.Threading.Tasks;usingPolly;namespace{public mandAttribute {//////最多重试几0///publicintMaxRetryTimes{get;set;}=//////publicintRetryIntervalMilliseconds{get;set;}=///是否///publicboolEnableCircuitBreaker{get;set;}=///熔断前出现///publicintExceptionsAllowedBeforeBreaking{get;set;}=///熔断多长时间(毫秒///publicintMillisecondsOfBreak{get;set;}=//////执行超过多少毫秒则认为超时(0表示测超时///publicintTimeOutMilliseconds{get;set;}=

//////缓存多少毫秒(0表示不缓存),用“类名+方法名+所有参数ToString拼接”做缓///publicintCacheTTLMilliseconds{get;set;}=0;privatePolicypolicy; /////////<paramname="fallBackMethod">降级的方法名</param> {this.FallBackMethod=}publicstringFallBackMethod{get;set;publicoverrideasynkInvoke(AspectContextcontext,AspectDelegate{ mand中保持一个policy对象即//其实主要是CircuitBreaker要求对于同一段代码要共个policy对 mandAttribute对象,天然的一个policy对象享//因为同一个方法共个policy,因此这个CircuitBreaker是针对所有请求的//Attribute也不会在运行时再去改变属性的值,共享同一个policylock(this)//因为Invoke可能是并发调用,因此要确保policy赋值的线程安{if(policy=={policy=.FallbackAsync(async(ctx,t){ fallBackMethod.Invoke(context.Implementation,context.Parameters);//不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke时候context

//还是第一次的对象,所以要通过Polly的上下文来传递//context.ReturnValue=fallBackResult;aspectContext.ReturnValue=fallBackResult;},async(ex,t)=>{if(MaxRetryTimes>{ }if{ Breaking,TimeSpan.FromMilliseconds(MillisecondsOfBreak)));}if(TimeOutMilliseconds>{ }}}

//把本地调用的AspectContextPolly,主要给FallbackAsync中使ContextpollyCtx=newContext();pollyCtx["aspectContext"]=context;//Install-Package.Extensions.Caching.Memoryif(CacheTTLMilliseconds>0){//用类名+方法名+参数的下划线连接起来作为缓存 context.ServiceMethod+string.Join("_",

ifmemoryCache.TryGetValue(cacheKey,outvar{}{

context.ReturnValue=awaitpolicy.ExecuteAsync(ctx=>next(context),using(varcacheEntry={cacheEntry.Value=context.ReturnValue; }}}{awaitpolicy.ExecuteAsync(ctx=>next(context),}}}}todo:要测试在webapi和控制台中是否可以十二、结合core再自己调用ProxyGeneratorBuilder进行类对象的注入了。Install-Package修改Startup.csConfigureServices返回值从void改为using{return} 注 在Controller中就可以通过构造函数进行依赖注入了:publicclassValuesController:{privatepublicValuesController({this.p=}}当然要通过反射扫描所有Service类,只要类中有标记了CustomInterceptorAttribute的方法都算RegisterServices还是手动指定从哪个程序{returnservices.BuildAspectCoreServiceProvider();}privatestaticvoidRegisterServices(Assemblyasm,IServiceCollection{//遍历程序集中的所有publicforeach(Typetypein{//判断类中是否有标注了CustomInterceptorAttribute的方boolhasCustomInterceptorAttr=.Any(m=>m.GetCustomAttribute(typeof(CustomInterceptorAttribute))!=null);if(hasCustomInterceptorAttr){}}}Ocelot网关对于在微服务体系中、和Consul通讯的微服务来讲,使用服务名即可。但是对于手机、web端等外部者仍然需要和N多服务器交互,需要他们的服务器地址、端ocelot中文文档: 一、Ocelot建一个空的core项目。Install-Package 下创建ReRoutes下就是多个路由规{"ReRoutes":{"DownstreamPathTemplate":"/api/{url}","DownstreamScheme":"http","DownstreamHostAndPorts":[{"Host":"localhost","Port":5001}"UpstreamPathTemplate":"/MsgService/{url}","UpstreamHttpMethod":["Get","Post"]{"DownstreamPathTemplate":"/api/{url}","DownstreamScheme":"http","DownstreamHostAndPorts":[{"Host":"localhost","Port":5003}"UpstreamHttpMethod":["Get","Post"]}]}这样当MsgService/Send?msg=aaa的时候就会Program.cs的CreateWebHostBuilder.ConfigureAppConfiguration((hostingContext,builder){builder.AddJsonFile("Ocelot.json",false,在 {}publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironment{if{}}二、{{"DownstreamPathTemplate":"/api/{url}","DownstreamScheme":"http","UpstreamPathTemplate":"/MsgService/{url}","UpstreamHttpMethod":["Get","Post"],"ServiceName":"MsgService","LoadBalancerOptions":{"UseServiceDiscovery":}{{"Host":"localhost","Port":8500}}}有多个服务就ReRoutes下面配

即可,请求报文体发的路径是"/api/{url}"。LoadBalancerOptions中"LeastConnection"表示负载均衡算法是“选是Consul服务器的配置。 、 Fabric中的服务()三、Ocelot文档:比如我调用的api开发了一个版,clientid是rpwb,然后限制钟之内,不能累计超过1000次。目前开放式api的限流都是这个套路。geturlJWT一、JWTRestfulapp等使用的接口,则需要Restful接口不是web,App中很难直接处理SessionId,而且有跨域的WebSessionSession的等静态文件处理服务器上校验权限;每次都要根据SessionIdRedis服务器获取用户信息,JWT(JsonWebToken)Restful接口进行验证的机制的基础。JWTJWT字符串中,用户信息部分是明文的,再加上一部分签才能解析。用户端只是、转发这个JWT字符串。如果客户端篡改了明文部分,那么部分约等于是明文的,因此不能在 PayloadPayloadSignaturenginx、CDNJWT二、.NetJWTvarpayload=newDictionary<string,{{"UserId",123{"UserName","admin"IJwtAlgorithmalgorithm=newHMACSHA256Algorithm();IJsonSerializerserializer=newJsonNetSerializer();IBase64UrlEncoderurlEncoder=newJwtBase64UrlEncoder();vartoken=encoder.Encode(payload,secret);2) {IJsonSerializerserializer=newJsonNetSerializer();IDateTimeProviderprovider=newUtcDateTimeProvider();IBase64UrlEncoderurlEncoder=newvarjson=decoder.Decode(token,secret,verify:true);}{}catch{}catch{}doubleexp= ow.AddSeconds(10)-newDateTime(1970,1,不用秘钥解析数据因为payload部分是明文的,所以在不知道秘钥的时候也可以用Decode、DecodeToObject等不需要秘钥的方法把payload部分解析出来。 {IJsonSerializerserializer=newJsonNetSerializer();IDateTimeProviderprovider=newUtcDateTimeProvider();IJwtValidatorvalidator=newJwtValidator(serializer,provider);IBase64UrlEncoderurlEncoder=newJwtBase64UrlEncoder();IJwtDecoderdecoder=newJwtDecoder(serializer,validator,varjson=decoder.Decode(token);}catch{}catch{Console.Wriine("Tokenhas}Ocelot+Identity一、相关概念API客户端(Client):Client就是android客户端、ios客户端、第identityserver新建一个空的webID4.IdServerInstall-PackageIdentityServer4usingIdentityServer4.Models;namespace{publicclass{///返回//////publicstaticIEnumerable<ApiResource>{List<ApiResource>resources=newresources.Add(newApiResource("MsgAPI消息服务API"));resources.Add(newApiResource("ProductAPI",产品API"));returnresources;}///返回//////publicstaticIEnumerable<Client>{List<Client>clients=newList<Client>();clients.Add(newClient{ClientId="clientPC1",//API账号、客户端IdAllowedGrantTypesGrantTypes.ClientCredentials,ClientSecrets={newSecret("123321".Sha256())//秘AllowedScopes={"MsgAPI","ProductAPI"}//这个账号支持哪些应return}}}修改{}{},发Post请求,表单请求内容(注意不是报文头 OcelotWebID4.Ocelot1{{"DownstreamPathTemplate":"/api/{url}","DownstreamScheme":"http","UpstreamPathTemplate":"/MsgService/{url}","UpstreamHttpMethod":["Get","Post"],"ServiceName":"MsgService","LoadBalancerOptions":{"UseServiceDiscovery":true,"AuthenticationOptions":{"AuthenticationProviderKey":"MsgKey","AllowedScopes":[]}{"DownstreamPathTemplate":"/api/{url}","DownstreamScheme":"http","UpstreamPathTemplate":"/ProductService/{url}","UpstreamHttpMethod":["Get","Post"],"ServiceName":"ProductService","LoadBalancerOptions":{"UseServiceDiscovery":true,"AuthenticationOptions":{"AuthenticationProviderKey":"ProductKey","AllowedScopes":[]}}{{"Host":"localhost","Port":8500}}}把/MsgService的都转给消息后端服务器(使用Consul进行服务发现)。也可以把IdentityServerOcelot,但是我们不做,后边会讲为什么不放。{usingusing.AspNetCore.Builder;using usingOcelot.DependencyInjection;using{publicclass{publicvoidConfigureServices(IServiceCollection{{o.Authority="o.ApiNameMsgAPI";//要连接的应用的名字o.RequireHttpsMetadata=false;o.SupportedTokens=SupportedTokens.Both;o.ApiSecret="123321";//秘钥.AddIdentityServerAuthentication("MsgKey",.AddIdentityServerAuthentication("ProductKey",isaOpt);}//Thismethodgetscalledbytheruntime.UsethismethodtoconfiguretheHTTPrequestpipeline.publicvoidConfigure(IApplicationBuilderapp,IHostingEnvironmentenv){if{}}}} Server传json数据),在请求头(不是报文体)里加上:OcelotAuthorizationIJwtDecoder的这个不传递keyIDictionary<string,object>DecodeToObject(stringtoken),就可以在不验证的情况下获取client_id等信息。然这个服务器也要经过Ocelot转发。五、用户名登如果Api和用户名、无关,那么上面那样做就可以了,但是有时候需要用户验1ID4.IdServer项目中usingIdentityServer4.Models;usingSystem.Linq;using{publicclassProfileService:{publicasynkGetProfileDataAsync(ProfileDataReqontext{varclaims=context.Subject.Claims.ToList();context.IssuedClaims=claims.ToList();}{}}}usingIdentityServer4.Models;usingSystem.Security.Claims;usingSystem.Threading.Tasks;{{publicasynkValidateAsync(ResourceOwnerPasswordValidationContext{if(context.UserName=="yzk"&&context.Password=="123"){context.Result=newGrantValidationResult(subject:context.UserName,claimsnewClaim[]{newClaim("Name",context.UserName),newClaim("UserId","111"),newClaim("RealName","杨"),newClaim(""," ")});}{context.Result=newGrantValidationResult(TokenRequestErrors.InvalidGrant,"invalidcustomcredential");}}}}修改后的usingIdentityServer4;using{publicclass{//////返回应用列//////{List<ApiResource>resources=newresources.Add(newApiResource("MsgAPI消息服务API"));resources.Add(newApiResource("ProductAPI","产品API"));returnresources;}//////返回账号列//////{List<Client>clients=newList<Client>();clients.Add(newClient{ClientId="clientPC1",//API账号、客户端IdAllowedGrantTypesGrantTypes.ResourceOwnerPassword,ClientSecrets={newSecret("123321".Sha256())//秘AllowedScopes={"MsgAPI",// }//这个账号支持哪些应return}}}{varidResources=new{new}主要是增加了AddInMemoryIdentityResourcesAddResourceOwnerValidator然后Startup.cs的ConfigureServices中增加.AddIdentityServerAuthentication(options{options.Authority="";options.RequireHttpsMetadata=false; 中就可以获取到ResourceOwnerPasswordValidator中为用户设置的claims等信息了。publicvoidSend_MI(dynamicmodel){stringuserId=string=this.User.FindFirst("").Value; }开发一个服务应用LoginServicepublicclass{publicstringusername{get;set;}publicstringpassword{get;set;}usingSystem.Net.Http;usingSystem.Threading.Tasks; {publicclassLoginController:{publicasynk<ActionResult>RequestToken(RequestTokenParam{Dictionary<string,string>dict=newDictionary<string,string>();dict["client_id"]="clientPC1";dict["client_secret"]="123321";dict["grant_type"]="password";dict["username"]=model.username;dict["password"]=model.password;using(HttpClienthttp=newusing(varcontent=new{varmsg=awaithttp.PostAsync("",content);stringresult=awaitmsg.Content.ReadAsStringAsync();}}}}LoginService/api/Login/json报文体 Thrift高效通讯Restful采用Http进行通讯,优点是开放、标准、简单、兼容性升级容易;缺点是性能TCP通讯,所以通常性能更好。.NetCore下的RPC(方法调用)框架有gRPC、Thrift等,可以类比.Net的特点有关,不谈业务场景、业务数据的性能测试都是“参考”。并不是gRPC,并不是Http不好,没有好与坏。客户端就要更

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论