openshift 4.3 Istio的搭建

本文档覆盖了官方文档的Setup的所有章节

安装Istio

本次安装的Istio版本为1.6.0,环境为openshift 4.3

注:不建议使用openshift 1.11(即kubernetes 3.11)安装istio,可能会出现如下兼容性问题,参见此issue

must only have "properties", "required" or "description" at the root if the status subresource is enabled

openshift安装Istio

istio的安装涉及到两个文件:profile和manifest。前者用于控制组件的安装和组件的参数,profile配置文件所在的目录为install/kubernetes/operator/profiles;后者为安装所使用的yaml文件,如service,deployment等,会用到profile提供的参数,manifest配置文件所在的目录为install/kubernetes/operator/charts。因此可以通过两种方式安装istio,一种是通过profile进行安装,istio默认使用这种方式,如:

$ istioctl manifest apply --set profile=default

第二种是通过导出的manifest进行安装,如:

$ kubectl apply -f $HOME/generated-manifest.yaml

参考不同平台可以参考对应的SetUp。在openshift下面部署istio需要注意版本

OpenShift 4.1 and above use nftables, which is incompatible with the Istio proxy-init container. Make sure to use CNI instead.

首先创建istio-system命名空间

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: istio-system
labels:
istio-injection: disabled
EOF

允许istio的serviceaccount使用UID为0的用户,使用的命名空间为istio-system

$ oc adm policy add-scc-to-group anyuid system:serviceaccounts:istio-system

istio默认会注入一个名为istio-initinitContainer,用于将pod的网络流量导向istio的sidecar proxy,该initContainer需要用到完整的NET_ADMINNET_RAW capabilities来配置网络,由此可能造成安全问题,使用istio CNI插件可以替换istio-init,且无需提升kubernetes RBAC权限,区别见下:

# with istio-cni
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
runAsGroup: 1337
runAsNonRoot: true
runAsUser: 1337 # without istio-cni
capabilities:
add:
- NET_ADMIN
- NET_RAW
drop:
- ALL
privileged: false
readOnlyRootFilesystem: false
runAsGroup: 0
runAsNonRoot: false
runAsUser: 0

由于openshift 4.1以上版本不再使用iptables,转而使用nftables,因此需要安装istio CNI插件,否则在sidecar注入时会出现如下istio iptables-restore: unable to initialize table 'nat'的错误,即无法执行iptables-resotre命令。

执行如下命令安装istio-cni并使用default类型的profile(见下)安装istio,具体参数含义参见官方文档

cat <<'EOF' > cni-annotations.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
cni:
enabled: true
namespace: kube-system
values:
cni:
excludeNamespaces:
- istio-system
- kube-system
chained: false
cniBinDir: /var/lib/cni/bin
cniConfDir: /etc/cni/multus/net.d
cniConfFileName: istio-cni.conf
sidecarInjectorWebhook:
injectedAnnotations:
"k8s.v1.cni.cncf.io/networks": istio-cni
EOF
$ istioctl manifest apply -f cni-annotations.yaml

安装结果如下:

# oc get pod
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-64f6f9d5c6-lwcp8 1/1 Running 0 41m
istiod-5bb879d86c-6ttml 1/1 Running 0 42m
prometheus-77b9c64b9c-r2pld 2/2 Running 0 41m
# oc get pod -nkube-system
NAME READY STATUS RESTARTS AGE
istio-cni-node-2xzl8 2/2 Running 0 41m
istio-cni-node-4nb6k 2/2 Running 0 41m
istio-cni-node-7j5ck 2/2 Running 0 41m
istio-cni-node-f9bnf 2/2 Running 0 41m
istio-cni-node-lp7v6 2/2 Running 0 41m

为ingress gateway暴露router:

$ oc -n istio-system expose svc/istio-ingressgateway --port=http2

至此istio的基本组件已经安装完毕,可以使用如下方式导出本次安装的profile

$ istioctl profile dump -f cni-annotations.yaml > generated-profile.yaml

使用如下命令导出安装istio的manefest的内容

$ istioctl manifest generate -f cni-annotations.yaml  > generated-manifest.yaml

