Loading [MathJax]/jax/output/CommonHTML/config.js
部署DeepSeek模型,进群交流最in玩法!
立即加群
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >0554-6.1.0-同一java进程中同时访问认证和非认证集群的问题(续)

0554-6.1.0-同一java进程中同时访问认证和非认证集群的问题(续)

作者头像
Fayson
发布于 2019-11-28 13:16:09
发布于 2019-11-28 13:16:09
2.2K00
代码可运行
举报
文章被收录于专栏:Hadoop实操Hadoop实操
运行总次数:0
代码可运行

作者:李继武

1

文档编写目的

Fayson在前面的文章《0553-6.1.0-如何使用Java代码同时访问安全和非安全CDH集群》,本篇文章介绍在同一Java进程中,通过多线程同时访问Kerberos认证集群和非认证集群时出现的一些异常及解决方法。

  • 测试环境:CDH6.1.0

2

集群准备

1.非认证集群,在该集群中根目录下创建了一个NONEKRBCDH目录用以标识

2.认证集群,在该集群中根目录下创建了一个KRBCDH目录用以标识

3

环境准备

本次测试是将代码直接放在linux系统上运行,所以将两套集群的配置文件分别放在两个不同的目录下:

1.认证集群的配置信息包括krb5.conf和keytab文件放在/root/krbconf下

2.非认证集群的配置信息放在/root/conf下

4

工具类

1.初始化配置文件工具类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.cloudera.hdfs.utils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class HDFSUtils {
  public static Configuration initConfiguration(String confPath) {
     Configuration configuration = new Configuration();
     System.out.println(confPath + File.separator + "core-site.xml");
     configuration.addResource(new Path(confPath + File.separator +"core-site.xml"));
     configuration.addResource(new Path(confPath + File.separator +"hdfs-site.xml"));
     return configuration;
  }
}

5

代码测试

1.如下测试是在两个线程循环访问两个集群,每个线程连接时都执行,UserGroupInformation.setConfiguration操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.cloudera.hdfs;

import com.amazonaws.services.workdocs.model.User;
import com.cloudera.hdfs.utils.HDFSUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.io.IOException;

public class Test {
  public static void main(String[] args) throws IOException {
     //初始化认证集群配置文件
     Configuration configuration = HDFSUtils.initConfiguration(File.separator + "root"
             + File.separator + "krbconf");
     configuration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
     //该线程循环访问认证集群
     new Thread(() -> {
       try {
         while (true) {
           //配置kerberos认证的配置文件
           System.setProperty("java.security.krb5.conf", File.separator + "root" +
                File.separator+ "krbconf" + File.separator + "krb5.conf");
           //进行身份认证
           UserGroupInformation.setConfiguration(configuration);
           UserGroupInformation.loginUserFromKeytab("hive@MACRO.COM", 
                File.separator + "root"+ File.separator + "krbconf" + File.separator + "hive.keytab");
           System.out.println("当前用户是:" + 
           UserGroupInformation.getCurrentUser());
           //列出根目录下所有文件
           FileSystem fileSystem = FileSystem.get(configuration);
           FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
           for (FileStatus file : files) {
                System.out.println("KRB:" + file.getPath());
           }
         }
         } catch (Exception e) {
            e.printStackTrace();
            }
     }).start();


     //初始化非认证配置文件
     Configuration noAuthconfiguration = HDFSUtils.initConfiguration(File.separator + "root"
           + File.separator + "conf");
     noAuthconfiguration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

     //该线程循环访问非认证集群
     new Thread(() -> {
        try {
          while (true) {
              System.out.println("当前用户是:" + UserGroupInformation.getCurrentUser());
              UserGroupInformation.setConfiguration(noAuthconfiguration);
              //列出根目录下所有文件
              FileSystem fileSystem = FileSystem.get(noAuthconfiguration);
              FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
              for (FileStatus file : files) {
                  System.out.println("NONEKRB:" + file.getPath());
              }
            }
         } catch (Exception e) {
             e.printStackTrace();
         }
        }).start();
    }
}

问题:

在访问认证集群的线程认证结束之后准备访问集群,这时访问非认证集群的线程将UserGroupInformation中的认证方式改成SIMPLE之后,导致访问认证集群的线程报错:认证方式不对

2.在上一步的基础上,将线程中认证访问集群的代码加锁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.cloudera.hdfs;

import com.amazonaws.services.workdocs.model.User;
import com.cloudera.hdfs.utils.HDFSUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.io.IOException;

