0%

又到一年软考季,在小红书上发了一篇系统架构师的论文经验心得,不少人问要论文模板,也有同学想让帮忙改进自己写的准备论文。于是趁此机会整理进行了整理。

24年5月参加了软考系统架构师考试。架构师证书,要说有用,说起来也没什么用处。要说没用,但每年考的人还不少,且通过率也不高。至于我为什么参加这个考试,倒也没有别的初衷。一方面看到20%左右的通过率想挑战一下自己试试,另一方面自己之前工作的title便是架构师,然这只是一个名号罢了,不过如果有了一个证书,也可以调侃称自己是持证上岗了,出去江湖行走,说出去也更有底气一些哈哈。

客观选择题倒还好,主要涉及操作系统、系统架构、软件工程、数据库等方面的知识,考前通过小程序刷题掌握了七七八八。案例和工作中的实际内容关系也比较大,一个必选,另外四选二,相对容易地拿下。唯独论文,2800字的长篇让我考前如临大敌,考中几度想要中途放弃 考后犹感劫后余生。

平时时间都看客观题了,准备论文的时候已经没有几天。考前准备了两篇完整论文,分别是云原生架构和架构风格。大数据架构让AI给生成了一份,但并没有太多关注或者去背下来。考试是论文是四选一,万万没想到,恰好有一个就是大数据Lambda架构,相对于单元测试之类的,只能说大数据这个还相对好写一些,毕竟之前工作和数据团队对接比较多,大概也知道他们的处理流程,硬着头皮上吧。

写的过程中可谓是绞尽脑汁,写一会就想统计一下当前章节的字数,郁闷怎么字数还凑不够,发愁怎么写上更多冗余的废话以填充空白的答卷。刚写到正文就时间过半,此时脑袋空空,要不是考场不让提前交卷自己肯定就跑路了。心下已准备好背水一战大不了下次重新来过,突然也就静了下来,把自己想到的对应技术细节和实践经验疯狂码字,正文写完两段感觉有戏,然后有的没的全都往上怼,最终在考前几分钟得以完成。然后回看自己的论文,感觉还挺满意。说是作家看自己的作品都像是看自己的孩子,自己当时好像也是有这种感觉。

下面介绍一下论文的建议层次结构和值得强调的事项。

论文的建议整体结构

文章结构可以分为如下5个部分,每个部分确定好大概字数。摘要(300字)、背景(300字)、过渡(200字)、正文(1700字)、结尾(200字)

  • 摘要部分简明概述整个项目的背景、目标、项目关键成果。
  • 背景部分应进一步展开项目背景,问题与挑战,架构的选择理由和必要性。
  • 过渡部分可以简要总结架构或风格的特点,并自然引入其在项目中的具体实施。
  • 正文部分详细阐述架构的各层设计及实现细节。
  • 结尾总结项目带来的成效,并展望未来的改进方向。可以包括在实际操作中的优化空间及未来计划,以增强论文的深度和展望性。

几个值得关注和强调的点

  • 尽量让你写的项目看起来足够真实。很多同学担心自己的项目经验不够丰富,其实大家无论是微服务架构、lambda架构、软件架构风格等等,其实都可以灵活处理,把一个项目从不同的角度去阐述,也就形成了不同的论文,只是着重点不同而已。
  • 务必确保整体行文的层次和结构,让阅卷人一眼就找到自己的关注点。杂乱无章东一榔头西一棒追看起来很头疼。
  • 多准备几篇,考试的场景会比你线下写论文要紧张得多,多准备多输入方能下笔如有神。
  • 很多软考论文都是泛泛而谈,空洞无物,考官难以产生共鸣。但如果论文确实结合了实际项目,融入了一些具体细节,多讲一些遇到的问题、具体方案以及如何处理,比如“基于Canal采用Kafka传输binlog变更数据”这种落地细节替代的空泛的”消息队列“,这样论文就更加立体鲜活,相比空洞的理论,这会为你的文章增色不少,如果阅卷人有实际项目经验,也更容易引起共鸣。
  • 技术细节与业务价值结合​​:我们做架构终究是服务于业务,解决业务问题的。因此在论文中时刻要谨记,阐述你的技术决策和架构方案,务必要体现其业务价值。不仅是在背景和正文中,甚至在每个子模块中都要有对应呈现。
  • 问题导向论证:在背景里阐述了问题和挑战,在正文中要有回应。比如大数据架构“传统架构无法满足实时分析”,那么正文中则需要采用”Spark Streaming/Flink 处理实时订单”等技术选型来进行呼应。一咏三叹,不断论证你的架构是如何解决技术问题和业务问题的。
  • 项目的结果要能够量化,这样才有说服力。比如”运营决策效率大大提升”就是定性,但缺乏数据支持,不足以让人产生信任感。 ”2024年3月上线后运营决策效率提升40%“,说服力就得到了增强。

