一、Skywalking介绍

Skywalking是一款分布式链路追踪组件,什么是链路追踪?

随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。

然后微服务面临了这些问题:

  • 某个核心服务挂了,导致大量报错,如何快速确定哪里出了问题?
  • 用户请求响应延迟高,怎么确定是哪些服务导致的?
  • 应用程序有性能瓶颈,怎样确定瓶颈在哪里?
  • 如何准实时的了解应用部署环境(CPU、内存、进程、线程、网络、带宽)情况,以便快速扩容/缩容、流量控制、业务迁移
  • 如何统计各个调用的性能指标,比如:吞吐量(TPS)、响应时间及错误记录等

分布式链路跟踪系统就是为了解决这些问题应运而生。

分布式链路追踪组件

  • 阿里巴巴鹰眼(EagleEye)
  • 美团CAT
  • 京东Hydra
  • Twitter Zipkin (Java经常用到) 【.NET Java】
  • Apache SkyWalking (APM) 【go,python,.NET, Java】
  • Pinpoint(APM)

.NET用的最多的两款是SkyWalking、Zipkin。这里介绍Skywalking使用。

Skywalking有哪些功能?

  • 多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。
  • 多个语言自动探针。包括 Java,.NET Core 和 Node.JS。
  • 轻量高效。无需大数据平台,和大量的服务器资源。
  • 模块化。UI、存储、集群管理都有多种机制可选。
  • 支持告警。
  • 优秀的可视化解决方案。

    **Skywalking整体架构 **

整个架构,分成上、下、左、右四部分:

  • 探针基于不同的来源可能是不一样的, 但作用都是收集数据, 将数据格式化为 SkyWalking 适用的格式.
  • 平台后端是一个支持集群模式运行的后台, 用于数据聚合, 数据分析以及驱动数据流从探针到用户界面的流程. 平台后端还提供了各种可插拔的能力, 如不同来源数据(如来自 Zipkin)格式化, 不同存储系统以及集群管理. 你甚至还可以使用观测分析语言来进行自定义聚合分析.
  • 存储是开放式的. 你可以选择一个既有的存储系统, 如 ElasticSearch, H2 或 MySQL 集群(Sharding-Sphere 管理), 也可以选择自己实现一个存储系统. 当然, 我们非常欢迎你贡献新的存储系统实现.
  • 用户界面对于 SkyWalking 的最终用户来说非常炫酷且强大. 同样它也是可定制以匹配你已存在的后端的

Tracing、Logging和Metrics

在微服务领域,很早以来就形成了Tracing、Logging和Metrics相辅相成,合力支撑多维度、多形态的监控体系,三类监控各有侧重:

Tracing:它在单次请求的范围内,处理信息。 任何的数据、元数据信息都被绑定到系统中的单个事务上。例如:一次调用远程服务的RPC执行过程;一次实际的SQL查询语句;一次HTTP请求的业务性ID;

Logging:日志,不知道大家有没有想过它的定义或者边界。Logging即是记录处理的离散事件,比如我们应用的调试信息或者错误信息等发送到ES;审计跟踪时间信息通过Kafka处理送到BigTable等数据仓储等等,大多数情况下记录的数据很分散,并且相互独立,也许是错误信息,也许仅仅只是记录当前的事件状态,或者是警告信息等等。

Metrics:当我们想知道我们服务的请求QPS是多少,或者当天的用户登录次数等等,这时我们可能需要将一部分事件进行聚合或计数,也就是我们说的Metrics。可聚合性即是Metrics的特征,它们是一段时间内某个度量(计数器或者直方图)的原子或者是元数据。例如接收的HTTP数量可以被建模为计数器,每次的HTTP请求即是我们的度量元数据,可以进行简单的加法聚合,当持续了一段时间我们又可以建模为直方图。

二、Skywalking搭建

这里用Docker搭建

数据存储用ES,搭建ES

