Dapr + .NET Core实战(二) 服务调用

服务调用是什么

在分布式应用程序中的服务之间进行调用会涉及到许多挑战。例如:

  • 维护其他服务的地址

  • 如何安全地调用服务。

  • 在发生短暂的 暂时性错误 时如何处理重试

  • 分布式应用程序调用链路追踪

服务调用构建块通过使用 Dapr 挎斗作为服务的 反向代理 来解决这些难题。

工作原理

f0d339c469399afbe4a66b063f8f3b10.png

由于调用经过Sidecar,Dapr 可以注入一些有其他行为:

  • 失败时自动重试调用。

  • 通过相互 (mTLS) 身份验证(包括自动证书滚动更新),在服务之间进行调用。

  • 使用访问控制策略控制客户端可以执行的操作。

  • 捕获服务间所有调用的跟踪和指标,以提供分布式调用链路追踪与诊断。

任何应用程序都可以通过使用 Dapr 中内置的本机 Invoke API 来调用 Dapr Sidecar。可以通过 HTTP 或 gRPC 调用 API。使用以下 URL 调用 HTTP API:

http://localhost:<dapr-port>/v1.0/invoke/<application-id>/method/<method-name>
  • <dapr-port> Dapr 正在侦听的 HTTP 端口。

  • <application-id> 要调用的服务的应用程序 ID。

  • <method-name> 要在远程服务上调用的方法的名称。

项目演示

我们使用.NET5创建两个WebAPI项目:BackEnd和FrontEnd,通过FrontEnd调用BackEnd

2e59c962a21b2e1d919b8f6d4d246ff1.png

指定BackEnd默认启动端口5000

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>().UseUrls("http://*:5000");});

通过Dapr CLI启动BackEnd,指定sidecar端口为3511,默认为3500,指定app-port是5000,与BackEnd默认端口保持一致

