缓存管理
This commit is contained in:
parent
43521cf93f
commit
4ac4026187
26
README.md
26
README.md
@ -3,6 +3,17 @@
|
||||
P2P CDN
|
||||
|
||||
|
||||
/data/path/filename.xx
|
||||
|
||||
缓存指定资源后, 假设资源按 16kb 分片
|
||||
a1 要求返回第 1 片,
|
||||
a2 要求返回第 2 片, 如果 a2 提前完成, 继续返回第 3 片
|
||||
全部分片接收完毕后合并进行 size 和 hash 验证
|
||||
|
||||
资源表汇报给
|
||||
|
||||
|
||||
|
||||
持有资源变动时, 通知节点列表
|
||||
获取一个资源时, 先查找拥有此资源的节点列表
|
||||
|
||||
@ -34,3 +45,18 @@ O1双向查询
|
||||
|
||||
建立连接后交换资源列表及过期时间
|
||||
|
||||
### 最短响应时间
|
||||
1. 请求某个资源时, 先向节点列表伺服器请求拥有此资源的节点列表, 再通过节点列表取一个建立连接信道, 随后获取此资源
|
||||
2. 由于节点是持久在线, 资源伺服器对节点空间位置进行节点网络分布预测, 返回给距离请求节点最近的几个节点列表(减少地域距离耗时)
|
||||
3. 同时向多个节点建立连接, 获取某个资源时从不同节点请求不同分片, 这需要预先了解资源大小分片数量(通过并发减少串行下载时间, 且能从更快的节点下载更多的分片, 慢的节点减少分片下载)
|
||||
4. 建立连接需要多次三方通信握手, 且保持连接也需要续握手, 如何减少握手时间?
|
||||
5. 每个资源都从服务器请求节点列表效率极差, 如何复用,
|
||||
6. 建立连接耗时较大, 如何复用连接?
|
||||
|
||||
在线与资源分布计算,
|
||||
假设 10-100 同时在线, 每节点储量为1000资源(1GB)
|
||||
100 设备储存 100G资源, 去除重复 75% 则 25G 资源被减耗
|
||||
高峰访问不均, 利用率上升 50% 则实 %50 流量被减耗
|
||||
由于峰值浮动, 在低谷期减耗效率仅为 10%
|
||||
在线人数越多则减耗比率越大
|
||||
|
||||
|
@ -2,3 +2,4 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>PCDN</title>
|
||||
<script src="./main.js"></script>
|
||||
<img src="test.jpg" />
|
||||
|
52
main.js
52
main.js
@ -1,33 +1,33 @@
|
||||
//export class Node {
|
||||
// id: ''
|
||||
// name: ''
|
||||
// assets: new Map()
|
||||
// get(name) {}
|
||||
// set(name) {}
|
||||
// del(name) {}
|
||||
//}
|
||||
//
|
||||
//export const nodes = new Map() // 在线的节点
|
||||
//export const assets = new Map() // 在线的资源
|
||||
//
|
||||
//// 示例: 查询持有某个资源的节点列表
|
||||
//const list = query('xxx.jpg').map(item => 'node id')
|
||||
//const 测速排序 = () => {}
|
||||
//
|
||||
//// 查询某个
|
||||
//
|
||||
//// 示例: 通过PCDN节点网络获取某个资源
|
||||
//const pcdn = new PCDN({ server: '/pcdn' })
|
||||
//pcdn.get('xxx.jpg').then(file => {})
|
||||
// 连接信令服务器
|
||||
const protocol = window.location.protocol.replace('http', 'ws')
|
||||
const ws = new WebSocket(`${protocol}//${window.location.host}/api`)
|
||||
ws.onopen = () => {
|
||||
console.log('WebSocket connection opened')
|
||||
ws.send(JSON.stringify({ type: 'init', data: 'Hello Server' }))
|
||||
}
|
||||
ws.onmessage = (event) => {
|
||||
console.log('Message from server:', event.data)
|
||||
}
|
||||
ws.onerror = (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
}
|
||||
ws.onclose = () => {
|
||||
console.log('WebSocket connection closed')
|
||||
}
|
||||
|
||||
// Service Worker
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.addEventListener('message', event => {
|
||||
console.log('收到消息 Service Worker: ', event.data) // 接收消息
|
||||
event.source.postMessage('Hello from main thread') // 回应 Service Worker
|
||||
})
|
||||
navigator.serviceWorker.register('/sw.js').then((registration) => {
|
||||
console.log('Service Worker 注册成功: ')
|
||||
}).catch((error) => {
|
||||
console.log('Service Worker 注册失败: ')
|
||||
})
|
||||
navigator.serviceWorker.register('/sw.js')
|
||||
//.then((registration) => {
|
||||
// console.log('Service Worker 注册成功')
|
||||
// registration.showNotification('Hello World')
|
||||
//})
|
||||
}
|
||||
|
||||
//navigator.storage.estimate().then((estimate) => {
|
||||
// console.log('Storage usage: ', estimate.usage / 1000 / 1000 / 1000, estimate.quota / 1000 / 1000 / 1000)
|
||||
//})
|
||||
|
10
package.json
10
package.json
@ -2,13 +2,19 @@
|
||||
"name": "pcdn",
|
||||
"version": "1.0.0",
|
||||
"description": "P2P CDN",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "vite --open"
|
||||
"dev": "concurrently 'vite --open' 'node server.js'",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"author": "satori.love",
|
||||
"license": "GPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"vite": "^5.2.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"ws": "^8.18.1"
|
||||
}
|
||||
}
|
||||
|
BIN
public/test.jpg
Normal file
BIN
public/test.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
29
server.js
Normal file
29
server.js
Normal file
@ -0,0 +1,29 @@
|
||||
import http from 'http'
|
||||
import { WebSocketServer } from 'ws'
|
||||
|
||||
// 创建一个 HTTP 服务器
|
||||
const server = http.createServer((req, res) => {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' })
|
||||
res.end('WebSocket server is running')
|
||||
})
|
||||
|
||||
// 创建 WebSocket 服务器,并将其绑定到 HTTP 服务器
|
||||
const wss = new WebSocketServer({ server })
|
||||
|
||||
// 处理 WebSocket 连接
|
||||
wss.on('connection', ws => {
|
||||
console.log('A new client connected!')
|
||||
|
||||
// 监听客户端发送的消息
|
||||
ws.on('message', message => {
|
||||
console.log('收到数据:', message)
|
||||
})
|
||||
|
||||
// 发送欢迎消息给客户端
|
||||
ws.send('Hello from WebSocket server!')
|
||||
})
|
||||
|
||||
// 启动 HTTP 服务器,监听端口
|
||||
server.listen(8080, () => {
|
||||
console.log('Server is listening on http://localhost:8080')
|
||||
})
|
81
sw.js
81
sw.js
@ -1,20 +1,85 @@
|
||||
const CACHE_NAME = 'file-cache-v1'
|
||||
const FILE_TYPES = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml']
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
console.log('Service Worker 安装')
|
||||
})
|
||||
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
console.log('Service Worker 激活')
|
||||
console.log('Service Worker 激活, 立即接管页面')
|
||||
event.waitUntil(clients.claim())
|
||||
})
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
console.log('Fetch intercepted for:', event.request.url)
|
||||
self.clients.matchAll().then(clients => {
|
||||
clients.forEach(client => {
|
||||
client.postMessage('Hello from Service Worker')
|
||||
//console.log('Service Worker 获取资源:', event.request.url)
|
||||
|
||||
if (!event.request.url.match(/\.(jpeg|jpg|gif|png|webp|svg)$/i)) {
|
||||
return event.respondWith(fetch(event.request))
|
||||
}
|
||||
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(async (cachedResponse) => {
|
||||
// 如果文件已缓存,则返回缓存的响应
|
||||
if (cachedResponse) {
|
||||
console.log('使用了缓存:', event.request.url)
|
||||
|
||||
for (const key of await caches.keys()) {
|
||||
const cache = await caches.open(key)
|
||||
|
||||
const requests = await cache.keys()
|
||||
requests.forEach((request) => {
|
||||
console.log(request.url)
|
||||
})
|
||||
}
|
||||
|
||||
return cachedResponse
|
||||
}
|
||||
|
||||
// 如果缓存中没有,则发起网络请求并缓存新图像(检查网络响应是否为文件)
|
||||
return fetch(event.request).then(async (networkResponse) => {
|
||||
if (networkResponse && networkResponse.ok && FILE_TYPES.includes(networkResponse.headers.get('Content-Type'))) {
|
||||
const cache = await caches.open(CACHE_NAME)
|
||||
await cache.put(event.request, networkResponse.clone())
|
||||
}
|
||||
return networkResponse
|
||||
})
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
//// 先尝试从 webRTC 获取资源, 如果失败则从网络获取资源
|
||||
//event.respondWith(async function () {
|
||||
// const response = await fetch(event.request)
|
||||
// return response
|
||||
//}())
|
||||
|
||||
//event.respondWith(fetch(event.request))
|
||||
//self.clients.matchAll().then(clients => {
|
||||
// clients.forEach(client => {
|
||||
// client.postMessage('Hello from Service Worker')
|
||||
// })
|
||||
//})
|
||||
})
|
||||
|
||||
self.addEventListener('message', event => {
|
||||
console.log('收到主线程消息: ', event.data)
|
||||
console.log("%c收到主线程消息: " + event.data, 'color: red;')
|
||||
})
|
||||
|
||||
//// 检查通知权限
|
||||
//if (Notification.permission === 'granted') {
|
||||
// // 如果已经授权,则可以显示通知
|
||||
// registration.showNotification('Hello World')
|
||||
//} else if (Notification.permission === 'default') {
|
||||
// // 如果权限尚未授予,则请求权限
|
||||
// Notification.requestPermission().then(permission => {
|
||||
// if (permission === 'granted') {
|
||||
// // 权限授予成功后显示通知
|
||||
// showNotification();
|
||||
// } else {
|
||||
// console.log('Notification permission denied');
|
||||
// }
|
||||
// }).catch(err => {
|
||||
// console.log('Failed to request notification permission', err);
|
||||
// });
|
||||
//} else {
|
||||
// console.log('Notification permission denied');
|
||||
//}
|
Loading…
Reference in New Issue
Block a user