项目成果的定量和定性

  • 量化指标可以是基础性能提升(TPS从1千→2万)、业务价值(审核流程平均耗时从3天→1.8天)、成本效益(服务器费用月均节省23万元)、风险控制(全年P3以上故障时间<8分钟)。
  • 如果有时候成果不好定量,则可以进行适当包装,比如客户满意度可以表述为【公司因该项目获得客户”年度最佳合作伙伴” 】;集团表彰可以说自己子公司因此获得集团”数字化转型标杆案例” ;也可以提​方法论输出,比如项目经验经过提炼而在集团内部推广至12个子公司;专利沉淀可以说已经申请3项技术发明专利。

总之,结果一定要能够可衡量,不好衡量也要有佐证,来显示项目的积极效果和业务价值。

背景

本文讲解如何基于Docker部署ElasticSearch以及对应ik分词插件。

安装ElasticSearch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.14.2

# 要启动单节点 Elasticsearch 集群进行开发或测试,请指定单节点发现以绕过启动检查:

# -d 以守护进程模式后台运行容器
docker run -d \
--name elasticsearch \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e xpack.security.enabled=false \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-v /data/opt/es_data/data:/usr/share/elasticsearch/data \
-v /data/opt/es_data/logs:/usr/share/elasticsearch/logs \
-v /data/opt/es_data/plugins:/usr/share/elasticsearch/plugins \
docker.elastic.co/elasticsearch/elasticsearch:8.14.2

启动遇到的问题

1
docker logs -f elasticsearch

启动异常:AccessDeniedException: /usr/share/elasticsearch/data/nodes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
java.lang.IllegalStateException: failed to obtain node locks, tried [/usr/share/elasticsearch/data]; maybe these locations are not writable or multiple nodes were started on the same data path?at org.elasticsearch.server@8.14.2/org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:293)
at org.elasticsearch.server@8.14.2/org.elasticsearch.node.NodeConstruction.validateSettings(NodeConstruction.java:509)
at org.elasticsearch.server@8.14.2/org.elasticsearch.node.NodeConstruction.prepareConstruction(NodeConstruction.java:256)
at org.elasticsearch.server@8.14.2/org.elasticsearch.node.Node.<init>(Node.java:192)
at org.elasticsearch.server@8.14.2/org.elasticsearch.bootstrap.Elasticsearch$2.<init>(Elasticsearch.java:240)
at org.elasticsearch.server@8.14.2/org.elasticsearch.bootstrap.Elasticsearch.initPhase3(Elasticsearch.java:240)
at org.elasticsearch.server@8.14.2/org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:75)\nCaused by: java.io.IOException: failed to obtain lock on /usr/share/elasticsearch/data
at org.elasticsearch.server@8.14.2/org.elasticsearch.env.NodeEnvironment$NodeLock.<init>(NodeEnvironment.java:238)
at org.elasticsearch.server@8.14.2/org.elasticsearch.env.NodeEnvironment$NodeLock.<init>(NodeEnvironment.java:206)
at org.elasticsearch.server@8.14.2/org.elasticsearch.env.NodeEnvironment.<init>(NodeEnvironment.java:285)
... 6 more\nCaused by: java.nio.file.NoSuchFileException: /usr/share/elasticsearch/data/node.lock
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
at java.base/sun.nio.fs.UnixPath.toRealPath(UnixPath.java:886)
at org.apache.lucene.core@9.10.0/org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:94)
at org.apache.lucene.core@9.10.0/org.apache.lucene.store.FSLockFactory.obtainLock(FSLockFactory.java:43)
at org.apache.lucene.core@9.10.0/org.apache.lucene.store.BaseDirectory.obtainLock(BaseDirectory.java:44)
at org.elasticsearch.server@8.14.2/org.elasticsearch.env.NodeEnvironment$NodeLock.<init>(NodeEnvironment.java:231)
... 8 more
Suppressed: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/node.lock
at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106)
at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:261)
at java.base/java.nio.file.Files.newByteChannel(Files.java:379)
at java.base/java.nio.file.Files.createFile(Files.java:657)
at org.apache.lucene.core@9.10.0/org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:84)
... 11 more\n

发现确实权限不足导致

磁盘主机目录权限

1
2
# 挂载主机目录时需赋予读写权限
chmod -R 777 /data/opt/es_data

启动验证

1
2
3
4
curl -s  'http://localhost:9200'

# 提交请求 _cat/nodes 查看节点是否启动运行
curl -X GET "localhost:9200/_cat/nodes?v=true&pretty"

启动验证

下载插件