public class Test {
  public static void main(String[] args) throws IOException {
     //初始化认证集群配置文件
     Configuration configuration = HDFSUtils.initConfiguration(File.separator + "root"
             + File.separator + "krbconf");
     configuration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
     //该线程循环访问认证集群
     new Thread(() -> {
       try {
         while (true) {
            synchronized ("A") {
              //配置kerberos认证的配置文件
              System.setProperty("java.security.krb5.conf", File.separator + "root" +
                    File.separator+ "krbconf" + File.separator + "krb5.conf");
              //进行身份认证
              UserGroupInformation.setConfiguration(configuration);
              UserGroupInformation.loginUserFromKeytab("hive@MACRO.COM", 
                    File.separator + "root"+ File.separator + "krbconf" + File.separator + "hive.keytab");
           System.out.println("当前用户是:" + 
           UserGroupInformation.getCurrentUser());
           //列出根目录下所有文件
           FileSystem fileSystem = FileSystem.get(configuration);
           FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
           for (FileStatus file : files) {
                System.out.println("KRB:" + file.getPath());
           }
          }
         }
         } catch (Exception e) {
            e.printStackTrace();
            }
     }).start();

     //初始化非认证配置文件
     Configuration noAuthconfiguration = HDFSUtils.initConfiguration(File.separator + "root"
           + File.separator + "conf");
     noAuthconfiguration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

     //该线程循环访问非认证集群
     new Thread(() -> {
        try {
          while (true) {
            synchronized ("A") {
              System.out.println("当前用户是:" + UserGroupInformation.getCurrentUser());
              UserGroupInformation.setConfiguration(noAuthconfiguration);
              //列出根目录下所有文件
              FileSystem fileSystem = FileSystem.get(noAuthconfiguration);
              FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
              for (FileStatus file : files) {
                  System.out.println("NONEKRB:" + file.getPath());
              }
             } 
           }
         } catch (Exception e) {
             e.printStackTrace();
         }
        }).start();
    }
}

问题:

此时虽然不再报错了,但是我们从结果中看出,两个线程访问的是同一个集群

原因在于没有重置UserGroupInformation

3.在上一步的基础上,访问非认证集群之前增加重置UserGroupInformation操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.cloudera.hdfs;

import com.amazonaws.services.workdocs.model.User;
import com.cloudera.hdfs.utils.HDFSUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.io.IOException;

public class Test {
  public static void main(String[] args) throws IOException {
     //初始化认证集群配置文件
     Configuration configuration = HDFSUtils.initConfiguration(File.separator + "root"
             + File.separator + "krbconf");
     configuration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
     //该线程循环访问认证集群
     new Thread(() -> {
       try {
         while (true) {
            synchronized ("A") {
              //配置kerberos认证的配置文件
              System.setProperty("java.security.krb5.conf", File.separator + "root" +
                    File.separator+ "krbconf" + File.separator + "krb5.conf");
              //进行身份认证
              UserGroupInformation.setConfiguration(configuration);
              UserGroupInformation.loginUserFromKeytab("hive@MACRO.COM", 
                    File.separator + "root"+ File.separator + "krbconf" + File.separator + "hive.keytab");
           System.out.println("当前用户是:" + 
           UserGroupInformation.getCurrentUser());
           //列出根目录下所有文件
           FileSystem fileSystem = FileSystem.get(configuration);
           FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
           for (FileStatus file : files) {
                System.out.println("KRB:" + file.getPath());
           }
          }
         }
         } catch (Exception e) {
            e.printStackTrace();
            }
     }).start();


     //初始化非认证配置文件
     Configuration noAuthconfiguration = HDFSUtils.initConfiguration(File.separator + "root"
           + File.separator + "conf");
     noAuthconfiguration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

     //该线程循环访问非认证集群
     new Thread(() -> {
        try {
          while (true) {
            synchronized ("A") {
              //重置认证信息
              UserGroupInformation.reset();
              System.out.println("当前用户是:" + UserGroupInformation.getCurrentUser());
              UserGroupInformation.setConfiguration(noAuthconfiguration);
              //列出根目录下所有文件
              FileSystem fileSystem = FileSystem.get(noAuthconfiguration);
              FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
              for (FileStatus file : files) {
                  System.out.println("NONEKRB:" + file.getPath());
              }
             } 
           }
         } catch (Exception e) {
             e.printStackTrace();
         }
        }).start();
    }
}

从结果来看,测试成功:

4.进一步测试增加重置UserGroupInformation但是不加锁的情况

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.cloudera.hdfs;

import com.amazonaws.services.workdocs.model.User;
import com.cloudera.hdfs.utils.HDFSUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.io.IOException;

