本教程已加入 Istio 系列:https://istio.whuanle.cn

3,快速入门

在本章中,我们正式迈入学习 Istio 的第一步。因为 Istio 的知识体系是较为庞大的,因此我们可以先通过本章的入门教程快速了解如何使用 Istio 部署一套微服务,以及 Istio 核心功能的使用方法,了解 Istio 可以为微服务解决什么问题。

在本章中,我们将会学习到如何部署一套微服务、如何使用 Istio 暴露服务到集群外,并且如何使用可观测性组件监测流量和系统指标。

在后面的章节中,笔者会针对每个 Istio 组件做单独讲解,而在本章中,我们只需要大概了解使用方法即可。

书店微服务

本章教程示例使用的是 Istio 官方的一套微服务,这套微服务是一个在线书店,打开页面之后会看到一个分类、书的信息以及书的评论,页面的内容由不同的子服务提供。

书店微服务分为四个单独的微服务,在上图中已经使用红色方框画出来了。这四个微服务分别是:

  • productpage: 汇集所有服务的数据,生成浏览页面。
  • details:存储了书籍的信息,如描述、作者、出版社等。
  • reviews:存储了书籍相关的评论,但是不包含评分打星。
  • ratings:存储评论中的评分打星。

在这个微服务中,Productpage 服务对外提供 Web 访问页面,而且其它的三个服务只能在集群内部访问。四个服务分别采用了不同的语言开发,Productpage 聚合其它三个服务的信息生成一个页面。

在微服务设计中,我们不要每个子服务都暴露端口到集群外部,应该通过一些应用集中数据后给外部显示。我们可以使用 API 网关,代理子服务一部分接口,然后在 API 网关中实现基于客户端或第三方调用的身份验证。

productpage、details、ratings 都只有一个 v1 版本,而 reviews 有三个版本。

ratings 负责给出用户打分的数据,例如一星、两星。而 reviews 三个版本分别对 ratings 的数据做以下处理:

  • reviews v1:屏蔽星级,不显示打分;
  • reviews v2:显示星级,使用灰色星星表示,★★★★☆;
  • reviews v3:显示星级,使用红色星星表示,★★★★☆;

【图源 istio 官网

服务依赖图如下所示:

接下来我们将会使用 Kuubernetes Deployment 部署这些服务,这跟常规的 Kubernetes 部署并无差别。

预先准备

给这些示例服务创建一个命名空间。

kubectl create namespace bookinfo

给命名空间添加 Istio 的标签,指示 Istio 在部署应用(只对 Pod 起效)的时候,自动注入 Envoy Sidecar Proxy 容器:

kubectl label namespace bookinfo istio-injection=enabled

开启让 Istio 注入 Sidecar 有很多种方式,其中一种是给命名空间设置下标签,在此命名空间下部署的 Pod,会被自动注入 Sidecar 。

你可以从本系列教程的 git 仓库中找到这些示例,文件位置:https://github.com/whuanle/istio_book/tree/main/3

仓库拉取后打开 3 目录,执行命令进行部署:

kubectl -n bookinfo apply -f details_deploy.yaml
kubectl -n bookinfo apply -f details_svc.yaml
kubectl -n bookinfo apply -f details_sa.yaml
kubectl -n bookinfo apply -f ratings_deploy.yaml
kubectl -n bookinfo apply -f ratings_svc.yaml
kubectl -n bookinfo apply -f ratings_sa.yaml
kubectl -n bookinfo apply -f reviews_v1_deploy.yaml
kubectl -n bookinfo apply -f reviews_v2_deploy.yaml
kubectl -n bookinfo apply -f reviews_v3_deploy.yaml
kubectl -n bookinfo apply -f reviews_svc.yaml
kubectl -n bookinfo apply -f reviews_sa.yaml
kubectl -n bookinfo apply -f productpage_deploy.yaml
kubectl -n bookinfo apply -f productpage_svc.yaml
kubectl -n bookinfo apply -f productpage_sa.yaml

或者你可以参考下面的四个小节,通过手动的方式部署应用,了解每一个应用是如何定义的。

details 应用

存储了书籍信息的应用。

部署命令:

kubectl -n bookinfo apply -f details_deploy.yaml
kubectl -n bookinfo apply -f details_svc.yaml
kubectl -n bookinfo apply -f details_sa.yaml

使用 Deployment 部署 details 应用。