插件下载可在docker内部通过elasticsearch-plugin 在线安装,也可离线下载,复制到plugin目录下。

在线安装

1
2
3
docker exec -it elasticsearch /bin/bash

bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/8.4.1

Es插件版本兼容

​​问题原因​​

错误提示 ​​Plugin [analysis-ik] was built for Elasticsearch version 8.4.1 but version 8.14.2 is running​​ 表示 IK 分词器插件版本与当前 Elasticsearch 版本不兼容。

主要原因为​版本差异过大​或更新滞后​:IK 插件版本(8.4.1)远低于 Elasticsearch 版本(8.14.2),导致版本校验失败 。

解决方式

可以采用离线安装,修改 IK 插件配置文件适配当前版本​​,适用于​已有接近版本的 IK 插件(如 8.10.4),需快速适配 8.14.2。

离线安装

在线安装经常会因为网络问题导致插件下载失败,所以可以采取离线安装。

​下载插件​​:从 IK 官方仓库或其他仓库(https://release.infinilabs.com/) 下载与 Elasticsearch 版本最接近的插件(如 8.10.4)。

版本匹配

如果插件版本和Elastic-Search版本一致,则可复制到plugin目录下或者使用elasticsearch-plugin进行安装。

1
2
3
docker cp elasticsearch-analysis-ik-8.14.2.zip elasticsearch:/usr/share/elasticsearch/plugins/
docker exec -it elasticsearch /bin/bash
elasticsearch-plugin install file:///usr/share/elasticsearch/plugins/elasticsearch-analysis-ik-8.14.2.zip

版本不匹配

如果版本不匹配,则找​已有接近版本的 IK 插件下载并调整配置:

​​解压并修改配置​​:
1
2
unzip elasticsearch-analysis-ik-8.10.4.zip -d elasticsearch-analysis-ik-8.14.2
cd elasticsearch-analysis-ik-8.14.2
编辑 plugin-descriptor.properties 文件:
1
2
version=8.14.2
elasticsearch.version=8.14.2

​​关键点​​:确保两处版本号与 Elasticsearch 一致

重新打包并安装:
1
2
3
4
zip -r elasticsearch-analysis-ik-8.14.2.zip *
docker cp elasticsearch-analysis-ik-8.14.2.zip elasticsearch:/usr/share/elasticsearch/plugins/
docker exec -it elasticsearch /bin/bash
elasticsearch-plugin install file:///usr/share/elasticsearch/plugins/elasticsearch-analysis-ik-8.14.2.zip

重启Docker:

1
2
3
4
5
6
7
8
9
docker restart  elasticsearch
# 验证IK分词效果

# 测试 ik_max_word(最细粒度分词)
curl -X POST "http://localhost:9200/_analyze" -H 'Content-Type: application/json' -d '{
"analyzer": "ik_max_word",
"text": "中华人民共和国成立"
}'

创建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
curl -X PUT "localhost:9200/my_index?pretty" -H 'Content-Type: application/json' -d'
{
"mappings" : {
"properties" : {
"entity_name" : {
"type" : "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"aliaes" : {
"type" : "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"col_name" : {
"type" : "keyword",
"index" : false
},
"col_comment" : {
"type" : "keyword",
"index" : false
}
}
}
}'

背景

近期我们的一个BI数据产品在合作伙伴的私有化部署实践中,我们遇到了一个具有代表性的技术挑战:合作伙伴的基础设施采用基于openEuler的一体机架构,需要将包含StarRocks的全套数据分析组件进行容器化封装部署。由于官方文档存在以下痛点:

  1. 服务组件说明分散(FE/BE节点配置分离)
  2. 容器化部署路径不明确
  3. 缺少典型问题解决方案

本文将通过完整的实战记录,详解基于Docker的企业级StarRocks部署方案。

容器化部署全流程

1. 镜像准备与优化

1.1 镜像加速配置(国内环境推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 创建或更新Docker守护进程配置
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.nju.edu.cn"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"insecure-registries": [],
"data-root": "/var/lib/docker"
}
EOF

1.2 镜像选择策略

在镜像选型过程中,观察到StarRocks官方推荐的allin1-ubuntu镜像具有最高下载量。针对Docker镜像的跨平台特性,了解到allin1-ubuntu的命名源于镜像内部集成的是Ubuntu用户空间环境(包含apt包管理、系统工具链等),而非要求必须部署在Ubuntu宿主机上。

这也就意味着CentOS/openEuler 操作系统上也可以采用starrocks/allin1-ubuntu,选对对应的tag即可.

1
2
docker pull starrocks/allin1-ubuntu:3.1.14

执行完毕,稍等一会,因为镜像本身比较大.

