架构设计基础设施保障IaaS存储1

简介: 架构设计基础设施保障IaaS存储1

1. 云硬盘

  1. HDD(普通云盘)

特征: 性能一般, IOPS大概在数百左右。

应用场景: 数据不被经常访问或者低I/O负载的应用场景,需要低成本并且有随机读写I/O的应用环境。

  1. 混合HDD(高效云盘)

特征: 结合HDD和SSD硬盘构建, IOPS为1000~5000左右。

应用场景: 开发与测试业务、系统盘。

  1. SSD云盘

特征: 具有稳定的IO能力, IOPS能够达到10000~25000左右。

应用场景:I/O密集型应用、中小型关系数据库、NoSQL数据库。

  1. 企业级SSD(ESSD云盘)

特征: 优化增强的SSD云盘, 一般是采用企业级的闪存硬件, IOPS能够达到10000~1000000左右。

应用场景: 大型OLTP数据库等关系型数据库、NoSQL数据库、ELK分布式日志存储等。

测试:

  1. 安装fio工具
yum -y install fio
  1. iops测试
fio --name=disktest --filename=~/disktest --rw=randread --refill_buffers --bs=4k --size=1G -runtime=5 -direct=1 -iodepth=128 -ioengine=libaio

输出结果:

[root@iZm5egp1t778ocdk7f1j6fZ ~]# fio --name=disktest --filename=~/disktest --rw=randread --refill_buffers --bs=4k --size=1G -runtime=5 -direct=1 -iodepth=128 -ioengine=libaio
disktest: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=128
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [r(1)][100.0%][r=8560KiB/s,w=0KiB/s][r=2140,w=0 IOPS][eta 00m:00s]
disktest: (groupid=0, jobs=1): err= 0: pid=1417: Thu Nov 12 22:09:25 2020
read: IOPS=2151, BW=8606KiB/s (8812kB/s)(42.3MiB/5032msec)
 slat (usec): min=2, max=166, avg= 6.54, stdev= 3.69
 clat (usec): min=794, max=157946, avg=59467.61, stdev=47971.33
  lat (usec): min=799, max=157950, avg=59474.73, stdev=47971.03
 clat percentiles (usec):
  |  1.00th=[  1172],  5.00th=[  1434], 10.00th=[  1614], 20.00th=[  1860],
  | 30.00th=[  2147], 40.00th=[  2999], 50.00th=[ 98042], 60.00th=[ 98042],
  | 70.00th=[ 99091], 80.00th=[ 99091], 90.00th=[ 99091], 95.00th=[100140],
  | 99.00th=[127402], 99.50th=[127402], 99.90th=[156238], 99.95th=[156238],
  | 99.99th=[158335]
bw (  KiB/s): min= 8544, max= 8560, per=99.46%, avg=8558.40, stdev= 5.06, samples=10
iops  : min= 2136, max= 2140, avg=2139.60, stdev= 1.26, samples=10
  lat (usec): 1000=0.16%
  lat (msec): 2=25.15%, 4=15.13%, 10=0.03%, 50=0.59%, 100=56.23%
  lat (msec): 250=2.71%
  cpu : usr=0.58%, sys=1.93%, ctx=1154, majf=0, minf=163
  IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.3%, >=64=99.4%
  submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
  complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
  issued rwts: total=10826,0,0,0 short=0,0,0,0 dropped=0,0,0,0
  latency: target=0, window=0, percentile=100.00%, depth=128
Run status group 0 (all jobs):
READ: bw=8606KiB/s (8812kB/s), 8606KiB/s-8606KiB/s (8812kB/s-8812kB/s), io=42.3MiB (44.3MB), run=5032-5032msec
Disk stats (read/write):
  vda: ios=10486/0, merge=0/1, ticks=614779/0, in_queue=485314, util=75.89%

iops平均达到2139.60,与高效云盘标示的2120基本是一致。