校验安装结果

$ istioctl verify-install -f generated-manifest.yaml

istio会使用UID为1337的用户将sidecar注入到应用中,openshift默认不允许使用该用户,执行如下命令进行授权。target-namespace为应用所在的命名空间。

$ oc adm policy add-scc-to-group privileged system:serviceaccounts:<target-namespace>
$ oc adm policy add-scc-to-group anyuid system:serviceaccounts:<target-namespace>

当清理应用pod后,需要删除添加的权限

$ oc adm policy remove-scc-from-group privileged system:serviceaccounts:<target-namespace>
$ oc adm policy remove-scc-from-group anyuid system:serviceaccounts:<target-namespace>

openshift下使用multus管理CNI,它需要在应用的命名空间中部署NetworkAttachmentDefinition来使用istio-cni插件,使用如下命令创建NetworkAttachmentDefinitiontarget-namespace替换为实际应用所在的命名空间。

$ cat <<EOF | oc -n <target-namespace> create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: istio-cni
EOF

移除应用后,使用如下方式移除NetworkAttachmentDefinition

$ oc -n <target-namespace> delete network-attachment-definition istio-cni
更新istio配置

例如可以使用如下方式卸载已经安装的第三方工具Prometheus,注意必须带上文件cni-annotations.yaml,否则会使用默认的profile重新配置istio,这样会导致删除istio-cni。如果组件的配置没有改变,则不会重新该组件的pod

$ istioctl manifest apply -f cni-annotations.yaml --set addonComponents.prometheus.enabled=false
openshif卸载istio
$ istioctl manifest generate -f cni-annotations.yaml | kubectl delete -f -

标准安装istio

istioctl 使用内置的charts生成manifest,这些charts位于目录install/kubernetes/operator/charts

# ll
total 36
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 base
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 gateways
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-cni
drwxr-xr-x. 5 root root 4096 Apr 21 06:51 istio-control
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istiocoredns
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-operator
drwxr-xr-x. 3 root root 4096 Apr 21 06:51 istio-policy
drwxr-xr-x. 8 root root 4096 Apr 21 06:51 istio-telemetry
drwxr-xr-x. 4 root root 4096 Apr 21 06:51 security

直接执行如下命令即可安装官方默认配置的istio。

$ istioctl manifest apply --set profile=default

istio默认支持如下6种profile

# istioctl profile list
Istio configuration profiles:
default
demo
empty
minimal
preview
remote

安装的组件的区别如下:

default demo minimal remote
Core components
istio-egressgateway X
istio-ingressgateway X X
istio-pilot X X X
Addons
grafana X
istio-tracing X
kiali X
prometheus X X X

使用如下方式可以查看某个profile的配置信息,profile类型helm的values.yaml,用于给部署用的yaml提供配置参数。每个组件包含两部分内容:components下的组件以及组件的参数value

istio提倡使用IstioOperator API进行定制化配置。

$ istioctl profile dump default

使用如下方式可以查看某个组件的配置:

$ istioctl profile dump --config-path components.pilot default

在安装前可以使用如下方式导出需要安装的所有yaml信息 ,包括CRD,deployment,service等

$ istioctl manifest generate --set profile=default --set hub=docker-local.com/openshift4 > $HOME/generated-manifest.yaml

在进行确认或修改之后可以使用apply命令执行安装

$ kubectl apply -f $HOME/generated-manifest.yaml

使用如下方式校验安装结果

$ istioctl verify-install -f $HOME/generated-manifest.yaml

自定义配置:

  • 使用--set选项进行设置,如下面用于设置profile中的global.controlPlaneSecurityEnabled为true

    $ istioctl manifest apply --set values.global.controlPlaneSecurityEnabled=true
  • 如果修改的参数比较多,可以使用yaml文件统一进行配置,实际使用IstioOperator API进行profile的修改

    $ istioctl manifest apply -f samples/operator/pilot-k8s.yaml

istio的核心组件定义在 IstioOperator API的components下面:

Components
base
pilot
proxy
sidecarInjector
telemetry
policy
citadel
nodeagent
galley
ingressGateways
egressGateways
cni