1
2
3
[root@iZ2ze8dvta0psx9lf45hk2Z]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
starrocks/allin1-ubuntu 3.1.14 b15dd4d85c19 9 months ago 4.36GB

2. 服务启动与验证

2.1 容器初始化命令

1
2
3
4
5
6
7
8
9
10
docker run -d --name starrocks \
-p 9030:9030 \ # FE查询服务端口
-p 8030:8030 \ # FE HTTP接口
-p 8040:8040 \ # BE HTTP服务端口
--security-opt seccomp=unconfined \
--ulimit nofile=65536:65536 \ # 文件描述符优化
-v /data/starrocks/fe:/data/deploy/starrocks/fe \ # 持久化存储:挂载数据卷保证容灾能力
-v /data/starrocks/be:/data/deploy/starrocks/be \
starrocks/allin1-ubuntu:3.1.14

2.2 服务健康检查

1
2
3
4
5
# 检查容器状态
docker ps -a --filter name=starrocks

# 实时查看启动日志
docker logs -f starrocks

启动完毕,尝试通过mysql客户端连接9030端口。

1
mysql -h 127.0.0.1 -P 9030 -uroot

3. 典型问题排查

3.1 服务端口不可用

启动过程中,日志一直提醒FE service query port:9030 is NOT alive.

1
2
3
4
5
6
7
8
9
10
11
2025-04-29 14:16:10 2025-04-29 05:16:10+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:12 2025-04-29 05:16:12,355 INFO exited: feservice (exit status 255; not expected)
2025-04-29 14:16:12 2025-04-29 05:16:12+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:12 2025-04-29 05:16:12,832 INFO gave up: feservice entered FATAL state, too many start retries too quickly
2025-04-29 14:16:14 2025-04-29 05:16:14+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:16 2025-04-29 05:16:16+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:18 2025-04-29 05:16:18+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:20 2025-04-29 05:16:20+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:22 2025-04-29 05:16:22+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:24 2025-04-29 05:16:24+00:00 WARN FE service query port:9030 is NOT alive yet!
2025-04-29 14:16:27 2025-04-29 05:16:27+00:00 WARN FE service query port:9030 is NOT alive yet!

问题排查:

attach到 docker image 内部,看看具体fe服务启动发生了什么异常。

1
2
3
4
5
6
7
docker ps -a

# 进入容器调试环境
docker exec -it starrocks /bin/bash

# 查看FE日志(关键路径)
tail -n 100 /data/deploy/starrocks/fe/log/fe.log

果然发现问题,原来是磁盘空间不足。

磁盘日志异常

查看磁盘占用信息:
磁盘占用信息

3.2 常见问题根源:

  • 存储空间不足(日志文件路径:/data/deploy)
  • 内存分配异常(建议容器内存≥4GB)
  • 端口冲突(检查宿主机的8030/9030端口占用)

4. 安全加固与数据导入

4.1 账户安全配置:

默认StarRocks root用户是没有密码的,用起来会很不方便,也不安全。

1
2
3
4
5
宿主机执行:
mysql -h 127.0.0.1 -P9030 -uroot

然后将root用户密码设置一下:
alter USER 'root' IDENTIFIED BY 'root';

创建数据库和对应表后,就可以进行数据导入了。

4.2 高效数据加载方案

采用Stream Load实现TB级数据高效导入,不依赖外部组件。方便快捷。

https://docs.starrocks.io/zh/docs/3.2/loading/Stream_Load_transaction_interface/

1
2
3
4
5
6
7
8
curl --location-trusted -u root:root \
-H "Expect:100-continue" \
-H "timeout:100" \
-H "max_filter_ratio:0.2" \
-H "column_separator:," \
-H "skip_header:1" \
-T reviews.csv -XPUT \
http://${BE_IP}:8040/api/retail_online/reviews/_stream_load

注意,这里的端口8040为Be服务的Http端口.

关键参数说明:

参数名 功能说明 推荐值
max_filter_ratio 允许的数据过滤比例 0.1-0.3
timeout 超时控制(秒) ≥300
exec_mem_limit 单次导入内存限制(MB) ≥2048

成功后会输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"TxnId": 4,
"Label": "7a9798c6-b31c-41e4-a335-a3612e846ed0",
"Status": "Success",
"Message": "OK",
"NumberTotalRows": 8,
"NumberLoadedRows": 8,
"NumberFilteredRows": 0,
"NumberUnselectedRows": 0,
"LoadBytes": 1483,
"LoadTimeMs": 32,
"BeginTxnTimeMs": 1,
"StreamLoadPlanTimeMs": 3,
"ReadDataTimeMs": 0,
"WriteDataTimeMs": 12,
"CommitAndPublishTimeMs": 16
}

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment