《Pyflink》Flink集群安装,Python+Flink调研

Flink集群安装,Python+Flink调研

Flink集群部署

  1. 下载对应版本安装包:https://flink.apache.org/downloads.html

    实验环境为hadoop2.7, scala2.11 所以下载flink-1.7.1-bin-hadoop27-scala_2.11.tgz

  2. 配置conf/flink-conf.yaml

    jobmanager.rpc.address : master 节点
    jobmanager.heap.mb : JobManager可用的内存数量
    taskmanager.heap.mb : 每个TaskManager可以用内存数量
    taskmanager.numberOfTaskSlots : 每个机器可用的CPU数量
    parallelism.default : 集群中总的CPU数量
    taskmanager.tmp.dirs : 临时目录
    
  3. 配置conf/slaves

    slave1
    slave2
    

    点击查看更多配置项

  4. 把在master上配置好的,文件夹发送到各个worker节点上

    scp -r flink-1.7.1 hadoop@slavle1:~
    scp -r flink-1.7.1 hadoop@slavle2:~
    
  5. 启动/终止 Flink

    # 启动一个JobManager,并通过SSH连接列在slaves文件中的所有节点以便在每个节点上启动TaskManager
    flink-1.7.1/bin/start-cluster.sh
    # 停止flink集群,直接在master节点运行bin/stop-cluster.sh
    flink-1.7.1/bin/stop-cluster.sh
    

    启动后在web界面输入:master:8081 查看Web-UI

运行Python脚本

  • 以官网的一个示例进行测试,可以复制粘贴这些代码存储为wordcount.py并在本地运行。

  • wordcount.py

    from flink.plan.Environment import get_environment
    from flink.functions.GroupReduceFunction import GroupReduceFunctionclass Adder(GroupReduceFunction):def reduce(self, iterator, collector):count, word = iterator.next()count += sum([x[0] for x in iterator])collector.collect((count, word))
    # 1. 获取一个运行环境    
    env = get_environment() # 2. 加载/创建初始数据
    data = env.from_elements("Who's there?","I think I hear them. Stand, ho! Who's there?")# 3. 指定对这些数据的操作    
    data \.flat_map(lambda x, c: [(1, word) for word in x.lower().split()]) \.group_by(1) \.reduce_group(Adder(), combinable=True) \.output()# 4. 运行程序    
    env.execute(local=True) # 设置execute(local=True)强制程序在本机运行
    
  • 执行方法

    为了在Flink中运行计划任务,到Flink目录下,运行/bin文件夹下的pyflink.sh脚本。对于python2.7版本,运行pyflink2.sh;对于python3.4版本,运行pyflink3.sh。包含计划任务的脚本应当作为第一个输入参数,其后可添加一些另外的python包,最后,在“-”之后,输入其他附加参数。
    ./bin/pyflink<2/3>.sh <Script>[ <pathToPackage1>[ <pathToPackageX]][ - <param1>[ <paramX>]]

  • 针对上面的示例,在master-shell输入:
    flink-1.7.1/bin/pyflink.sh ./wordcount.py

  • vi flink-1.7.1/log/flink-hadoop-taskexecutor-0-slave1.out查看输出:

任务详解

  • 从示例程序可以看出,Flink程序看起来就像普通的python程序一样。每个程序都包含相同的基本组成部分:

    1. 获取一个运行环境
    2. 加载/创建初始数据
    3. 指定对这些数据的操作
    4. 指定计算结果的存放位置
    5. 运行程序
  • Environment(运行环境)是所有Flink程序的基础。通过调用Environment类中的一些静态方法来建立一个环境:

    get_environment()
    
  • 运行环境可通过多种读文件的方式来指定数据源。如果是简单的按行读取文本文件:

    env = get_environment()
    text = env.read_text("file:///path/to/file")
    

    这样,你就获得了可以进行操作(apply transformations)的数据集。关于数据源和输入格式的更多信息,请参考Data Sources

    一旦你获得了一个数据集DataSet,你就可以通过transformations来创建一个新的数据集,并把它写入到文件,再次transform,或者与其他数据集相结合。你可以通过对数据集调用自己个性化定制的函数来进行数据操作。例如,一个类似这样的数据映射操作:

    data.map(lambda x: x*2)
    

    这将会创建一个新的数据集,其中的每个数据都是原来数据集中的2倍。若要获取关于所有transformations的更多信息,及所有数据操作的列表,请参考Transformations。

  • 当需要将所获得的数据集写入到磁盘时,调用下面三种函数的其中一个即可。

      data.write_text("<file-path>", WriteMode=Constants.NO_OVERWRITE)write_csv("<file-path>", line_delimiter='\n', field_delimiter=',', write_mode=Constants.NO_OVERWRITE)output()
    

    其中,最后一种方法仅适用于在本机上进行开发/调试,它会将数据集的内容输出到标准输出。(请注意,当函数在集群上运行时,结果将会输出到整个集群节点的标准输出流,即输出到workers的.out文件。)前两种方法,能够将数据集写入到对应的文件中。关于写入到文件的更多信息,请参考Data Sinks。

    当设计好了程序之后,你需要在环境中执行execute命令来运行程序。可以选择在本机运行,也可以提交到集群运行,这取决于Flink的创建方式。你可以通过设置execute(local=True)强制程序在本机运行。

