使用 C# 开发 Kubernetes 组件,获取集群资源信息

写什么呢

前段时间使用 C# 写了个项目,使用 Kubernetes API Server,获取信息以及监控 Kubernetes 资源,然后结合 Neting 做 API 网关。

体验地址 http://neting.whuanle.cn:30080/

账号 admin,密码 admin123

3e4d40eb2393837e59d225b61c70aa4a.png

本篇文章主要介绍,如何通过 C# 开发基于 Kuberetes 的应用,实现获取 Kubernets 中各种资源的信息,以及实现 Conroller 的前提知识。而在下一篇中则会讲解如何实现 Conroller 和 Kubernetes Operator。

Kubernetes API Server

kube-apiserver 是 k8s 主要进程之一,apiserver 组件公开了 Kubernetes API (HTTP API),apiserver 是 Kubernetes 控制面的前端,我们可以用 Go、C# 等编程语言写代码,远程调用 Kubernetes,控制集群的运行。apiserver 暴露的 endiont 端口是 6443。

为了控制集群的运行,Kubernetes 官方提供了一个名为 kubectl 的二进制命令行工具,正是 apiserver 提供了接口服务,kubectl 解析用户输入的指令后,向 apiserver 发起 HTTP 请求,再将结果反馈给用户。

kubectl

kubectl 是 Kubernetes 自带的一个非常强大的控制集群的工具,通过命令行操作去管理整个集群。

Kubernetes 有很多可视化面板,例如 Dashboard,其背后也是调用 apiserver 的 API,相当于前端调后端。

总之,我们使用的各种管理集群的工具,其后端都是 apiserver,通过 apiserver,我们还可以定制各种各样的管理集群的工具,例如网格管理工具 istio。腾讯云、阿里云等云平台都提供了在线的 kubernetes 服务,还有控制台可视化操作,也是利用了 apiserver。

你可以参考笔者写的 Kubernetes 电子书,了解更多:https://k8s.whuanle.cn/1.basic/5.k8s.html

f5d515c2f6843324043cac9b95f4839b.png

简而言之, Kubernetes API Server 是第三方操作 Kubernetes 的入口。

暴露 Kubernetes API Server

首先查看 kube-system 中运行的 Kubernetes 组件,有个 kube-apiserver-master 正在运行。

root@master:~# kubectl get pods -o wide  -n kube-system
NAME                             READY   STATUS    RESTARTS         AGE   IP          NODE     NOMINATED NODE   READINESS GATES
... ...
kube-apiserver-master            1/1     Running   2 (76d ago)      81d   10.0.0.4    master   <none>           <none>
... ...

虽然这些组件很重要,但是只会有一个实例,并且以 Pod 形式运行,而不是 Deployment,这些组件只能放在 master 节点运行。

然后查看 admin.conf 文件,可以通过 /etc/kubernetes/admin.conf 或 $HOME/.kube/config 路径查看到。

fd8440a1d6151d0ca620f618cb8482e3.png

admin.conf 文件是访问 Kubernetes API Server 的凭证,通过这个文件,我们可以使用编程访问 Kubernetes 的 API 接口。

但是 admin.conf 是很重要的文件,如果是开发环境开发集群,那就随便造,如果是生产环境,请勿使用,可通过角色绑定等方式限制 API 访问授权。

然后把 admin.conf 或 config 文件下载到本地。

你可以使用 kubectl edit pods kube-apiserver-master -n kube-system 命令,查看 Kubernetes API Server 的一些配置信息。

由于 Kubernetes API Server 默认是通过集群内访问的,如果需要远程访问,则需要暴露到集群外(与是否都在内网无关,与是否在集群内有关)。

将 API Server 暴露到集群外:

kubectl expose pod  kube-apiserver-master --type=NodePort --port=6443 -n kube-system

查看节点随机分配的端口:

root@master:~# kubectl get svc -n kube-system
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
kube-apiserver-master   NodePort    10.101.230.138   <none>        6443:32263/TCP           25s

32263 端口是 Kubernetes 自动分配,每个人的都不一样。

然后通过 IP:32263 即可测试访问。

82fbe6b198f36aa47065278b8f8a3397.png

如果你的集群安装了 CoreDNS,那么通过其他节点的 IP,也可以访问到这个服务。