也可以挂在动态硬盘进行测试, 不同的类型和存储空间, IOPS是不一样:

2. 对象存储

  1. Amazon S3 vs 阿里云 OSS

Amazon S3,全称亚马逊简易存储服务(Amazon Simple Storage Service)

阿里云 OSS(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。

对比:

  1. 对象存储VS云硬盘
  • 提供接口访问
    对象存储本质是一个网络化的服务, 云硬盘是挂载到虚拟机的虚拟硬盘,必须连接到虚拟机才能操作。
  • 存储结构不一致
  • 云硬盘是一个可以作为一个真正的文件系统, 而云存储是一个近似键值(key和value)的存储服务。
  • 海量数据存储
  • 云硬盘一般会受自身容量的限制, 不能支撑海量数据存储, 对象存储得益于其底层设计, 天生就能够支撑大数据存储。对象存储服务不仅可以支持海量的小文件, 也适合处理大型文件。
  1. 实践操作

流程:

  1. 开通OSS服务OSS产品详情页
  2. 创建存储空间, Bucket名称要具备唯一性。
  3. 开通对应的访问权限

不要采用主账号,会存在安全隐患, 授权给RAM用户。

  1. 添加依赖
<dependency>
 <groupId>com.aliyun.oss</groupId>
 <artifactId>aliyun-sdk-oss</artifactId>
 <version>3.10.2</version>
</dependency>
  1. 上传文件

UploadApplication:

public class UploadApplication {
 public static void main(String[] args) throws Exception{
  // 创建OSSClient实例。
  OSS ossClient = new OSSClientBuilder().build(Constants.endpoint, Constants.accessKeyId, Constants.accessKeySecret);
  // 创建PutObjectRequest对象。
  PutObjectRequest putObjectRequest = new PutObjectRequest(Constants.bucketName, "readme", new File("d:/readme.txt"));
  // 上传文件。
  PutObjectResult result = ossClient.putObject(putObjectRequest);
  System.out.println("upload complete.");
  // 关闭OSSClient。
  ossClient.shutdown();
 }
}
  1. 下载文件

DownloadApplication:

public class DownloadApplication {
 public static void main(String[] args) {
  // Endpoint以杭州为例,其它Region请按实际情况填写。
  String endpoint = Constants.endpoint;
  // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
  String accessKeyId = Constants.accessKeyId;
  String accessKeySecret = Constants.accessKeySecret;
  String bucketName = Constants.bucketName;
  String objectName = "readme";
  // 创建OSSClient实例。
  OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
  // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
  ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File("e:/"+ objectName));
  // 关闭OSSClient。
  ossClient.shutdown();
  System.out.println("download complete.");
 }
}

3. 表单上传案例

  1. 应用场景

表单上传非常适合嵌入在HTML网页中来上传Object,比较常见的场景是网站应用,以招聘网站为例, 流程比对:

  • 不使用表单上传
  1. 网站用户上传简历。
  1. 网站服务器回应上传页面。
  2. 简历被上传到网站服务器。
  3. 网站服务器再将简历上传到OSS。
  1. 采用表单上传
  1. 网站用户上传简历。
  1. 网站服务器回应上传页面。
  2. 简历上传到OSS。

使用表单上传,少了一步转发流程, 并且在上传量过大时, 减少了业务应用方服务扩容的压力。

  1. 通过STS临时授权访问OSS

通过阿里云STS(Security Token Service)进行临时授权访问, 可以为第三方应用颁发一个自定义时效和权限的访问凭证, 用以保障服务安全性(类似于OAuth2的授权码访问模式)。

实现机制:

  1. RAM用户STS授权配置

进入RAM访问控制后台->用户->添加权限, 输入框填写"sts"过滤, 选择AliyunSTSAssumeRoleAccess权限。

  1. 创建权限策略

输入权限策略名称, 可以选择脚本配置, 更为灵活。

策略内容:

