“unable to open user login file\\服务器项目管理目录\data\logedin\用户名.log ”

本文档详细介绍了Visual SourceSafe (VSS) 的服务器端及客户端配置步骤,并针对客户端访问服务器时出现的“unable to open user login file”错误提供了具体的解决方案。此外,还介绍了如何在JBuilder中使用VSS以及如何上传整个目录到VSS。

服务器端设置

http://blog.youkuaiyun.com/phoebeofhust/archive/2008/04/05/2253464.aspx

客户端设置

http://blog.youkuaiyun.com/phoebeofhust/archive/2008/04/05/2253474.aspx

当配置完毕之后, 在本地的客户端进行访问服务器端的时候可能出现

VSS客户端不能访问问题“unable to open user login file\\服务器项目管理目录\data\logedin\用户名.log ”

的错误。解决办法:

将VSS数据库目录[共享与安全>共享>权限>EveryOne]设置为”更改“权限,并在[安全]选项中加入域用户,赋予读写权限即可。

在JBuilder中使用VSS

http://www.svn8.com/xm/200908/04-8218.html

VSS上如何上传整个目录??

将需要上传的目录整个拖到VSS的目录下。在提示窗体中选中下面的多选框,第一行的第一个和第二个,就可以了。

c3b946ec121bbae42e2e218d.jpg

阅读全文
类别: 项目错误总结  查看评论

转载于:https://my.oschina.net/rigger21/blog/3627