第三方插件可以在IstioOperator API 的addonComponents下指定,如:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
addonComponents:
grafana:
enabled: true

每个组件都有一个KubernetesResourceSpec,用于设置如下k8s属性

  1. Resources
  2. Readiness probes
  3. Replica count
  4. HorizontalPodAutoscaler
  5. PodDisruptionBudget
  6. Pod annotations
  7. Service annotations
  8. ImagePullPolicy
  9. Priority class name
  10. Node selector
  11. Affinity and anti-affinity
  12. Service
  13. Toleration
  14. Strategy
  15. Env
标准卸载istio
$ istioctl manifest generate <your original installation options> | kubectl delete -f -

更新Istio

金丝雀升级

revision安装方式支持同时部署多个版本的istio,在升级时可以将流量逐步转移到新版本的istio上。每个修订revision都是一个完整的istio控制面,具有独立的Deployment, Service等。

控制面升级

使用如下方式可以安装一个名为canary的istio修订版本。下面方式默认会使用default profile创建一套新的istio,如果新的istio和老的istio有组件重叠,则可能导致组件重建。从下面的AGE字段可以看出,新的Prometheus覆盖了老的Prometheusingressgateway也一样,因此最好的方式是指定文件,参见istio install

$ istioctl install --set revision=canary

命令执行成功后,可以看到存在2个控制面,每个控制面有各自的DeploymentService等。

$ oc get pod
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-c9648ffbd-9pmwk 1/1 Running 0 113m
istiod-788cf6c878-cmn47 1/1 Running 0 139m
istiod-canary-79599d745b-ph7gj 1/1 Running 0 113m
prometheus-597596ffdd-v28hk 2/2 Running 0 113m $ oc get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
istio-ingressgateway 1/1 1 1 138m
istiod 1/1 1 1 139m
istiod-canary 1/1 1 1 113m
prometheus 1/1 1 1 138m

sidecar注入配置也有2套

$ oc get mutatingwebhookconfigurations
NAME CREATED AT
istio-sidecar-injector 2020-05-22T02:42:57Z
istio-sidecar-injector-canary 2020-05-22T03:08:28Z
数据面升级

创建新的istio修订版本并不会影响现有的代理。为了升级代理,需要将代理的配置指向新的控制面。通过命名空间标签istio.io/rev设置控制sidecar注入的控制面。

下面操作升级了test-ns命名空间,移除标签istio-injection,并增加标签istio.io/rev,指向新的istio canary。注意必须移除标签istio-injection,否则istio会优先处理istio-injection(原因是为了向后兼容)

$ kubectl label namespace test-ns istio-injection- istio.io/rev=canary

在升级命名空间后,需要重启pod来触发sidecar的注入,如下使用滚动升级

$ kubectl rollout restart deployment -n test-ns

通过如下方式可以查看使用canaryistio修订版的pod

$ kubectl get pods -n test-ns -l istio.io/rev=canary

为了验证test-ns命名空间中的新pod使用了istiod-canary服务,可以选择一个pod使用如下命令进行验证。从输出中可以看到其使用了istiod-canary控制面

$ istioctl proxy-config endpoints ${pod_name}.test-ns --cluster xds-grpc -ojson | grep hostname
"hostname": "istiod-canary.istio-system.svc"

可以通过如下方式导出canary修订版的配置信息

$ istioctl manifest generate --revision=canary >canary.yaml

替换升级

升级过程中可能会造成流量中断,为了最小化影响,需要确保istio中的各个组件(除Citadel)至少有两个副本正在运行,此外需要通过PodDistruptionBudgets保证至少有一个可用的pod

  • 首先下载最新的istio

  • 校验当前环境中支持的升级到的版本,如下命令会给出推荐的版本

    $ istioctl manifest versions
  • 确认需要升级的cluster是否正确

    $ kubectl config view
  • 通过如下命令执行升级,<your-custom-configuration-file>为当前版本的 IstioOperator API 配置 文件

    $ istioctl upgrade -f `<your-custom-configuration-file>`

    istioctl upgrade不支持--set命令

  • 在更新完毕之后,需要手动重启带有istio sidecar的pod来更新istio数据面

    $ kubectl rollout restart deployment

