【GO】k8s 管理系统项目23[前端部分–工作负载-Pod]

news2024/9/26 5:24:27

k8s 管理系统项目[前端部分–工作负载-Deployment]

1. 代码部分

1.1 准备工作

由于Pod页面和Deployment内容差不多.那么就直接把Deployment的内容复制过来.再做修改.

  1. 替换Deployment为Pod
  2. 替换Deploy为Pod
  3. 替换deployment为pod
  4. 替换deploy为pod
  5. 禁用新增的按钮,删除新增方法,表单
  6. 删除扩容和重启的按钮,方法,抽屉

1.2 Pod前端代码

src/views/workload/Pod.vue

<template>
  <div class="pod">
    <el-row>
      <!-- 头部1 -->
      <el-col :span="24">
        <div>
          <el-card class="pod-head-card" shadow="never" :body-style="{padding:'10px'}">
            <el-row>
              <el-col :span="6">
                <div>
                  <span>命名空间: </span>
                  <el-select v-model="namespaceValue" filterable placeholder="请选择">
                    <el-option
                        v-for="(item, index) in namespaceList"
                        :key="index"
                        :label="item.metadata.name"
                        :value="item.metadata.name">
                    </el-option>
                  </el-select>
                </div>
              </el-col>
              <el-col :span="2" :offset="16">
                <div>
                  <el-button style="border-radius:2px;" icon="Refresh" plain @click="getPods()">刷新</el-button>
                </div>
              </el-col>
            </el-row>
          </el-card>
        </div>
      </el-col>
      <!-- 头部2 -->
      <el-col :span="24">
        <div>
          <el-card class="pod-head-card" shadow="never" :body-style="{padding:'10px'}">
            <el-row>
              <el-col :span="2">
                <div>
                  <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
                </div>
              </el-col>
              <el-col :span="6">
                <div>
                  <el-input class="pod-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
                  <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getPods()">搜索</el-button>
                </div>
              </el-col>
            </el-row>
          </el-card>
        </div>
      </el-col>
      <!-- 数据表格 -->
      <el-col :span="24">
        <div>
          <el-card class="pod-body-card" shadow="never" :body-style="{padding:'5px'}">
            <!-- 数据表格 -->
            <!-- row-key 用来定义行数据的key,结合expand-row-keys使用,往expandKeys中增加key来展开行 -->
            <!-- expand-row-keys 展开的行的key数组 -->
            <!-- expand-change 展开触发时,调用这个方法 -->
            <el-table
                style="width:100%;font-size:12px;margin-bottom:10px;"
                :data="podList"
                v-loading="appLoading"
                :row-key="getRowKeys"
                :expand-row-keys="expandKeys"
                @expand-change="expandChange">
              <el-table-column width="10"></el-table-column>
              <!-- 展开 -->
              <el-table-column type="expand">
                <!-- 插槽,里面是展开的内容,props标识展开的行的数据 -->
                <template #default="props">
                  <el-tabs v-model="activeName" type="card">
                    <!-- tab容器标签页 -->
                    <el-tab-pane label="容器" name="container">
                      <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
                        <!-- 嵌套数据表格 -->
                        <el-table
                            style="width:100%;font-size:12px;"
                            :data="props.row.spec.containers">
                          <el-table-column align=left prop="name" label="容器名"></el-table-column>
                          <el-table-column align=left prop="image" label="镜像"></el-table-column>
                          <el-table-column align=center label="Pod IP">
                            <span>{{ props.row.status.podIP }}</span>
                          </el-table-column>
                          <el-table-column align=center prop="args" label="启动命令"></el-table-column>
                          <el-table-column align=center label="环境变量">
                            <template v-slot="scope">
                              <!-- 气泡弹出框,内容是所有的环境变量 -->
                              <el-popover :width="500" placement="left" trigger="hover">
                                <el-table style="width:100%;font-size:12px;" size="mini" :show-header="false" :data="scope.row.env">
                                  <el-table-column property="name" label="名称"></el-table-column>
                                  <el-table-column property="value" label="值"></el-table-column>
                                </el-table>
                                <template #reference>
                                  <el-button size="small">此处查看</el-button>
                                </template>
                              </el-popover>
                            </template>
                          </el-table-column>
                        </el-table>
                      </el-card>
                    </el-tab-pane>
                    <!-- tab日志标签页 -->
                    <el-tab-pane label="日志" name="log">
                      <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
                        <el-row :gutter="10">
                          <el-col :span="3">
                            <!-- 容器选择框 -->
                            <el-select size="small" v-model="containerValue" placeholder="请选择">
                              <el-option v-for="item in containerList" :key="item" :value="item">
                              </el-option>
                            </el-select>
                          </el-col>
                          <el-col :span="2">
                            <!-- 查看日志按钮 -->
                            <el-button style="border-radius:2px;" size="small" type="primary" @click="getPodLog(props.row.metadata.name)">查看</el-button>
                          </el-col>
                          <el-col :span="24" style="margin-top: 5px">
                            <!-- 显示日志内容 -->
                            <el-card shadow="never" class="pod-body-log-card" :body-style="{padding:'5px'}">
                              <span class="pod-body-log-span">{{ logContent }}</span>
                            </el-card>
                          </el-col>
                        </el-row>
                      </el-card>
                    </el-tab-pane>
                    <!-- tab终端标签页 -->
                    <el-tab-pane label="终端" name="shell">
                      <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
                        <el-row :gutter="10">
                          <el-col :span="3">
                            <!-- 容器选择框 -->
                            <el-select size="small" v-model="containerValue" placeholder="请选择">
                              <el-option v-for="item in containerList" :key="item" :value="item">
                              </el-option>
                            </el-select>
                          </el-col>
                          <el-col :span="1">
                            <!-- 连接按钮 -->
                            <el-button style="border-radius:2px;" size="small" type="primary" @click="initSocket(props.row)">连接</el-button>
                          </el-col>
                          <el-col :span="1">
                            <!-- 关闭连接按钮 -->
                            <el-button style="border-radius:2px;" size="small" type="danger" @click="closeSocket()">关闭</el-button>
                          </el-col>
                          <el-col :span="24" style="margin-top: 5px">
                            <el-card shadow="never" class="pod-body-shell-card" :body-style="{padding:'5px'}">
                              <!-- xterm虚拟终端 -->
                              <div id="xterm"></div>
                            </el-card>
                          </el-col>
                        </el-row>
                      </el-card>
                    </el-tab-pane>
                  </el-tabs>
                </template>
              </el-table-column>
              <el-table-column align=left label="Pod名">
                <template v-slot="scope">
                  <!-- 三元运算:expandMap[scope.row.metadata.name]为1则
                  触发关闭(expandedRows为空数组),为0则触发展开expandedRows有值 -->
                  <a class="pod-body-podname" @click="expandMap[scope.row.metadata.name] ? expandChange(scope.row, []) : expandChange(scope.row, [scope.row])">{{ scope.row.metadata.name }}</a>
                </template>
              </el-table-column>
              <el-table-column align=center min-width="150" label="节点">
                <template v-slot="scope">
                  <el-tag v-if="scope.row.spec.nodeName !== undefined" type="warning">{{ scope.row.spec.nodeName }}</el-tag>
                </template>
              </el-table-column>
              <el-table-column align=center label="状态">
                <template v-slot="scope">
                  <div :class="{'success-dot':scope.row.status.phase == 'Running' || scope.row.status.phase == 'Succeeded', 'warning-dot':scope.row.status.phase == 'Pending', 'error-dot':scope.row.status.phase != 'Running' && scope.row.status.phase != 'Pending' && scope.row.status.phase != 'Succeeded'}"></div>
                  <span :class="{'success-status':scope.row.status.phase == 'Running' || scope.row.status.phase == 'Succeeded', 'warning-status':scope.row.status.phase == 'Pending', 'error-status':scope.row.status.phase != 'Running' && scope.row.status.phase != 'Pending' && scope.row.status.phase != 'Succeeded'}">{{ scope.row.status.phase }} </span>
                </template>
              </el-table-column>
              <el-table-column align=center label="重启数">
                <template v-slot="scope">
                  <span>{{ restartTotal(scope) }} </span>
                </template>
              </el-table-column>
              <el-table-column align=center min-width="100" label="创建时间">
                <template v-slot="scope">
                  <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
                </template>
              </el-table-column>
              <el-table-column align=center label="操作" width="200">
                <template v-slot="scope">
                  <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getPodDetail(scope)">YAML</el-button>
                  <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delPod)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
            <el-pagination
                class="pod-body-pagination"
                background
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage"
                :page-sizes="pagesizeList"
                :page-size="pagesize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="podTotal">
            </el-pagination>
          </el-card>
        </div>
      </el-col>
    </el-row>
    <!-- 展示YAML信息的弹框 -->
    <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
      <codemirror
          :value="contentYaml"
          border
          :options="cmOptions"
          height="500"
          style="font-size:14px;"
          @change="onChange"
      ></codemirror>
      <template #footer>
                <span class="dialog-footer">
                    <el-button @click="yamlDialog = false">取 消</el-button>
                    <el-button type="primary" @click="updatePod()">更 新</el-button>
                </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import common from "../common/Config";