docker run -d -p 9200:9200 -p 9300:9300 --name es -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms128m -Xmx256m" elasticsearch:7.16.3

搭建skywalking-oap服务,这里用的是8.9.1版本,oap服务需要关联ES

docker run --name skywalking-oap \
--restart always \
-p 11800:11800 -p 12800:12800 -d \
-e TZ=Asia/Shanghai \
-e SW_ES_USER= \
-e SW_ES_PASSWORD= \
-e SW_STORAGE=elasticsearch \
-e SW_STORAGE_ES_CLUSTER_NODES=192.168.101.10:9200 \
-v /etc/localtime:/etc/localtime:ro \
apache/skywalking-oap-server:8.9.1

搭建skywalking-ui界面,需要关联oap服务

docker run -d \
--name skywalking-ui \
--restart always \
-p 8080:8080 \
--link skywalking-oap:skywalking-oap \
-e TZ=Asia/Shanghai \
-e SW_OAP_ADDRESS=http://skywalking-oap:12800 \
-v /etc/localtime:/etc/localtime:ro \
apache/skywalking-ui:8.9.1

搭建完成,打开ip:8080查看skywalking界面

三、.NET6接入Skywalking

1、单个服务接入

新建一个.NET6站点,安装Nuget包

SkyAPM.Agent.AspNetCore

Properties下launchSettings.json增加

"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore", //必须配置

"SKYWALKING__SERVICENAME": "Service1" // 必须配置,在skywalking做标识,服务名称

{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6413",
"sslPort": 44308
}
},
"profiles": {
"NET6AndSkyWalking": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5025",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore", //必须配置
"SKYWALKING__SERVICENAME": "Service1" // 必须配置,在skywalking做标识,服务名称
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

如果不在launchSettings.json加,也可以在Program.cs加

Environment.SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "SkyAPM.Agent.AspNetCore");
Environment.SetEnvironmentVariable("SKYWALKING__SERVICENAME", "Service1");

生成skywalking.json文件

1、安装CLI(SkyAPM.DotNet.CLI),cmd命令:

dotnet tool install -g SkyAPM.DotNet.CLI

2、自动生成skyapm.json文件,cmd命令:

1.dotnet skyapm config [service name] [server]:11800
2.eg: dotnet skyapm config service1 192.168.101.10:11800

执行了命令会生成skywalking.json文件,把skywalking.json放到项目根目录,设置较新复制到输出目录,然后修改ServiceName设置为项目名,和上面的SKYWALKING__SERVICENAME一致。

skyapm.json文件

{
"SkyWalking": {
"ServiceName": "service1",
"Namespace": "",
"HeaderVersions": [
"sw8"
],
"Sampling": {
"SamplePer3Secs": -1,
"Percentage": -1.0
},
"Logging": {
"Level": "Information",
"FilePath": "logs\\skyapm-{Date}.log"
},
"Transport": {
"Interval": 3000,
"ProtocolVersion": "v8",
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "192.168.101.10:11800",
"Timeout": 10000,
"ConnectTimeout": 10000,
"ReportTimeout": 600000,
"Authentication": ""
}
}
}
}

SamplePer3Secs:每三秒采样的Trace数量 ,默认为负数,代表在保证不超过内存Buffer区的前提下,采集所有的Trace

Percentage:采样率,默认负数,采集全部,其它数值格式:0.5,0.8...

这时候运行项目已经有基本的链路追踪功能了!

试一下运行,项目,然后看链路追踪界面(注意一下时间搜索的时间范围向后选一些),这个可能会延迟几秒钟才显示出来。

仪表盘



追踪



自定义链路日志