sidecar注入

为了使用Istio的特性,pods必须运行在istio sidecar proxy的网格中。下面介绍两种注入istio sidecar的方式:手动注入和自动注入。

手动注入通过直接修改,如deployment的配置信息,将proxy配置注入到配置中;当应用所在的命名空间启用自动注入时,会在pod创建时通过mutating webhook admission controller 注入proxy配置。

sidecar的(手动或自动)注入会用到istio-sidecar-injector configmap。

  • 手动注入

    当前版本手动注入时有一个问题,就是使用istio CNI之后无法将annotation k8s.v1.cni.cncf.io/networks注入(或导出)到配置文件中,导致出现如下问题,参见该issue

    in new validator: 10.80.2.222
    Listening on 127.0.0.1:15001
    Listening on 127.0.0.1:15006
    Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
    Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
    Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
    Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
    Error connecting to 127.0.0.6:15002: dial tcp 127.0.0.1:0->127.0.0.6:15002: connect: connection refused
    • 手动注入需要满足一个条件,即在应用所在的命名空间中创建NetworkAttachmentDefinition

    • 一种是直接使用istio-sidecar-injector的默认配置直接注入sidecar

      $ istioctl kube-inject -f samples/sleep/sleep.yaml | kubectl apply -f -

      可以使用如下方式直接先导出注入sidecar的deployment,然后使用kubectl直接部署

      $ istioctl kube-inject -f samples/sleep/sleep.yaml -o sleep-injected.yaml --injectConfigMapName istio-sidecar-injector
      $ kubectl apply -f deployment-injected.yaml
    • 另一种是先导出istio-sidecar-injector的默认配置,可以修改后再手动注入sidecar

      导出配置:

      $ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml
      $ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.values}' > inject-values.yaml
      $ kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml

      手动注入:

      $ istioctl kube-inject \
      --injectConfigFile inject-config.yaml \
      --meshConfigFile mesh-config.yaml \
      --valuesFile inject-values.yaml \
      --filename samples/sleep/sleep.yaml \
      | kubectl apply -f -
  • 自动注入

    自动注入时需要满足两个条件:

    • 给应用所在的命名空间打上标签istio-injection=enabled

      $ kubectl label namespace <app-namespace> istio-injection=enabled
    • 与手动注入相同,需要在应用所在的命名空间中创建NetworkAttachmentDefinition,然后在该命名空间下面正常创建(或删除并重建)pod即可自动注入sidecar。需要注意的是自动注入发生在pod层,并不体现在deployment上面,可以使用describe pod查看注入的sidecar。自动注入通过mutatingwebhookconfiguration定义了注入sidecar的规则,当前是istio-injection=enabled

      namespaceSelector:
      matchLabels:
      istio-injection: enabled

      可以通过如下命令修改注入的规则,修改后需要重启已经注入sidecar的pod,使规则生效

      $ kubectl edit mutatingwebhookconfiguration istio-sidecar-injector

      自动注入下,sidecar inject的webhook默认是打开的,如果要禁用该webhook,可以在上面cni-annotations.yaml文件中将sidecarInjectorWebhook.enabled置为false,这样就不会自动注入。

sidecar的注入控制

有两种方式可以控制sidecar的注入:

  • 第一种是修改pod template spec的sidecar.istio.io/inject annotation:当该annotation为true时会进行自动注入sidecar,为false则不会注入sidecar。默认为true。这种情况需要修改应用的deployment。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: ignored
    spec:
    template:
    metadata:
    annotations:
    sidecar.istio.io/inject: "false"
    spec:
    containers:
    - name: ignored
    image: tutum/curl
    command: ["/bin/sleep","infinity"]
  • 第二种是修改istio-sidecar-injector configmap,通过在neverInjectSelector数组中罗列出标签,并禁止对匹配这些标签的pod注入sidecar(各个匹配项的关系为OR)。如下内容中不会对具有标签openshift.io/build.nameopenshift.io/deployer-pod-for.name的pod注入sidecar。这种方式不需要修改应用的deployment。类似地,可以使用alwaysInjectSelector对某些具有特殊标签的pod注入sidecar

    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: istio-sidecar-injector
    data:
    config: |-
    policy: enabled
    neverInjectSelector:
    - matchExpressions:
    - {key: openshift.io/build.name, operator: Exists}
    - matchExpressions:
    - {key: openshift.io/deployer-pod-for.name, operator: Exists}
    template: |-
    initContainers:
    ...

