Docker技术入门与实战【3.0】

news2026/4/30 20:30:39
第15章 构建Docker容器集群对Docker不熟悉的读者在生产环境中使用Docker的过程中往往会碰到构建集群的需求。这里最核心的问题就是让不同主机中的Docker容器可以互相访问。本章将介绍几种解决方案包括利用端口映射实现容器之间的快速互联使用Ambassador容器解决跨主机的容器互联等。最后对现有方案的问题进行探讨。在实际应用中读者可根据自身情况灵活选择或组合几种方案来满足需求。15.1 使用自定义网桥连接跨主机容器Docker默认的网桥是docker0。它只会在本机连接所有的容器。举例来说容器的虚拟网卡在主机上看一般叫做veth*而docker0网桥把所有这些网卡桥接在一起如下所示[rootopnvz ~]# brctl showbridge name bridge id STP enabled interfacesdocker0 8000.56847afe9799 no veth0889veth3c7bveth4061在容器中看到的地址一般是像下面这样的地址rootac6474aeb31d:~# ip a1: lo: LOOPBACK UP LOWER_UP mtu 1500 qdisc noqueue state UNKNOWN group defaultlink/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever11: eth0: BROADCAST UP LOWER_UP mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 4a:7d:68:da:09:cf brd ff:ff:ff:ff:ff:ffinet 172.17.0.3/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::487d:68ff:feda:9cf/64 scope linkvalid_lft forever preferred_lft forever这样就可以把这个网络看成是一个私有的网络如果要让外网连接到容器中就需要做端口映射即-p参数。例如主机A和主机B的网卡一都连着物理交换机的同一个vlan 101这样网桥一和网桥三就相当于在同一个物理网络中了而容器一、容器三、容器四也在同一物理网络中了它们之间可以相互通信而且可以跟同一vlan中的其他物理机器互联如图15-1所示。下面以ubuntu系统为例创建跨多个主机主机的容器联网。首先创建自己的网桥br0编辑/etc/network/interface文件auto br0iface br0 inet staticaddress 192.168.7.31netmask 255.255.240.0gateway 192.168.7.254bridge_ports em1bridge_stp offdns-nameservers 8.8.8.8 192.168.6.1重启后默认将本地物理网卡em1连接到了br0上。在本地修改/etc/default/docker文件添加最后一行内容# Docker Upstart and SysVinit configuration file# Customize location of Docker binary (especially for development testing).#DOCKER/usr/local/bin/docker# Use DOCKER_OPTS to modify the daemon startup options.#DOCKER_OPTS--dns 8.8.8.8 --dns 8.8.4.4# If you need Docker to use an HTTP proxy it can also be specified here.#export http_proxyhttp://127.0.0.1:3128/# This is also a handy place to tweak where Dockers temporary files go.#export TMPDIR/mnt/bigdrive/docker-tmpDOCKER_OPTS-bbr0在启动Docker的时候使用-b参数可以将容器绑定到指定网桥br0上。重启Docker服务后再进入容器可以看到它已经连接到物理网络上了rootubuntudocker:~# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES58b043aa05eb desk_hz:v1 /startup.sh 5 days ago Up 2 seconds 5900/tcp, 6080/tcp, 22/tcp yanlxrootubuntudocker:~# brctl showbridge name bridge id STP enabled interfacesbr0 8000.7e6e617c8d53 no em1vethe6e5这样的情况下容器端口通过映射直接暴露到物理网络上多台物理主机的容器通过访问外部映射端口即可相互联网了。这样实现的主要问题是需要知道容器所在物理主机的IP地址。15.2 使用Ambassador容器当两个Docker容器在同一主机或虚拟机时可以通过--link命令让两者直接互相访问。如果要跨主机实现容器互联则往往需要容器知道其他物理主机的IP地址。利用Ambassador容器机制可以让互联的容器无需知道所在物理主机的IP地址即可互联。基本场景Ambassador容器也是一种Docker容器它在内部提供了转发服务。如图15-2所示。当客户端容器要访问服务端容器的时候直接访问客户端Ambassador容器这个请求会被客户端Ambassador转发出去到达服务端主机。服务端Ambassador容器监听在对应端口上收到请求后再转发请求给服务端容器。使用Ambassador容器以redis镜像为例。首先在服务端主机上创建一个服务端容器redis-server$ sudo docker run -d -name redis-server crosbymichael/redis创建一个服务端Ambassador容器redis_ambassador连接到服务端容器redis-server并监听本地的6379端口$ sudo docker run -d -link redis-server:redis -name redis_ambassador -p 6379:6379 svendowideit/ambassador在客户端主机上创建客户端Ambassador容器告诉它服务端物理主机的监听地址是tcp://x.x.x.x6379将本地收集到6379端口的流量转发到服务端物理主机$ sudo docker run -d -name redis_ambassador -expose 6379 -e REDIS_PORT_6379_TCPtcp://x.x.x.x:6379 svendowideit/ambassador最后创建一个客户端容器进行测试默认访问6379端口实际上是访问的服务端容器内的redis应用$ sudo docker run -i -t -rm -link redis_ambassador:redis relateiq/redis-cliredis 172.17.0.160:6379 pingPONGAmbassador镜像的DockerfileAmbassador镜像的Dockerfile如下所示。其实现十分简单主要是一行正则表达式从环境变量中找到包含“TCP”字符串的变量然后使用正则表达式.*_PORT([0-9])_TCPtcp:\/\/(.):(.*)从中提取IP和端口号最后利用socat一个socket转发程序将流量转发到指定的地址上FROM docker-utMAINTAINER SvenDowideithome.org.auCMD env | grep _TCP | sed s/.*_PORT_\([0-9]*\)_TCPtcp:\/\/\(.*\):\(.*\)/socat TCP4-LISTEN:\1, fork, reuseaddr TCP4:\2:\3 \/ | sh top这种情况下需要额外的Ambassador容器并且也仍然需要知道目标容器所在的物理主机的地址。15.3 本章小结本章介绍了实现Docker容器集群的两种基本方式通过端口映射方法实现利用外部物理网络的构建以及通过Ambassador容器来解决容器跨主机情况下通过内网地址访问的问题。实际上要实现容器集群的管理关键要实现两方面的需求一是容器名称的动态管理即容器利用固定的名称可以互相访问即使有容器发生重启另外一方面是需要底层网络提供灵活的跨主机的支持租户隔离的连接。现有的方案在这两方面的解决并没有做到十分完美。一旦容器发生重启容器内分配到的IP发生变化原先的连接就无法使用了。同时底层直接暴露在物理网络上依赖于指定物理地址的访问无法实现灵活的租户隔离等需求。要解决容器名称的动态管理有不同的思路包括添加反向代理的方式、社区内正在讨论的几个补丁以及SkyDNSSkyDock、etcd、consul等工具本质上就是实现一套容器名到地址的访问或者说实现容器的DNS系统。而解决底层网络的灵活连接则需要使用Overlay技术。这方面可以基于VXLAN等网络虚拟化协议实现跨主机甚至跨物理网络的大二层连通。事实上管理虚拟机的OpenStack等项目提供了相对成熟的基于SDN的网络管理方案已经可以很好地支持容器之间的网络管理。现在已经有包括Shipyard、Kubernetes等项目实现一整套的容器集群管理方案笔者将在第三部分中进行介绍。第16章 在公有云上使用DockerDocker目前已经得到了众多的公有云平台的良好支持包括Aliyun、Amazon、Rackspace、Softlayer、腾讯云等。在国内的公有云厂商中阿里云率先对其ECS服务器上安装Docker提供了更友好的支持。本章将以国内的阿里云为例介绍在公有云平台上安装、使用Docker的过程和注意事项。其中第一节介绍了在阿里云的ECS服务器上安装Docker的详细步骤和用法第二节介绍了在阿里云上使用Docker的一些特色服务。16.1 公有云上安装Docker以阿里云提供的CentOS6.5系统和Ubuntu 14.04系统为例介绍安装和使用Docker的过程。16.1.1 CentOS 6.5系统首先在阿里云网站上申请机器选择CentOS 6.5系统。通过ssh登录阿里云的服务器查看系统版本号以及内核版本$ ssh useryour_aliyun_vmWelcome to aliyun Elastic Compute Service!# lsb_release -aLSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarchDistributor ID: CentOSDescription: CentOS release 6.5 (Final)Release: 6.5Codename: Final# uname -aLinux xxxxxxx 2.6.32-431.23.3.el6.x86_64 #1 SMP Thu Jul 31 17:20:51 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux可以看到内核默认为比较旧的2.6系列版本。1.升级内核Docker推荐使用3.8以上内核所以推荐首先升级内核。导入KEY安装软件源。在YUM的ELRepo源中有mainline3.13.1、long-term3.10.28这2个内核版本考虑到long-term会长期保持支持和更新所以选择这个版本# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org# yum --enablerepoelrepo-kernel install kernel-lt -yLoaded plugins: securitybase | 3.7 kB 00:00base/primary_db | 4.6 MB 00:00elrepo | 2.9 kB 00:00elrepo/primary_db | 709 kB 00:46elrepo-kernel | 2.9 kB 00:00elrepo-kernel/primary_db | 20 kB 00:01epel | 4.4 kB 00:00epel/primary_db | 6.3 MB 00:01extras | 3.4 kB 00:00extras/primary_db | 29 kB 00:00updates | 3.4 kB 00:00updates/primary_db | 181 kB 00:00Setting up Install ProcessResolving Dependencies-- Running transaction check--- Package kernel-lt.x86_64 0:3.10.59-1.el6.elrepo will be installed-- Finished Dependency ResolutionDependencies ResolvedPackage Arch Version Repository SizeInstalling:kernel-lt x86_64 3.10.59-1.el6.elrepo elrepo-kernel 33 MTransaction SummaryInstall 1 Package(s)Total download size: 33 MInstalled size: 153 MDownloading Packages:kernel-lt-3.10.59-1.el6.elrepo.x86_64.rpm | 33 MB 28:58Running rpm_check_debugRunning Transaction TestTransaction Test SucceededRunning TransactionWarning: RPMDB altered outside of yum.Installing : kernel-lt-3.10.59-1.el6.elrepo.x86_64 1/1Verifying : kernel-lt-3.10.59-1.el6.elrepo.x86_64 1/1Installed:kernel-lt.x86_64 0:3.10.59-1.el6.elrepoComplete!安装后检查/etc/grub.conf文件查看默认的启动内核。新安装的内核一般在第一个这里把default1改为default0就好了default1timeout5splashimage(hd0 0)/boot/grub/splash.xpm.gzhiddenmenutitle CentOS (3.10.59-1.el6.elrepo.x86_64)root (hd0 0)kernel /boot/vmlinuz-3.10.59-1.el6.elrepo.x86_64 ro rootUUID94e4e384-0ace-437f-bc96-057dd64f42ee rd_NO_LUKS rd_NO_LVM LANGen_US.UTF-8 rd_NO_MD SYSFONTlatarcyrheb-sun16 crashkinitrd /boot/initramfs-3.10.59-1.el6.elrepo.x86_64.imgtitle CentOS (2.6.32-431.23.3.el6.x86_64)root (hd0 0)kernel /boot/vmlinuz-2.6.32-431.23.3.el6.x86_64 ro rootUUID94e4e384-0ace-437f-bc96-057dd64f42ee rd_NO_LUKS rd_NO_LVM LANGen_US.UTF-8 rd_NO_MD SYSFONTlatarcyrheb-sun16 crashkeinitrd /boot/initramfs-2.6.32-431.23.3.el6.x86_64.img~ 重启云主机查看内核是否升级成功# uname -aLinux xxxxxxx 3.10.59-1.el6.elrepo.x86_64 #1 SMP Thu Oct 30 23:46:31 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux2.安装Docker添加软件源并安装Docker软件# yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm# yum install docker-io3.启动Docker使用service命令启动Docker发现会提示有问题# service docker startStarting cgconfig service: [ OK ]Starting docker: [ OK ]# docker versionClient version: 1.2.0Client API version: 1.14Go version (client): go1.3.3Git commit (client): fa7b24f/1.2.0OS/Arch (client): linux/amd642014/11/05 21:03:08 Cannot connect to the Docker daemon. Is docker -d running on this host?使用docker-d启动方式来查看详细的启动过程# docker -d2014/11/05 21:10:56 docker daemon: 1.2.0 fa7b24f/1.2.0; execdriver: native; graphdriver:[40a2dcc2] job serveapi(unix:///var/run/docker.sock)[info] Listening for HTTP on unix (/var/run/docker.sock)[40a2dcc2] job init_networkdriver()[40a2dcc2.init_networkdriver()] creating new bridge for docker0Could not find a free IP address range for interface docker0. Please configure its address manually and run docker -b docker0[40a2dcc2] -job init_networkdriver() ERR (1)2014/11/05 21:10:56 Could not find a free IP address range for interface docker0. Please configure its address manually and run docker -b docker0提示没有空余ip分配给docker0了。可以使用--bip参数来手工分配给ip地址。比如# docker --bip192.168.100.1/24 -d [2] 2388[rootiZ23pznlje4Z ~]# 2014/11/05 21:16:55 docker daemon: 1.2.0 fa7b24f/1.2.0; execdriver: native; graphdriver:[dc6906e7] job serveapi(unix:///var/run/docker.sock)[info] Listening for HTTP on unix (/var/run/docker.sock)[dc6906e7] job init_networkdriver()[dc6906e7] -job init_networkdriver() OK (0)2014/11/05 21:16:55 WARNING: Your kernel does not support cgroup swap limit.[info] Loading containers:[info] : done.[dc6906e7] job acceptconnections()[dc6906e7] -job acceptconnections() OK (0)仍然有警告Your kernel does not support cgroup swap limit。使用lxc-checkconfig进行检查# lxc-checkconfigKernel configuration not found at /proc/config.gz; searchinghttp://www.hzcourse.com/resource/readBook?path/openresources/teach_ebook/uncompressed/15029/OEBPS/Text/...Kernel configuration found at /boot/config-3.10.59-1.el6.elrepo.x86_64--- Namespaces ---Namespaces: enabledUtsname namespace: enabledIpc namespace: enabledPid namespace: enabledUser namespace: missingNetwork namespace: enabledMultiple /dev/pts instances: enabled--- Control groups ---Cgroup: enabledCgroup clone_children flag: enabledCgroup device: enabledCgroup sched: enabledCgroup cpu account: enabledCgroup memory controller: enabledCgroup cpuset: enabled--- Misc ---Veth pair device: enabledMacvlan: enabledVlan: enabledFile capabilities: enabledNote : Before booting a new kernel you can check its configurationusage : CONFIG/path/to/config /usr/bin/lxc-checkconfig可以看到Control groups项目在内核是支持的所以可以暂时忽略这个告警。4.测试使用首先下载ubuntu镜像。这里使用Dockerpool官方网站的标准ubuntu镜像来进行测试。下载镜像重新标记镜像# docker pull dl.dockerpool.com:5000/ubuntu:14.04# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEdl.dockerpool.com:5000/ubuntu latest 5506de2b643b 12 days ago 197.8 MB# docker tag 550 ubuntu# docker rmi dl.dockerpool.com:5000/ubuntu[dc6906e7] job image_delete(dl.dockerpool.com:5000/ubuntu)[dc6906e7] job log(untag 5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5 )[dc6906e7] -job log(untag 5506de2b643be1e6febbf3b8a240760c6843244c41e12aa2f60ccbb7153d17f5 ) OK (0)[dc6906e7] -job image_delete(dl.dockerpool.com:5000/ubuntu) OK (0)Untagged: dl.dockerpool.com:5000/ubuntu:latest利用刚下载的镜像启动一个容器并测试网络# docker run -ti ubunturoot66ff9a55a4f5:/# ping www.dockerpool.comPING www.dockerpool.com (xxx.xxx.xxx.xxx) 56(84) bytes of data.^C64 bytes from 203.195.193.251: icmp_seq1 ttl47 time31.4 ms

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…