自定义链路日志可以在重要的地方加上,这样就能知道程序跑到这个地方时的关键信息了。

  public class HomeController : Controller
{
private readonly IEntrySegmentContextAccessor _segContext;
public HomeController(IEntrySegmentContextAccessor segContext)
{
_segContext = segContext;
} public IActionResult Index()
{
return View();
} /// <summary>
/// 自定链路日志
/// </summary>
/// <returns></returns>
public string SkywalkingLog()
{
//获取全局traceId
var traceId = _segContext.Context.TraceId;
_segContext.Context.Span.AddLog(LogEvent.Message("自定义日志1"));
Thread.Sleep(1000);
_segContext.Context.Span.AddLog(LogEvent.Message("自定义日志2"));
return traceId;
}
}

调用/Home/SkywalkingLog后Skywalking界面效果,看到了程序添加的日志

2、多服务追踪

链路追踪在多服务的时候才能体现它的精髓,一个链路能跟踪到请求涉及的所有服务。

这里新增一个.NET6的web项目,前面的步骤和上面的Service1一样,只是把服务名改为Service2。

然后在Service2增加一个接口 /UserInfo/GetUserInfo

 public class UserInfoController : Controller
{
private readonly IEntrySegmentContextAccessor _segContext;
public UserInfoController(IEntrySegmentContextAccessor segContext)
{
_segContext = segContext;
}
[HttpGet]
public string GetUserInfo(string userId)
{
string result = $"userId:{userId},userName:张三";
_segContext.Context.Span.AddLog(LogEvent.Message(result)); return result;
}
}

然后在Service1增加一个接口/Home/GetUser调用Service2

后在Service2增加一个接口 /UserInfo/GetUserInfo

 public class UserInfoController : Controller
{
private readonly IEntrySegmentContextAccessor _segContext;
public UserInfoController(IEntrySegmentContextAccessor segContext)
{
_segContext = segContext;
}
[HttpGet]
public string GetUserInfo(string userId)
{
string result = $"userId:{userId},userName:张三";
_segContext.Context.Span.AddLog(LogEvent.Message(result)); return result;
}
}

然后在Service1增加一个接口/Home/GetUser调用Service2

 public async Task<string> GetUser()
{
var client = new HttpClient();
//调用Service2
var response=await client.GetAsync("http://localhost:5199/UserInfo/GetUserInfo");
var result = await response.Content.ReadAsStringAsync();
return result;
}

然后调用Service1的接口/Home/GetUser



然后看链路追踪,会显示出对应的Service对应的耗时,点进去还能看到当前服务的详情和打的日志。



多服务的时候还能看到服务之间对应的调用关系

四、微服务网关接入Skywalking

新建一个.NET6的Web项目,引用Nuget包

SkyAPM.Agent.AspNetCore
Ocelot

把Web项目改为Ocelot网关

首先在根目录新增ocelot.json文件

{
"Routes": [
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
"DownstreamHostAndPorts": [
{
"Host": "127.0.0.1",
"Port": 5025 //服务端口
} //可以多个,自行负载均衡 ],
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ]
},
{
//转发到下游服务地址--url变量
"DownstreamPathTemplate": "/{url}",
//下游http协议
"DownstreamScheme": "http",
//负载方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 轮询
},
"DownstreamHostAndPorts": [
{
"Host": "127.0.0.1",
"Port": 5199 //服务端口
} //可以多个,自行负载均衡 ],
//上游地址
"UpstreamPathTemplate": "/T2/{url}", //网关地址--url变量 //冲突的还可以加权重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ]
}
]
}

然后把Program.cs修改为Ocelot网关

using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using SkyApm.Utilities.DependencyInjection; var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);//ocelot
builder.Services.AddSkyApmExtensions(); // 添加Skywalking相关配置 builder.Services.AddOcelot(); //ocelot
var app = builder.Build(); app.UseOcelot().Wait(); //ocelot app.Run();

修改Properties下的launchSettings.json文件