更多istio CNI与sidecar注入和流量重定向相关的参数参见官方文档

卸载自动注入

使用如下方式可以卸载自动注入功能:

$ kubectl delete mutatingwebhookconfiguration istio-sidecar-injector
$ kubectl -n istio-system delete service istio-sidecar-injector
$ kubectl -n istio-system delete deployment istio-sidecar-injector
$ kubectl -n istio-system delete serviceaccount istio-sidecar-injector-service-account
$ kubectl delete clusterrole istio-sidecar-injector-istio-system
$ kubectl delete clusterrolebinding istio-sidecar-injector-admin-role-binding-istio-system

注意上面命令并不会卸载已经注入到pod的sidecar,需要通过滚动更新或直接删除pod来生效

或者使用如下方式对某个命名空间禁用自动注入(推荐):

$ kubectl label namespace <target-namespace> istio-injection-

Istio CNI的兼容

与init容器的兼容

当使用istio CNI的时候,kubelet会按照如下步骤启动注入sidecar的pod:

  • 使用istio CNI插件进行配置,将流量导入到pod中的istio sidecar proxy容器
  • 执行所有init容器,并成功运行结束
  • 启动pod中的istio sidecar proxy和其他容器

由于init容器会在sidecar proxy容器之前运行,因此可能导致应用本身的init容器的通信中断。为了避免发生这种情况,可以通过如下配置避免重定向应用的init容器的流量:

  • 设置traffic.sidecar.istio.io/excludeOutboundIPRanges annotation来禁用将流量重定向到与init容器通信的任何cidr。
  • 设置traffic.sidecar.istio.io/excludeOutboundPorts annotation来禁止将流量重定向到init容器使用的出站端口

与其他CNI插件的兼容

istio CNI插件作为CNI插件链中的一环,当创建或删除一个pod时,会按照顺序启动插件链上的每个插件,istio CNI插件仅仅(通过pod的网络命名空间中的iptables)将应用的pod流量重定向到注入的istio proxy sidecar容器。

istio CNI插件不会干涉配置pod网络的基本CNI插件。

更多细节参见CNI specification reference

TIPs:

  • 不同平台下使用istio CNI执行initContainer时可能会出现istio-validation无法启动的错误,这种情况下默认会导致kubelet删除并重建pod,为了定位问题,可以将repair.deletePods配置为false,这样就不会立即删除pod

    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
    components:
    cni:
    ...
    values:
    cni:
    repair:
    enabled: true
    deletePods: false
    ...