然后将下载的 admin.conf 或者 config 文件(请改名为 admin.conf),修改里面的 server 属性,因为我们此时是通过远程访问的。

连接到 API Server

新建一个 MyKubernetes 控制台项目,然后将 admin.conf 文件复制放到项目中,随项目生成输出。

116235f3fc8a2fd4506e9851cd3dd013.png

然后在 Nuget 中搜索 KubernetesClient 包,笔者当前使用的是 7.0.1。

然后在项目中设置环境变量:

b91d650ad593438d9a557f721df9df8a.png

这个环境变量本身是 ASP.NET Core 自带的,控制台程序中没有。

下面写一个方法,用于实例化和获取 Kubernetes 客户端:

private static Kubernetes GetClient(){KubernetesClientConfiguration config;if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development"){// 通过配置文件config = KubernetesClientConfiguration.BuildConfigFromConfigFile("./admin.conf");}else{// 通过默认的 Service Account 访问,必须在 kubernetes 中运行时才能使用config = KubernetesClientConfiguration.BuildDefaultConfig(); }return new Kubernetes(config);}

逻辑很简单,如果是开发环境,则使用 admin.conf 文件访问,如果是非开发环境,则 BuildDefaultConfig() 自动获取访问凭证,此方式只在 Pod 中运行时有效,利用 Service Account 认证。

下面测试一下,获取全部命名空间:

static async Task Main(){var client = GetClient();var namespaces  = await client.ListNamespaceAsync();foreach (var item in namespaces.Items){Console.WriteLine(item.Metadata.Name);}}

f600b2d37110b781300d0bbc000708e4.png

好了!你已经会获取 Kubernetes 资源了,打开入门的第一步!秀儿!

客户端小知识

虽然打开了入门的第一步,但是不要急着使用各种 API ,这里我们来了解一下 Kubernetes 各种资源在客户端中的定义,和如何解析结构。

首先,在 Kubernetes Client C# 的代码中,所有 Kubernetes 资源的模型类,都在 k8s.Models 中记录。

如果我们要在 Kubernetes 中,查看一个对象的定义,如 kube-systtem 命名空间的:

kubectl get namespace kube-system -o yaml
apiVersion: v1
kind: Namespace
metadata:creationTimestamp: "2021-11-03T13:57:10Z"labels:kubernetes.io/metadata.name: kube-systemname: kube-systemresourceVersion: "33"uid: f0c1f00d-2ee4-40fb-b772-665ac2a282d7
spec:finalizers:- kubernetes
status:phase: Active

C# 中,模型的结构与其一模一样:

0f79f5adb16ea8c830cdb2748dc626ee.png

在客户端中,模型的名称以 apiVersion 版本做前缀,并且通过 V1NamespaceList 获取这类对象的列表。

如果要获取某类资源,其接口都是以 List 开头的,如 client.ListNamespaceAsync()client.ListAPIServiceAsync()client.ListPodForAllNamespacesAsync() 等。

看来,学习已经步入正轨了,让我们来实验练习吧!

88c6cf0f311338ffb05c0961f92b5509.png

如何解析一个 Service

这里笔者贴心给读者准备了一些练习,第一个练习是解析一个 Service 的信息出来。

查看前面创建的 Servicie:

kubectl get svc  kube-apiserver-master -n kube-system -o yaml

对应结构如下:

apiVersion: v1
kind: Service
metadata:creationTimestamp: "2022-01-24T12:51:32Z"labels:component: kube-apiservertier: control-planename: kube-apiserver-masternamespace: kube-systemresourceVersion: "24215604"uid: ede0e3df-8ef6-45c6-9a8d-2a2048c6cb12
spec:clusterIP: 10.101.230.138clusterIPs:- 10.101.230.138externalTrafficPolicy: ClusterinternalTrafficPolicy: ClusteripFamilies:- IPv4ipFamilyPolicy: SingleStackports:- nodePort: 32263port: 6443protocol: TCPtargetPort: 6443selector:component: kube-apiservertier: control-planesessionAffinity: Nonetype: NodePort
status:loadBalancer: {}

我们在 C# 中定义一个这样的模型类:

public class ServiceInfo{/// <summary>/// SVC 名称/// </summary>public string Name { get; set; } = null!;/// <summary>/// 三种类型之一 <see cref="ServiceType"/>/// </summary>public string? ServiceType { get; set; }/// <summary>/// 命名空间/// </summary>public string Namespace { get; set; } = null!;/// <summary>/// 有些 Service 没有此选项/// </summary>public string ClusterIP { get; set; } = null!;/// <summary>/// 外网访问 IP/// </summary>public string[]? ExternalAddress { get; set; }public IDictionary<string, string>? Labels { get; set; }public IDictionary<string, string>? Selector { get; set; }/// <summary>/// name,port/// </summary>public List<string>? Ports { get; set; }public string[]? Endpoints { get; set; }public DateTime? CreationTime { get; set; }// 关联的 Pod 以及 pod 的 ip}

下面,指定获取哪个命名空间的 Service 及其关联的 Endpoint 信息。

static async Task Main(){var result = await GetServiceAsync("kube-apiserver-master","kube-system");Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(result));}public static async Task<ServiceInfo> GetServiceAsync(string svcName, string namespaceName){var client = GetClient();var service = await client.ReadNamespacedServiceAsync(svcName, namespaceName);// 获取 service 本身的信息ServiceInfo info = new ServiceInfo{Name = service.Metadata.Name,Namespace = service.Metadata.NamespaceProperty,ServiceType = service.Spec.Type,Labels = service.Metadata.Labels,ClusterIP = service.Spec.ClusterIP,CreationTime = service.Metadata.CreationTimestamp,Selector = service.Spec.Selector.ToDictionary(x => x.Key, x => x.Value),ExternalAddress = service.Spec.ExternalIPs?.ToArray(),};// service -> endpoint 的信息var endpoint = await client.ReadNamespacedEndpointsAsync(svcName, namespaceName);List<string> address = new List<string>();foreach (var sub in endpoint.Subsets){foreach (var addr in sub.Addresses){foreach (var port in sub.Ports){address.Add($"{addr.Ip}:{port.Port}/{port.Protocol}");}}}info.Endpoints = address.ToArray();return info;}

输出结果如下:

40e32778ba8597cbbfc332700aacba31.png

亲,如果你对 Kubernetes 的网络知识不太清楚,请先打开 https://k8s.whuanle.cn/4.network/1.network.html 了解一下呢。

实践 2

我们知道,一个 Service 可以关联多个 Pod,为多个 Pod 提供负载均衡等功能。同时 Service 有 externalIP、clusterIP 等属性,要真正解析出一个 Service 是比较困难的。例如 Service 可以只有端口,没有 IP;也可以只使用 DNS 域名访问;也可以不绑定任何 Pod,可以从 Service A DNS -> Service B IP 间接访问 B;

Service 包含的情况比较多,读者可以参考下面这个图,下面我们通过代码,获取一个 Service 的 IP 和端口信息,然后生成对应的 IP+端口结构。

705800692b1c55e28afc9a13d2560c30.png

单纯获取 IP 和 端口是没用的,因为他们是分开的,你获取到的 IP 可能是 Cluter、Node、LoadBalancer 的,有可能只是 DNS 没有 IP,那么你这个端口怎么访问呢?这个时候必须根据一定的规则,解析信息,筛选无效数据,才能得出有用的访问地址。

首先定义一部分枚举和模型:

public enum ServiceType{ClusterIP,NodePort,LoadBalancer,ExternalName}/// <summary>/// Kubernetes Service 和 IP/// </summary>public class SvcPort{// LoadBalancer -> NodePort -> Port -> Target-Port/// <summary>/// 127.0.0.1:8080/tcp、127.0.0.1:8080/http/// </summary>public string Address { get; set; } = null!;/// <summary>/// LoadBalancer、NodePort、Cluster/// </summary>public string Type { get; set; } = null!;public string IP { get; set; } = null!;public int Port { get; set; }}public class SvcIpPort{public List<SvcPort>? LoadBalancers { get; set; }public List<SvcPort>? NodePorts { get; set; }public List<SvcPort>? Clusters { get; set; }public string? ExternalName { get; set; }}

编写解析代码:

static async Task Main(){var result = await GetSvcIpsAsync("kube-apiserver-master","kube-system");Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(result));}public static async Task<SvcIpPort> GetSvcIpsAsync(string svcName, string namespaceName){var client = GetClient();var service = await client.ReadNamespacedServiceAsync(svcName, namespaceName);SvcIpPort svc = new SvcIpPort();// LoadBalancerif (service.Spec.Type == nameof(ServiceType.LoadBalancer)){svc.LoadBalancers = new List<SvcPort>();var ips = svc.LoadBalancers;// 负载均衡器 IPvar lbIP = service.Spec.LoadBalancerIP;var ports = service.Spec.Ports.Where(x => x.NodePort != null).ToArray();foreach (var port in ports){ips.Add(new SvcPort{Address = $"{lbIP}:{port.NodePort}/{port.Protocol}",IP = lbIP,Port = (int)port.NodePort!,Type = nameof(ServiceType.LoadBalancer)});}}if (service.Spec.Type == nameof(ServiceType.LoadBalancer) || service.Spec.Type == nameof(ServiceType.NodePort)){svc.NodePorts = new List<SvcPort>();var ips = svc.NodePorts;// 负载均衡器 IP,有些情况可以设置 ClusterIP 为 None;也可以手动设置为 None,只要有公网 IP 就行var clusterIP = service.Spec.ClusterIP;var ports = service.Spec.Ports.Where(x => x.NodePort != null).ToArray();foreach (var port in ports){ips.Add(new SvcPort{Address = $"{clusterIP}:{port.NodePort}/{port.Protocol}",IP = clusterIP,Port = (int)port.NodePort!,Type = nameof(ServiceType.NodePort)});}}// 下面这部分代码是正常的,使用 {} 可以隔离部分代码,避免变量重名// if (service.Spec.Type == nameof(ServiceType.ClusterIP))// 如果 Service 没有 Cluster IP,可能使用了无头模式,也有可能不想出现 ClusterIP//if(service.Spec.ClusterIP == "None"){svc.Clusters = new List<SvcPort>();var ips = svc.Clusters;var clusterIP = service.Spec.ClusterIP;var ports = service.Spec.Ports.ToArray();foreach (var port in ports){ips.Add(new SvcPort{Address = $"{clusterIP}:{port.Port}/{port.Protocol}",IP = clusterIP,Port = port.Port,Type = nameof(ServiceType.ClusterIP)});}}if (!string.IsNullOrEmpty(service.Spec.ExternalName)){/* NAME            TYPE           CLUSTER-IP       EXTERNAL-IP          PORT(S)     AGEmyapp-svcname   ExternalName   <none>           myapp.baidu.com      <none>      1mmyapp-svcname ->  myapp-svc 访问 myapp-svc.default.svc.cluster.local,变成 myapp.baidu.com*/svc.ExternalName = service.Spec.ExternalName;}return svc;}

规则解析比较复杂,这里就不详细讲解,读者如有疑问,可联系笔者讨论。

主要规则:LoadBalancer -> NodePort -> Port -> Target-Port 。

最终结果如下:

3312dc68c1be42d022edde3e09ed5a34.png

通过这部分代码,可以解析出 Service 在 External Name、LoadBalancer、NodePort、ClusterIP 等情况下可真正访问的地址列表。

实践3 Endpoint 列表

如果对 Endpoint 不太了解,亲请打开 https://k8s.whuanle.cn/4.network/2.endpoint.html 看一下相关知识。

81fa982169a99e21e723eed58fd32796.png

在 Kubernetes 中,Service 不是直接关联 Pod 的,而是通过 Endpoint 间接代理 Pod。当然除了 Service -> Pod,通过 Endpoint,也可以实现接入集群外的第三方服务。例如数据库集群不在 Kubernetes 集群中,但是想通过 Kubernetes Service 统一访问,则可以利用 Endpoint 进行解耦。这里不多说,读者可以参考 https://k8s.whuanle.cn/4.network/2.endpoint.html 。

这里这小节中,笔者也将会讲解如何在 Kubernetes 中分页获取资源。

首先定义以下模型:

public class SvcInfoList{/// <summary>/// 分页属性,具有临时有效期,具体由 Kubernetes 确定/// </summary>public string? ContinueProperty { get; set; }/// <summary>/// 预计剩余数量/// </summary>public int RemainingItemCount { get; set; }/// <summary>/// SVC 列表/// </summary>public List<SvcInfo> Items { get; set; } = new List<SvcInfo>();}public class SvcInfo{/// <summary>/// SVC 名称/// </summary>public string Name { get; set; } = null!;/// <summary>/// 三种类型之一 <see cref="ServiceType"/>/// </summary>public string? ServiceType { get; set; }/// <summary>/// 有些 Service 没有 IP,值为 None/// </summary>public string ClusterIP { get; set; } = null!;public DateTime? CreationTime { get; set; }public IDictionary<string, string>? Labels { get; set; }public IDictionary<string, string>? Selector { get; set; }/// <summary>/// name,port/// </summary>public List<string> Ports { get; set; }public string[]? Endpoints { get; set; }}

Kubernetes 中的分页,没有 PageNo、PageSize、Skip、Take 、Limit 这些,并且分页可能只是预计,不一定完全准确。

第一次访问获取对象列表时,不能使用 ContinueProperty 属性。

第一次访问 Kubernets 后,获取 10 条数据,那么 Kubernetes 会返回一个 ContinueProperty 令牌,和剩余数量 RemainingItemCount。

那么我们可以通过 RemainingItemCount 计算大概的分页数字。因为 Kubernetes 是不能直接分页的,而是通过类似游标的东西,记录当前访问的位置,然后继续向下获取对象。ContinueProperty 保存了当前查询游标的令牌,但是这个令牌有效期是几分钟。

解析方法:

public static async Task<SvcInfoList> GetServicesAsync(string namespaceName, int pageSize = 1, string? continueProperty = null){var client = GetClient();V1ServiceList services;if (string.IsNullOrEmpty(continueProperty)){services = await client.ListNamespacedServiceAsync(namespaceName, limit: pageSize);}else{try{services = await client.ListNamespacedServiceAsync(namespaceName, continueParameter: continueProperty, limit: pageSize);}catch (Microsoft.Rest.HttpOperationException ex){throw ex;}catch{throw;}}SvcInfoList svcList = new SvcInfoList{ContinueProperty = services.Metadata.ContinueProperty,RemainingItemCount = (int)services.Metadata.RemainingItemCount.GetValueOrDefault(),Items = new List<SvcInfo>()};List<SvcInfo> svcInfos = svcList.Items;foreach (var item in services.Items){SvcInfo service = new SvcInfo{Name = item.Metadata.Name,ServiceType = item.Spec.Type,ClusterIP = item.Spec.ClusterIP,Labels = item.Metadata.Labels,Selector = item.Spec.Selector,CreationTime = item.Metadata.CreationTimestamp};// 处理端口if (item.Spec.Type == nameof(ServiceType.LoadBalancer) || item.Spec.Type == nameof(ServiceType.NodePort)){service.Ports = new List<string>();foreach (var port in item.Spec.Ports){service.Ports.Add($"{port.Port}:{port.NodePort}/{port.Protocol}");}}else if (item.Spec.Type == nameof(ServiceType.ClusterIP)){service.Ports = new List<string>();foreach (var port in item.Spec.Ports){service.Ports.Add($"{port.Port}/{port.Protocol}");}}var endpoint = await client.ReadNamespacedEndpointsAsync(item.Metadata.Name, namespaceName);if (endpoint != null && endpoint.Subsets.Count != 0){List<string> address = new List<string>();foreach (var sub in endpoint.Subsets){if (sub.Addresses == null) continue;foreach (var addr in sub.Addresses){foreach (var port in sub.Ports){address.Add($"{addr.Ip}:{port.Port}/{port.Protocol}");}}}service.Endpoints = address.ToArray();}svcInfos.Add(service);}return svcList;}

规则解析比较复杂,这里就不详细讲解,读者如有疑问,可联系笔者讨论。

调用方法:

static async Task Main(){var result = await GetServicesAsync("default", 2);Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(result.Items));if (result.RemainingItemCount != 0){while (result.RemainingItemCount != 0){Console.WriteLine($"剩余 {result.RemainingItemCount} 条数据,{result.RemainingItemCount / 3 + (result.RemainingItemCount % 3 == 0 ? 0 : 1)} 页,按下回车键继续获取!");Console.ReadKey();result = await GetServicesAsync("default", 2, result.ContinueProperty); Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(result.Items));}}}

38d97a67b482ab3d8b5c9da9d96622f4.png

90998c3b98c2c42e178d941d0254c254.png

上面的实践中,代码较多,建议读者启动后进行调试,一步步调试下来,慢慢检查数据,对比 Kubernetes 中的各种对象,逐渐加深理解。

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

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

相关文章

whitelabel error page什么意思_什么是RESTful API?总算能说清楚了

要弄清楚什么是RESTful API,首先要弄清楚什么是REST。REST -- REpresentational State Transfer&#xff0c;英语的直译就是“表现层状态转移”。如果看这个概念&#xff0c;估计没几个人能明白是什么意思。那下面就让我来用一句人话解释一下什么是RESTful:URL定位资源&#xf…

【转】Asp.net控件开发学习笔记整理篇 - 数据回传

最近一直在做MVC项目&#xff0c;对于WEBFORM 好像快忘记了。周末无聊&#xff0c;顺带看看他人的笔记。再次温习下。 复习大纲&#xff1a; 导航、页面生命周期及其它导论 一、服务器控件生命周期 二、控件开发基础 三、Asp.net服务端状态管理 四、Asp.net客户端状态管理 五、…

BZOJ2326 [HNOI2011]数学作业

首先&#xff0c;列方程 我们定义s[i] 10 ^ ((int) log(i)) 于是&#xff0c;f[i] (f[i - 1] * s[i] i) % p 反正总之就是个沙茶递推 然后我们来看优化。。。怎么感觉像矩阵乘法呢&#xff1f; 发现要按照log(i)即i的位数分类讨论&#xff0c;在相同位数的时候令矩阵为 s[i]…

简直不敢相信!这个史上最被低估的学科,看完竟瑟瑟发抖!

▲ 点击查看历史&#xff0c;无疑是大众参与度较高的知识性学科之一&#xff0c;既没有艰深的原理和公式&#xff0c;也不需要较高的欣赏能力。不仅门槛低&#xff0c;而且具有故事性&#xff0c;容易形成话题&#xff0c;茶余饭后&#xff0c;几乎每个人、每个孩子都能谈论几句…

一款强大的Kubernetes API流量查看神器

点击上方蓝字关注 &#x1f446;&#x1f446;大家好&#xff0c;我是小碗汤&#xff0c;今天分享一个k8s流量查看器~mizu。mizu 是为 Kubernetes 提供的一个简单而强大的 API 流量查看器&#xff0c;可以查看微服务之间的所有 API 通信&#xff0c;以帮助调试和排除故障。相当…

辉光UIView的category

辉光UIView的category 本人视频教程系类 iOS中CALayer的使用 效果如下&#xff1a; 源码&#xff1a; UIViewGlowView.h 与 UIViewGlowView.m // // UIViewGlowView.h // YouXianClock // // Created by YouXianMing on 14-12-21. // Copyright (c) 2014年 YouXianMing. …

javascript 动态创建表格

<html><head><script>function createTable(rows,lines){this.rowsrows;this.lineslines;var Bodydocument.getElementById(body);var Tabledocument.createElement(table);//创建table标签元素Table.setAttribute(border,1);//给table标签添加其他属性for(v…

linux c之加入了加入原文件 math.h调用abs()函数出现implicit declaration of function错误

今天在vim 写C语言的时候 代码我已经导入了#include<math.h> 但是当我调用ads()函数的时候出现了下面错误 解决办法&#xff1a; 把abs函数改写成fabs函数就行&#xff0c;然后去网上找原因&#xff0c;发现fabs是求浮点数的&#xff0c;ads求整形的&#xff0c;以后在…

你的女神今日结婚了!!!你失恋了......

1 新垣结衣结了婚▼2 我和朋友最近的聊天内容&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼3 白粥盖浇饭&#xff1f;&#xff1f;&#xff1f;&#xff08;素材来源网络&#xff0c;侵删&#xff09;▼4 中国人的辈分可以复杂到什么程度&#xff1f;&#xff08…

我的技术回顾那些与ABP框架有关的故事-2017年

推荐阅读&#xff1a;我的技术回顾那些与ABP框架有关的故事-2015年从ABP框架国内社区发展回顾.NET技术变迁-2016年从2022年来回顾ABP框架&#xff0c;我们会发现无论是商业模式还是架构设计思路&#xff0c;如果没有良好的商业模式的话&#xff0c;ABP框架很容易进入难产的状态…

Camera360与全球1.8亿用户共同创造更美的照片

Camera360是成都品果科技有限公司推出的基于IOS、Windows Phone和安卓系统的功能强大的手机摄影软件。能拍摄出不同风格&#xff0c;不同特效的照片&#xff0c;同时具有互联网分享功能。Camera360在全球拥有1.8亿用户&#xff0c;国外0.95亿&#xff0c;国内0.85亿&#xff0c…

八皇后问题(一)

问题描述: 要在8*8的国际象棋棋盘中放8个皇后,使任意两个皇后都不能互相吃掉。规则是皇后能吃掉同一行、同一列、同一对角线的棋子。如下图即是两种方案: 思路: 比如我们搞个数组,数组的下表表示多少行,然后数值表示多少列,比如a[4] = 5,意思就代表第四行,第五列 首先…

linux shell 嵌套expect 与服务器交互脚本

2019独角兽企业重金招聘Python工程师标准>>> 我们与服务器进行交互是该用expect 脚本的&#xff0c;用 “/usr/bin/expect <<-EOF” 来开启expect 脚本 用spawn 来开启一个新的进程 expect 来接受命令&#xff0c;send来发送交互命令 结束用 EOF来over expect…

SkyWalking集成与案例

今天我们通过代码的形式来了解下&#xff0c;如何在项目中使用Skywalking。前几篇文章可以参考&#xff1a;《学习Skywalking 搭建篇》《Skywalking执行效果 多图篇》《Skywalking的ES索引 收藏篇》今天说说代码篇。先说下比较常见的开源 APM 如下&#xff1a;CAT&#xff1…

Windows Azure 安全最佳实践 - 第 6 部分:Azure 服务如何扩展应用程序安全性

多种 Windows Azure服务可以帮助您将应用程序安全性扩展到云。 有三种服务可提供多个提供程序之间的身份标识映射、内部部署数据中心间的连接和相互发送消息的应用程序功能&#xff08;无论应用程序位于何处&#xff09;。 使用Windows Azure Active Directory&#xff0c;您…

Windows Server 2012活动目录基础配置与应用(新手教程)之3---将客户机加入到指定域...

在WIN 2012服务器上安装AD后&#xff0c;WIN2012就从普通的服务器变成了域控制器。一个域也就产生了。但遗憾的是&#xff0c;目前这个域的规模还很小&#xff0c;只有DC这一台主机-------光杆司令&#xff01;&#xff01;下面尝试扩大域的规模&#xff0c;将客户机加入到域。…

论物理学界的神预言

全世界只有3.14 % 的人关注了爆炸吧知识一沙见世界 一花窥天堂手心握无限 须臾纳永恒杨振宁曾说读上面的四句诗可以感受到物理的美但物理的美不止于此物理还有一种庄严美一种神秘美一种初窥宇宙奥秘的畏惧美物理就是如此的迷人任何语言在它的面前都很贫瘠数学让人摆脱了愚昧而…

聊一聊如何用C#轻松完成一个SAGA分布式事务

背景 银行跨行转账业务是一个典型分布式事务场景&#xff0c;假设 A 需要跨行转账给 B&#xff0c;那么就涉及两个银行的数据&#xff0c;无法通过一个数据库的本地事务保证转账的 ACID &#xff0c;只能够通过分布式事务来解决。市面上使用比较多的分布式事务框架&#xff0c…

梯度消失和梯度爆炸_知识干货-动手学深度学习-05 梯度消失和梯度爆炸以及Kaggle房价预测...

梯度消失和梯度爆炸考虑到环境因素的其他问题Kaggle房价预测梯度消失和梯度爆炸深度模型有关数值稳定性的典型问题是消失&#xff08;vanishing&#xff09;和爆炸&#xff08;explosion&#xff09;。当神经网络的层数较多时&#xff0c;模型的数值稳定性容易变差。PyTorch的默…