public class Test {
  public static void main(String[] args) throws IOException {
     //初始化认证集群配置文件
     Configuration configuration = HDFSUtils.initConfiguration(File.separator + "root"
             + File.separator + "krbconf");
     configuration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
     //该线程循环访问认证集群
     new Thread(() -> {
       try {
         while (true) {
            //synchronized ("A") {
              //配置kerberos认证的配置文件
              System.setProperty("java.security.krb5.conf", File.separator + "root" +
                    File.separator+ "krbconf" + File.separator + "krb5.conf");
              //进行身份认证
              UserGroupInformation.setConfiguration(configuration);
              UserGroupInformation.loginUserFromKeytab("hive@MACRO.COM", 
                    File.separator + "root"+ File.separator + "krbconf" + File.separator + "hive.keytab");
           System.out.println("当前用户是:" + 
           UserGroupInformation.getCurrentUser());
           //列出根目录下所有文件
           FileSystem fileSystem = FileSystem.get(configuration);
           FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
           for (FileStatus file : files) {
                System.out.println("KRB:" + file.getPath());
           }
          //}
         }
         } catch (Exception e) {
            e.printStackTrace();
        }
     }).start();


     //初始化非认证配置文件
     Configuration noAuthconfiguration = HDFSUtils.initConfiguration(File.separator + "root"
           + File.separator + "conf");
     noAuthconfiguration.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");

     //该线程循环访问非认证集群
     new Thread(() -> {
        try {
          while (true) {
              //synchronized ("A") {
              //重置认证信息
              UserGroupInformation.reset();
              System.out.println("当前用户是:" + UserGroupInformation.getCurrentUser());
              UserGroupInformation.setConfiguration(noAuthconfiguration);
              //列出根目录下所有文件
              FileSystem fileSystem = FileSystem.get(noAuthconfiguration);
              FileStatus[] files = fileSystem.listStatus(new Path("hdfs://nameservice1/"));
              for (FileStatus file : files) {
                  System.out.println("NONEKRB:" + file.getPath());
              }
             //} 
           }
         } catch (Exception e) {
             e.printStackTrace();
         }
        }).start();
    }
}

问题:

在访问认证集群的线程认证结束之后准备访问集群时,会出现这时正好被访问非认证集群的线程把认证信息清除的情况,无法找到用户,导致报错。

6

总结

1.因为java进程的kerberos身份认证信息存放在UserGroupInformation的静态字段中,因此该进程的内存中仅能存取一份身份信息,这也导致一个线程修改该身份信息之后会直接影响另一个线程。

2.如果要在不同的线程中访问认证集群和非认证集群,只能通过加锁和重置身份信息的方式,但这会显著影响程序执行效率。

提示:代码块部分可以左右滑动查看噢

为天地立心,为生民立命,为往圣继绝学,为万世开太平。 温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。

推荐关注Hadoop实操,第一时间,分享更多Hadoop干货,欢迎转发和分享。

原创文章,欢迎转载,转载请注明:转载自微信公众号Hadoop实操

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hadoop实操 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
0553-6.1.0-如何使用Java代码同时访问安全和非安全CDH集群
做Hadoop应用开发的过程中,用户会有这样的需求,在同一个Java应用中同时访问安全和非安装的CDH集群。同一个Java应用即同一个进程同一个JVM,由于一些全局的变量可能会导致无法同时访问安全和非安全的集群。本篇文章Fayson介绍下如何使用Java代码同时访问安全和非安全的CDH集群。
Fayson
2019/11/28
1.7K0
Win10 IDEA连接虚拟机中的Hadoop(HDFS)
IDEA自带Maven,如果需要自己安装Maven可以参考Maven安装教程 创建项目,选择Maven,模板选择第一个maven-archetype-archetype
超级小的大杯柠檬水
2024/11/21
1440
Win10 IDEA连接虚拟机中的Hadoop(HDFS)
Hadoop2.2.0二次开发报错:No FileSystem for scheme: hdfs
当引入Hadoop-common-2.2.0.jar包进行二次开发,比如读写HDFS文件时,初次运行报错。
星哥玩云
2022/06/29
1.1K0
添加kerberos后,Flink任务的运行认证及各组件的认证
https://www.psvmc.cn/article/2022-11-08-bigdata-kerberos-centos.html
码客说
2023/08/11
1.5K0
Hadoop快速入门——第二章、分布式集群(第四节、搭建开发环境)
个人建议,先改一下【镜像】位置为国内的,我就没改,直接update了,玩了好几把【连连看】都没下载完毕。
红目香薰
2022/11/29
2280
Hadoop快速入门——第二章、分布式集群(第四节、搭建开发环境)
如何使用Scala代码访问Kerberos环境的HDFS
前面Fayson介绍了《如何使用Java API访问HDFS为目录设置配额》,随着开发语言的多样性,也有基于Scala语言进行开发,本篇文章主要介绍如何使用Scala代码访问Kerberos环境的HDFS。
Fayson
2018/11/16
2K0
HDFS Java API 实践
安装集群:https://michael.blog.csdn.net/article/details/114607857
Michael阿明
2021/09/06
4190
Hadoop之HDFS04【JavaAPI操作】
  前面项目中我们是创建的java项目来演示的,但是hadoop相关的依赖太多了,不方便,本文通过maven项目来演示HDFS的java API操作
