微前端基础

news/2024/5/16 13:09:21/文章来源:https://blog.csdn.net/woyebuzhidao321/article/details/128992758

一、什么是微前端

微前端是一种软件架构,可以将前端应用拆解成一些更小的能够独立开发部署的微型应用,然后再将这些微应用进行组合使其成为整体应用的架构模式。微前端架构类似于组件架构,但不同的是,组件不能独立构建和发布,但是微前端中的应用是可以的。微前端架构与框架无关,每个微应用都可以使用不同的框架。

在这里插入图片描述

二、 微前端的价值

1. 增量迁移

迁移是一项非常耗时且艰难的任务,比如有一个管理系统使用 AngularJS 开发维护已经有三年时间,但是随时间的推移和团队成员的变更,无论从开发成本还是用人需求上,AngularJS 已经不能满足要求,于是团队想要更新技术栈,想在其他框架中实现新的需求,但是现有项目怎么办?直接迁移是不可能的,在新的框架中完全重写也不太现实。
使用微前端架构就可以解决问题,在保留原有项目的同时,可以完全使用新的框架开发新的需求,然后再使用微前端架构将旧的项目和新的项目进行整合。这样既可以使产品得到更好的用户体验,也可以使团队成员在技术上得到进步,产品开发成本也降到的最低。

2. 独立发布

在目前的单页应用架构中,使用组件构建用户界面,应用中的每个组件或功能开发完成或者bug修复完成后,每次都需要对整个产品重新进行构建和发布,任务耗时操作上也比较繁琐。
在使用了微前端架构后,可以将不能的功能模块拆分成独立的应用,此时功能模块就可以单独构建单独发布了,构建时间也会变得非常快,应用发布后不需要更改其他内容应用就会自动更新,这意味着你可以进行频繁的构建发布操作了。

3. 允许单个团队做出技术决策

因为微前端构架与框架无关,当一个应用由多个团队进行开发时,每个团队都可以使用自己擅长的技术栈进行开发,也就是它允许适当的让团队决策使用哪种技术,从而使团队协作变得不再僵硬。
在这里插入图片描述
微前端的使用场景:

  1. 拆分巨型应用,使应用变得更加可维护

  2. 兼容历史应用,实现增量开发

三、 如何实现微前端

1. 多个微应用如何进行组合?

在微前端架构中,除了存在多个微应用以外,还存在一个容器应用,每个微应用都需要被注册到容器应用中。
微前端中的每个应用在浏览器中都是一个独立的 JavaScript 模块,通过模块化的方式被容器应用启动和运行。
使用模块化的方式运行应用可以防止不同的微应用在同时运行时发生冲突。

2. 在微应用中如何实现路由 ?

在微前端架构中,当路由发生变化时,容器应用首先会拦截路由的变化,根据路由匹配微前端应用,当匹配到微应用以后,再启动微应用路由,匹配具体的页面组件。

3. 微应用与微应用之间如何实现状态共享?

在微应用中可以通过发布订阅模式实现状态共享,比如使用 RxJS。

4. 微应用与微应用之间如何实现框架和库的共享?

通过 import-map 和 webpack 中的 externals 属性。

四、. Systemjs 模块化解决方案

1 概述

在微前端架构中,微应用被打包为模块,但浏览器不支持模块化,需要使用 systemjs 实现浏览器中的模块化。

systemjs 是一个用于实现模块化的 JavaScript 库,有属于自己的模块化规范。

在开发阶段我们可以使用 ES 模块规范,然后使用 webpack 将其转换为 systemjs 支持的模块。

2 体验

案例:通过 webpack 将 react 应用打包为 systemjs 模块,在通过 systemjs 在浏览器中加载模块