details_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
app: details
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: details
version: v1
template:
metadata:
labels:
app: details
version: v1
spec:
serviceAccountName: bookinfo-details
containers:
- name: details
image: docker.io/istio/examples-bookinfo-details-v1:1.17.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
securityContext:
runAsUser: 1000

部署 details。

kubectl -n bookinfo apply -f details_deploy.yaml

为 details 服务配置 Kubernetes Service 。

details_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
service: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
kubectl -n bookinfo apply -f details_svc.yaml

接下来为 details 服务创建一个 ServiceAccount。

Istio 为服务之间的通信提供基于双向 TLS 的认证,这是是通过给每个 ServiceAccount 创建一个证书实现的,可以使用 ServiceAccount 验证对方的身份,不同的应用可以共享同一个 ServiceAccount,但是为每个 Deployment 使用单独的 ServiceAccount 可以更好地组织和管理安全配置。

details_sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-details
labels:
account: details
kubectl -n bookinfo apply -f details_sa.yaml

ratings 应用

提供每条评论的打星数据。

部署命令:

kubectl -n bookinfo apply -f ratings_deploy.yaml
kubectl -n bookinfo apply -f ratings_svc.yaml
kubectl -n bookinfo apply -f ratings_sa.yaml

ratings_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: ratings-v1
labels:
app: ratings
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: ratings
version: v1
template:
metadata:
labels:
app: ratings
version: v1
spec:
serviceAccountName: bookinfo-ratings
containers:
- name: ratings
image: docker.io/istio/examples-bookinfo-ratings-v1:1.17.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
securityContext:
runAsUser: 1000

ratings_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
app: ratings
service: ratings
spec:
ports:
- port: 9080
name: http
selector:
app: ratings

ratings_sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-ratings
labels:
account: ratings

reviews v1/v2/v3 应用

提供书籍的评论信息。

部署命令:

kubectl -n bookinfo apply -f reviews_v1_deploy.yaml
kubectl -n bookinfo apply -f reviews_v2_deploy.yaml
kubectl -n bookinfo apply -f reviews_v3_deploy.yaml
kubectl -n bookinfo apply -f reviews_svc.yaml
kubectl -n bookinfo apply -f reviews_sa.yaml

为三个版本的 reviews 创建三个 Deployment。

reviews_v1_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v1:1.17.0
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
securityContext:
runAsUser: 1000
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}

reviews_v2_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v2
labels:
app: reviews
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v2
template:
metadata:
labels:
app: reviews
version: v2
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v2:1.17.0
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
securityContext:
runAsUser: 1000
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}

reviews_v3_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v3
labels:
app: reviews
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v3
template:
metadata:
labels:
app: reviews
version: v3
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: docker.io/istio/examples-bookinfo-reviews-v3:1.17.0
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
securityContext:
runAsUser: 1000
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}

给三个 Deployment 创建一个 Service,三个相同应用的不同版本共有同一个 Service。

reviews_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
service: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews

reviews_sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
labels:
account: reviews

productpage 应用

页面聚合服务,供用户浏览书籍信息。

部署命令:

kubectl -n bookinfo apply -f productpage_deploy.yaml
kubectl -n bookinfo apply -f productpage_svc.yaml
kubectl -n bookinfo apply -f productpage_sa.yaml

productpage_deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
labels:
app: productpage
version: v1
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: docker.io/istio/examples-bookinfo-productpage-v1:1.17.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
securityContext:
runAsUser: 1000
volumes:
- name: tmp
emptyDir: {}

productpage_svc.yaml

apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage

productpage_sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
labels:
account: productpage

检查

执行命令完成后,查看 bookinfo 命名空间下的 Pod。

kubectl get pods -n bookinfo

可以看到,每个 Pod 的 READY 属性都是 2/2 ,这表示该 Pod 中有两个容器,并且当前有两个容器已经就绪。

如果我们查看其中一个 Pod 的组成结构,会发现有 Pod 被塞进了一个 istio-proxy 容器。

如果 Kubernetes 中没有安装 Dashbooard ,那么可以使用 kubectl -n bookinfo describe pod {Pod ID} 查看组成结构。

接着使用 kubectl -n bookinfo get svc 查看 Service,四个微服务都已经被注册了 Service。

然后我们访问 productpage 对应的 CLUSTER-IP:

curl 10.233.37.130:9080

默认 Istio 不会开启零信任双向认证模式,因此在集群内可以自己访问应用。如果开启了 mTLS 双向认证模式,则只能在 Pod 中访问应用。

可以看到返回了一堆 html,说明我们的部署是正常的。

临时访问