dapr run --dapr-http-port 3511 --app-port 5000 --app-id backend dotnet  .\BackEnd\bin\Debug\net5.0\BackEnd.dll
C:\demo\test\DaprBackEnd>dapr run --dapr-http-port 3511 --app-port 5000 --app-id backend dotnet  .\BackEnd\bin\Debug\net5.0\BackEnd.dll
Starting Dapr with id backend. HTTP Port: 3511. gRPC Port: 30204
time="2021-09-23T14:14:08.3785429+08:00" level=info msg="starting Dapr Runtime -- version 1.4.0 -- commit ed969edc72b3934fffb481f079b736f3588e373a" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.3831089+08:00" level=info msg="log level set to: info" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.3831089+08:00" level=info msg="metrics server started on :30205/" app_id=backend instance=chesterchen-lap scope=dapr.metrics type=log ver=1.4.0
time="2021-09-23T14:14:08.3861203+08:00" level=info msg="standalone mode configured" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.3861203+08:00" level=info msg="app id: backend" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.3871107+08:00" level=info msg="mTLS is disabled. Skipping certificate request and tls validation" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4115681+08:00" level=info msg="local service entry announced: backend -> 10.32.193.9:30209" app_id=backend instance=chesterchen-lap scope=dapr.contrib type=log ver=1.4.0
time="2021-09-23T14:14:08.4115681+08:00" level=info msg="Initialized name resolution to mdns" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4127024+08:00" level=info msg="loading components" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4160224+08:00" level=info msg="component loaded. name: pubsub, type: pubsub.redis/v1" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4160224+08:00" level=info msg="waiting for all outstanding components to be processed" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4187042+08:00" level=info msg="component loaded. name: statestore, type: state.redis/v1" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4187042+08:00" level=info msg="all outstanding components processed" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4192486+08:00" level=info msg="enabled gRPC tracing middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.grpc.api type=log ver=1.4.0
time="2021-09-23T14:14:08.4192486+08:00" level=info msg="enabled gRPC metrics middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.grpc.api type=log ver=1.4.0
time="2021-09-23T14:14:08.4192486+08:00" level=info msg="API gRPC server is running on port 30204" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4197888+08:00" level=info msg="enabled metrics http middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.http type=log ver=1.4.0
time="2021-09-23T14:14:08.4197888+08:00" level=info msg="enabled tracing http middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.http type=log ver=1.4.0
time="2021-09-23T14:14:08.4202954+08:00" level=info msg="http server is running on port 3511" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.420335+08:00" level=info msg="The request body size parameter is: 4" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.420335+08:00" level=info msg="enabled gRPC tracing middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.grpc.internal type=log ver=1.4.0
time="2021-09-23T14:14:08.4225403+08:00" level=info msg="enabled gRPC metrics middleware" app_id=backend instance=chesterchen-lap scope=dapr.runtime.grpc.internal type=log ver=1.4.0
time="2021-09-23T14:14:08.4230868+08:00" level=info msg="internal gRPC server is running on port 30209" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.4230868+08:00" level=info msg="application protocol: http. waiting on port 5000.  This will block until the app is listening on that port." app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Now listening on: http://[::]:5000
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Application started. Press Ctrl+C to shut down.
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Hosting environment: Production
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Content root path: C:\demo\test\DaprBackEnd
time="2021-09-23T14:14:08.7252681+08:00" level=info msg="application discovered on port 5000" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
== APP ==       Request starting HTTP/1.1 GET http://127.0.0.1:5000/dapr/config application/json -
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
== APP ==       Request finished HTTP/1.1 GET http://127.0.0.1:5000/dapr/config application/json - - 404 0 - 17.3850ms
time="2021-09-23T14:14:08.7693649+08:00" level=info msg="application configuration loaded" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:14:08.7699003+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s" app_id=backend instance=chesterchen-lap scope=dapr.runtime.actor type=log ver=1.4.0
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
== APP ==       Request starting HTTP/1.1 GET http://127.0.0.1:5000/dapr/subscribe application/json -
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
time="2021-09-23T14:14:08.7736383+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 387.518ms" app_id=backend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
== APP ==       Request finished HTTP/1.1 GET http://127.0.0.1:5000/dapr/subscribe application/json - - 404 0 - 0.1789ms
time="2021-09-23T14:14:08.7888444+08:00" level=info msg="placement tables updated, version: 0" app_id=backend instance=chesterchen-lap scope=dapr.runtime.actor.internal.placement type=log ver=1.4.0
Updating metadata for app command: dotnet .\BackEnd\bin\Debug\net5.0\BackEnd.dll
You're up and running! Both Dapr and your app logs will appear here.

现在修改FrontEnd里Demo,指定启动端口5001

public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>().UseUrls("http://*:5001");});

引入Nuget包 Dapr.Client,新建DaprController

5d0d1c3f7c352ef04cf44646961146b0.png

1.使用 HttpClient调用HTTP服务