npm install webpack@5.17.0 webpack-cli@4.4.0 webpack-dev-server@3.11.2 html-webpack-plugin@4.5.1 @babel/core@7.12.10 @babel/cli@7.12.10 @babel/preset-env@7.12.@babel/preset-react@7.12.10 babel-loader@8.2.
// package.json
{
"name": "systemjs-react",
"scripts": {
"start": "webpack serve"
},
"dependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"babel-loader": "^8.2.2",
"html-webpack-plugin": "^4.5.1",
"webpack": "^5.17.0",
"webpack-cli": "^4.4.0",
"webpack-dev-server": "^3.11.2"
}
}
// webpack.config.js
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.join(__dirname, "build"),
filename: "index.js",
libraryTarget: "system"
},
devtool: "source-map",
devServer: {
port: 9000 ,
contentBase: path.join(__dirname, "build"),
historyApiFallback: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/react"]
}
}
}plugins: [
new HtmlWebpackPlugin({
inject: false,
template: "./src/index.html"
})
],
externals: ["react", "react-dom", "react-router-dom"]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>systemjs-react</title>
<script type="systemjs-importmap">
{
"imports": {
"react":
"https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom/umd/react-
dom.production.min.js",
"react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-
dom@5.2.0/umd/react-router-dom.min.js"
}
}
</script>
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js"></script>
</head>
<body>
<div id="root"></div>
<script>
System.import("./index.js")
</script>
</body>
</html>

五、 微前端框架 single-spa

1 single-spa 概述

single-spa 是一个实现微前端架构的框架。

在 single-spa 框架中有三种类型的微前端应用:

  1. single-spa-application / parcel:微前端架构中的微应用,可以使用 vue、react、angular 等框架。

  2. single-spa root config:创建微前端容器应用。

  3. utility modules:公共模块应用,非渲染组件,用于跨应用共享 javascript 逻辑的微应用。

2 创建容器应用

  1. 安装 single-spa 脚手架工具:npm install create-single-spa@2.0.3 -g

在这里插入图片描述

  1. 创建微前端应用目录:mkdir workspace && cd “$_”

  2. 创建微前端容器应用:create-single-spa

    1. 应用文件夹填写 container

    2. 应用选择 single-spa root config

    3. 组织名称填写 study
      组织名称可以理解为团队名称,微前端架构允许多团队共同开发应用,组织名称可以标识应用由哪个团队开发。
      应用名称的命名规则为 @组织名称/应用名称,比如 @study/todos

  3. 启动应用:npm start

  4. 访问应用:localhost:9000

  5. 默认代码解析

    1. Root-config.js
// workspace/container/src/study-root-config.js
import { registerApplication, start } from "single-spa"
/*
注册微前端应用1. name: 字符串类型, 微前端应用名称 "@组织名称/应用名称"
2. app: 函数类型, 返回 Promise, 通过 systemjs 引用打包好的微前端应用模块代码
(umd)
3. activeWhen: 路由匹配时激活应用
*/
registerApplication({
name: "@single-spa/welcome",
app: () =>
System.import(
"https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"
),
activeWhen: ["/"]
})
  1. index.ejs
// start 方法必须在 single spa 的配置文件中调用
// 在调用 start 之前, 应用会被加载, 但不会初始化, 挂载或卸载.
start({
// 是否可以通过 history.pushState() 和 history.replaceState() 更改触发
single-spa 路由
// true 不允许 false 允许
urlRerouteOnly: true
})
<!-- 导入微前端容器应用 -->
<script>
System.import("@study/root-config")
</script>
<!--
import-map-overrides 可以覆盖导入映射
当前项目中用于配合 single-spa Inspector 调试工具使用.
可以手动覆盖项目中的 JavaScript 模块加载地址, 用于调试.
-->
<import-map-overrides-full show-when-local-storage="devtools" dev-libs>
</import-map-overrides-full>
 <!-- 模块加载器 -->
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js">
</script>
<!-- systemjs 用来解析 AMD 模块的插件 -->
<script
src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/extras/amd.min.js"
></script>
<!-- 用于覆盖通过 import-map 设置的 JavaScript 模块下载地址 -->
<script src="https://cdn.jsdelivr.net/npm/import-map-
overrides@2.2.0/dist/import-map-overrides.js"></script>
<!-- 用于支持 Angular 应用 -->
<script
src="https://cdn.jsdelivr.net/npm/zone.js@0.10.3/dist/zone.min.js">
</script>
<!-- single-spa 预加载 -->
<link
rel="preload"
href="https://cdn.jsdelivr.net/npm/single-spa@5.8.3/lib/system/single-
spa.min.js"
as="script"
/>
<!-- JavaScript 模块下载地址 此处可放置微前端项目中的公共模块 -->
<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-
spa@5.8.3/lib/system/single-spa.min.js"
}
}
</script>