接着为了查看页面效果,我们在暂未使用 Istio-ingressgateway 之前,临时创建一个 Service 暴露 productpage 的页面。

productpage_tmpsvc.yaml

apiVersion: v1
kind: Service
metadata:
name: productpagetmp
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
type: NodePort
kubectl -n bookinfo apply -f  productpage_tmpsvc.yaml

查看所有 Service:

root@k8smain:/data/learn/book# kubectl -n bookinfo get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.233.63.247 <none> 9080/TCP 40m
productpage ClusterIP 10.233.37.130 <none> 9080/TCP 23m
productpagetmp NodePort 10.233.47.14 <none> 9080:30258/TCP 77s
ratings ClusterIP 10.233.7.6 <none> 9080/TCP 36m
reviews ClusterIP 10.233.58.219 <none> 9080/TCP 23m

然后在页面中访问 30258 端口(大家的端口不一样,按自己的来)。

接着打开 http://192.168.3.150:30258/productpage?u=normal

因为当前使用 Service 绑定 Pod,因此会使用轮询实现负载均衡,你可以多次刷新 http://192.168.3.150:30258/productpage?u=normal,会查到右侧的评分星星有所变化。

Istio 默认情况下使用轮询负载均衡的方法。

页面右侧评论显示规则是 无星星 => 黑色星星 => 红色星星。

部署入口网关

什么是 Gateway

终于来到体验 Istio 的时刻了,在本小节中,我们将会为 productpage 创建 Istio Gateway,对外提供网页访问。

在第二章中,我们已经部署了 istio-ingressgateway,这个组件起到了类似 nginx、apisix 的效果,对外提供端口访问,然后将流量转发到内部服务中。

但是 istio-ingressgateway 并不能直接转发流量到 Pod,它还需要进行一些配置。我们要为 productpage 创建一个站点,绑定对应的域名,这样外部访问 istio-ingressgateway 的端口时,istio-ingressgateway 才知道该将流量转发给谁。在 Istio 中,定义这种绑定关系的资源叫 Gateway

后面的章节会解释清楚,这里大概了解即可。

Gateway 类似 Nginx 需要创建一个反向代理时需要绑定的域名配置。

部署 Gateway

创建一个 Gateway,绑定域名入口。

ingress_gateway.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"

hosts 表示对外开放的访问路径,你可以绑定域名、IP 等。这里使用 * ,表示所有访问都可以进入此网关。

kubectl -n bookinfo apply -f ingress_gateway.yaml

这一步就像 nginx 的监听配置:

server {
listen 80;
server_name example.org www.example.org;
#...
}

当我们创建 Istio Gateway 之后,istio-ingressgateway 会为我们监控流量,检测不同的域名或端口属于哪个 Istio Gateway 。

部署 VirtualService

什么是 VirtualService

虽然创建了 Istio Gateway,但是我们还不能直接通过网关访问到前面部署的微服务,我们还需要创建 Istio VirtualService 将 Istio Gateway 跟对应的 Kubernetes Service 绑定起来,然后流量才能正式流向 Pod。

请一定要注意这里,流量实际并不会经过 Service 中,但是 VirtualService 需要通过 Service 来发现 Pod。

这里类似 nginx 配置反向代理,配置监听之后,还需要指向将请求映射到哪个地址。

server {
listen 80;
server_name example.org www.example.org;
#...
} location /some/path/ {
proxy_pass http://A:9080;
}

为什么不直接将 Gateway 跟 Service 绑定,而是中间加个 VirtualService 呢?有句话叫做,计算机领域中的问题,都可以通过增加一个层来解决。

VirtualService 的主要目标是为服务提供稳定的入口地址,并通过配置一系列的路由规则来控制流量在网格内的行为。

就以最简单的路由区配来说,Kubernetes Service 是不支持路由规则的,而 Istio 可以通过指定路由后缀中;Service 不支持流量分析,负载均衡只有轮询。而 Istio 利用 Service 来发现 Pod,然后直接将流量转发到 Pod 中,可以实现各种功能。

VirtualService 可以用于实现以下功能:

请求路由:将请求路由到特定的服务或版本,例如将请求分发到不同版本的服务,以实现灰度发布或金丝雀发布。

请求重试:为失败的请求配置重试策略,以提高服务的可用性。

请求超时:设置请求的超时时间,以便在特定时间内没有得到响应时中断请求。

请求镜像:将请求的副本发送到另一个服务,用于测试新版本的服务,而不影响实际的生产流量。