创建项目

  • 除了搭建好Flink运行环境,就无需进行其他准备工作了。Python包可以从你的Flink版本对应的/resource文件夹找到。在执行工作任务时,Flink 包,plan包和optional包均可以通过HDFS自动分发。

    Python API官方已经在安装了Python2.7或3.4的Linux/Windows系统上测试过。本次我是在安装了Python3.6的Linux环境进行测试。

    默认情况下,Flink通过调用”python”或”python3″来启动python进程,这取决于使用了哪种启动脚本。通过在 flink-conf.yaml 中设置 “python.binary.python[2/3]”对应的值,来设定你所需要的启动方式。

惰性评价

  • 所有的Flink程序都是延迟执行的。当程序的主函数执行时,数据的载入和操作并没有在当时发生。与此相反,每一个被创建出来的操作都被加入到程序的计划中。当程序环境中的某个对象调用了execute()函数时,这些操作才会被真正的执行。不论该程序是在本地运行还是集群上运行。

    延迟求值能够让你建立复杂的程序,并在Flink上以一个整体的计划单元来运行。

数据变换

  • 数据变换(Data transformations)可以将一个或多个数据集映射为一个新的数据集。程序能够将多种变换结合到一起来进行复杂的整合变换。

该小节将概述各种可以实现的数据变换。transformations documentation数据变换文档中,有关于所有数据变换和示例的全面介绍。

  1. Map:输入一个元素,输出一个元素

    data.map(lambda x: x * 2)
    
  2. FlatMap:输入一个元素,输出0,1,或多个元素

    data.flat_map(
    lambda x,c: [(1,word) for word in line.lower().split() for line 
    in x])
    
  3. MapPartition:通过一次函数调用实现并行的分割操作。该函数将分割变换作为一个”迭代器”,并且能够产生任意数量的输出值。每次分割变换的元素数量取决于变换的并行性和之前的操作结果。

    data.map_partition(lambda x,c: [value * 2 for value in x])
    
  4. Filter:对每一个元素,计算一个布尔表达式的值,保留函数计算结果为true的元素。

    data.filter(lambda x: x > 1000)
    
  5. Reduce:通过不断的将两个元素组合为一个,来将一组元素结合为一个单一的元素。这种缩减变换可以应用于整个数据集,也可以应用于已分组的数据集。

    data.reduce(lambda x,y : x + y)
    
  6. ReduceGroup:将一组元素缩减为1个或多个元素。缩减分组变换可以被应用于一个完整的数据集,或者一个分组数据集。

    lass Adder(GroupReduceFunction):
    def reduce(self, iterator, collector):count, word = iterator.next()count += sum([x[0] for x in iterator)      collector.collect((count, word))data.reduce_group(Adder())
    
  7. Aggregate:对一个数据集包含所有元组的一个域,或者数据集的每个数据组,执行某项built-in操作(求和,求最小值,求最大值)。聚集变换可以被应用于一个完整的数据集,或者一个分组数据集。

    # This code finds the sum of all of the values in the first field
    and the maximum of all of the values in the second field
    data.aggregate(Aggregation.Sum, 0).and_agg(Aggregation.Max, 1)# min(), max(), and sum() syntactic sugar functions are also available
    data.sum(0).and_agg(Aggregation.Max, 1)
    
  8. Join:对两个数据集进行联合变换,将得到一个新的数据集,其中包含在两个数据集中拥有相等关键字的所有元素对。也可通过JoinFunction来把成对的元素变为单独的元素。关于join keys的更多信息请查看 keys

    # In this case tuple fields are used as keys.
    # "0" is the join field on the first tuple
    # "1" is the join field on the second tuple.
    result = input1.join(input2).where(0).equal_to(1)
    
  9. CoGroup:是Reduce变换在二维空间的一个变体。将来自一个或多个域的数据加入数据组。变换函数transformation function将被每一对数据组调用。关于定义coGroup keys的更多信息,请查看 keys 。

    data1.co_group(data2).where(0).equal_to(1)
    
  10. Cross:计算两个输入数据集的笛卡尔乘积(向量叉乘),得到所有元素对。也可通过CrossFunction实现将一对元素转变为一个单独的元素。

    result = data1.cross(data2)
    
  11. Union:将两个数据集进行合并。

    data.union(data2)
    
  12. ZipWithIndex:为数据组中的元素逐个分配连续的索引。了解更多信息,请参考 【Zip Elements Guide】(zip_elements_guide.html#zip-with-a-dense-index).

    data.zip_with_index()
    

指定keys

  • 一些变换(例如Join和CoGroup),需要在进行变换前,为作为输入参数的数据集指定一个关键字,而另一些变换(例如Reduce和GroupReduce),则允许在变换操作之前,对数据集根据某个关键字进行分组。

    数据集可通过如下方式分组

    reduced = data \
    .group_by(<define key here>) \
    .reduce_group(<do something>)
    

    Flink中的数据模型并不是基于键-值对。你无需将数据集整理为keys和values的形式。键是”虚拟的”:它们被定义为在真实数据之上,引导分组操作的函数。

为元组定义keys

  • 最简单的情形是对一个数据集中的元组按照一个或多个域进行分组:

    grouped = data \
    .group_by(0) \
    .reduce(/*do something*/)
    

    数据集中的元组被按照第一个域分组。对于接下来的group-reduce函数,输入的数据组中,每个元组的第一个域都有相同的值。

    grouped = data \
    .group_by(0,1) \
    .reduce(/*do something*/)
    

    在上面的例子中,数据集的分组基于第一个和第二个域形成的复合关键字,因此,reduce函数输入数据组中,每个元组两个域的值均相同。
    关于嵌套元组需要注意:如果你有一个使用了嵌套元组的数据集,指定group_by()操作,系统将把整个元组作为关键字使用。

向Flink传递函数

  • 一些特定的操作需要采用用户自定义的函数,因此它们都接受lambda表达式和rich functions作为输入参数。

    data.filter(lambda x: x > 5)class Filter(FilterFunction):def filter(self, value):return value > 5data.filter(Filter())
    

Rich functions可以将函数作为输入参数,允许使用broadcast-variables(广播变量),能够由init()函数参数化,是复杂函数的一个可考虑的实现方式。它们也是在reduce操作中,定义一个可选的combine function的唯一方式。
Lambda表达式可以让函数在一行代码上实现,非常便捷。需要注意的是,如果某个操作会返回多个数值,则其使用的lambda表达式应当返回一个迭代器。(所有函数将接收一个collector输入 参数)。

数据类型

  • Flink的Python API目前仅支持python中的基本数据类型(int,float,bool,string)以及byte arrays。
    运行环境对数据类型的支持,包括序列化器serializer,反序列化器deserializer,以及自定义类型的类。

    class MyObj(object):def __init__(self, i):self.value = iclass MySerializer(object):def serialize(self, value):return struct.pack(">i", value.value)class MyDeserializer(object):def _deserialize(self, read):i = struct.unpack(">i", read(4))[0]return MyObj(i)env.register_custom_type(MyObj, MySerializer(), MyDeserializer())
    

    Tuples/Lists

    可以使用元组(或列表)来表示复杂类型。Python中的元组可以转换为Flink中的Tuple类型,它们包含数量固定的不同类型的域(最多25个)。每个域的元组可以是基本数据类型,也可以是其他的元组类型,从而形成嵌套元组类型。

    
    word_counts = env.from_elements(("hello", 1), ("world",2))counts = word_counts.map(lambda x: x[1])
    

    当进行一些要求指定关键字的操作时,例如对数据记录进行分组或配对。通过设定关键字,可以非常便捷地指定元组中各个域的位置。你可以指定多个位置,从而实现复合关键字(更多信息,查阅Section Data Transformations)。

    wordCounts \
    .group_by(0) \
    .reduce(MyReduceFunction())
    

数据源

  • 数据源创建了初始的数据集,包括来自文件,以及来自数据接口/集合两种方式。

    1. 基于文件的:

      read_text(path) – 按行读取文件,并将每一行以String形式返回。
      read_csv(path,type) – 解析以逗号(或其他字符)划分数据域的文件。
      返回一个包含若干元组的数据集。支持基本的java数据类型作为字段类型。

    2. 基于数据集合的:

      from_elements(*args) – 基于一系列数据创建一个数据集,包含所有元素。
      generate_sequence(from, to) – 按照指定的间隔,生成一系列数据。

  • Examples

    env  = get_environment\# read text file from local files system
    localLiens = env.read_text("file:#/path/to/my/textfile")\# read text file from a HDFS running at nnHost:nnPort
    hdfsLines = env.read_text("hdfs://nnHost:nnPort/path/to/my/textfile")\# read a CSV file with three fields, schema defined using constants defined in flink.plan.Constants
    csvInput = env.read_csv("hdfs:///the/CSV/file", (INT, STRING, DOUBLE))\# create a set from some given elements
    values = env.from_elements("Foo", "bar", "foobar", "fubar")\# generate a number sequence
    numbers = env.generate_sequence(1, 10000000)
    

数据接收器

  • 数据接收器可以接受DataSet,并用来存储和返回它们:

    1. write_text() –按行以String形式写入数据。可通过对每个数据项调用str()函数获取String。

    2. write_csv(…) – 将元组写入逗号分隔数值文件。行数和数据字段均可配置。每个字段的值可通过对数据项调用str()方法得到。

    3. output() – 在标准输出上打印每个数据项的str()字符串。
      一个数据集可以同时作为多个操作的输入数据。程序可以在写入或打印一个数据集的同时,对其进行其他的变换操作。

  • 标准数据池相关方法示例如下:

    write DataSet to a file on the local file system
    textData.write_text("file:///my/result/on/localFS")write DataSet to a file on a HDFS with a namenode running at nnHost:nnPort
    textData.write_text("hdfs://nnHost:nnPort/my/result/on/localFS")write DataSet to a file and overwrite the file if it exists
    textData.write_text("file:///my/result/on/localFS", WriteMode.OVERWRITE)tuples as lines with pipe as the separator "a|b|c"
    values.write_csv("file:///path/to/the/result/file", line_delimiter="\n", field_delimiter="|")this writes tuples in the text formatting "(a, b, c)", rather than as CSV lines
    values.write_text("file:///path/to/the/result/file")
    

广播变量

  • 使用广播变量,能够在使用普通输入参数的基础上,使得一个数据集同时被多个并行的操作所使用。这对于实现辅助数据集,或者是基于数据的参数化法非常有用。这样,数据集就可以以集合的形式被访问。

  • 注册广播变量:广播数据集可通过调用with_broadcast_set(DataSet,String)函数,按照名字注册广播变量。

  • 访问广播变量:通过对调用self.context.get_broadcast_variable(String)可获取广播变量。

    class MapperBcv(MapFunction):
    def map(self, value):factor = self.context.get_broadcast_variable("bcv")[0][0]return value * factor# 1. The DataSet to be broadcasted
    toBroadcast = env.from_elements(1, 2, 3)
    data = env.from_elements("a", "b")# 2. Broadcast the DataSet
    data.map(MapperBcv()).with_broadcast_set("bcv", toBroadcast)
  • 确保在进行广播变量的注册和访问时,应当采用相同的名字(示例中的”bcv”)。

    注意:由于广播变量的内容被保存在每个节点的内部存储中,不适合包含过多内容。一些简单的参数,例如标量值,可简单地通过参数化rich function来实现。

并行执行

  • 该章节将描述如何在Flink中配置程序的并行执行。一个Flink程序可以包含多个任务(操作,数据源和数据池)。一个任务可以被划分为多个可并行运行的部分,每个部分处理输入数据的一个子集。并行运行的实例数量被称作它的并行性或并行度degree of parallelism (DOP)。
    在Flink中可以为任务指定不同等级的并行度。

运行环境级

  • Flink程序可在一个运行环境execution environment的上下文中运行。一个运行环境为其中运行的所有操作,数据源和数据池定义了一个默认的并行度。运行环境的并行度可通过对某个操作的并行度进行配置来修改。

    一个运行环境的并行度可通过调用set_parallelism()方法来指定。例如,为了将WordCount示例程序中的所有操作,数据源和数据池的并行度设置为3,可以通过如下方式设置运行环境的默认并行度。

    env = get_environment()
    env.set_parallelism(3)text.flat_map(lambda x,c: x.lower().split()) \.group_by(1) \.reduce_group(Adder(), combinable=True) \.output()env.execute()
    

系统级

  • 通过设置位于./conf/flink-conf.yaml.文件的parallelism.default属性,改变系统级的默认并行度,可设置所有运行环境的默认并行度。具体细节可查阅Configuration文档。

执行方法

  • 为了在Flink中运行计划任务,到Flink目录下,运行/bin文件夹下的pyflink.sh脚本。对于python2.7版本,运行pyflink2.sh;对于python3.4版本,运行pyflink3.sh。包含计划任务的脚本应当作为第一个输入参数,其后可添加一些另外的python包,最后,在“-”之后,输入其他附加参数。

    ./bin/pyflink<2/3>.sh <Script>[ <pathToPackage1>[ <pathToPackageX]][ - <param1>[ <paramX>]]
    

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

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

相关文章

hdu 4539(状压dp)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid4539 思路&#xff1a;跟poj1185简直就是如出一辙&#xff01; 1 #include<iostream>2 #include<cstdio>3 #include<cstring>4 #include<algorithm>5 using namespace std;6 7 int row…

万字长文入门 Redis 命令、事务、锁、订阅、性能测试

Redis 基本数据类型Redis 中&#xff0c;常用的数据类型有以下几种&#xff1a;String&#xff1a;字符串类型&#xff0c;二进制安全字符串&#xff1b;Hash&#xff1a;哈希表&#xff1b;List 列表&#xff1a;链表结构&#xff0c;按照插入顺序排序的字符串元素的集合&…

基于应用日志的扫描器检测实践

基于应用日志的扫描器检测实践 在网络上搜索web扫描器时&#xff0c;各类扫描器工具、扫描攻略玲琅满目&#xff0c;但对扫描器检测方法的内容却少之又少。因此&#xff0c;本文对各类web扫描特特征进行了梳理和总结&#xff0c;并结合苏宁应用防火墙&#xff08;SNWAF&#x…

将一个压缩文件分成多个压缩文件;RAR文件分卷

有时候需要上传压缩文件&#xff0c;但是限制了单个文件的大小&#xff0c;那我们怎么才能将一个比较大的压缩文件分割成多个压缩文件&#xff0c;从而符合要求的进行文件的上传呢&#xff1f;这里小编告诉你一个技巧。 工具/原料 电脑 winrar&#xff08;一般电脑都自带了&…

python画相关性可视化图_Python可视化很简单,一文教你绘制饼图、极线图和气泡图...

matplotlib库作为Python数据化可视化的最经典和最常用库&#xff0c;掌握了它就相当于学会了Python的数据化可视化&#xff0c;上次呢&#xff0c;已经和大家聊了关于柱状图、条形图和直方图相关的东东&#xff0c;相信大家已经掌握了哈&#xff0c;那今天呢&#xff0c;咱们再…

图像处理技术(二)滤波去噪

在图像处理领域中&#xff0c;在真正的应用过程前&#xff0c;通常需要对图像进行预先处理&#xff0c;达到去除干扰项的目的。滤波去噪就是其中的一项图像预处理工作。在.NET下常用OpenCV进行图像处理工作,常用的.NET下的OpenCV库有Emgu CV和OpenCVSharp。EmguCV是.NET平台下对…

iOS开发之Runtime关联属性

2019独角兽企业重金招聘Python工程师标准>>> 首先&#xff0c;推荐给大家一个非常好用的一个网站&#xff1a; 非盈利无广告开发者专用网址导航&#xff1a;http://www.dev666.com/ API介绍 我们先看看Runtime提供的关联API&#xff0c;只有这三个API&#xff0c;使…

DecisionTree决策树算法及参数详解+实例+graphviz生成决策树

DecisionTree决策树大全 原文&#xff1a;http://ihoge.cn/2018/DecisionTree.html 利用信息墒判定先对那个特征进行分裂 信息墒是衡量信息不确定性的指标&#xff0c;信息墒公式&#xff1a; H(X)−∑x∈XP(x)log2P(x)其中P(x)表示事件x出现的概率。回到决策树的构建问题上…

穿皮裤放屁,裤子会鼓吗?真相看这里!

1 拉莫斯&#xff1a;没事儿&#xff0c;打今儿起我管你叫哥&#xff0c;你管我叫爸&#xff0c;咱俩各论各的。▼2 妈妈都是为了你好▼3 秃头女孩最后的倔强▼4 新浪OS&#xff1a;呼~太紧张了&#xff0c;放松下▼5 这什么鬼玩意儿&#xff1f;▼6 这到底是爱老婆&…

史上最强物理科普

全世界只有3.14 % 的人关注了爆炸吧知识一沙见世界 一花窥天堂手心握无限 须臾纳永恒杨振宁曾说读上面的四句诗可以感受到物理的美但物理的美不止于此物理还有一种庄严美一种神秘美一种初窥宇宙奥秘的畏惧美物理就是如此的迷人任何语言在它的面前都很贫瘠数学让人摆脱了愚昧而…

直方图python高度_python – 子图中直方图的动画

normed 直方图的True参数使直方图绘制分布的密度.从the documentation开始&#xff1a; normed : boolean, optional If True, the first element of the return tuple will be the counts normalized to form a probability density, i.e., n/(len(x)dbin), i.e., the integra…

Kubernetes:全面了解 Deployment

本文为作者的 Kubernetes 系列电子书的一部分&#xff0c;电子书已经开源&#xff0c;欢迎关注&#xff0c;电子书浏览地址&#xff1a;https://k8s.whuanle.cn【适合国内访问】https://ek8s.whuanle.cn 【gitbook】Deployment 是 Kubernetes 提供的一种自我修复机制来解决机器…

史上最冤!美国原子弹之父被骂了9年!最后他上台领奖,竟一把推开了总统.........

全世界只有3.14 % 的人关注了爆炸吧知识原子裂变不及人心善变“漫天奇光异彩&#xff0c;犹如圣灵逞威&#xff0c;祇有千只太阳&#xff0c;始能与它争辉。”1945年7月15日&#xff0c;奥本海默注视着远处的蘑菇云&#xff0c;想起了《摩诃婆罗多经&#xff1a;福者之歌》中的…

spring 基于java的配置

2019独角兽企业重金招聘Python工程师标准>>> 7.10 Classpath scanning and managed componets 文档地址: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-classpath-scanning 本章中大部分例子是用xml来指定配置元数据,以…

WPF 实现3D翻转倒计时控件~

WPF开发者QQ群&#xff1a; 340500857由于微信群人数太多入群请添加小编微信号yanjinhuawechat 或 W_Feng_aiQ 邀请入群需备注WPF开发者 PS&#xff1a;有更好的方式欢迎推荐。接着上一篇倒计时控件01—代码如下一、创建 NumberCardControl.xaml代码如下。<UserControl x:Cl…

Android之Android studio基本调试和快捷键

第一种调试方法: 如果APP是单进程,直接debug运行,如下图 第二种调试方法: 第二种就是调试当前已经处于运行状态下的App,这也是我们用的更多的一种调试手段,即 Attach debugger to Android process 。点击运行按钮右侧第三个按钮,弹出 Choose Process 窗口,选择对应的进…

Windows 2008 R2安装DHCP服务器问题及解决方法

错误一&#xff1a;0x80074E6F 指定的服务器已在目录服务中造成此错误的原因是DHCP服务器没有正常卸载&#xff0c;第二次安装就会报如下图错误解决方法1.卸载DHCP服务器2.重启服务器3.打开adsiedit.msc4.如下图展开到 CNNetServices5.删除CNYour ServerName6.重新安装DHCP服务…