六、创建不基于框架的微应用

  1. 应用初始化:mkdir lagou && cd "$_"
  2. 配置 webpack
const { merge } = require("webpack-merge")
const singleSpaDefaults = require("webpack-config-single-spa")module.exports = () => {
const defaultConfig = singleSpaDefaults({
// 组织名称
orgName: "study",
// 项目名称
projectName: "lagou"
})return merge(defaultConfig, {
devServer: {
port: 9001
}
})
}
  1. 在 package.json 文件中添加应用启动命令
"scripts": {
"start": "webpack serve"
}
  1. 在应用入口文件中导出微前端应用所需的生命周期函数,生命周期函数必须返回 Promise
let lagouContainer = nullexport const bootstrap = async function () {
console.log("应用正在启动")
}
export const mount = async function () {
console.log("应用正在挂载")
lagouContainer = document.createElement("div")
lagouContainer.innerHTML = "Hello Lagou"
lagouContainer.id = "lagouContainer"
document.body.appendChild(lagouContainer)
}
export const unmount = async function () {
console.log("应用正在卸载")
document.body.removeChild(lagouContainer)
}
  1. 在为前端容器应用中注册微前端应用
registerApplication({
name: "@study/lagou",
app: () => System.import("@study/lagou"),
activeWhen: ["/lagou"]
})
  1. 在模板文件中指定模块访问地址
<script type="systemjs-importmap">
{
"imports": {
"@study/lagou": "//localhost:9001/study-lagou.js"
}
}
</script>
  1. 修改默认应用代码
// 注意: 参数的传递方式发生了变化, 原来是传递了一个对象, 对象中有三项配置, 现在是传递了三个参数
registerApplication(
"@single-spa/welcome",
() =>
System.import(
"https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"
),
location => location.pathname === "/"
)

七、创建基于 React 的微应用

  1. 创建应用:create-single-spa

    1. 应用目录输入 todos

    2. 框架选择 react

  2. 修改应用端口 && 启动应用

"scripts": {
"start": "webpack serve --port 9002",
}
}
  1. 注册应用,将 React 项目的入口文件注册到基座应用中.
registerApplication({
name: "@study/todos",
app: () => System.import("@study/todos"),
activeWhen: ["/todos"]
})
  1. 指定微前端应用模块的引用地址
<!--=在注册应用时 systemjs 引用了 @study/todos 模块, 所以需要配置该模块的引用地址-->
<script type="systemjs-importmap">
{
"imports": {
"@study/root-config": "//localhost:9000/study-root-config.js",
"@study/todos": "//localhost:9002/study-todos.js"
}
}
</script>
  1. 指定公共库的访问地址

默认情况下,应用中的 react 和 react-dom 没有被 webpack 打包, single-spa 认为它是公共库,不应该单独打包。

<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-
spa@5.8.3/lib/system/single-spa.min.js",
"react":
"https://cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom@17.0.1/umd/react-
dom.production.min.js",
"react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-
dom@5.2.0/umd/react-router-dom.min.js"
}
}
</script>
  1. 微前端 React 应用入口文件代码解析
// react、react-dom 的引用是 index.ejs 文件中 import-map 中指定的版本
import React from "react"
import ReactDOM from "react-dom"
// single-spa-react 用于创建使用 React 框架实现的微前端应用
import singleSpaReact from "single-spa-react"
// 用于渲染在页面中的根组件
import rootComponent from "./root.component"// 指定根组件的渲染位置
const domElementGetter = () => document.getElementById("todosContainer")
// 错误边界函数
const errorBoundary = () => <div>发生错误时此处内容将会被渲染</div>// 创建基于 React 框架的微前端应用, 返回生命周期函数对象
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent,
domElementGetter,
errorBoundary
})
// 暴露必要的生命周期函数export const { bootstrap, mount, unmount } = lifecycles
  1. 路由配置
import React from "react"
import {BrowserRouter, Switch, Route, Redirect, Link} from "react-router-
dom"
import Home from "./pages/Home"
import About from "./pages/About"export default function Root(props) {
return (
<BrowserRouter basename="/todos">
<div>{props.name}</div>
<div>
<Link to="/home">Home</Link>
<Link to="/about">About</Link>
</div>
<Switch>
<Route path="/home">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Redirect to="/home" />
</Route>
</Switch>
</BrowserRouter>
)
}
  1. 修改 webpack 配置
const { merge } = require("webpack-merge")
const singleSpaDefaults = require("webpack-config-single-spa-react")module.exports = (webpackConfigEnv, argv) => {
const defaultConfig = singleSpaDefaults({
orgName: "study",
projectName: "todos",
webpackConfigEnv,
argv
})
return merge(defaultConfig, {
externals: ["react-router-dom"]
})
}

八、创建基于 Vue 的微应用

  1. 创建应用:create-single-spa

    1. 项目文件夹填写 realworld

    2. 框架选择 Vue

    3. 生成 Vue 2 项目

  2. 提取 vue && vue-router

// vue.config.js
module.exports = {
chainWebpack: config => {
config.externals(["vue", "vue-router"])
}
}
<script type="systemjs-importmap">
{
"imports": {
"vue": "https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js",
"vue-router": "https://cdn.jsdelivr.net/npm/vue-router@3.0.7/dist/vue-
router.min.js"
}
}
</script>
  1. 修改启动命令 && 启动应用
"scripts": {"start": "vue-cli-service serve --port 9003",
}
  1. Vue 应用配置路由
import Vue from "vue"
import VueRouter from "vue-router"
import singleSpaVue from "single-spa-vue"
import App from "./App.vue"Vue.use(VueRouter)Vue.config.productionTip = false// 路由组件
const Foo = { template: "<div>foo</div>" }
const Bar = { template: "<div>bar</div>" }// 路由规则
const routes = [
{ path: "/foo", component: Foo },
{ path: "/bar", component: Bar }
]// 路由实例const router = new VueRouter({ routes, mode: "history", base: "/realworld"
})const vueLifecycles = singleSpaVue({
Vue,
// 应用配置
appOptions: {
// 路由
router,
// 渲染组件
render(h) {
return h(App, {
// 向组件中传递的数据
props: {
name: this.name,
mountParcel: this.mountParcel,
singleSpa: this.singleSpa
}
})
}
}
})
// 导出生命周期函数
export const bootstrap = vueLifecycles.bootstrap
export const mount = vueLifecycles.mount
export const unmount = vueLifecycles.unmount
<template>
<div id="app">
<h1>{{ name }}</h1>
<p>
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
</div>
</template><script>
export default {
name: "App",
props: ["name"]
}
</script>

九、创建 Parcel 应用

Parcel 用来创建公共 UI,涉及到跨框架共享 UI 时需要使用 Parcel。
Parcel 的定义可以使用任何 single-spa 支持的框架,它也是单独的应用,需要单独启动,但是它不关联路由。
Parcel 应用的模块访问地址也需要被添加到 import-map 中,其他微应用通过 System.import 方法进行 引用。

需求:创建 navbar parcel,在不同的应用中使用它。

  1. 使用 React 创建 Parcel 应用 create-single-spa
import React from "react"
import ReactDOM from "react-dom"
import singleSpaReact from "single-spa-react"
import Root from "./root.component"const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: Root,
errorBoundary(err, info, props) {
// Customize the root error boundary for your microfrontend here.
return null
}
})export const { bootstrap, mount, unmount } = lifecycles
export default function Root(props) {
return (
<BrowserRouter>
<div>
<Link to="/">@single-spa/welcome</Link>{" "}
<Link to="/lagou">@study/lagou</Link>{" "}
<Link to="/todos">@study/todos</Link>{" "}
<Link to="/realworld">@study/realworld</Link>
</div>
</BrowserRouter>
)
}
  1. 在 webpack 配置文件中去除 react-router-dom
externals: ["react-router-dom"]
  1. 指定端口,启动应用
"scripts": {
"start": "webpack serve --port 9004",
}
  1. 在模板文件中指定应用模块地址
{
"imports": {
"@study/navbar": "//localhost:9004/study-navbar.js"
}
}
  1. 在 React 应用中使用它
import Parcel from "single-spa-react/parcel"<Parcel config={System.import("@study/navbar")} />
  1. 在 Vue 应用中使用它
<Parcel :config="parcelConfig" :mountParcel="mountParcel" /><script>
import Parcel from "single-spa-vue/dist/esm/parcel"
import { mountRootParcel } from "single-spa"export default {
components: {
Parcel
},
data() {
return {
parcelConfig: window.System.import("@study/navbar"),
mountParcel: mountRootParcel
}
}
}
</script>

十、创建 utility modules

用于放置跨应用共享的 JavaScript 逻辑,它也是独立的应用,需要单独构建单独启动。

  1. 创建应用:create-single-spa

    1. 文件夹填写 tools

    2. 应用选择 in-browser utility module (styleguide, api cache, etc)

  2. 修改端口,启动应用

"scripts": {
"start": "webpack serve --port 9005",
}
  1. 应用中导出方法
export function sayHello(who) {
console.log(`%c${who} Say Hello`, "color: skyblue")
}
  1. 在模板文件中声明应用模块访问地址
<script type="systemjs-importmap">
{
"imports": {
"@study/tools": "//localhost:9005/study-tools.js"
}
}
</script>
  1. 在 React 应用中使用该方法
import React, { useEffect, useState } from "react"function useToolsModule() {
const [toolsModule, setToolsModule] = useState()
useEffect(() => {
System.import("@study/tools").then(setToolsModule)
}, [])
return toolsModule
}const Home = () => {
const toolsModule = useToolsModule()
if (toolsModule) toolsModule.sayHello("todos")
return <div>Todos home works</div>
}export default Home
  1. 在 Vue 应用中使用该方法
<h1 @click="handleClick">{{ name }}</h1>
async handleClick() {
let toolsModule = await window.System.import("@study/tools")
toolsModule.sayHello("realworld")
}

十一、实现跨应用通信

跨应用通信可以使用 RxJS,因为它无关于框架,也就是可以在任何其他框架中使用。

  1. 在 index.ejs 文件中添加 rxjs 的 import-map
 {
"imports": {
"rxjs":
"https://cdn.jsdelivr.net/npm/rxjs@6.6.3/bundles/rxjs.umd.min.js"
}
}
  1. 在 utility modules 中导出一个 ReplaySubject,它可以广播历史消息,就算应用是动态加载进来的,也可以接收到数据。
import { ReplaySubject } from "rxjs"export const sharedSubject = new ReplaySubject()
  1. 在 React 应用中订阅它
useEffect(() => {
let subjection = null
if (toolsModule) {
subjection = toolsModule.sharedSubject.subscribe(console.log)
}
return () => subjection.unsubscribe()
}, [toolsModule])
  1. 在 Vue 应用中订阅它
async mounted() {
let toolsModule = await window.System.import("@study/tools")
toolsModule.sharedSubject.subscribe(console.log)
}

十二、Layout Engine

允许使用组件的方式声明顶层路由,并且提供了更加便捷的路由API用来注册应用。

  1. 下载布局引擎 npm install single-spa-layout@1.3.1

  2. 构建路由

<template id="single-spa-layout">
<single-spa-router>
<application name="@study/navbar"></application>
<route default>
<application name="@single-spa/welcome"></application>
</route>
<route path="lagou">
<application name="@study/lagou"></application>
</route>
<route path="todos">
<application name="@study/todos"></application>
</route>
<route path="realworld">
<application name="@study/realworld"></application>
</route>
</single-spa-router>
</template>
<script type="systemjs-importmap">
{
"imports": {
"@single-spa/welcome": "https://unpkg.com/single-spa-
welcome/dist/single-spa-welcome.js"
}
}
</script>
  1. 获取路由信息 && 注册应用
import { registerApplication, start } from "single-spa"
import { constructApplications, constructRoutes } from "single-spa-layout"// 获取路由配置对象
const routes = constructRoutes(document.querySelector("#single-spa-layout"))
// 获取路由信息数组
const applications = constructApplications({
routes,
loadApp({ name }) {
return System.import(name)
}
})applications.forEach(registerApplication)start({
urlRerouteOnly: true
})

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

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