流量分割:将流量按照特定的比例分发到不同的服务或版本,以实现流量控制。

部署 VirtualService

productpage_vs.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
kubectl -n bookinfo apply -f productpage_vs.yaml

关于 VistualService 中各种配置的作用,在 4.1 章节中会有介绍。

这里的 YAML 分为两大部分,第一部分是 http.match,表示暴露了哪些 API 地址,外部访问时只能访问到这些地址。

可以通过 http.match 限制集群外部访问此地址时所能使用的 URL。

然后通过 http.route 绑定 Kubernetes Service ,通过 Service 中的服务发现,将流量转发到对应的 Pod 中。

host 这里,由于 VirtualService 跟 Service/Pod 在同一个命名空间中,所以只需要配置 Service 的名称即可,如果要跨命名空间访问,则需要加上完整的命名空间名称。

什么是 DestinationRule

在本章中,会提前预告 DestinationRule,下一章才会使用 DestinationRule,这里我们知道还有 DestinationRule 这个东西即可。

Istio VistualService 中可以限制外部能够访问的路由地址,而 DestinationRule 则可以配置访问的 Pod 策略。可以为 Istio VistualService 绑定一个 Istio DestinationRule,通过 DestinationRule 我们还可以定义版本子集等,通过更加丰富的策略转发流量。

由于只暴露了五个地址,所以外部直接访问 / ,是打不开页面的。

检查

为了确保网关没问题,我们需要执行 Istio 命令查看日志:

istioctl analyze

然后我们查看为 productpage 创建的网关。

root@k8smain:/data/learn/book# kubectl get gw -A
NAMESPACE NAME AGE
bookinfo bookinfo-gateway 26m

Kubernetes 本身也有一个 Gateway,因此不能使用 kubectl get gateway 来获取 Istio 的 Gateway,而是使用简写 gw

然后查看 VistualService。

root@k8smain:/data/learn/book# kubectl get vs -A
NAMESPACE NAME GATEWAYS HOSTS AGE
bookinfo bookinfo ["bookinfo-gateway"] ["*"] 79m

在第二章中,我们通过 Helm 部署了 istio-ingressgateway,其访问端口如下:

在本节部署 bookinfo-gateway 的时候,我们使用了端口 80,因此不需要另外配置 ,直接通过 istio-ingressgateway 的 32309 端口访问即可。

访问时一定需要带 /productpage ,因为我们并没有放通 /

尝试修改 Gateway 端口

如果需要更换端口,可以修改 istio-ingressgateway 的 Service,增加新的端口映射。

kubectl edit svc istio-ingressgateway -n istio-system

然后修改前面的 ingress_gateway.yaml,将端口从 80 改成 666 。

即可通过 32666 端口访问到此微服务。

示例:http://192.168.3.150:30666/productpage

Istio 入门(三):体验 Istio、微服务部署、可观测性的更多相关文章

  1. docker微服务部署之:三,搭建Zuul微服务项目

    docker微服务部署之:二.搭建文章微服务项目 一.新增demo_eureka模块,并编写代码 右键demo_parent->new->Module->Maven,选择Module ...

  2. 解读与部署(三):基于 Kubernetes 的微服务部署即代码

    在基于 Kubernetes 的基础设施即代码一文中,我概要地介绍了基于 Kubernetes 的 .NET Core 微服务和 CI/CD 动手实践工作坊使用的基础设施是如何使用代码描述的,以及它的 ...

  3. 将微服务部署到 Azure Kubernetes 服务 (AKS) 实践

    本文是对 <.NET Tutorial - Deploy a microservice to Azure> 的翻译和实践.入门级踩坑实践,k8s 大佬请回避,以免耽误您宝贵的时间. 介绍 ...

  4. 转载 (三)surging 微服务框架使用系列之我的第一个服务(审计日志)

    (三)surging 微服务框架使用系列之我的第一个服务(审计日志)   前言:前面准备了那么久的准备工作,现在终于可以开始构建我们自己的服务了.这篇博客就让我们一起构建自己的第一个服务---审计日志 ...

  5. docker微服务部署之:七、Rancher进行微服务扩容和缩容

    docker微服务部署之:六.Rancher管理部署微服务 Rancher有两个特色用起来很方便,那就是扩容和缩容. 一.扩容前的准备工作 为了能直观的查看效果,需要修改下demo_article项目 ...

  6. docker微服务部署之:六、Rancher管理部署微服务

    docker微服务部署之:五.利用DockerMaven插件自动构建镜像 一. 什么是Rancher Rancher是一个开源的企业级容器管理平台.通过Rancher,企业再也不必自己使用一系列的开源 ...

  7. docker微服务部署之:五、利用DockerMaven插件自动构建镜像

    docker微服务部署之:四.安装docker.docker中安装mysql和jdk1.8.手动构建镜像.部署项目 在上一篇文章中,我们是手动构建镜像,即: 4.1.2.5.1.2.6.1.2中的将d ...

  8. docker微服务部署之:四、安装docker、docker中安装mysql和jdk1.8、手动构建镜像、部署项目

    docker微服务部署之:三,搭建Zuul微服务项目 1.Centos7安装Docker 详见:Centos7安装Docker 2.Docker中安装jdk1.8 详见:使用Docker构建jdk1. ...

  9. docker微服务部署之:二、搭建文章微服务项目

    docker微服务部署之:一,搭建Eureka微服务项目 一.新增demo_article模块,并编写代码 右键demo_parent->new->Module->Maven,选择M ...

  10. docker微服务部署之:一,搭建Eureka微服务项目

    先说明一下docker需要搭建的微服务的基本情况: 项目情况:一个demo_parent项目,下面三个子模块:demo_eureka(eureka服务).demo_article(文章服务).demo ...