import httpClient from '../../utils/request';
//引入xterm终端依赖
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import 'xterm/css/xterm.css';
import 'xterm/lib/xterm.js';
import yaml2obj from 'js-yaml';
import json2yaml from 'json2yaml';
export default {
  data() {
    return {
      //编辑器配置
      cmOptions: common.cmOptions,
      contentYaml: '',
      //分页
      currentPage: 1,
      pagesize: 10,
      pagesizeList: [10, 20, 30],
      //
      searchInput: '',
      namespaceValue: 'default',
      namespaceList: [],
      namespaceListUrl: common.k8sNamespaceList,
      appLoading: false,
      podList: [],
      podTotal: 0,
      getPodsData: {
        url: common.k8sPodList,
        params: {
          filter_name: '',
          namespace: '',
          page: '',
          limit: '',
        }
      },
      //详情
      podDetail: {},
      getPodDetailData: {
        url: common.k8sPodDetail,
        params: {
          pod_name: '',
          namespace: ''
        }
      },
      //yaml更新
      yamlDialog: false,
      updatePodData: {
        url: common.k8sPodUpdate,
        params: {
          namespace: '',
          content: ''
        }
      },
      //删除
      delPodData: {
        url: common.k8sPodDel,
        params: {
          pod_name: '',
          namespace: ''
        }
      },
      //expand扩展
      activeName: 'container',
      expandKeys: [],
      expandMap: {},
      //日志
      containerList: {},
      containerValue: '',
      getPodContainerData: {
        url: common.k8sPodContainer,
        params: {
          pod_name: '',
          namespace: ''
        }
      },
      logContent: '',
      getPodLogData: {
        url: common.k8sPodLog,
        params: {
          container_name: '',
          pod_name: '',
          namespace: ''
        }
      },
      //terminal
      term: null,
      socket: null
    }
  },
  methods: {
    transYaml(content) {
      return json2yaml.stringify(content)
    },
    transObj(content) {
      return yaml2obj.load(content)
    },
    onChange(val) {
      this.contentYaml = val
    },
    handleSizeChange(size) {
      this.pagesize = size;
      this.getPods()
    },
    handleCurrentChange(currentPage) {
      this.currentPage = currentPage;
      this.getPods()
    },
    handleClose(done) {
      this.$confirm('确认关闭?')
          .then(() => {
            done();
          })
          .catch(() => {});
    },
    ellipsis(value) {
      return value.length>15?value.substring(0,15)+'...':value
    },
    timeTrans(timestamp) {
      let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
      date = date.toJSON();
      date = date.substring(0, 19).replace('T', ' ')
      return date
    },
    restartTotal(e) {
      let index, sum = 0
      let containerStatuses = e.row.status.containerStatuses
      for ( index in containerStatuses) {
        sum = sum + containerStatuses[index].restartCount
      }
      return sum
    },
    getNamespaces() {
      httpClient.get(this.namespaceListUrl)
          .then(res => {
            this.namespaceList = res.data.items
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
    },
    getPods() {
      this.appLoading = true
      this.getPodsData.params.filter_name = this.searchInput
      this.getPodsData.params.namespace = this.namespaceValue
      this.getPodsData.params.page = this.currentPage
      this.getPodsData.params.limit = this.pagesize
      httpClient.get(this.getPodsData.url, {params: this.getPodsData.params})
          .then(res => {
            this.podList = res.data.items
            this.podTotal = res.data.total
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
      this.appLoading = false
    },
    getPodDetail(e) {
      this.getPodDetailData.params.pod_name = e.row.metadata.name
      this.getPodDetailData.params.namespace = this.namespaceValue
      httpClient.get(this.getPodDetailData.url, {params: this.getPodDetailData.params})
          .then(res => {
            this.podDetail = res.data
            this.contentYaml = this.transYaml(this.podDetail)
            this.yamlDialog = true
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
    },
    updatePod() {
      let content = JSON.stringify(this.transObj(this.contentYaml))
      this.updatePodData.params.namespace = this.namespaceValue
      this.updatePodData.params.content = content
      httpClient.put(this.updatePodData.url, this.updatePodData.params)
          .then(res => {
            this.$message.success({
              message: res.msg
            })
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
      this.yamlDialog = false
    },
    delPod(e) {
      this.delPodData.params.pod_name = e.row.metadata.name
      this.delPodData.params.namespace = this.namespaceValue
      httpClient.delete(this.delPodData.url, {data: this.delPodData.params})
          .then(res => {
            this.getPods()
            this.$message.success({
              message: res.msg
            })
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
    },
    handleConfirm(obj, operateName, fn) {
      this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
      this.$confirm(this.confirmContent,'提示',{
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      })
          .then(() => {
            fn(obj)
          })
          .catch(() => {
            this.$message.info({
              message: '已取消操作'
            })
          })
    },
    getRowKeys(row) {
      return row.metadata.name
    },
    //row,展开的当前行的数据
    //expandedRows,展开的所有行的数据组成的数组,但是这里用法是只会有一行,也就是数组长度永远为1
    expandChange(row, expandedRows) {
      //初始化变量
      //清空expandKeys,代表关闭所有展开的行
      this.expandKeys = []
      //清空日志内容
      this.logContent= ''
      //清空containervalue,展开时不显示上次的值
      this.containerValue = ''
      //将tab标签页顶部页面调成容器
      this.activeName = 'container'
      //expandedRows.length == 1表示展开,expandedRows.length == 0 表示关闭
      if (expandedRows.length > 0) {
        //expandMap key表示展开过的行的key,值为1表示展开标记,值为0表示关闭标记
        //expandMap用于数据表格点击name的展开,用于判断这一行是展开还是关闭的行为
        this.expandMap[row.metadata.name] = 1
        //将expandMap除了row.metadata.name,其他key的值都置为0
        this.setExpandMap(row.metadata.name)
        //这里才是真正的展开,将row.metadata.name添加到expandKeys数组中展开,然后执行方法获取container
        this.expandKeys.push(row.metadata.name)
        this. getPodContainer(row)
      } else {
        //关闭标记
        this.expandMap[row.metadata.name] = 0
      }
    },
    //匹配expandMap中podName,不相等的全都置为0,意为除了podName这行,其他全都标记关闭
    setExpandMap(podName) {
      let key
      for ( key in this.expandMap ) {
        key !== podName ? this.expandMap[key] = 0 : ''
      }
    },
    getPodContainer(row) {
      this.getPodContainerData.params.pod_name = row.metadata.name
      this.getPodContainerData.params.namespace = this.namespaceValue
      httpClient.get(this.getPodContainerData.url, {params: this.getPodContainerData.params})
          .then(res => {
            this.containerList = res.data
            this.containerValue = this.containerList[0]
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
    },
    getPodLog(podName) {
      this.getPodLogData.params.pod_name = podName
      this.getPodLogData.params.container_name = this.containerValue
      this.getPodLogData.params.namespace = this.namespaceValue
      httpClient.get(this.getPodLogData.url, {params: this.getPodLogData.params})
          .then(res => {
            this.logContent = res.data
          })
          .catch(res => {
            this.$message.error({
              message: res.msg
            })
          })
    },
    initTerm() {
      //初始化xterm实例
      this.term = new Terminal({
        rendererType: 'canvas', //渲染类型
        rows: 30, //行数
        cols: 110,
        convertEol: false, //启用时,光标将设置为下一行的开头
        scrollback: 10, //终端中的回滚量
        disableStdin: false, //是否应禁用输入
        cursorStyle: 'underline', //光标样式
        cursorBlink: true, //光标闪烁
        theme: {
          foreground: 'white', //字体
          background: '#060101', //背景色
          cursor: 'help' //设置光标
        }
      });
      //绑定dom
      this.term.open(document.getElementById('xterm'))
      //终端适应父元素大小
      const fitAddon = new FitAddon()
      this.term.loadAddon(fitAddon)
      fitAddon.fit();
      //获取终端的焦点
      this.term.focus();
      let _this = this; //一定要重新定义一个this,不然this指向会出问题
      //onData方法用于定义输入的动作
      this.term.onData(function (key) {
        // 这里key值是输入的值,数据格式就是后端定义的 {"operation":"stdin","data":"ls"}
        let msgOrder = {
          operation: 'stdin',
          data: key,
        };
        //发送数据
        _this.socket.send(JSON.stringify(msgOrder));
      });
      //发送resize请求
      let msgOrder2 = {
        operation: 'resize',
        cols: this.term.cols,
        rows: this.term.rows,
      };
      this.socket.send(JSON.stringify(msgOrder2))
    },
    //初始化websocket
    initSocket(row) {
      //定义websocket连接地址
      let terminalWsUrl = common.k8sTerminalWs + "?pod_name=" + row.metadata.name + "&container_name=" + this.containerValue + "&namespace=" + this.namespaceValue
      //实例化
      this.socket = new WebSocket(terminalWsUrl);
      //关闭连接时的方法
      this.socketOnClose();
      //建立连接时的方法
      this.socketOnOpen();
      //接收消息的方法
      this.socketOnMessage();
      //报错时的方法
      this.socketOnError();
    },
    socketOnOpen() {
      this.socket.onopen = () => {
        //简历连接成功后,初始化虚拟终端
        this.initTerm()
      }
    },
    socketOnMessage() {
      this.socket.onmessage = (msg) => {
        //接收到消息后将字符串转为对象,输出data内容
        let content = JSON.parse(msg.data)
        this.term.write(content.data)
      }
    },
    socketOnClose() {
      this.socket.onclose = () => {
        //关闭连接后打印在终端里
        this.term.write("链接已关闭")
      }
    },
    socketOnError() {
      this.socket.onerror = () => {
        console.log('socket 链接失败')
      }
    },
    //关闭连接
    closeSocket() {
      //若没有实例化,则不需要关闭
      if (this.socket === null) {
        return
      }
      this.term.write("链接关闭中。。。")
      this.socket.close()
    }
  },
  watch: {
    namespaceValue: {
      handler() {
        localStorage.setItem('namespace', this.namespaceValue)
        this.currentPage = 1
        this.getPods()
      }
    },
    //若tab标签页切到日志,则重新加载日志内容
    activeName: {
      handler() {
        if ( this.activeName == 'log' ) {
          this.expandKeys.length == 1 ? this.getPodLog(this.expandKeys[0]) : ''
        }
      }
    }
  },
  beforeMount() {
    if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
      this.namespaceValue = localStorage.getItem('namespace')
    }
    this.getNamespaces()
    this.getPods()
  },
  beforeUnmount() {
    //若websocket连接没有关闭,则在改生命周期关闭
    if ( this.socket !== null ) {
      this.socket.close()
    }
  },
}
</script>


<style scoped>
.pod-head-card,.pod-body-card {
  border-radius: 1px;
  margin-bottom: 5px;
}
.pod-head-search {
  width:160px;
  margin-right:10px;
}
.pod-body-podname {
  color: #4795EE;
}
.pod-body-podname:hover {
  color: rgb(84, 138, 238);
  cursor: pointer;
  font-weight: bold;
}
/* pod状态栏圆点的css实现 */
.success-dot{
  display:inline-block;
  width: 7px;
  height:7px;
  background: rgb(27, 202, 21);
  border-radius:50%;
  border:1px solid rgb(27, 202, 21);
  margin-right: 10px;
}
.warning-dot{
  display:inline-block;
  width: 7px;
  height:7px;
  background: rgb(233, 200, 16);
  border-radius:50%;
  border:1px solid rgb(233, 200, 16);
  margin-right: 10px;
}
.error-dot{
  display:inline-block;
  width: 7px;
  height:7px;
  background: rgb(226, 23, 23);
  border-radius:50%;
  border:1px solid rgb(226, 23, 23);
  margin-right: 10px;
}
.success-status {
  color: rgb(27, 202, 21);
}
.warning-status {
  color: rgb(233, 200, 16);
}
.error-status {
  color: rgb(226, 23, 23);
}
/deep/ .el-tabs__item {
  font-size: 12px;
}
/deep/ .el-tabs__header {
  margin-bottom: 8px;
}
.pod-body-log-card, .pod-body-shell-card {
  border-radius:1px;
  height:600px;
  overflow:auto;
  background-color: #060101;
}
.pod-body-log-card {
  color: aliceblue;
}
.pod-body-log-span {
  white-space:pre;
}
</style>

2. 功能测试

2.1 获取pod清单和分页

请添加图片描述
请添加图片描述

2.2 获取pod详细信息

2.2.1 pod详情

请添加图片描述

2.2.2 Pod环境变量

请添加图片描述

2.2.2 Pod日志

请添加图片描述

2.2.4 控制台

请添加图片描述

2.3 Yaml

请添加图片描述

2.4 删除Pod

请添加图片描述

请添加图片描述

请添加图片描述

3. 两个小bug

3.1 router错误

之前写后端路由时/api/k8s/pod/detail写成了/api/k8s/pods/detail

造成获取yaml时无法获得消息.

尝试用api调用发现问题,修改了router下的路由问题解决

3.2 翻页的问题

之前后端GetPods中取total写成了

	filtered := selectableData.Filter()
	// 排序和分页
	data := filtered.Sort().Paginate()
	total := len(data.GenericDataList)

改了下问题解决

	filtered := selectableData.Filter()
	total := len(filtered.GenericDataList)
	// 排序和分页
	data := filtered.Sort().Paginate()

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

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

相关文章

django后端服务、logstash和flink接入VictoriaMetrics指标监控

0.简介 通过指标监控可以设置对应的告警&#xff0c;快速发现问题&#xff0c;并通过相应的指标定位问题。 背景&#xff1a;使用的 VictoriaMetrics(简称 VM) 作为监控的解决方案&#xff0c;需要将 django 服务、logstash 和 flink 引擎接入进来&#xff0c;VM 可以实时的获…

SpringBoot:SpringBoot配置文件.properties、.yml 和 .ymal(2)

SpringBoot配置文件1. 配置文件格式1.1 application.properties配置文件1.2 application.yml配置文件1.3 application.yaml配置文件1.4 三种配置文件优先级和区别2. yaml格式2.1 语法规则2.2 yaml书写2.2.1 字面量&#xff1a;单个的、不可拆分的值2.2.2 数组&#xff1a;一组按…

操作系统权限提升(十八)之Linux提权-内核提权

Linux 内核提权 Linux 内核提权原理 内核提权是利用Linux内核的漏洞进行提权的&#xff0c;内核漏洞进行提权一般包括三个环节&#xff1a; 1、对目标系统进行信息收集&#xff0c;获取到系统内核信息及版本信息&#xff1b; 2、根据内核版本获取其对应的漏洞以及EXP 3、使…

第七届蓝桥杯省赛 C++ A/B组 - 四平方和

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;蓝桥杯题解集合 &#x1f4dd;原题地址&#xff1a;四平方和 &#x1f4e3;专栏定位&#xff1a;为想参加蓝桥杯的小伙伴整理常考算法题解&#xff0c;祝大家…

Docker简介与用法

文章目录1、Docker简介1.1、Docker能解决什么问题1.2、什么是虚拟机技术1.2.1、虚拟机的缺点1.3、什么是容器1.3.1、容器与虚拟机比较1.4、分析 Docker 容器架构1.4.1、Docker客户端和服务器1.4.2、Docker 镜像(Image)1.4.3、Docker 容器(Container)1.4.4、Docker 仓库(reposit…

Windows程序员学习Linux环境内存管理

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Windows程序员如何学习Linux环境内存管理。由于很多程序在Windows环境下开发好后&#xff0c;还要部署到Linux服务器上去&#xff0c;所以作为Windows程序员有必要学习Linux环境的内存…

【计算机三级网络技术】 第三篇 IP地址规划技术

IP地址规划技术 文章目录IP地址规划技术一、IP 地址规划以及划分地址新技术1.IP地址的标准分类&#xff08;第一阶段&#xff09;2.划分子网的三级地址结构(第二阶段)3.构成超网的无类域间路由技术(第三阶段)4.网络地址转换技术(第四阶段)二、IP 地址分类1.A类、B类与C类IP地址…

数据的表示和运算

文章目录数制与编码进制间的转换BCD码定点数与浮点数定点数是什么&#xff1f;浮点数是什么&#xff1f;定点数与浮点数的区别机器数和真值原码、反码、补码、移码基本定义整数的加减法刷题小结最后数制与编码 进制间的转换 二进制、八进制、十进制、十六进制之间的转换不用多…

前端杂学1

1.简单且必须掌握的 1.MVVM是什么 将MVC中的V变为了MVVM&#xff0c;实现了双向绑定。其中VM就是vue的作用&#xff0c;这样页面的动态化可以通过vue来操作&#xff0c;而不是页面直接与后端操作&#xff0c;实现了前后端的分离 2.为什么vue采用异步渲染 &#xff1f; 调…

Kubernetes之服务发现

本文使用wordpressmysql搭建个人博客来讲解服务发现相关知识。 环境准备 wordpress需要连接到mysql才能正常工作&#xff0c;所以需要为mysql的pod创建一个mysql的svc&#xff0c;只要不删除重建svc&#xff0c;其IP不会变。 此时wordpress的pod需要连接mysql的svc的时候&…

HyperGBM用4记组合拳提升AutoML模型泛化能力

本文作者&#xff1a;杨健&#xff0c;九章云极 DataCanvas 主任架构师 如何有效提高模型的泛化能力&#xff0c;始终是机器学习领域的重要课题。经过大量的实践证明比较有效的方式包括&#xff1a; 利用Early Stopping防止过拟合通过正则化降低模型的复杂度使用更多的训练数…

第四阶段01-酷鲨商城项目准备

1. 关于csmall-product项目 这是“酷鲨商城”大项目中的“商品管理”项目&#xff0c;是一个后台管理项目&#xff08;给管理员&#xff0c;或运营人员使用的项目&#xff0c;并不是普通用户使用的&#xff09;&#xff0c;并且&#xff0c;只会涉及与发布商品可能相关的功能开…

企业工程项目管理系统平台(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

React(二):jsx事件绑定、条件渲染、列表渲染、jsx的本质、购物车案例

React&#xff08;二&#xff09;一、jsx事件绑定1.this的绑定方式2.jsx中绑定this的三种方式3.事件对象和传参&#xff08;1&#xff09;事件对象怎么传&#xff08;2&#xff09;其他参数怎么传&#xff1f;二、条件渲染1.直接if-else2.三元表达式3.利用逻辑中断4.案例练习5.…

HTML#5表单标签

一. 表单标签介绍表单: 在网页中主要负责数据采集功能,使用<form>标签定义表单表单项: 不同类型的input元素, 下拉列表, 文本域<form> 定义表单<input> 定义表单项,通过typr属性控制输入形式<label> 为表单项定义标注<select> 定义下拉列表<o…

【GO】31.grpc 客户端负载均衡源码分析

这篇文章是记录自己查看客户端grpc负载均衡源码的过程&#xff0c;并没有太详细的讲解&#xff0c;参考价值不大&#xff0c;可以直接跳过&#xff0c;主要给自己看的。一.主要接口&#xff1a;Balancer Resolver1.Balancer定义Resolver定义具体位置为1.grpc源码对解析器(resol…

异步通知实验

目录 一、异步通知简介 阻塞、非阻塞、异步通知区别 信号与信号修改测试 测试 二、驱动编写 1、定义fasync_struct 结构体指针变量 2、操作集添加fasync 3、实现imx6uirq_fasync 函数 4、关闭驱动文件操作 ​编辑 5、定时器处理函数 三、编写APP 1、编写信号的处理…

ElasticSearch 学习笔记总结(二)

文章目录一、ES JavaAPI 环境准备二、ES JavaAPI 索引1. 索引 创建2. 索引 查找3. 索引 删除三、ES JavaAPI 文档1. 文档 创建2. 文档 修改3. 文档 查询4. 文档 删除4. 文档 批量新增 和 批量删除5. 高级查询 索引全量查询6. 高级查询四、ES 集群1. ES集群 概念2. window 集群搭…

阿里P8:做测试10年我的一些经验分享,希望你们少走弯路

我是在2015年毕业的&#xff0c;当时是读的普通本科&#xff0c;不上不下的专业水平&#xff0c;毕业的时候&#xff0c;恰好遇到了金融危机。校园招聘里阴差阳错的巧合&#xff0c;让我走上了软件测试工程师的道路。 入职第一天&#xff0c;来了个高大上的讲师&#xff0c;记…

如何使用码匠连接 PostgreSQL

目录 在码匠中集成 PostgreSQL 在码匠中使用 PostgreSQL 关于码匠 PostgreSQL 是一种特性非常齐全的自由软件的对象-关系型数据库管理系统&#xff08;ORDBMS&#xff09;&#xff0c;它具有许多强大的功能&#xff0c;PostgreSQL 支持大部分的 SQL 标准并且提供了很多其他现…