openshift 4.3 Istio的搭建(istio 系列一)的更多相关文章

  1. 搭建Istio基础环境

    需求 搭建istio基础环境(基于1.5.1版本) 安装步骤 在安装 Istio 之前,需要一个运行着 Kubernetes 的环境,安装步骤可以参考前面的文章 下载istio,然后解压,然后将 is ...

  2. Istio 运维实战系列(2):让人头大的『无头服务』-上

    本系列文章将介绍用户从 Spring Cloud,Dubbo 等传统微服务框架迁移到 Istio 服务网格时的一些经验,以及在使用 Istio 过程中可能遇到的一些常见问题的解决方法. 什么是『无头服 ...

  3. Istio 运维实战系列(3):让人头大的『无头服务』-下

    本系列文章将介绍用户从 Spring Cloud,Dubbo 等传统微服务框架迁移到 Istio 服务网格时的一些经验,以及在使用 Istio 过程中可能遇到的一些常见问题的解决方法. 失败的 Eur ...

  4. Istio安全-认证(istio 系列七)

    Istio安全-认证 目录 Istio安全-认证 认证策略 配置 自动mutual TLS 全局启用istio的mutual TLS STRIC模式 卸载 针对单个命名空间或负载启用mutual TL ...

  5. Istio(九):istio安全之授权

    目录 一.模块概览 二.系统环境 三.istio授权 3.1 istio授权 3.2 来源 3.3 操作 3.4 条件 四.实战:授权(访问控制) 4.1 访问控制 4.2 清理 一.模块概览 在Ku ...

  6. istio环境搭建for macbook

    首先需要搭建docker+k8s环境,如何搭建这里就不再赘述,可以自行搜索. 打开命令行,运行命令: curl -L https://git.io/getLatestIstio | ISTIO_VER ...

  7. Istio 运维实战系列(1):应用容器对 Envoy Sidecar 的启动依赖问题

    本系列文章将介绍用户从 Spring Cloud,Dubbo 等传统微服务框架迁移到 Istio 服务网格时的一些经验,以及在使用 Istio 过程中可能遇到的一些常见问题的解决方法. 故障现象 该问 ...

  8. ABP框架搭建项目系列教程基础版完结篇

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...

  9. [转]Ubuntu10下MySQL搭建Amoeba系列(文章索引)

    一.前言(Introduction) 使用了Amoeba有一段时间了,发现官方博客:Amoeba使用指南有很多地方都是错误的,在我实战中给到一些错误的指示,所以我想写些在搭建的实战中给大家一点指引.欢 ...

随机推荐

  1. CVPR2020|3D-VID:基于LiDar Video信息的3D目标检测框架

    作者:蒋天园 Date:2020-04-18 来源:3D-VID:基于LiDar Video信息的3D目标检测框架|CVPR2020 Brief paper地址:https://arxiv.org/p ...

  2. Python数据可视化---pygal模块

    目录 pygal模块 安装pygal模块 pygal模块介绍 柱状图 单列柱状图 堆叠柱状图 横向柱状图 折线图 简单折线图 纵向折线图 堆叠折线图 饼状图 简单饼状图 多级饼状图 圆环图 半圆图 雷 ...

  3. Connections in Galaxy War ZOJ - 3261 (并查集)

    点权并查集的反向离线操作 题目大意:有n个stars,每一个都一定的“颜值”.然后stars与stars之间可以相连,query c表示再与c相连的stars中,颜值比c高的,stars的标号,如果有 ...

  4. B2 - TV Subscriptions (Hard Version)

    题目连接:https://codeforces.com/contest/1247/problem/B2 题解:双指针,,一个头,一个尾,头部进入,尾部退出,一开始先记录1到k,并记录每个数字出现的次数 ...

  5. nginx配置虚拟主机、反向代理和负载均衡

    为了实现这个功能,需要修改nginx的配置文件,将nginx.conf清理一下,使结构更清晰. worker_processes ; events { worker_connections ; } h ...

  6. 关于C++线程池的实现的思考

    今天突然对前些日子一直很疑惑的c++线程池有了新的想法.其实所谓的线程池无非就是两个技术点,一个,多线程,指工作线程和主线程分离,或者说数据接收和处理分两个线程,一般就是讲需要运行的函数放到子线程执行 ...

  7. 虚拟机体验NAS私人云全揭秘:序言——虚拟机体验NAS私人云缘由

    "世界在新冠肺炎疫情后将永远改变",对于2020春天在全球蔓延的新冠肺炎疫情,美国前国务卿基辛格做了这样的评价.确实,也改变了我们.春节期间,本着少添乱的原则,响应国家号召,自我隔 ...

  8. [V&N2020 公开赛]TimeTravel 复现

    大佬友链(狗头):https://www.cnblogs.com/p201821440039/ 参考博客: https://www.zhaoj.in/read-6407.html https://cj ...

  9. 2020-MRCTF

    ez_bypass I put something in F12 for you include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx} ...

  10. [XML] XML格式【有道翻译】API 的数据转化输出

    <?php header("content-type:text/html;charset=utf-8"); //echo "飞飞仔超级智障"; $cont ...