相关文章

大数据时代的小数据神器 - asqlcell

自从Google发布了经典的MapReduce论文&#xff0c;以及Yahoo开源了Hadoop的实现&#xff0c;大数据这个词就成为了一个行业的热门。在不断提高的机器性能和各种层出不穷的工具框架加持下&#xff0c;数据分析开始从过去的采样抽查变成全量整体&#xff0c;原先被抽样丢弃的隐藏…

网络安全实验室7.综合关

7.综合关 1.渗透测试第一期 url&#xff1a;http://lab1.xseclab.com/base14_2d7aae2ae829d1d5f45c59e8046bbc54/ 进入忘记密码页面&#xff0c;右键查看源码&#xff0c;发现一个手机号 解题思路&#xff1a;通过给admin用户绑定13388758688手机号码&#xff0c;然后再进行…

使用vue3,vite,less,flask,python从零开始学习硅谷外卖(16-40集)

严正声明&#xff01; 重要的事情说一遍&#xff0c;本文章仅供分享&#xff0c;文章和代码都是开源的&#xff0c;严禁以此牟利&#xff0c;严禁侵犯尚硅谷原作视频的任何权益&#xff0c;我知道学习编程的人各种各样的心思都有&#xff0c;但这不是你对开源社区侵权的理由&am…

【算法题解】15. 设计最小栈

这是一道 中等难度 的题。 题目来自&#xff1a;leetcode 题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在 常数时间 内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void p…

驱动 | Linux | NVMe 不完全总结

本文主要参考这里 1’ 2 的解析和 linux 源码 3。 此处推荐一个可以便捷查看 linux 源码的网站 bootlin 4。 更新&#xff1a;2022 / 02 / 11 驱动 | Linux | NVMe 不完全总结NVMe 的前世今生从系统角度看 NVMe 驱动NVMe CommandPCI 总线从架构角度看 NVMe 驱动NVMe 驱动的文件…

详细解读503服务不可用的错误以及如何解决503服务不可用

文章目录1. 问题引言2. 什么是503服务不可用错误3 尝试解决问题3.1 重新加载页面3.2 检查该站点是否为其他人关闭3.3 重新启动设备3.3 联系网站4. 其他解决问的方法1. 问题引言 你以前遇到过错误503吗&#xff1f; 例如&#xff0c;您可能会收到消息&#xff0c;如503服务不可…

三种方式查看linux终端terminal是否可以访问外网ping,curl,wget

方法1&#xff1a;ping注意不要用ping www.google.com.hk来验证&#xff0c;因为有墙&#xff0c;墙阻止了你接受网址发回的响应数据。即使你那啥过&#xff0c;浏览器都可以访问Google&#xff0c;terminal里面也是无法得到响应 百度在墙内&#xff0c;所以可以正常拿到响应信…

sklearn降维算法1 - 降维思想与PCA实现

目录1、概述1.1 维度概念2、PCA与SVD2.1 降维实现2.2 重要参数n_components2.2.1 案例&#xff1a;高维数据的可视化2.2.2 最大似然估计自选超参数2.2.3 按信息量占比选超参数1、概述 1.1 维度概念 shape返回的结果&#xff0c;几维几个方括号嵌套 特征矩阵特指二维的 一般来…

truffle 创建测试合约并部署到测试网络

1、npm 安装truffle npm install -g truffle2、创建truffle项目 mkdir imooc-on-blockchain-truffle && cd imooc-on-blockchain-truffle3、初始化truffle目录&#xff0c;会生成如下几个目录 contracts 存放.sol合约文件migrations 部署脚本目录test 测试文件目录t…

【GlobalMapper精品教程】045:空间分析工具(2)——相交