{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5127",
"sslPort": 44306
}
},
"profiles": {
"Ocelot.Web": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7019;http://localhost:5019",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "SkyAPM.Agent.AspNetCore", //skywalking必须配置
"SKYWALKING__SERVICENAME": "Ocelot.Web" // 必须配置,在skywalking做标识
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

把skyapm.json复制过来修改一下

{
"SkyWalking": {
"ServiceName": "Ocelot.Web",
"Namespace": "",
"HeaderVersions": [
"sw8"
],
"Sampling": {
"SamplePer3Secs": -1,
"Percentage": -1.0
},
"Logging": {
"Level": "Information",
"FilePath": "logs\\skyapm-{Date}.log"
},
"Transport": {
"Interval": 3000,
"ProtocolVersion": "v8",
"QueueSize": 30000,
"BatchSize": 3000,
"gRPC": {
"Servers": "192.168.101.10:11800",
"Timeout": 10000,
"ConnectTimeout": 10000,
"ReportTimeout": 600000,
"Authentication": ""
}
}
}
}

到这里就完成了,启动网关项目,Service1项目,Service2项目,访问/T1/Home/GetUser



访问成功,看Skywalking追踪界面,三个站点都追踪到了

五、配置Skywalking告警

进入容器

 docker exec -it 7c21 /bin/bash

如果报文件夹不存在就用下面的,因为版本不一样可能会不一样

 docker exec -it 7c21 /bin/sh

进入config目录



配置文件规则解读

通过cat alarm-settings.yml可以查阅文件内容,如下:

# Sample alarm rules.
rules:
# Rule unique name, must be ended with `_rule`.
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
service_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_sla
op: "<"
threshold: 8000
# The length of time to evaluate the metrics
period: 10
# How many times after the metrics match the condition, will trigger alarm
count: 2
# How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
silence-period: 3
message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
service_resp_time_percentile_rule:
# Metrics value need to be long, double or int
metrics-name: service_percentile
op: ">"
threshold: 1000,1000,1000,1000,1000
period: 10
count: 3
silence-period: 5
message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
service_instance_resp_time_rule:
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-period: 5
message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
database_access_resp_time_rule:
metrics-name: database_access_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
endpoint_relation_resp_time_rule:
metrics-name: endpoint_relation_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
# Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
# Because the number of endpoint is much more than service and instance.
#
# endpoint_avg_rule:
# metrics-name: endpoint_avg
# op: ">"
# threshold: 1000
# period: 10
# count: 2
# silence-period: 5
# message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/

规则常用指标解读

rule name: 规则名称,必须唯一,必须以 _rule结尾;

metrics name: oal(Observability Analysis Language)脚本中的度量名;名称在SkyWalking后端服务中已经定义,进入容器skywalking-oap之后,进入如下目录就可以找到。

include names: 本规则告警生效的实体名称,如服务名,终端名;

exclude-names:将此规则作用于不匹配的实体名称上,如服务名,终端名;

threshold: 阈值,可以是一个数组,即可以配置多个值;

op: 操作符, 可以设定 >, <, =;

period: 多久检查一次当前的指标数据是否符合告警规则;以分钟为单位

count: 超过阈值条件,达到count次数,触发告警;

silence period:在同一个周期,指定的silence period时间内,忽略相同的告警消息;

更多告警规则详情,请参照这个地址:

https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/backend-alarm.md

修改告警规则

rules:
service_sal_rule:
# 指定指标名称
metrics-name: service_sal
# 小于
op: "<"
# 指定阈值
threshold: 8000
# 每10分钟检测告警该规则
period: 10
# 触发2次规则就告警
count: 2
# 设置三分钟内容相同告警,不重复告警
silence-period: 3
# 配置告警信息
message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes

概要:服务成功率在过去2分钟内低于80%

告警API编写

这个本质还是SkyWalking根据规则进行检查,如果符合规则条件,就通过WebHook、gRPCHook、WeChat Hook、Dingtalk Hook、Feishu Hook等方式进行消息通知;接收到告警数据信息之后,可以自行处理消息。这里为了方便,就采用WebHook的方式进行演示,即触发告警条件之后,SkyWalking会调用配置的WebHook 接口,并传递对应的告警信

定义数据模型

public class AlarmMsg
{
public int scopeId { get; set; }
public string? scope { get; set; }
public string? name { get; set; }
public string? id0 { get; set; }
public string? id1 { get; set; }
public string? ruleName { get; set; }
public string? alarmMessage { get; set; }
}

定义WebHook调用API,这里在Service1下的HomeController里加接口接收告警信息

 		/// <summary>
/// 故意报错测试告警
/// </summary>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public string Error()
{
//故意报错
throw new Exception($"出错啦:{DateTime.Now}");
}
/// <summary>
/// 告警
/// </summary>
/// <param name="msgs"></param>
[HttpPost]
public void AlarmMsg([FromBody]List<AlarmMsg>List<AlarmMsg> msgs)
{
string msg = $"{DateTime.Now},触发告警:";
msg += msgs.FirstOrDefault()?.alarmMessage;
Console.WriteLine(msg);
//todo 发邮件或发短信
}

配置webkook

webhooks:
- http://192.168.101.9:5025/Home/AlarmMsg

重启 Skywalking-oap服务

请求几次/Home/Error产生错误请求



等待告警webhook调用



到这里,告警据完成了。

六、Skywalking无入侵原理解密

为什么要在launchSettings.json文件里面加SkyAPM.Agent.AspNetCore呢,为什么加了就可以了呢?



其实用的是.NET Core框架里面的扩展,它是怎做到的呢,举个例子

在Service1做测试,建一个CustomHostingStartup.cs

namespace NET6AndSkyWalking.Models
{
/// <summary>
/// 必须实现IHostingStartup 接口
/// 必须标记HostingStartup特性
/// 发生在HostBuild时候,IOC容器初始化之前,无侵入式扩展
/// </summary>
public class CustomHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
Console.WriteLine("自定义扩展执行...");
//拿到IWebHostBuilder,一切都可做
}
}
}