{
 "Version": "1",
 "Statement": [
  {
"Effect": "Allow",
"Action": [
 "oss:*"
],
"Resource": [
 "acs:oss:*:*:cloudstorage-test",
 "acs:oss:*:*:cloudstorage-test/*"
]
  }
 ]
}

意思是对名称为cloudstorage-test的Bucket具有完全控制权限。如果更细力度的控制, 可以修改Action,例如:

"Action": [ "oss:ListBuckets", "oss:GetBucketStat", "oss:GetBucketInfo", "oss:GetBucketTagging", "oss:GetBucketAcl" ],  
  1. 创建访问角色

打开"RAM角色管理",点击"创建RAM角色“,可信实体类型选择“阿里云账号”

接下来输入角色名称, 选择当前云账号;添加上面所创建的权限策略“oss_access”。

配置完成后, 会生成一个ARN值, 需要将它记录下来。

  1. 申请STS的访问TOKEN信息

StsServiceApplication代码:

public class StsServiceApplication {
 public static void main(String[] args) {
  String endpoint = "sts.cn-beijing.aliyuncs.com";
  String AccessKeyId = Constants.accessKeyId;
  String accessKeySecret = Constants.accessKeySecret;
  String roleArn = "acs:ram::1567235516853620:role/ram-oss-access";
  String roleSessionName = "oss_access_session";
  String policy = "{\n" +
 " \"Version\": \"1\", \n" +
 " \"Statement\": [\n" +
 "  {\n" +
 "\"Action\": [\n" +
 " \"oss:*\"\n" +
 "], \n" +
 "\"Resource\": [\n" +
 " \"acs:oss:*:*:*\" \n" +
 "], \n" +
 "\"Effect\": \"Allow\"\n" +
 "  }\n" +
 " ]\n" +
 "}";
  try {
// 添加endpoint(直接使用STS endpoint,前两个参数留空,无需添加region ID)
DefaultProfile.addEndpoint("", "", "Sts", endpoint);
// 构造default profile(参数留空,无需添加region ID)
IClientProfile profile = DefaultProfile.getProfile("", AccessKeyId, accessKeySecret);
// 用profile构造client
DefaultAcsClient client = new DefaultAcsClient(profile);
final AssumeRoleRequest request = new AssumeRoleRequest();
request.setMethod(MethodType.POST);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy); // 若policy为空,则用户将获得该角色下所有权限
request.setDurationSeconds(1000L); // 设置凭证有效时间
final AssumeRoleResponse response = client.getAcsResponse(request);
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
  } catch (ClientException e) {
System.out.println("Failed:");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
System.out.println("RequestId: " + e.getRequestId());
  }
 }
}

返回结果:

Expiration: 2020-11-15T06:37:51Z
Access Key Id: STS.NT2Mshx5eaKbLScAzcwXLLK5V
Access Key Secret: 7buxRohgRr6vT1EVAqq4FWjxaUFRQMuC4vvV55utenkJ
Security Token: CAISjwJ1q6Ft5B2yfSjIr5eHBsnclepE1omJTnXSpXo2e9dgo46etDz2IHxMenFgA+sfv/0ynGBR5/YSlrt0UIRyTEfPYNBr2Y9a6higZIyZdz4iUQhC2vOfAmG2J0PR7q27OpfELr70fvOqdCqz9Etayqf7cjOPRkGsNYbz57dsctUQWHvXD1dBH8wEZHEhyqkgOGDWKOymPzPzn2PUFzAIgAdnjn5l4qnNpa/54xHF3lrh0b1X9cajYLrcNpQyY80kDorsgrwrLfSbiBQ9sUYaqP1E64Vf4irCs92nBF1c3g6LKeK88Kc0cFcnPvhgQPcV9aWkxaQp6rzJ8Z7+zlNKJvoQWi/USZu70Fd2+ykG8lpTGoABiIGFt+WCBkX/yLkY3uHDiWq4Uud32DzXWQAQpGmOWXwYzPRepi0XCcC029hPoXwCsj6mWbd/Ls2bUQsLUPtG3ozr6WawG2XUBXgZI5dNip8dZJCWZSet9qGsNXubhA3hTC+Wi7MNOariEkmr1kjqnG6N/YNaWuMYJ3BUobvLL4g=
RequestId: 480E0B98-ACA5-4C98-AA82-6D9901CD7EE4
  1. 表单上传