随机推荐

  1. PHP利用 JSON 将XML转换为数组

    在很多开发项目中,我们都会遇到将XML文件转换为数组使用,因此在本篇 PHP教程 中,UncleToo和大家一起学习 如何转换XML为数组 . 现在有一个uncletoo.xml的配置文件,格式如下: ...

  2. API Gateway vs Load Balancer:选择适合你的网络流量管理组件

    本文从对比了 API Gateway 和 Load Balancer 的功能区别,帮助读者更好地了解他们在系统架构中扮演的角色. 作者陈泵,API7.ai 技术工程师. 原文链接 由于互联网技术的发展 ...

  3. 【GPT开发】人人都能用ChatGPT4.0做Avatar虚拟人直播

    0 前言 最近朋友圈以及身边很多朋友都在研究GPT开发,做了各种各样的小工具小Demo,AI工具用起来是真的香!在他们的影响下,我也继续捣鼓GPT Demo,希望更多的开发者加入一起多多交流. 上一篇 ...

  4. [ Docker ] 部署 nps 和 npc 实现内网穿透

    https://www.cnblogs.com/yeungchie/ 云主机上运行 nps 创建映射目录 mkdir -p ~/docker/nps/config 拉取镜像 docker pull o ...

  5. 魔王语言问题c语言实现及思路求解

    文章目录 问题描述及需求分析 需求分析 问题分析及实现路线(队列+栈) 结构体核心代码 队列核心代码 入队 出队 栈的核心代码 入栈 出栈 全部代码 单向循环队列和栈(改变B的对应密码) 总结 问题描 ...

  6. Go坑:time.After可能导致的内存泄露问题分析

    Go 中 time.After 可能导致的内存泄露 一.Time 包中定时器函数 go v1.20.4 定时函数:NewTicker,NewTimer 和 time.After 介绍 time 包中有 ...

  7. 【C#】图片上传并根据长宽大小进行正方形、长方形及等比缩放。

    #region 正方型裁剪并缩放 /// <summary> /// 正方型裁剪 /// 以图片中心为轴心,截取正方型,然后等比缩放 /// 用于头像处理 /// </summary ...

  8. Web进阶LNMP网站部署

    Web进阶LNMP网站部署 目录 Web进阶LNMP网站部署 LNMP架构工作流程 部署LNMP架构 1.安装nginx 2.安装php 3.安装数据库 将Nginx和PHP建立连接 1.修改ngin ...

  9. 2021-04-10:给定两个可能有环也可能无环的单链表,头节点head1和head2。请实现一个函数,如果两个链表相交,请返回相交的 第一个节点。如果不相交,返回null。【要求】如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度 请达到O(1)。

    2021-04-10:给定两个可能有环也可能无环的单链表,头节点head1和head2.请实现一个函数,如果两个链表相交,请返回相交的 第一个节点.如果不相交,返回null.[要求]如果两个链表长度之 ...

  10. 【Vue2.x源码系列08】Diff算法原理

    什么是虚拟DOM DOM是很慢的,其元素非常庞大,当我们频繁的去做 DOM更新,会产生一定的性能问题,我们可以直观感受一下 div元素包含的海量属性 在Javascript对象中,虚拟DOM 表现为一 ...