启动Service1,可以看到新增的扩展打印了



如果这个扩展是在其他类库呢?

新建一个Common类库,把刚才的类移到Common类库,然后Service添加对Common的引用。

这时候就要修改launchsettings.json文件,加入Common的程序集了



启动Service1,成功执行



同样的道理,通过查看源码可以看到,SkyAPM.Agent.AspNetCore组件里面也有这样的一个类,把Skywalking的代码无侵入扩展进来了。

演示源码:https://github.com/weixiaolong325/NET6AndSkyWalking

.NET6接入Skywalking链路追踪完整流程的更多相关文章

  1. 使用Skywalking分布式链路追踪系统

    使用Skywalking分布式链路追踪系统 https://www.cnblogs.com/sunyuliang/p/11424848.html 当我们用很多服务时,各个服务间的调用关系是怎么样的?各 ...

  2. .NetCore从零开始使用Skywalking分布式追踪系统

    本文将从0开妈搭建两个webapi项目,使用Skywalking来追踪他们之间的调用关系及响应时间.开发环境为VisualStudio2019 1:安装Skywalking,可参考:https://w ...

  3. 在spring boot中三分钟上手apache顶级分布式链路追踪系统skywalking

    原文:https://juejin.im/post/5cd10e81e51d453b560f2d53 skywalking在apache里全票通过成为了apache顶级链路追踪系统 项目地址:gith ...

  4. 分布式链路追踪自从用了SkyWalking,睡得真香!

    本篇文章介绍链路追踪的另外一种解决方案Skywalking,文章目录如下: 什么是Skywalking? 上一篇文章介绍了分布式链路追踪的一种方式:Spring Cloud Sleuth+ZipKin ...

  5. NET Core微服务之路:SkyWalking+SkyApm-dotnet分布式链路追踪系统的分享

    对于普通系统或者服务来说,一般通过打日志来进行埋点,然后再通过elk或splunk进行定位及分析问题,更有甚者直接远程服务器,直接操作查看日志,那么,随着业务越来越复杂,企业应用也进入了分布式服务化的 ...

  6. SkyWalking+SkyApm-dotnet分布式链路追踪系统

    SkyWalking+SkyApm-dotnet分布式链路追踪系统 对于普通系统或者服务来说,一般通过打日志来进行埋点,然后再通过elk或splunk进行定位及分析问题,更有甚者直接远程服务器,直接操 ...

  7. 全链路追踪技术选型:pinpoint vs skywalking

    目前分布式链路追踪系统基本都是根据谷歌的<Dapper大规模分布式系统的跟踪系统>这篇论文发展而来,主流的有zipkin,pinpoint,skywalking,cat,jaeger等. ...

  8. skywalking与pinpoint全链路追踪方案对比

    由于公司目前有200多微服务,微服务之间的调用关系错综复杂,调用关系人工维护基本不可能实现,需要调研一套全链路追踪方案,初步调研之后选取了skywalking和pinpoint进行对比; 选取skyw ...

  9. .NET Core集成SkyWalking+SkyAPM-dotne实现分布式链路追踪

    .NET Core集成SkyWalking+SkyAPM-dotnet实现分布式链路追踪 SkyWalking是一款APM(应用性能管理),其他的还有Cat.Zipkin.Pinpoint等. 随着微 ...