FormPostApplication代码:

public class FormPostApplication {
 // The local file path to upload.
 private String localFilePath = "d:/trade_stock.sql";
 // OSS domain, such as http://oss-cn-hangzhou.aliyuncs.com
 private String endpoint = Constants.endpoint;
 // Access key Id. Please get it from https://ak-console.aliyun.com
 private String accessKeyId = "STS.NTcqigyooFzFUeV2GRZPWDLt8";
 private String accessKeySecret = "HwdZYJ8wVUopdNscwDYFf7oPgBpA4WXgG6K4JggztqW9";
 private String oss_security_token= "CAISjwJ1q6Ft5B2yfSjIr5fWOtPTlLBO8bitV0Pn1kcHVt97q4nf2jz2IHxMenFgA+sfv/0ynGBR5/YSlrt0UIRyTEfPYNBr2Y9a6higZIyZW2tYUAhC2vOfAmG2J0PR7q27OpfELr70fvOqdCqz9Etayqf7cjOPRkGsNYbz57dsctUQWHvXD1dBH8wEZHEhyqkgOGDWKOymPzPzn2PUFzAIgAdnjn5l4qnNpa/54xHF3lrh0b1X9cajYLrcNpQyY80kDorsgrwrLfSbiBQ9sUYaqP1E64Vf4irCs92nBF1c3g6LKeK88Kc0cFcnPvhgQPcV9aWkxaQp6rzJ8Z7+zlNKJvoQWi/USZu70Fd2+ykG8lpTGoABUJly6VzNT0fNrAW2uTyuuGX+PI/PaV7df5cewy7WoAnvtjDe0PM8vBWuD6zY3dQFgQOPFkY8RxxQUrSkZ9wpS3E7FBjzTfkFGlRHmmc+ad8uCLPaWIb/B9QGI6uKidSXnEnLqcK+8xsB1HBsyCkL600PJfcuSWBs9CHh9uiJTG0=";
 // The existing bucket name
 private String bucketName = Constants.bucketName;
 // The key name for the file to upload.
 private String key = "trade_stock";
 private void postObject() throws Exception {
  // append the 'bucketname.' prior to the domain, such as http://bucket1.oss-cn-hangzhou.aliyuncs.com.
  String urlStr = endpoint.replace("http://", "http://" + bucketName + ".");
  // form fields
  Map<String, String> formFields = new LinkedHashMap<String, String>();
  // key
  formFields.put("key", this.key);
  // Content-Disposition
  formFields.put("Content-Disposition", "attachment;filename="
 + localFilePath);
  // OSSAccessKeyId
  formFields.put("OSSAccessKeyId", accessKeyId);
  // policy
  String policy
 = "{\"expiration\": \"2120-01-01T12:00:00.000Z\",\"conditions\": [[\"content-length-range\", 0, 104857600]]}";
  String encodePolicy = new String(Base64.encodeBase64(policy.getBytes()));
  formFields.put("policy", encodePolicy);
  // Signature
  String signaturecom = computeSignature(accessKeySecret, encodePolicy);
  formFields.put("Signature", signaturecom);
  // Set security token.
  formFields.put("x-oss-security-token", oss_security_token);
  String ret = formUpload(urlStr, formFields, localFilePath);
  System.out.println("Post Object [" + this.key + "] to bucket [" + bucketName + "]");
  System.out.println("post reponse:" + ret);
 }
 private static String computeSignature(String accessKeySecret, String encodePolicy)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
  // convert to UTF-8
  byte[] key = accessKeySecret.getBytes("UTF-8");
  byte[] data = encodePolicy.getBytes("UTF-8");
  // hmac-sha1
  Mac mac = Mac.getInstance("HmacSHA1");
  mac.init(new SecretKeySpec(key, "HmacSHA1"));
  byte[] sha = mac.doFinal(data);
  // base64
  return new String(Base64.encodeBase64(sha));
 }
 private static String formUpload(String urlStr, Map<String, String> formFields, String localFile)