用户4919348
2019/04/18
4700
【说站】利用Java连接Hadoop进行编程
这篇文章主要介绍了利用Java连接Hadoop进行编程,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下!
很酷的站长
2022/11/24
5380
【说站】利用Java连接Hadoop进行编程
如何使用Java代码访问HDFS.docx
在开发Hadoop应用时,需要用到hadoop-client API来访问HDFS并进行本地调试。本篇文章则主要讲述如何使用Java代码访问Kerberos和非Kerberos环境下HDFS服务。
Fayson
2018/03/29
2K0
如何使用Java代码访问HDFS.docx
如何在集群外节点跨网段向HDFS写数据
Fayson想了想这个问题其实在各个环境是都可能碰到的,于是在这篇文章给大家系统介绍一下。
Fayson
2018/03/29
2.8K0
如何在集群外节点跨网段向HDFS写数据
如何使用Java代码访问Kerberos环境下的Kudu
前面Fayson介绍了《如何使用Java API访问CDH的Kudu》,文章是在非安全环境下实现,随着对集群安全要求的提高,在Kerberos环境下的使用API访问Kudu也会有一些变化,本篇文章Fayson主要介绍如何使用Java代码访问Kerberos环境下的Kudu。
Fayson
2018/11/16
3K0
安全知识&kerberos初识
问题一 kinit alice beeline -u “jdbc:hive2://baogang2:10000/default;principal=hive/baogang2@TDH” 请问这个beeline连接到inceptor中之后,当前用户是谁?principal=hive/baogang2@TDH指的又是什么? 当前用户是baogang2 principal=hive/baogang2@TDH指的是在baogang2的权限下使用hive 问题二 尝试写一个访问
小爷毛毛_卓寿杰
2019/02/13
1K0
安全知识&kerberos初识
如何跨平台在本地开发环境提交MapReduce作业到CDH集群
在开发Hadoop的MapReduce作业时需要重复的打包并手动传输到集群运行往往比较麻烦,有时我们也需要在本地能够直接调试代码如在Intellij能直接连接到集群提交作业,或者我们需要跨平台的提交MapReduce作业到集群。那么如何实现呢?本篇文章主要讲述如何跨平台在本地开发环境下提交作业到Hadoop集群,这里我们还是分为Kerberos环境和非Kerberos环境。
Fayson
2018/03/29
1.2K0
如何跨平台在本地开发环境提交MapReduce作业到CDH集群
HDFS Java API
官网 http://hadoop.apache.org/docs/r2.7.3/api/index.html
程裕强
2022/05/06
1.6K0
HDFS Java API
0692-5.16.1-外部客户端跨网段访问Hadoop集群方式(续)
在生产环境的CDH集群中,为了分开集群对网络的使用会为集群配备两套网络(管理网段和数据网段),数据网段主要用于集群内部数据交换,一般使用万兆网络以确保集群内数据传输性能,管理网段主要用于集群管理,一般使用千兆网络。一般情况下在集群外进行集群管理和数据传输的都是通过千兆网络进行交互,在集群外是无法直接访问集群内的万兆网络。
Fayson
2019/08/28
2.6K0
0692-5.16.1-外部客户端跨网段访问Hadoop集群方式(续)
09_java访问Hadoop的HDFS
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/111278.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/05
3650
Hdfs FileSystem Client
Java抽象类org.apache.hadoop.fs.FileSystem定义了hadoop的一个文件系统接口。Hadoop中关于文件操作类基本上全部是在"org.apache.hadoop.fs"包中,这些API能够支持的操作包含:打开文件,读写文件,删除文件等。
Dlimeng
2023/06/30
1890
Hdfs FileSystem Client
Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统
前言   我们知道HDFS集群中,所有的文件都是存放在DN的数据块中的。那我们该怎么去查看数据块的相关属性的呢?这就是我今天分享的内容了 一、HDFS中数据块概述 1.1、HDFS集群中数据块存放位置   我们知道hadoop集群遵循的是主/从的架构,namenode很多时候都不作为文件的读写操作,只负责任务的调度和掌握数据块在哪些datanode的分布,   保存的是一些数据结构,是namespace或者类似索引之类的东西,真正的数据存储和对数据的读写是发生在datanode里的。   找到${HADOO
用户1195962
2018/01/18
1.3K0
Hadoop(八)Java程序访问HDFS集群中数据块与查看文件系统
添加kerberos后,Flink任务的运行认证及Hive使用JDBC连接的认证
https://www.psvmc.cn/article/2022-11-08-bigdata-kerberos-centos.html
码客说
2023/08/08
1.2K0
推荐阅读
相关推荐
0553-6.1.0-如何使用Java代码同时访问安全和非安全CDH集群
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验