using Dapr.Client;using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;namespace FrontEnd.Controllers
{[ApiController][Route("[controller]")]public class DaprController : ControllerBase{private readonly ILogger<DaprController> _logger;public DaprController(ILogger<DaprController> logger){_logger = logger;}// 通过HttpClient调用BackEnd[HttpGet]public async Task<ActionResult> GetAsync(){using var httpClient = DaprClient.CreateInvokeHttpClient();var result = await httpClient.GetAsync("http://backend/WeatherForecast");var resultContent = string.Format("result is {0} {1}", result.StatusCode, await result.Content.ReadAsStringAsync());return Ok(resultContent);}}
}

GetAsync API中通过DaprClient.CreateInvokeHttpClient()新建了HttpClient,通过GetAsync方法调用了backend服务中的WeatherForecastAPI。

Sidecar使用可插接式名称解析组件来解析服务BackEnd的地址。在自承载模式下,Dapr 使用 mdn 来查找它。在 Kubernetes 模式下运行时,Kubernetes DNS 服务将确定地址。

2.使用 DaprClient调用HTTP服务

// 通过DaprClient调用BackEnd[HttpGet("get2")]public async Task<ActionResult> Get2Async(){using var daprClient = new DaprClientBuilder().Build();var result = await daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "backend", "WeatherForecast");return Ok(result);}

DaprController中新增API Get2Async 

3.使用注入方式调用 DaprClient

首先引入Nuget包Dapr.AspNetCore,然后在Startup.cs注入Dapr

public void ConfigureServices(IServiceCollection services){services.AddControllers().AddDapr();}

新建DaprDIController

using Dapr.Client;using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;namespace FrontEnd.Controllers
{[Route("[controller]")][ApiController]public class DaprDIController : ControllerBase{private readonly ILogger<DaprDIController> _logger;private readonly DaprClient _daprClient;public DaprDIController(ILogger<DaprDIController> logger, DaprClient daprClient){_logger = logger;_daprClient = daprClient;}[HttpGet()]public async Task<ActionResult> GetAsync(){var result = await _daprClient.InvokeMethodAsync<IEnumerable<WeatherForecast>>(HttpMethod.Get, "backend", "WeatherForecast");return Ok(result);}}
}

以上代码通过注入方式注入DaprClient

4.使用DaprClient同样可以调用GRPC

await daprClient.InvokeMethodGrpcAsync<Order, OrderConfirmation>("orderservice", "submitOrder", order);

与HTTP调用方式一致,不再为GRPC新建server

通过Dapr CLI启动FrontEnd,指定sidecar端口为3501,默认为3500,指定app-port是5001,与FrontEnd默认端口保持一致

dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll
C:\demo\test\DaprBackEnd>dapr run --dapr-http-port 3501 --app-port 5001  --app-id frontend dotnet  .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll
Starting Dapr with id frontend. HTTP Port: 3501. gRPC Port: 1045
time="2021-09-23T14:15:24.5222236+08:00" level=info msg="starting Dapr Runtime -- version 1.4.0 -- commit ed969edc72b3934fffb481f079b736f3588e373a" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5269659+08:00" level=info msg="log level set to: info" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5269659+08:00" level=info msg="metrics server started on :1046/" app_id=frontend instance=chesterchen-lap scope=dapr.metrics type=log ver=1.4.0
time="2021-09-23T14:15:24.5302603+08:00" level=info msg="standalone mode configured" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5302904+08:00" level=info msg="app id: frontend" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5302904+08:00" level=info msg="mTLS is disabled. Skipping certificate request and tls validation" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.559128+08:00" level=info msg="local service entry announced: frontend -> 10.32.193.9:1051" app_id=frontend instance=chesterchen-lap scope=dapr.contrib type=log ver=1.4.0
time="2021-09-23T14:15:24.559128+08:00" level=info msg="Initialized name resolution to mdns" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.560108+08:00" level=info msg="loading components" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5641089+08:00" level=info msg="component loaded. name: pubsub, type: pubsub.redis/v1" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5641089+08:00" level=info msg="waiting for all outstanding components to be processed" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5671082+08:00" level=info msg="component loaded. name: statestore, type: state.redis/v1" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5671082+08:00" level=info msg="all outstanding components processed" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5671082+08:00" level=info msg="enabled gRPC tracing middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.grpc.api type=log ver=1.4.0
time="2021-09-23T14:15:24.5671082+08:00" level=info msg="enabled gRPC metrics middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.grpc.api type=log ver=1.4.0
time="2021-09-23T14:15:24.5671082+08:00" level=info msg="API gRPC server is running on port 1045" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5684039+08:00" level=info msg="enabled metrics http middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.http type=log ver=1.4.0
time="2021-09-23T14:15:24.5700491+08:00" level=info msg="enabled tracing http middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.http type=log ver=1.4.0
time="2021-09-23T14:15:24.5700491+08:00" level=info msg="http server is running on port 3501" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5705931+08:00" level=info msg="The request body size parameter is: 4" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5705931+08:00" level=info msg="enabled gRPC tracing middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.grpc.internal type=log ver=1.4.0
time="2021-09-23T14:15:24.5705931+08:00" level=info msg="enabled gRPC metrics middleware" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.grpc.internal type=log ver=1.4.0
time="2021-09-23T14:15:24.5711294+08:00" level=info msg="internal gRPC server is running on port 1051" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.5711294+08:00" level=info msg="application protocol: http. waiting on port 5001.  This will block until the app is listening on that port." app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Now listening on: http://[::]:5001
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Application started. Press Ctrl+C to shut down.
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Hosting environment: Production
== APP == info: Microsoft.Hosting.Lifetime[0]
== APP ==       Content root path: C:\demo\test\DaprBackEnd
time="2021-09-23T14:15:24.8729143+08:00" level=info msg="application discovered on port 5001" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
== APP ==       Request starting HTTP/1.1 GET http://127.0.0.1:5001/dapr/config application/json -
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
== APP ==       Request finished HTTP/1.1 GET http://127.0.0.1:5001/dapr/config application/json - - 404 0 - 19.0408ms
time="2021-09-23T14:15:24.9188354+08:00" level=info msg="application configuration loaded" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.9193692+08:00" level=info msg="actor runtime started. actor idle timeout: 1h0m0s. actor scan interval: 30s" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.actor type=log ver=1.4.0
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
== APP ==       Request starting HTTP/1.1 GET http://127.0.0.1:5001/dapr/subscribe application/json -
== APP == info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
== APP ==       Request finished HTTP/1.1 GET http://127.0.0.1:5001/dapr/subscribe application/json - - 404 0 - 0.2000ms
time="2021-09-23T14:15:24.9236093+08:00" level=info msg="dapr initialized. Status: Running. Init Elapsed 393.349ms" app_id=frontend instance=chesterchen-lap scope=dapr.runtime type=log ver=1.4.0
time="2021-09-23T14:15:24.9393948+08:00" level=info msg="placement tables updated, version: 0" app_id=frontend instance=chesterchen-lap scope=dapr.runtime.actor.internal.placement type=log ver=1.4.0
Updating metadata for app command: dotnet .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll
You're up and running! Both Dapr and your app logs will appear here.

  Dapr CLI查看运行中的app

dapr list
APP ID    HTTP PORT  GRPC PORT  APP PORT  COMMAND               AGE  CREATED              PIDbackend   3511       1033       5000      dotnet .\BackEnd\...  9s   2021-09-24 09:25.17  860frontend  3501       1056       5001      dotnet .\FrontEnd...  7s   2021-09-24 09:25.19  5236

测试调用

1.浏览器地址栏输入

http://localhost:3501/v1.0/invoke/frontend/method/dapr
http://localhost:3501/v1.0/invoke/frontend/method/dapr/get2
http://localhost:3501/v1.0/invoke/frontend/method/DaprDI

可以看到正常响应

48d429e08818f33910a19f684164794d.png

 2.DaprCLI测试调用

打开cmd输入

dapr invoke --app-id frontend --verb "GET" --method dapr

也可以看到调用成功

C:\Users\chesterychen>dapr invoke --app-id frontend --verb "GET" --method dapr
result is OK [{"date":"2021-09-24T14:20:51.2386681+08:00","temperatureC":47,"temperatureF":116,"summary":"Mild"},{"date":"2021-09-25T14:20:51.2386705+08:00","temperatureC":50,"temperatureF":121,"summary":"Mild"},{"date":"2021-09-26T14:20:51.2386707+08:00","temperatureC":34,"temperatureF":93,"summary":"Hot"},{"date":"2021-09-27T14:20:51.2386708+08:00","temperatureC":42,"temperatureF":107,"summary":"Bracing"},{"date":"2021-09-28T14:20:51.2386709+08:00","temperatureC":-19,"temperatureF":-2,"summary":"Warm"}]
App invoked successfully

PS:单机运行的情况下,每个服务的sidecar是一个进程,名为daprd,下图两个分别是backend和frontend连个服务的

0c3fc6bb2ac8dfa9cb8a14fb58da8e46.png

 链路追踪

自承载的方式下,Dapr默认启动了zipkin容器,可以通过以下链接查看

http://localhost:9411/zipkin/

e45695d0cd2d3e858f0f9a990d9ae3d6.png

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

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

相关文章

华为新员工入职时信息安全保密手册

一、新员工入职信息安全须知 新员工入职后&#xff0c;在信息安全方面有哪些注意事项&#xff1f; 接受“信息安全与保密意识”培训&#xff1b; 每年应至少参加一次信息安全网上考试&#xff1b; 办理员工卡&#xff1b; 签署劳动合同&#xff08;含保密职责&#xff09;&…

第五周项目2-对象作为数据成员

回想Engineer类的数据成员&#xff0c;有眼镜、背包等。某Engineer的眼镜、背包&#xff0c;是Glass、Bag类的对象。类中的数据成员&#xff0c;其类型可以是简单类型&#xff0c;也可以是类。通过这种方式&#xff0c;将某些类组合到另外的类中&#xff0c;当作其中的一个“部…

谷歌排名第一的编程语言,死磕它这两点,小白也能学的会!不信你看!

全世界只有3.14 % 的人关注了爆炸吧知识谷歌排名第一的编程语言时什么&#xff1f;毫无疑问&#xff1a;肯定是 Python。也难怪&#xff0c;作为大数据时代和人工智能时代的必备语言&#xff0c;Python 的优点太多了&#xff0c;语言简洁、易学、开发效率高、可移植性强......另…

android主动显示流程,Activity加载显示基本流程

本文章是基于Android源码6.0讲解Activity加载显示基本流程首先上一张图给大家一个直观的了解首先一个布局页面的加载是在Activity中的setContentView(R.layout.res)开始;我们就从Acitvity源码中的setContentView方法入手public void setContentView(LayoutRes int layoutResID)…

VIM之Project 项目管理工具

VIM是Linux和Unix下常用的文本编辑工具&#xff0c;在编写代码和阅读代码中经常使用。但VIM进行代码项目管理时&#xff0c;没有IDE集成开发工具方便&#xff0c;现在提供一个VIM插件Project&#xff0c;可以对代码项目进行简单的集中管理一、 下载安装1、 在 Vim 网站上下载最…

vue数组刷新_Vue数组更新方法

Vue的核心是数据与视图的双向绑定&#xff0c;当我们修改数组时&#xff0c;Vue会检测到数据变化&#xff0c;所以用v-for渲染的视图也会立即更新。Vue包含了一组观察数组变异的方法&#xff0c;使用他们改变数组也会触发视图更新。push()pop()shift()unshift()splice()sort()r…

python提供什么机制处理程序运行错误_浅谈Python异常处理机制

异常机制己经成为衡量一门编程语言是否成熟的标准之一&#xff0c;使用异常处理机制的 Python 程序有更好的容错性&#xff0c;更加健壮。 对于计算机程序而言&#xff0c;情况就更复杂了一一没有人能保证自己写的程序永远不会出辛苦&#xff01;就算程序没有错误&#xff0c;你…

WPF DataGrid 通过自定义表头模拟首行固定

WPF DataGrid 通过自定义表头模拟首行固定独立观察员 2021 年 9 月 25 日最近工作中要在 WPF 中做个表格&#xff0c;自然首选就是 DataGrid 控件了。问题是&#xff0c;UI 设计的表格是在首行有一个新增按钮&#xff0c;那一行样式和其它数据行是一样的&#xff0c;就在表头下…

python和C语言分别实现插入排序

python语言代码&#xff1a;代码1 defInsertSort(numbers,n):2 fori inrange(1,n):3 j i-14 tem numbers[i]5 whilenumbers[j]>tem andj>0:6 numbers[j1] numbers[j]7 j -18 else:9 numbers[j1] tem10 print"Onthe sort:",numbers11 12 a [9,8,7,6,5,4,3,2,1,0…

Windows用户安全小技巧

本文适用于具有管理员用户和标准用户的所有Windows系统&#xff0c;如Windows 2000以上的操作系统&#xff0c;UAC是Windows Vista以上版本的具有功能。新安装的Windows系统或者新购买的含有Windows系统计算机一开始都需要安装许多软件并需要设置较多的含有Windows安全或用户控…

根据url获取html源码,通过URL访问和获取html源代码

Uniform Resource Locator ,在Internet的WWW服务程序上用于指定信息位置的表示方法指定互联网或本地上(web服务中)的文件、对象资源 等&#xff0c;或者说它相当于一个互联网上资源的一个指针协议 主机 路径 资源http://www.itfuture.org/forum/index.jsp …

从网恋到失恋只需要一秒...

1 原来放下一个人如此简单...▼2 而且到现在衣服都没找到▼3 这东西叫糖醋液&#xff0c;实验室比例是&#xff1a;糖&#xff1a;醋&#xff1a;酒&#xff1a;水1&#xff1a;2&#xff1a;3&#xff1a;4▼4 老师&#xff1a;这孩子真有原则▼5 呵&#xff0c;绝交吧▼…

Log4net数据表

USE [ASPNETDB] GO /****** 对象: Table [dbo].[Log] 脚本日期: 12/21/2011 22:41:53 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[Log]([ID] [int] IDENTITY(1,1) NOT NULL,[Date] [datetime] NOT NULL,[Threa…

go float64 比较_Go 每日一库之 plot

Go 每日一库之 plot简介本文介绍 Go 语言的一个非常强大、好用的绘图库——plot。plot内置了很多常用的组件&#xff0c;基本满足日常需求。同时&#xff0c;它也提供了定制化的接口&#xff0c;可以实现我们的个性化需求。plot主要用于将数据可视化&#xff0c;便于我们观察、…

大前端快闪:package.json文件知多少?

最近在公司某项目参与了一些前端工作&#xff0c;作为后端抠脚大汉&#xff0c;改点前端细节磕磕绊绊&#xff0c;改点大前端、工程化、HTTP交互倒也还能做到柳暗花明。于是打算用后端程序猿的视角记录一些{大前端}的知识快闪&#xff0c;也算是帮助读者构建完整的全栈技能体系…

大牛C++编程开发学习建议50条

2019独角兽企业重金招聘Python工程师标准>>> 每个从事C开发的朋友相信都能给后来者一些建议&#xff0c;但是真正为此进行大致总结的很少。本文就给出了网上流传的对C编程开发学习的50条建议&#xff0c;总结的还是相当不错的&#xff0c;编程学习者&#xff08;不仅…

JQuery函数在IE浏览器中测试的注意事项

这几天刚学JQuery&#xff0c;在测试hide&#xff0c;show&#xff0c;slideToggle函数的时候&#xff0c;在firefox浏览器都很正常&#xff0c;而在IE浏览器里面却出现一些动画异常。这些过渡效果快结束的时候&#xff0c;都出现了一些跳动的现象&#xff0c;例如我对一个段落…

html2canvas改成同步,html2canvas转为图片异步转同步问题(记录)

描述&#xff1a;最近使用html2canvas插件截取页面上指定dom为图片&#xff0c;然后将生成的图片替换页面上的dom后&#xff0c;将替换后的页面内容保存至数据库&#xff0c;结果保存的是保存前的页面&#xff0c;初步判定是html2canvas的异步执行造成的。参考了两篇博文&#…

杨辉再发声明:没有及时交流工作进展,深表歉意

全世界只有3.14 % 的人关注了爆炸吧知识pixabay.com编者按加州大学付向东教授实名举报中科院上海神经所杨辉事件在过去一周成为学术界讨论的热点话题。付向东称自己2018年在神经所做学术报告后&#xff0c;杨辉重复其实验却未告知并抢发文章。杨辉7月3日发表声明&#xff0c;称…

fedora12下pppoe服务器的搭建

1. 查看系统上是否安装了pppoe服务器软件[rootlocalhost ~]# rpm -qa | grep pppoerp-pppoe-3.10-6.fc12.i686若显示以上信息则已经安装了pppoe软件&#xff0c;若无信息则首先安装pppoe软件[rootlocalhost ~]# yum install pppoe2. 配置系统支持IP转发[rootlocalhost ~]# vim …