throws Exception {
  String res = "";
  HttpURLConnection conn = null;
//  String boundary = "9431149156168";
  String boundary = "abc";
  try {
URL url = new URL(urlStr);
conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(30000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent",
  "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
// Set Content-MD5. The MD5 value is calculated based on the whole message body.
//conn.setRequestProperty("Content-MD5", "<yourContentMD5>");
conn.setRequestProperty("Content-Type",
  "multipart/form-data; boundary=" + boundary);
OutputStream out = new DataOutputStream(conn.getOutputStream());
// text
if (formFields != null) {
 StringBuffer strBuf = new StringBuffer();
 Iterator<Entry<String, String>> iter = formFields.entrySet().iterator();
 int i = 0;
 while (iter.hasNext()) {
  Entry<String, String> entry = iter.next();
  String inputName = entry.getKey();
  String inputValue = entry.getValue();
  if (inputValue == null) {
continue;
  }
  if (i == 0) {
strBuf.append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
  + inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
  } else {
strBuf.append("\r\n").append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
  + inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
  }
  i++;
 }
 out.write(strBuf.toString().getBytes());
}
// file
File file = new File(localFile);
String filename = file.getName();
String contentType = new MimetypesFileTypeMap().getContentType(file);
if (contentType == null || contentType.equals("")) {
 contentType = "application/octet-stream";
}
StringBuffer strBuf = new StringBuffer();
strBuf.append("\r\n").append("--").append(boundary)
  .append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\"file\"; "
  + "filename=\"" + filename + "\"\r\n");
strBuf.append("Content-Type: " + contentType + "\r\n\r\n");
out.write(strBuf.toString().getBytes());
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
 out.write(bufferOut, 0, bytes);
}
in.close();
byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes();
out.write(endData);
out.flush();
out.close();
// Gets the file data
strBuf = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
 strBuf.append(line).append("\n");
}
res = strBuf.toString();
reader.close();
reader = null;
  } catch (Exception e) {
System.err.println("Send post request exception: " + e);
throw e;
  } finally {
if (conn != null) {
 conn.disconnect();
 conn = null;
}
  }
  return res;
 }
 public static void main(String[] args) throws Exception {
  FormPostApplication ossPostObject = new FormPostApplication();
  ossPostObject.postObject();
 }
}
  1. 将上面所获取的key,secret和token填入。
  2. bucket名称要和上面授权对应的bucket一致。
  3. 这里是模拟form表单提交,编码采用UTF-8。
  4. policy里面可以配置超时时间, 内容长度范围等。
  5. 如果出现403错误,检查token等权限信息的配置是否正确。
  6. 如果出现400错误, 检查参数配置是否正确, 比如说MD5参数如果传递, 但没配置正确, 会出现此错误。
conn.setRequestProperty("Content-MD5", "<yourContentMD5>");

操作成功后, 能够在后台看到对应的文件信息。