// ====== 环境修复与全局对象安全 ====== (function() { // 安全获取全局对象的函数(支持严格模式和所有环境) const getGlobalObject = () => { // 1. 优先使用现代标准 globalThis if (typeof globalThis !== 'undefined') return globalThis; // 2. 处理严格模式限制 try { const globalFromFn = Function('return this')(); if (globalFromFn) return globalFromFn; } catch (e) { console.warn('[EnvFix] Function constructor blocked in strict mode'); } // 3. 环境特定对象 if (typeof global !== 'undefined') return global; // Node.js if (typeof window !== 'undefined') return window; // 浏览器 if (typeof self !== 'undefined') return self; // Web Worker // 4. Cocos Creator 原生环境特殊处理 if (typeof cc !== 'undefined' && cc.sys && cc.sys.__globalAdapter) { return cc.sys.__globalAdapter; } // 5. 最后手段:创建新的全局对象 console.error('[EnvFix] Unable to determine global object, creating new'); return {}; }; const globalObj = getGlobalObject(); // 修复关键全局变量(使用 Object.defineProperty 防止覆盖) const defineGlobal = (name, value) => { if (typeof globalObj[name] === 'undefined') { Object.defineProperty(globalObj, name, { value, writable: true, configurable: true, enumerable: true }); console.log(`[EnvFix] Defined global: ${name}`); } }; // 定义关键全局对象 defineGlobal('global', globalObj); defineGlobal('self', globalObj); defineGlobal('globalThis', globalObj); defineGlobal('window', globalObj); // 原生平台特殊处理 if (cc && cc.sys && cc.sys.isNative) { // 确保 XMLHttpRequest 存在 if (typeof XMLHttpRequest === 'undefined') { defineGlobal('XMLHttpRequest', function() { return cc.loader.getXMLHttpRequest(); }); } // 确保 document 对象存在 if (typeof document === 'undefined') { defineGlobal('document', { createElement: () => ({ appendChild: () => {} }), head: { appendChild: () => {} }, body: { appendChild: () => {} } }); } // 确保 location 对象存在 if (typeof location === 'undefined') { defineGlobal('location', { href: 'file://', protocol: 'file:', hostname: 'localhost', host: 'localhost', origin: 'file://' }); } console.log('[EnvFix] Native environment patched'); } // 确保 require 函数存在 if (typeof globalObj.require === 'undefined') { defineGlobal('require', function(module) { if (globalObj.__modules && globalObj.__modules[module]) { return globalObj.__modules[module]; } console.warn(`[RequireFallback] Module '${module}' not found`); return {}; }); } })(); // ====== 引擎初始化保护系统 ====== const EngineReady = (function() { let _promise = null; let _resolve = null; let _isReady = false; let _checkInterval = null; const safeCheckEngine = () => { // 引擎已初始化 if (cc && cc.game && cc.game._isEngineInited) { return true; } // 尝试监听初始化事件 if (cc && cc.game && cc.game.once) { const eventName = cc.game.EVENT_ENGINE_INITED || 'engine-inited'; cc.game.once(eventName, () => { _resolve && _resolve(); _isReady = true; _checkInterval && clearInterval(_checkInterval); }); return true; } return false; }; return { get isReady() { return _isReady; }, get promise() { return _promise; }, init() { if (!_promise) { _promise = new Promise(resolve => { _resolve = () => { _isReady = true; resolve(); _checkInterval && clearInterval(_checkInterval); }; // 首次检查 if (safeCheckEngine()) return; // 轮询检查 _checkInterval = setInterval(() => { safeCheckEngine() && _resolve(); }, 100); }); } return _promise; }, safeAccess(callback) { if (_isReady) { try { return callback(); } catch (e) { console.error('[EngineSafe] Error:', e); } } return _promise.then(callback).catch(e => { console.error('[EngineSafe] Async error:', e); }); } }; })(); EngineReady.init(); // ====== 游戏主入口 ====== async function gameMainEntry() { try { console.log('[Main] Waiting for engine initialization...'); await EngineReady.promise; console.log('[Main] Engine ready'); // 基本引擎配置 EngineReady.safeAccess(() => { if (cc.view) { cc.view.enableRetina(true); cc.view.resizeWithBrowserSize(true); cc.view.setDesignResolutionSize(960, 640, cc.ResolutionPolicy.SHOW_ALL); } }); // 加载SDK await loadGravityEngineSDK(); // 加载启动场景 await loadStartScene(); } catch (error) { console.error('[Main] Initialization failed:', error); try { cc.director.loadScene('start'); } catch (fallbackError) { displayErrorFallback('启动失败\n请重启应用'); } } } // 错误显示后备方案 function displayErrorFallback(message) { try { const errorDiv = document.createElement('div'); errorDiv.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: black; color: white; display: flex; justify-content: center; align-items: center; z-index: 9999; font: 24px Arial, sans-serif; text-align: center; white-space: pre-line; padding: 20px; `; errorDiv.textContent = message; document.body.appendChild(errorDiv); } catch (e) { console.error('[Fallback] Display failed:', e); } } // ====== SDK加载器增强版 ====== async function loadGravityEngineSDK() { // 使用相对路径解决加载问题 const sdkPaths = [ './assets/_plugs/lib/gravityengine.mg.cocoscreator.min.js', '_plugs/lib/gravityengine.mg.cocoscreator.min.js', 'lib/gravityengine.mg.cocoscreator.min.js' ]; for (const path of sdkPaths) { try { // 关键修复:在加载 SDK 前确保全局对象完整 ensureGlobalEnvironment(); // JSB 特殊处理:使用 require 加载 if (cc.sys.isNative && cc.sys.__globalAdapter?.require) { cc.sys.__globalAdapter.require(path); console.log('[SDK] Native require loaded:', path); } else { await loadScript(path); console.log('[SDK] Loaded from:', path); } // 关键修复:加载后再次检查全局对象 ensureGlobalEnvironment(); initGravityEngine(); return; } catch (e) { console.warn('[SDK] Load failed:', path, e.message); } } console.error('[SDK] All paths failed'); handleSDKLoadFailure(); } function ensureGlobalEnvironment() { // 获取全局对象 const getGlobalObject = () => { if (typeof globalThis !== 'undefined') return globalThis; if (typeof global !== 'undefined') return global; if (typeof window !== 'undefined') return window; if (typeof self !== 'undefined') return self; return Function('return this')() || {}; }; const globalObj = getGlobalObject(); // 确保 self 在所有环境中都存在 if (typeof self === 'undefined') { console.warn('[GlobalFix] self is undefined, patching...'); Object.defineProperty(globalObj, 'self', { value: globalObj, writable: true, configurable: true, enumerable: true }); } // 确保其他关键全局对象存在 const requiredGlobals = ['window', 'global', 'globalThis', 'document', 'location']; requiredGlobals.forEach(name => { if (typeof globalObj[name] === 'undefined') { console.warn(`[GlobalFix] ${name} is undefined, patching...`); Object.defineProperty(globalObj, name, { value: globalObj, writable: true, configurable: true, enumerable: true }); } }); // 原生平台特殊处理 if (cc && cc.sys && cc.sys.isNative) { // 确保 location 对象存在 if (typeof location === 'undefined') { Object.defineProperty(globalObj, 'location', { value: { href: 'file://', protocol: 'file:', hostname: 'localhost' }, writable: false, configurable: false, enumerable: true }); } } } function loadScript(path) { return new Promise((resolve, reject) => { // 优先使用 Cocos 的加载系统 if (cc.assetManager?.loadScript) { cc.assetManager.loadScript(path, (err) => { if (err) { // 原生平台特殊处理 if (cc.sys.isNative) { console.warn('[SDK] Using native fallback for script loading'); try { // 原生平台直接执行脚本 const jsb = cc.sys.__globalAdapter; if (jsb && jsb.require) { jsb.require(path); return resolve(); } } catch (nativeError) { console.error('[SDK] Native require failed:', nativeError); } } reject(err); } else { resolve(); } }); return; } // 后备方案:直接创建 script 标签 try { const script = document.createElement('script'); script.src = path; script.onload = () => resolve(); script.onerror = () => reject(new Error(`Failed to load ${path}`)); document.head.appendChild(script); console.warn('[SDK] Using DOM fallback for script loading'); } catch (e) { reject(e); } }); } function initGravityEngine() { let GravityEngine = null; // 1. 尝试标准方式获取 if (typeof GravityEngine === 'function') { console.log('[SDK] GravityEngine found in local scope'); } // 2. 尝试从全局对象中查找 else if (typeof window.GravityEngine === 'function') { GravityEngine = window.GravityEngine; console.warn('[SDK] Found GravityEngine in window object'); } // 3. 尝试从其他全局对象中查找 else if (typeof global.GravityEngine === 'function') { GravityEngine = global.GravityEngine; console.warn('[SDK] Found GravityEngine in global object'); } // 4. 尝试从 self 对象中查找 else if (typeof self.GravityEngine === 'function') { GravityEngine = self.GravityEngine; console.warn('[SDK] Found GravityEngine in self object'); } // 5. 最后尝试从 globalThis 中查找 else if (typeof globalThis.GravityEngine === 'function') { GravityEngine = globalThis.GravityEngine; console.warn('[SDK] Found GravityEngine in globalThis object'); } else { console.error('[SDK] GravityEngine not found'); return; } try { // 使用您的 AppID 624768904 GravityEngine.init({ appId: '624768904', enableLog: true }); console.log('[SDK] GravityEngine initialized with AppID 624768904'); } catch (e) { console.error('[SDK] Init failed:', e); } } function handleSDKLoadFailure() { console.warn('[SDK] Using fallback analytics'); window.GravityEngine = { init: () => console.warn('SDK unavailable'), trackEvent: () => {} }; } // ====== 场景加载器 ====== async function loadStartScene() { try { // 加载主资源包 await new Promise((resolve) => { if (!cc.assetManager?.loadBundle) { console.warn('[Scene] AssetManager unavailable'); return resolve(); } cc.assetManager.loadBundle('main', (err) => { if (err) console.error('[Scene] Bundle load error:', err); resolve(); }); }); // 加载场景 if (cc.director?.loadScene) { cc.director.loadScene('start'); } else { throw new Error('Director unavailable'); } } catch (error) { console.error('[Scene] Load failed:', error); try { cc.director.loadScene('start'); } catch (e) { throw new Error('Fallback scene load failed'); } } } // ====== UI_Entry组件 ====== const { ccclass, property } = cc._decorator; @ccclass export default class UI_Entry extends cc.Component { @property(cc.ProgressBar) progress_loading = null; loginTimeoutHandler = null; onLoad() { EngineReady.safeAccess(() => { try { cc.director.getCollisionManager().enabled = true; this._show(); } catch (e) { console.error('[UI] onLoad error:', e); this.startLoadGame(); } }).catch(e => { console.error('[UI] Engine access error:', e); this.startLoadGame(); }); } onDestroy() { this.loginTimeoutHandler && cc.Tween.stop(this.loginTimeoutHandler); } async _show() { this.progress_loading.progress = 0; // 平台SDK初始化 if (cc.sys.isBrowser) { try { await this.initYPSDK(); } catch (e) { console.error('[YPSDK] Init failed:', e); this.startLoadGame(); } } else { this.startLoadGame(); } // 登录超时保护 this.setLoginTimeout(); } setLoginTimeout() { if (cc.tween) { this.loginTimeoutHandler = cc.tween(this) .delay(10) .call(() => { console.warn('[Login] Timeout after 10s'); this.startLoadGame(); }) .start(); } else { setTimeout(() => this.startLoadGame(), 10000); } } async initYPSDK() { if (typeof YPSDK === 'undefined') { console.warn('[YPSDK] SDK unavailable'); return; } const config = { gameChannelList: { h5: { platformType: "h5", version: "1.0.0" }, tt: { platformType: "tt", appId: "tt09297f94961f881b02" }, wx: { platformType: "wx", appId: "wx6baaaa27ab5186ff" } } }; await YPSDK.init(39, "https://platform-shop-dev.hanyougame.com", config); await YPSDK.login(); if (YPSDK.setLoginCallBack) { YPSDK.setLoginCallBack(success => { if (!success) return; // 取消超时 this.loginTimeoutHandler && cc.Tween.stop(this.loginTimeoutHandler); // 初始化分析SDK if (r_GravityPlatform.default?.GA_Init) { r_GravityPlatform.default.GA_Init(YPSDK.Platform.loginData.bindingId); } this.startLoadGame(); }); } else { this.startLoadGame(); } } startLoadGame() { const tasks = [ this._loadGameConfig, this._loadRemoteConfig, this._loadExcelData, this._loadUserData, this._loadCommonBundle, this._loadMainBundle ].map(fn => fn.bind(this)); this.executeTasks(tasks, () => this._loadGame()); } executeTasks(tasks, finalCallback) { let completed = 0; const total = tasks.length; const runTask = async (index) => { if (index >= total) { finalCallback(); return; } try { await tasks[index](); completed++; this._setProgress(completed / total); runTask(index + 1); } catch (e) { console.error(`[Task ${index}] Failed:`, e); completed++; this._setProgress(completed / total); runTask(index + 1); // 继续执行后续任务 } }; runTask(0); } async _loadExcelData() { if (!r_ExcelLoader?.ExcelLoader?.loadAll) { console.warn('[Data] ExcelLoader unavailable'); return; } await r_ExcelLoader.ExcelLoader.loadAll(); console.log('[Data] Excel loaded'); } async _loadGameConfig() { if (!r_ResLoader.default?.loadRes) { console.warn('[Config] ResLoader unavailable'); return; } const jsonAsset = await r_ResLoader.default.loadRes( "resources", "config/GameConfig", cc.JsonAsset ); if (jsonAsset && r_GameConfig.default) { r_GameConfig.default.appConfig = jsonAsset.json; jsonAsset.decRef && jsonAsset.decRef(); console.log('[Config] Game config loaded'); } } async _loadRemoteConfig() { if (!r_GameConfig.default?.appConfig?.RemoteUrl) { console.warn('[Config] RemoteUrl not set'); return; } const remoteUrl = r_GameConfig.default.appConfig.RemoteUrl; const remotePath = cc.path.join(remoteUrl, "ADConfig.json"); try { const remoteConfig = await r_ResLoader.default.loadRemote(remotePath, { ext: ".json" }); if (remoteConfig?.json && r_GravityPlatform.default) { r_GravityPlatform.default.videoId = remoteConfig.json.ADUnitId[0]; r_GameConfig.default.adConfig = remoteConfig.json; console.log('[Config] Remote config loaded'); } } catch (e) { console.error('[Config] Remote load failed:', e); } } async _loadCommonBundle() { if (!r_ResLoader.default?.loadBundle) { console.warn('[Bundle] ResLoader unavailable'); return; } try { await r_ResLoader.default.loadBundle(r_BundleConfig.BundleNames.Common); console.log('[Bundle] Common loaded'); } catch (e) { console.error('[Bundle] Common load failed:', e); } } async _loadMainBundle() { if (!r_ResLoader.default?.loadBundle) { console.warn('[Bundle] ResLoader unavailable'); return; } try { await r_ResLoader.default.loadBundle(r_BundleConfig.MainGameBundle); console.log('[Bundle] Main loaded'); } catch (e) { console.error('[Bundle] Main load failed:', e); } } async _loadUserData() { try { // 音频初始化 r_AudioManager.AudioMgr?.init(); // 全局配置 r_GameGlobalVariable.GameGlobalVariable?.initPeiZhi(); // 网络检测 if (YPSDK?.Common?.curChannelData) { const platformType = YPSDK.Common.curChannelData.platformType; if (platformType === YPSDK.GamePlatformType.WX || platformType === YPSDK.GamePlatformType.TT) { r_YpNetMag.YpNetMag?.failSever(() => { r_YpNetMag.YpNetMag.isFail = true; }); } } // 用户数据初始化 if (YPSDK?.Platform?.loginData) { await r_YpNetMag.YpNetMag?.initServer(YPSDK.Platform.loginData); } } catch (e) { console.error('[User] Load failed:', e); } } _loadGame() { try { const guideIndex = r_PlayerDataManager.PlayerDataMgr.GetGuideIndexByTaskName( r_Const_Common.GuideName.战斗背包 ); if (guideIndex !== r_Const_Common.GameBagGuideIndex.引导完结) { // 新玩家流程 r_PlayerDataManager.PlayerDataMgr.GMSetGuideIndex?.( r_Const_Common.GuideName.战斗背包, r_Const_Common.GameBagGuideIndex.引导初始1 ); r_GameDataManager.GameDataMgr?.ClearGameBagData(); r_GameGlobalVariable.GameGlobalVariable.nowlevel = 1; r_UIManager.default?.open( r_BundleConfig.BundleNames.Game, r_UIConfig_Game.UIView_Game.UI_GameView ); } else { // 老玩家流程 r_EventManager.EventMgr?.dispatchEvent(r_EvenType.EVENT_TYPE.Game_Load_View, true); r_UIManager.default?.open( r_BundleConfig.BundleNames.Home, r_UIConfig_Home.UIView_Home.UI_Hall ); } // 白名单检查 this.checkWhiteList(); } catch (e) { console.error('[Game] Load failed:', e); try { cc.director.loadScene('start'); } catch (sceneError) { console.error('[Game] Scene load failed:', sceneError); } } } async checkWhiteList() { try { if (!YPSDK?.Platform?.loginData || !YPSDK.platformUrl) return; const url = `${YPSDK.platformUrl}/User/GetCfgData?userId=${YPSDK.Platform.loginData.userUid}&keyId=NoVideo`; if (r_HttpManager.HttpMgr?.requestData) { r_HttpManager.HttpMgr.requestData(res => { if (res?.data?.keyData === "true") { r_PlayerDataManager.PlayerDataMgr.WHITE_NAME_NO_VIDEO = true; } }, url); } } catch (e) { console.error('[WhiteList] Check failed:', e); } } _setProgress(progress) { if (!this.progress_loading) return; this.progress_loading.progress = Math.max(0, Math.min(1, progress)); } } // ====== 启动游戏 ====== if (cc?.game?.run) { cc.game.run(() => { // 确保环境修复完成 ensureGlobalEnvironment(); gameMainEntry(); }); } else { setTimeout(() => { ensureGlobalEnvironment(); gameMainEntry(); }, 1000); } 针对上述问题 给我修改后的完整代码
最新发布
07-16
package com.train.data.processor; import com.train.data.config.ConfigManager; import com.train.data.entity.InfoAppendix; import com.train.data.entity.SaleRecord; import com.train.data.utils.HdfsUtils; import com.train.data.utils.HiveTableUtils; import com.train.data.utils.KerberosUtils; import org.apache.flink.api.common.eventtime.WatermarkStrategy; import org.apache.flink.api.common.functions.FlatMapFunction; import org.apache.flink.api.common.functions.MapFunction; import org.apache.flink.api.common.restartstrategy.RestartStrategies; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.configuration.Configuration; import org.apache.flink.runtime.state.hashmap.HashMapStateBackend; import org.apache.flink.streaming.api.CheckpointingMode; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.CheckpointConfig; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.streaming.api.functions.source.RichSourceFunction; import org.apache.flink.table.api.EnvironmentSettings; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; import org.apache.flink.util.Collector; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; /** * 调试版本:文本文件处理作业,打印详细的SQL和错误信息 */ public class ZipFileProcessorJob { private static final Logger logger = LogManager.getLogger(ZipFileProcessorJob.class); public static void main(String[] args) throws Exception { logger.info("启动文本文件处理作业(调试版本)..."); try { // 1. 首先设置关键的系统属性(在任何Flink操作之前) setupCriticalSystemProperties(); // 2. 预先设置系统属性以避免Kerberos初始化问题 setupSystemProperties(); // 3. 初始化Kerberos认证(如果启用) initializeKerberosIfEnabled(); // 4. 创建执行环境(使用特殊配置避免delegation token问题) StreamExecutionEnvironment env = createSecureExecutionEnvironment(); // 5. 配置 Flink 作业 configureFlinkJob(env); // 6. 创建数据源:定时扫描 HDFS 目录,直接读取文本文件 DataStream<String> textFileStream = env .addSource(new TextFileSourceFunction()) .name("TextFileSource") .assignTimestampsAndWatermarks(WatermarkStrategy.noWatermarks()); // 7. 读取文件内容 DataStream<Tuple2<String, String>> fileContentStream = textFileStream .map(new TextFileReadFunction()) .name("TextFileReader"); // 8. 解析并写入 info_appendix 表 DataStream<InfoAppendix> infoAppendixStream = fileContentStream .filter(t -> t.f0.contains("GASMZ_info_appendix")) .flatMap(new InfoAppendixParseFunction()) .name("InfoAppendixParser"); infoAppendixStream.addSink(new DebugInfoAppendixSink()) .name("InfoAppendixDebugSink"); // 9. 解析并写入 sale_record 表 DataStream<SaleRecord> saleRecordStream = fileContentStream .filter(t -> t.f0.contains("GASMZ_sale")) .flatMap(new SaleRecordParseFunction()) .name("SaleRecordParser"); saleRecordStream.addSink(new DebugSaleRecordSink()) .name("SaleRecordDebugSink"); // 10. 执行作业 env.execute("TextFileProcessorJob-Debug"); } catch (Exception e) { logger.error("文本文件处理作业启动失败", e); throw e; } } /** * 设置关键系统属性(必须在Flink环境创建之前调用) */ private static void setupCriticalSystemProperties() { // 关键:禁用Flink的delegation token管理器 System.setProperty("flink.security.kerberos.token.provider.enabled", "false"); // 设置Flink为本地执行模式 System.setProperty("flink.execution.target", "local"); // 禁用Flink安全相关功能 System.setProperty("flink.security.ssl.enabled", "false"); // 设置Hadoop用户 System.setProperty("HADOOP_USER_NAME", "hive"); logger.info("关键系统属性设置完成"); } /** * 创建安全的执行环境 */ private static StreamExecutionEnvironment createSecureExecutionEnvironment() { try { // 创建配置 org.apache.flink.configuration.Configuration config = new org.apache.flink.configuration.Configuration(); // 禁用安全相关配置 config.setBoolean("security.kerberos.login.use-ticket-cache", false); // 设置为本地执行 config.setString("execution.target", "local"); // 创建本地环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironment(2, config); logger.info("安全执行环境创建成功"); return env; } catch (Exception e) { logger.warn("创建安全执行环境失败,使用默认环境: {}", e.getMessage()); return StreamExecutionEnvironment.getExecutionEnvironment(); } } /** * 设置系统属性以避免初始化问题 */ private static void setupSystemProperties() { try { // 设置Hadoop配置目录 System.setProperty("hadoop.home.dir", System.getProperty("user.dir")); if (ConfigManager.isKerberosEnabled()) { // 设置Kerberos配置文件路径 String krb5ConfPath = ConfigManager.getKrb5ConfPath(); if (krb5ConfPath != null) { // 如果是相对路径,转换为绝对路径 if (krb5ConfPath.startsWith("src\\main\\resources\\")) { krb5ConfPath = System.getProperty("user.dir") + "/" + krb5ConfPath; } System.setProperty("java.security.krb5.conf", krb5ConfPath); logger.info("设置Kerberos配置文件路径: {}", krb5ConfPath); } // 设置JAAS配置文件 String jaasConfPath = System.getProperty("user.dir") + "D:/Development/GZKY/cursor-flink-hive/src/main/resources/flink-jaas.conf"; System.setProperty("java.security.auth.login.config", jaasConfPath); // 设置其他Kerberos系统属性 System.setProperty("javax.security.auth.useSubjectCredsOnly", "false"); } else { // 禁用Kerberos时设置简单认证 System.setProperty("hadoop.security.authentication", "simple"); System.setProperty("hadoop.security.authorization", "false"); logger.info("Kerberos已禁用,使用简单认证模式"); } } catch (Exception e) { logger.warn("设置系统属性时发生错误: {}", e.getMessage()); } } /** * 如果启用Kerberos则进行初始化 */ private static void initializeKerberosIfEnabled() { try { if (ConfigManager.isKerberosEnabled()) { logger.info("Kerberos已启用,开始初始化..."); KerberosUtils.initKerberos(); logger.info("Kerberos初始化完成"); } else { logger.info("Kerberos已禁用,跳过Kerberos初始化"); } } catch (Exception e) { logger.error("Kerberos初始化失败,但程序将继续运行", e); } } /** 配置 Flink 作业参数 */ private static void configureFlinkJob(StreamExecutionEnvironment env) { env.setParallelism(ConfigManager.getFlinkJobParallelism()); env.setRestartStrategy(RestartStrategies.fixedDelayRestart( ConfigManager.getFlinkRestartAttempts(), org.apache.flink.api.common.time.Time.of(ConfigManager.getFlinkRestartDelay(), TimeUnit.MILLISECONDS) )); env.setStateBackend(new HashMapStateBackend()); env.enableCheckpointing(ConfigManager.getFlinkCheckpointInterval()); CheckpointConfig checkpointConfig = env.getCheckpointConfig(); checkpointConfig.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); checkpointConfig.setCheckpointTimeout(ConfigManager.getFlinkCheckpointTimeout()); checkpointConfig.setExternalizedCheckpointCleanup( CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION); logger.info("Flink 作业配置完成"); } // --------------------------------------------------------------------- // 自定义 SourceFunction:定时扫描 testInput 目录下的目标文本文件 // --------------------------------------------------------------------- public static class TextFileSourceFunction extends RichSourceFunction<String> { private static final Logger logger = LogManager.getLogger(TextFileSourceFunction.class); private volatile boolean isRunning = true; private final long scanInterval = ConfigManager.getZipProcessorInterval(); @Override public void run(SourceContext<String> ctx) { logger.info("TextFileSourceFunction 开始运行,扫描间隔: {} ms", scanInterval); // TaskManager 内部重新认证(如适用) try { KerberosUtils.reloginInTaskManager(); } catch (Exception e) { logger.warn("TaskManager 中 Kerberos 认证失败: {}", e.getMessage()); } while (isRunning) { try { String inputPath = ConfigManager.getHdfsInputPath(); List<String> textFiles; // 扫描 .txt 文件 try { textFiles = KerberosUtils.doAs(() -> HdfsUtils.listFilesByExtension(inputPath, ".txt")); logger.debug("扫描目录 {},找到 {} 个文本文件", inputPath, textFiles.size()); } catch (Exception e) { logger.error("扫描目录失败: {}", e.getMessage()); // 尝试重新认证再扫描 try { KerberosUtils.reloginInTaskManager(); textFiles = KerberosUtils.doAs(() -> HdfsUtils.listFilesByExtension(inputPath, ".txt")); } catch (Exception retryEx) { logger.error("重试后仍失败: {}", retryEx.getMessage()); textFiles = new ArrayList<>(); } } // 发送文件路径 for (String file : textFiles) { logger.info("发现文本文件: {}", file); ctx.collect(file); } Thread.sleep(scanInterval); } catch (Exception ex) { logger.error("扫描文本文件时发生错误", ex); try { Thread.sleep(10_000); } catch (InterruptedException ignored) { } } } } @Override public void cancel() { isRunning = false; logger.info("TextFileSourceFunction 已停止"); } } // --------------------------------------------------------------------- // MapFunction:读取文本文件内容 // --------------------------------------------------------------------- public static class TextFileReadFunction implements MapFunction<String, Tuple2<String, String>> { private static final Logger logger = LogManager.getLogger(TextFileReadFunction.class); @Override public Tuple2<String, String> map(String filePath) throws Exception { logger.info("开始读取文本文件: {}", filePath); FSDataInputStream is = KerberosUtils.doAs(() -> HdfsUtils.openFile(filePath)); StringBuilder sb = new StringBuilder(); try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { String line; while ((line = br.readLine()) != null) { sb.append(line).append('\n'); } } // 删除原文件以免重复处理 boolean deleted = KerberosUtils.doAs(() -> HdfsUtils.delete(filePath, false)); if (deleted) { logger.info("已处理并删除文件: {}", filePath); } else { logger.warn("文件删除失败: {}", filePath); } String fileName = filePath.substring(filePath.lastIndexOf('/') + 1); return Tuple2.of(fileName, sb.toString()); } } // ------------------------------------------------------------------- // InfoAppendix 解析(FlatMap)- 修复字段解析 // ------------------------------------------------------------------- public static class InfoAppendixParseFunction implements FlatMapFunction<Tuple2<String, String>, InfoAppendix> { private static final Logger logger = LogManager.getLogger(InfoAppendixParseFunction.class); @Override public void flatMap(Tuple2<String, String> value, Collector<InfoAppendix> out) { String fileName = value.f0; String[] rows = value.f1.split("\\n"); if (rows.length == 0) { logger.warn("文件 {} 内容为空", fileName); return; } for (String raw : rows) { try { String line = raw.replace("\r", "").trim(); if (line.isEmpty() || line.startsWith("statist_date")) { continue; } String[] f = HiveTableUtils.parseCsvLine(line, ConfigManager.getFileDelimiter()); // 修复:应该检查是否有10个字段 if (f.length < 10) { logger.warn("文件 {} 行字段不足 (<10):{}", fileName, line); continue; } InfoAppendix info = new InfoAppendix(); info.setStatistDate(f[0]); info.setStatisticsDate(f[1]); info.setInnerCode(f[2]); info.setOfficeNo(f[3]); info.setWindowNo(f[4]); info.setTicketNo(f[5]); info.setIdKind(f[6]); info.setIdNo(f[7]); info.setIdName(f[8]); // 修复:正确读取area_center_code字段 info.setAreaCenterCode(f[9]); info.setPk(HiveTableUtils.generatePrimaryKey( info.getStatisticsDate(), info.getOfficeNo(), info.getWindowNo(), info.getTicketNo())); logger.debug("解析成功 InfoAppendix:ticketNo={}, pk={}, areaCode={}", info.getTicketNo(), info.getPk(), info.getAreaCenterCode()); out.collect(info); } catch (Exception ex) { logger.error("解析 InfoAppendix 行失败,文件 {}:{}", fileName, raw, ex); } } } } // ------------------------------------------------------------------- // SaleRecord 解析(FlatMap)- 修复字段解析 // ------------------------------------------------------------------- public static class SaleRecordParseFunction implements FlatMapFunction<Tuple2<String, String>, SaleRecord> { private static final Logger logger = LogManager.getLogger(SaleRecordParseFunction.class); @Override public void flatMap(Tuple2<String, String> value, Collector<SaleRecord> out) { String fileName = value.f0; String[] rows = value.f1.split("\\n"); if (rows.length == 0) { logger.warn("文件 {} 内容为空", fileName); return; } for (String raw : rows) { try { String line = raw.replace("\r", "").trim(); if (line.isEmpty() || line.startsWith("statist_date")) { continue; } String[] f = HiveTableUtils.parseCsvLine(line, ConfigManager.getFileDelimiter()); // 修复:应该检查是否有26个字段 if (f.length < 26) { logger.warn("文件 {} 行字段不足 (<26):{}", fileName, line); continue; } SaleRecord r = new SaleRecord(); r.setStatistDate(f[0]); r.setTrainDate(f[1]); r.setBoardTrainCode(f[2]); r.setFromTeleCode(f[3]); r.setToTeleCode(f[4]); r.setFromStationName(f[5]); r.setToStationName(f[6]); r.setStartTime(f[7]); r.setCoachNo(f[8]); r.setSeatNo(f[9]); r.setSeatTypeCode(f[10]); r.setTicketType(f[11]); r.setTicketPrice(f[12]); r.setInnerCode(f[13]); r.setSaleTime(f[14]); r.setOfficeNo(f[15]); r.setWindowNo(f[16]); r.setOperaterNo(f[17]); r.setTicketNo(f[18]); r.setStatisticsDate(f[19]); r.setSequenceNo(f[20]); r.setStatisticsFlag(f[21]); r.setRelayTicketType(f[22]); r.setSaleMode(f[23]); r.setTicketState(f[24]); r.setAreaCenterCode(f[25]); r.setPk(HiveTableUtils.generatePrimaryKey( r.getStatisticsDate(), r.getOfficeNo(), r.getWindowNo(), r.getTicketNo())); logger.debug("解析成功 SaleRecord:ticketNo={}, pk={}, areaCode={}", r.getTicketNo(), r.getPk(), r.getAreaCenterCode()); out.collect(r); } catch (Exception ex) { logger.error("解析 SaleRecord 行失败,文件 {}:{}", fileName, raw, ex); } } } } // --------------------- 调试版本的 Sink 实现 --------------------- /** * 调试版本的 InfoAppendix Sink - 打印详细的SQL和错误信息 */ public static class DebugInfoAppendixSink extends RichSinkFunction<InfoAppendix> { private static final Logger logger = LogManager.getLogger(DebugInfoAppendixSink.class); private List<InfoAppendix> batch; private static final int BATCH_SIZE = 1; // 调试时设为1,逐条处理 private boolean useHive = false; private StreamTableEnvironment tableEnv; private String partitionValue; @Override public void open(Configuration parameters) throws Exception { super.open(parameters); batch = new ArrayList<>(); partitionValue = HiveTableUtils.generatePartitionValue(); // 检查是否启用Hive useHive = ConfigManager.isHiveSinkEnabled(); logger.info("=== DebugInfoAppendixSink 初始化开始 ==="); logger.info("useHive: {}", useHive); logger.info("partitionValue: {}", partitionValue); if (useHive) { try { logger.info("开始创建 TableEnvironment..."); // 为每个Sink创建独立的TableEnvironment StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); EnvironmentSettings settings = EnvironmentSettings.newInstance().inStreamingMode().build(); tableEnv = StreamTableEnvironment.create(env, settings); logger.info("TableEnvironment 创建成功"); // 配置Hive Catalog logger.info("开始配置 Hive Catalog..."); if (configureHiveCatalog()) { logger.info("InfoAppendix Sink Hive配置成功"); // 测试表连接 testTableConnection(); } else { logger.warn("InfoAppendix Sink Hive配置失败,使用日志模式"); useHive = false; } } catch (Exception e) { logger.error("InfoAppendix Sink 初始化失败,使用日志模式", e); useHive = false; } } logger.info("=== DebugInfoAppendixSink 初始化完成,Hive模式: {} ===", useHive); } private boolean configureHiveCatalog() { try { String hiveDatabaseName = ConfigManager.getHiveDatabaseName(); logger.info("Hive数据库名: {}", hiveDatabaseName); if (hiveDatabaseName == null || hiveDatabaseName.trim().isEmpty()) { logger.warn("Hive数据库名为空"); return false; } String hiveConfDir = System.getProperty("user.dir") + "/src/main/resources/"; logger.info("Hive配置目录: {}", hiveConfDir); java.io.File confDir = new java.io.File(hiveConfDir); if (!confDir.exists()) { logger.warn("Hive配置目录不存在: {}", hiveConfDir); return false; } String hiveCatalogSql = String.format( "CREATE CATALOG hive_catalog WITH (" + "'type' = 'hive', " + "'default-database' = '%s', " + "'hive-conf-dir' = '%s'" + ")", hiveDatabaseName, hiveConfDir ); logger.info("执行Hive Catalog创建SQL: {}", hiveCatalogSql); tableEnv.executeSql(hiveCatalogSql); logger.info("使用Catalog: hive_catalog"); tableEnv.useCatalog("hive_catalog"); logger.info("使用数据库: {}", hiveDatabaseName); tableEnv.useDatabase(hiveDatabaseName); return true; } catch (Exception e) { logger.error("配置Hive Catalog失败: ", e); return false; } } private void testTableConnection() { try { String tableName = ConfigManager.getInfoAppendixTableName(); logger.info("测试表连接,表名: {}", tableName); String testSql = "SELECT COUNT(*) FROM " + tableName + " LIMIT 1"; logger.info("执行测试SQL: {}", testSql); KerberosUtils.doAs(() -> { tableEnv.executeSql(testSql); return null; }); logger.info("表连接测试成功"); } catch (Exception e) { logger.error("表连接测试失败: ", e); throw new RuntimeException("表连接测试失败", e); } } @Override public void invoke(InfoAppendix value, Context ctx) { if (value == null) return; logger.info("=== 收到InfoAppendix数据 ==="); logger.info("ticketNo: {}, idName: {}, areaCode: {}, pk: {}", value.getTicketNo(), value.getIdName(), value.getAreaCenterCode(), value.getPk()); if (!useHive) { logger.info("Hive未启用,记录到日志: ticketNo={}, idName={}, areaCode={}", value.getTicketNo(), value.getIdName(), value.getAreaCenterCode()); return; } batch.add(value); if (batch.size() >= BATCH_SIZE) { processBatch(); } } @Override public void close() throws Exception { if (batch != null && !batch.isEmpty()) { processBatch(); } super.close(); } private void processBatch() { if (batch.isEmpty()) return; logger.info("=== 开始处理InfoAppendix批次,大小: {} ===", batch.size()); try { String tableName = ConfigManager.getInfoAppendixTableName(); logger.info("目标表名: {}", tableName); for (InfoAppendix info : batch) { try { String sql = String.format( "INSERT INTO %s PARTITION (sdate='%s') VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", tableName, partitionValue, escapeSqlValue(info.getStatistDate()), escapeSqlValue(info.getStatisticsDate()), escapeSqlValue(info.getInnerCode()), escapeSqlValue(info.getOfficeNo()), escapeSqlValue(info.getWindowNo()), escapeSqlValue(info.getTicketNo()), escapeSqlValue(info.getIdKind()), escapeSqlValue(info.getIdNo()), escapeSqlValue(info.getIdName()), escapeSqlValue(info.getAreaCenterCode()), escapeSqlValue(info.getPk()) ); logger.info("=== 执行SQL语句 ==="); logger.info("SQL: {}", sql); KerberosUtils.doAs(() -> { tableEnv.executeSql(sql); return null; }); logger.info("SQL执行成功: ticketNo={}", info.getTicketNo()); } catch (Exception e) { logger.error("=== SQL执行失败 ==="); logger.error("ticketNo: {}", info.getTicketNo()); logger.error("错误类型: {}", e.getClass().getSimpleName()); logger.error("错误消息: {}", e.getMessage()); logger.error("详细堆栈: ", e); // 回退到日志模式 logger.info("回退记录InfoAppendix数据: ticketNo={}, idName={}, areaCode={}", info.getTicketNo(), info.getIdName(), info.getAreaCenterCode()); } } logger.info("InfoAppendix批量处理完成,批次大小: {}", batch.size()); } catch (Exception e) { logger.error("InfoAppendix批量处理失败", e); // 全部回退到日志模式 for (InfoAppendix info : batch) { logger.info("回退记录InfoAppendix数据: ticketNo={}, idName={}, areaCode={}", info.getTicketNo(), info.getIdName(), info.getAreaCenterCode()); } } finally { batch.clear(); } } } /** * 调试版本的 SaleRecord Sink - 打印详细的SQL和错误信息 */ public static class DebugSaleRecordSink extends RichSinkFunction<SaleRecord> { private static final Logger logger = LogManager.getLogger(DebugSaleRecordSink.class); private List<SaleRecord> batch; private static final int BATCH_SIZE = 1; // 调试时设为1,逐条处理 private boolean useHive = false; private StreamTableEnvironment tableEnv; private String partitionValue; @Override public void open(Configuration parameters) throws Exception { super.open(parameters); batch = new ArrayList<>(); partitionValue = HiveTableUtils.generatePartitionValue(); // 检查是否启用Hive useHive = ConfigManager.isHiveSinkEnabled(); logger.info("=== DebugSaleRecordSink 初始化开始 ==="); logger.info("useHive: {}", useHive); logger.info("partitionValue: {}", partitionValue); if (useHive) { try { logger.info("开始创建 TableEnvironment..."); // 为每个Sink创建独立的TableEnvironment StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); EnvironmentSettings settings = EnvironmentSettings.newInstance().inStreamingMode().build(); tableEnv = StreamTableEnvironment.create(env, settings); logger.info("TableEnvironment 创建成功"); // 配置Hive Catalog logger.info("开始配置 Hive Catalog..."); if (configureHiveCatalog()) { logger.info("SaleRecord Sink Hive配置成功"); // 测试表连接 testTableConnection(); } else { logger.warn("SaleRecord Sink Hive配置失败,使用日志模式"); useHive = false; } } catch (Exception e) { logger.error("SaleRecord Sink 初始化失败,使用日志模式", e); useHive = false; } } logger.info("=== DebugSaleRecordSink 初始化完成,Hive模式: {} ===", useHive); } private boolean configureHiveCatalog() { try { String hiveDatabaseName = ConfigManager.getHiveDatabaseName(); logger.info("Hive数据库名: {}", hiveDatabaseName); if (hiveDatabaseName == null || hiveDatabaseName.trim().isEmpty()) { logger.warn("Hive数据库名为空"); return false; } String hiveConfDir = System.getProperty("user.dir") + "/src/main/resources/"; logger.info("Hive配置目录: {}", hiveConfDir); java.io.File confDir = new java.io.File(hiveConfDir); if (!confDir.exists()) { logger.warn("Hive配置目录不存在: {}", hiveConfDir); return false; } String hiveCatalogSql = String.format( "CREATE CATALOG hive_catalog WITH (" + "'type' = 'hive', " + "'default-database' = '%s', " + "'hive-conf-dir' = '%s'" + ")", hiveDatabaseName, hiveConfDir ); logger.info("执行Hive Catalog创建SQL: {}", hiveCatalogSql); tableEnv.executeSql(hiveCatalogSql); logger.info("使用Catalog: hive_catalog"); tableEnv.useCatalog("hive_catalog"); logger.info("使用数据库: {}", hiveDatabaseName); tableEnv.useDatabase(hiveDatabaseName); return true; } catch (Exception e) { logger.error("配置Hive Catalog失败: ", e); return false; } } private void testTableConnection() { try { String tableName = ConfigManager.getSaleRecordTableName(); logger.info("测试表连接,表名: {}", tableName); String testSql = "SELECT COUNT(*) FROM " + tableName + " LIMIT 1"; logger.info("执行测试SQL: {}", testSql); KerberosUtils.doAs(() -> { tableEnv.executeSql(testSql); return null; }); logger.info("表连接测试成功"); } catch (Exception e) { logger.error("表连接测试失败: ", e); throw new RuntimeException("表连接测试失败", e); } } @Override public void invoke(SaleRecord value, Context ctx) { if (value == null) return; logger.info("=== 收到SaleRecord数据 ==="); logger.info("ticketNo: {}, trainCode: {}, areaCode: {}, pk: {}", value.getTicketNo(), value.getBoardTrainCode(), value.getAreaCenterCode(), value.getPk()); if (!useHive) { logger.info("Hive未启用,记录到日志: ticketNo={}, trainCode={}, areaCode={}", value.getTicketNo(), value.getBoardTrainCode(), value.getAreaCenterCode()); return; } batch.add(value); if (batch.size() >= BATCH_SIZE) { processBatch(); } } @Override public void close() throws Exception { if (batch != null && !batch.isEmpty()) { processBatch(); } super.close(); } private void processBatch() { if (batch.isEmpty()) return; logger.info("=== 开始处理SaleRecord批次,大小: {} ===", batch.size()); try { String tableName = ConfigManager.getSaleRecordTableName(); logger.info("目标表名: {}", tableName); for (SaleRecord record : batch) { try { String sql = String.format( "INSERT INTO %s PARTITION (sdate='%s') VALUES " + "('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", tableName, partitionValue, escapeSqlValue(record.getStatistDate()), escapeSqlValue(record.getTrainDate()), escapeSqlValue(record.getBoardTrainCode()), escapeSqlValue(record.getFromTeleCode()), escapeSqlValue(record.getToTeleCode()), escapeSqlValue(record.getFromStationName()), escapeSqlValue(record.getToStationName()), escapeSqlValue(record.getStartTime()), escapeSqlValue(record.getCoachNo()), escapeSqlValue(record.getSeatNo()), escapeSqlValue(record.getSeatTypeCode()), escapeSqlValue(record.getTicketType()), escapeSqlValue(record.getTicketPrice()), escapeSqlValue(record.getInnerCode()), escapeSqlValue(record.getSaleTime()), escapeSqlValue(record.getOfficeNo()), escapeSqlValue(record.getWindowNo()), escapeSqlValue(record.getOperaterNo()), escapeSqlValue(record.getTicketNo()), escapeSqlValue(record.getStatisticsDate()), escapeSqlValue(record.getSequenceNo()), escapeSqlValue(record.getStatisticsFlag()), escapeSqlValue(record.getRelayTicketType()), escapeSqlValue(record.getSaleMode()), escapeSqlValue(record.getTicketState()), escapeSqlValue(record.getAreaCenterCode()), escapeSqlValue(record.getPk()) ); logger.info("=== 执行SQL语句 ==="); logger.info("SQL: {}", sql); KerberosUtils.doAs(() -> { tableEnv.executeSql(sql); return null; }); logger.info("SQL执行成功: ticketNo={}", record.getTicketNo()); } catch (Exception e) { logger.error("=== SQL执行失败 ==="); logger.error("ticketNo: {}", record.getTicketNo()); logger.error("错误类型: {}", e.getClass().getSimpleName()); logger.error("错误消息: {}", e.getMessage()); logger.error("详细堆栈: ", e); // 回退到日志模式 logger.info("回退记录SaleRecord数据: ticketNo={}, trainCode={}, areaCode={}", record.getTicketNo(), record.getBoardTrainCode(), record.getAreaCenterCode()); } } logger.info("SaleRecord批量处理完成,批次大小: {}", batch.size()); } catch (Exception e) { logger.error("SaleRecord批量处理失败", e); // 全部回退到日志模式 for (SaleRecord record : batch) { logger.info("回退记录SaleRecord数据: ticketNo={}, trainCode={}, areaCode={}", record.getTicketNo(), record.getBoardTrainCode(), record.getAreaCenterCode()); } } finally { batch.clear(); } } } /** * SQL值转义 */ private static String escapeSqlValue(String value) { if (value == null) { return ""; } return value.replace("'", "''"); } }这是我的代码
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值