GlobalMapper提供的空间分析(操作)的方法有:交集、并集、单并集、差异、对称差集、相交、重叠、接触、包含、等于、内部、分离等,本文主要讲述相交工具的使用。 文章目录 一、实验数据二、符号化设置三、相交运算四、结果展示五、心灵感悟一、实验数据 加载配套实验数据(…

分布式之分布式事务V2

写在前面 本文一起来看下分布式环境下的事务问题&#xff0c;即我们经常听到的分布式事务问题。想要解决分布式事务问题&#xff0c;需要使用到分布式事务相关的协议&#xff0c;主要有2PC即两阶段提交协议&#xff0c;TCC&#xff08;try-confirm-cancel&#xff09;&#xf…

html的表单标签(form)

目录标题1、表单标签主要有三大类&#xff1a;2、表单标签中常见的属性3、例子代码及结果4、注意&#xff1a;5、表单中特殊的属性表单标签可以用来数据交互&#xff0c;而前面学的六个标签只能发送不能接收。 表单标签的作用就是数据交互1、表单标签主要有三大类&#xff1a; …

ImageMagick任意文件读取漏洞(CVE-2022-44268)

0x00 前提 前几天爆出一个 ImageMagick 漏洞 &#xff0c;可以造成一个任意文件读取的危害比较可观&#xff0c;最近有时间来复现学习一下 主要是影响的范围很大&#xff0c;很多地方都有这个问题&#xff0c;需要来学习一下 0x01 介绍 ImageMagick 是一个免费的开源软件套…

SpringMVC:拦截器(12)

拦截器1. 拦截器概念2. 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1: 创建拦截器类步骤2: 配置拦截器类步骤3: SpringMVC添加SpringMvcSupport包扫描和interceptor包扫描步骤4: 简化SpringMvcSupport的编写5 测试3. 拦截器参数解析&#xff08;了解&#xff09;3.1 前置处理…

【Call for papers】SIGCOMM-2023(CCF-A/计算机网络/2023年2月15日截稿)

ACM SIGCOMM is the flagship annual conference of the ACM Special Interest Group on Data Communication (SIGCOMM). ACM SIGCOMM 2023, the 37th edition of the conference series, will be held in New York City, US, September 10 - 14, 2023. 文章目录1.会议信息2.时…

Redis集群搭建(主从、哨兵、分片)

1.单机安装Redis 首先需要安装Redis所需要的依赖&#xff1a; yum install -y gcc tcl然后将课前资料提供的Redis安装包上传到虚拟机的任意目录&#xff1a; 例如&#xff0c;我放到了/tmp目录&#xff1a; 解压缩&#xff1a; tar -xzf redis-6.2.4.tar.gz解压后&#xff1…

OpenPPL PPQ量化(5):执行引擎 源码剖析

目录 PPQ Graph Executor(PPQ 执行引擎) PPQ Backend Functions(PPQ 算子库) PPQ Executor(PPQ 执行引擎) Quantize Delegate (量化代理函数) Usage (用法示例) Hook (执行钩子函数) 前面四篇博客其实就讲了下面两行代码&#xff1a; ppq_ir load_onnx_graph(onnx_impor…

FlinkCEP - Flink的复杂事件处理

版本说明 本文中以Flink 1.16.1 版本讲解说明 Note:Flink1.16.1版本相较于之前版本增强的within函数&#xff0c; 支持模式序列中相邻事件间的超时定义&#xff0c;以前版本只支持模式序列中第一个事件到最后一个事件之间的最大时间间隔。 快速开始 基于Kafka connecter 流…

《计算机组成与设计》01. 计算机抽象及相关技术

文章目录计算机体系结构中的 8 个伟大思想面向摩尔定律的设计使用抽象简化设计加速经常性事件通过并行提高性能通过流水线提高性能存储层次通过冗余提高可靠性性能性能的度量时钟周期数和时钟周期长度与CPU时间的公式指令性能公式经典的 CPU 性能公式CPI 计算公式程序执行时间计…

【前端】Vue项目:旅游App-(23)detail:房东介绍、热门评论、预定须知组件

文章目录目标过程与代码房东介绍landlord热门评论HotComment预定须知Book效果总代码修改或添加的文件detail.vuedetail-book.vuedetail-hotComment.vuedetail-landlord.vue参考本项目博客总结&#xff1a;【前端】Vue项目&#xff1a;旅游App-博客总结 目标 根据detail页面获…