相关实践学习
对象存储OSS快速上手——如何使用ossbrowser
本实验是对象存储OSS入门级实验。通过本实验,用户可学会如何用对象OSS的插件,进行简单的数据存、查、删等操作。
目录
相关文章
|
5月前
|
JSON 前端开发 关系型数据库
如何物业管理(园区式)系统的房屋及设备设施板块?(附架构图+流程图+代码参考)
本文介绍了园区物业管理系统中房屋与设备设施管理的核心内容,涵盖设备信息、巡检、报修、保养四大功能模块,提供系统架构图、数据模型设计、关键实现建议及可落地的代码样例。通过打通资产与运维流程,实现降本增效、减少停机与投诉,助力运维数据化、智能化。
|
5月前
|
存储 弹性计算 运维
AI 时代下阿里云基础设施的稳定性架构揭秘
十五年磨一剑,稳定性为何是今天的“命门”?
|
7月前
|
存储 机器学习/深度学习 缓存
软考软件评测师——计算机组成与体系结构(分级存储架构)
本内容全面解析了计算机存储系统的四大核心领域:虚拟存储技术、局部性原理、分级存储体系架构及存储器类型。虚拟存储通过软硬件协同扩展内存,支持动态加载与地址转换;局部性原理揭示程序运行特性,指导缓存设计优化;分级存储架构从寄存器到外存逐级扩展,平衡速度、容量与成本;存储器类型按寻址和访问方式分类,并介绍新型存储技术。最后探讨了存储系统未来优化趋势,如异构集成、智能预取和近存储计算等,为突破性能瓶颈提供了新方向。
|
3月前
|
存储 NoSQL 前端开发
【赵渝强老师】MongoDB的分布式存储架构
MongoDB分片通过将数据分布到多台服务器,实现海量数据的高效存储与读写。其架构包含路由、配置服务器和分片服务器,支持水平扩展,结合复制集保障高可用性,适用于大规模生产环境。
374 1
|
6月前
|
人工智能 物联网 测试技术
智能化测试基础架构:软件质量保障的新纪元
本文介绍了智能化测试基础架构的核心构成与优势。该架构融合AI、领域工程与自动化技术,包含智能测试平台、测试智能体、赋能引擎和自动化工具链四部分,能自动生成用例、调度执行、分析结果,显著提升测试效率与覆盖率。其核心优势在于实现专家经验规模化、质量前移和快速适应业务变化,助力企业构建新一代质量保障体系。建议从构建知识图谱和试点关键领域智能体起步,逐步推进测试智能化转型。
|
7月前
|
存储 关系型数据库 MySQL
成本直降30%!RDS MySQL存储自动分层实战:OSS冷热分离架构设计指南
在日均订单量超500万的场景下,MySQL数据年增200%,但访问集中在近7天(85%)。通过冷热数据分离,将历史数据迁移至OSS,实现存储成本下降48%,年省72万元。结合RDS、OSS与Redis构建分层架构,自动化管理数据生命周期,优化查询性能与资源利用率,支撑PB级数据扩展。
526 3
|
存储 数据采集 弹性计算
Codota的存储架构通过多种方式保障数据安全
Codota的存储架构通过多种方式保障数据安全
146 4
|
7月前
|
存储 关系型数据库 数据库
高性能云盘:一文解析RDS数据库存储架构升级
性能、成本、弹性,是客户实际使用数据库过程中关注的三个重要方面。RDS业界率先推出的高性能云盘(原通用云盘),是PaaS层和IaaS层的深度融合的技术最佳实践,通过使用不同的存储介质,为客户提供同时满足低成本、低延迟、高持久性的体验。
|
10月前
|
存储 数据采集 机器学习/深度学习
新闻聚合项目:多源异构数据的采集与存储架构
本文探讨了新闻聚合项目中数据采集的技术挑战与解决方案,指出单纯依赖抓取技术存在局限性。通过代理IP、Cookie和User-Agent的精细设置,可有效提高采集策略;但多源异构数据的清洗与存储同样关键,需结合智能化算法处理语义差异。正反方围绕技术手段的有效性和局限性展开讨论,最终强调综合运用代理技术与智能数据处理的重要性。未来,随着机器学习和自然语言处理的发展,新闻聚合将实现更高效的热点捕捉与信息传播。附带的代码示例展示了如何从多个中文新闻网站抓取数据并统计热点关键词。
505 2
新闻聚合项目:多源异构数据的采集与存储架构