随机推荐

  1. [翻译] 使用 TensorFlow 进行分布式训练

    本文以两篇官方文档为基础来学习TensorFlow如何进行分布式训练,借此进入Strategy世界.

  2. 图片杂乱无章、分享麻烦?HMS Core图片分类服务教你快速筛选、分类、整合相册

    如今手机摄影越来越方便,随手一拍就能记录美好生活.但照片越多,整理越麻烦,有的时候我们想对照片进行二次加工.分享,需要不停翻找相册.HMS Core机器学习服务(ML Kit)提供了图片分类服务,方便 ...

  3. python基础练习题(题目 对10个数进行排序)

    day24 --------------------------------------------------------------- 实例037:排序 题目 对10个数进行排序. 分析:先输入1 ...

  4. XGBoost文本分类,多分类、二分类、10-Fold(K-Fold)

    做机器学习的时候经常用到XGB,简单记录一下 K折交叉验证也是模型常用的优化方法.一起记录... K折交叉验证:类似三个臭皮匠,顶个诸葛亮.我的理解是,就是用民主投票的方式,选取票数最高的那个当结果. ...

  5. 字节跳动构建Data Catalog数据目录系统的实践(上)

    作为数据目录产品,Data Catalog 通过汇总技术和业务元数据,解决大数据生产者组织梳理数据.数据消费者找数和理解数的业务场景,并服务于数据开发和数据治理的产品体系.本文介绍了字节跳动 Data ...

  6. [题解][P5206][WC2019] 数树 (op = 1)

    简要题意 给定 \(n, y\). 一张图有 \(|V| = n\) 个点,现在给出两棵树 \(T_1=G(V, E_1)\) 和 \(T_2=G(V, E_2)\). 定义这两棵树的权值 \(F(E ...

  7. C++基础-4-封装(构造函数与析构函数,深拷贝与浅拷贝,静态成员,this,友元,const修饰成员函数)

    4. 封装 4.1.1 封装的意义 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 con ...

  8. MongoDB排序时内存大小限制和创建索引的注意事项!

    线上服务的MongoDB中有一个很大的表,我查询时使用了sort()根据某个字段进行排序,结果报了下面这个错误: [Error] Executor error during find command ...

  9. 重新审视C# Span<T>数据结构

    先谈一下我对Span的看法, span是指向任意连续内存空间的类型安全.内存安全的视图. Span和Memory都是包装了可以在pipeline上使用的结构化数据的内存缓冲器,他们被设计用于在pipe ...

  10. k8s client-go源码分析 informer源码分析(3)-Reflector源码分析

    k8s client-go源码分析 informer源码分析(3)-Reflector源码分析 1.Reflector概述 Reflector从kube-apiserver中list&watc ...