请上传宽度大于 1200px,高度大于 164px 的封面图片
    调整图片尺寸与位置
    滚轮可以放大缩小图片尺寸,按住图片拖动可调整位置,多余的会自动被裁剪掉
取消
LarryYI(uid:233000)
分享常见解决方案,仅供个人参考使用! 职业资格认证:FCP-报表开发工程师
【帆软FR】窗口变化自适应-JS通用方案
一、场景汇总 tab切换、反复刷新等操作,导致frm的自适应异常,出现空白块. 浏览器缩放,报表块单元格出现多余边框线 浏览器窗口发生变化,由于自适应影响图表重新绘制,造成坐标轴显示顺序异常 二、解决方案 1、决策报表 https://pic2.zhimg.com/80/v2-0f414abb3f59f021bbe396030f20f136_720w.gif 参考js: //给表单body添加初始化js事件: $(window).resize(function() { var width = FR.windowWidth; var height = FR.windowHeight; var from = _g().getWidgetByName('form') if (form.oriWidth === width && form.oriHeight === height) { return; } form.oriWidth = width; form.oriHeight = height; form.loadContentPane(true); }); 2、普通报表 https://pic1.zhimg.com/80/v2-573f01474ddd150a60db55b4b754a010_720w.gif 参考js://分页预览添加加载结束事件: $(window).resize(function() { window.location.reload() }); //如果还有滚动条,可以加下面这句隐藏 /* setTimeout(function() { $('#content-container').css("overflow", "hidden"); }, 100)*/ 三. 额外场景补充 如果决策报表使用了上述js,同时写了报表块滚动的JS,则滚动JS会被上述JS所影响,导致滚动速度在缩放后越来越快,即使添加了清除定时器的语句也不行。解决方案为修改滚动JS,格式如下: setTimeout(function() { //隐藏报表块report0的滚动条(此报表块名为report0,根据具体情况修改) $("div").find(".frozen-north").style.overflow = "hidden"; $("div").find(".frozen-center").style.overflow = "hidden"; }, 200); window.flag = true; if (window.interval) { clearInterval(window.interval); } //鼠标悬停,滚动停止 setTimeout(function() { $("div").find(".frozen-center").mouseover(function() { window.flag = false; }); //鼠标离开,继续滚动 $("div").find(".frozen-center").mouseleave(function() { window.flag = true; }); var old = -1; if (window.interval) { clearInterval(window.interval); } window.interval = setInterval(function() { if (window.flag) { currentpos = $("div").find(".frozen-center").scrollTop; if (currentpos == old) { $("div").find(".frozen-center").scrollTop = 0; } else { old = currentpos; //以25ms的速度每次滚动1.5PX $("div").find(".frozen-center").scrollTop = currentpos + 1.5; } } }, 25); }, 1000); 编辑于 2021-7-5 22:44
nginx常见问题集锦
案例一:nginx转发后,报表访问正常但是访问平台失败 现象:访问模板正常,访问平台失败 https://pic1.zhimg.com/80/v2-7eb0eab28aeaa0cfc65fc4f4cd95a9e3_720w.png 原因:nginx.conf默认是用的是http1.0,tcp连接生命周期不够,导致一些耗时较长的图表请求超时。http1.1才支持长连接 ,不配置的话默认走了http1.0; 解决方案:给nginx.conf文件的配置: proxy_http_version 1.1; proxy_set_header Connection "; https://pic4.zhimg.com/80/v2-128ee50f3e90f454c4566a4ea9689208_720w.png 案例二:502 Bad GateWay 现象:访问模板或平台会报错502 Bad GateWay https://pic1.zhimg.com/80/v2-2f0dd24d9d832d2928558849e57c0fed_720w.png 原因:502 Bad Gateway这个是错误网关,无效网关。查看nginx相关设置,做了nginx的反向代理,原因是header过大,超出了默认的1k,就会引发上述的upstream sent too big header。(说白了就是nginx把外部请求给后端处理,后端返回的header太大,nginx处理不过来就会导致502。) 解决方案: 设置参数: proxy_buffer_size、proxy_buffers、proxy_busy_buffers_size 如: server { listen 80; server_name *.lxy.me; location / { ###############添加这3行 proxy_buffer_size 64k; proxy_buffers 256 32k; proxy_busy_buffers_size 128k;} 详细说明: (1)proxy_buffer_size 作用:Nginx使用该大小申请read_buf,即大小指定了 upstream header 最大长度,如果响应头超过了这个长度,Nginx会报upstream sent too big header错误,然后client收到的是502。 (2)proxy_buffers 作用:设置存储被代理服务器响应的body所占用的buffer个数和每个buffer大小。当前buf不够存响应body时才会新申请一个,最多申请256个buf。 (3)proxy_busy_buffers_size 作用:用来设置处于busy状态的buffer有多大。proxy_busy_buffers_size不是独立的空间,他是proxy_buffers和proxy_buffer_size的一部分。nginx会在没有完全读完后端响应就开始向客户端 传送数据,所以它会划出一部分busy状态的buffer来专门向客户端传送数据(建议为proxy_buffers中单个缓冲区的2倍),然后它继续从后端取数据。如果完整数据大小小于busy_buffer大小,当数据传输完成后,马上传给客户端;如果完整数据大小不小于busy_buffer大小,则装满busy_buffer后,马上传给客户端。 详细可见:https://www.cnblogs.com/wshenjin/p/11608744.html 案例三:504 Gateway Time-out 现象:做了nginx转发,数据比较多的报表导不到本地,显示导出准备,完成后本地没有报表,F12查看有504报错 https://pic1.zhimg.com/80/v2-eaffeea35f5dbc395e9d5ef67844f6b3_720w.png 原因:网页请求超时,也就是浏览网站网页所发出的请求没有反应或者未响应。nginx.conf或者php-fpm.conf设置不合理。 解决方案:根据服务器性能状况及网络流量情况,对nginx.conf中的下列字句进行设置: fastcgi_connect_timeout300s; fastcgi_send_timeout300s; fastcgi_read_timeout300s; fastcgi_buffer_size128k; fastcgi_buffers8128k; #8128fastcgi_busy_buffers_size256k; fastcgi_temp_file_write_size256k; fastcgi_intercept_errorson; 这些字句的设置规定了PHP-CGI的连接、发送和读取时间限制,需根据服务器性能及网络流量综合考虑设置。 【注】时间设置过长会给网站服务器造成压力,导致网站响应缓慢,甚至服务器宕机;时间设置过短,则就会出现504 Gateway Time-out或者其他CGI无响应错误。 【小结】 报错504 Gateway Time-out,一般有以下两种: 1)nginx默认的fastcgi进程响应缓冲区太小,fastcgi进程被挂起 默认的fastcgi进程响应的缓冲区是8K,设置大一点,在nginx.conf里,加入:fastcgi_buffers 8 128k(设置fastcgi缓冲区为8块128k大小的空间) 若还是出现问题,继续修改nginx的超时参数,将参数调大一点,如设置为60秒: send_timeout 60 2)PHP环境的配置问题 根据PHP程序情况及服务器带宽状况 设置 max_children 与 request_terminate_timeout 两个重要参数,注意: request_terminate_timeou设置在900s左右使php-cgi进程处理脚本的超时时间提高到900秒,防止进程被挂起以提高利用效率) max_children值根据服务器内存大小和CGI请求数目设置为合理的数值,一般设置为800M左右(保证有充足的php-cgi进程可以被使用) 修改完后都需重新加载配置,具体修改可参照:https://jingyan.baidu.com/article/2c8c281d9680760008252a8a.html 案例四:远程设计,大模板无法保存 现象:不是所有模板都无法报存,而是特别卡的模板无法保存,因此直接判断是因为模板比较大在传输时无法保存。后来检查了nginx的日志,找到了:client intended to send too large chunked body: 1048576+4096 bytes, client: 10.210.45.237, server: localhost, request: "POST /webroot/decision/remote/design/channel HTTP/1.1", host: "10.61.3.181:8090" 原因:从报错看出因为文件太了保存时被nginx拦截了 解决方案:在nginx的http里加了这行client_max_body_size 100M; 案例五:使用nginx转发之后的链接访问首页空白 现象:使用nginx端口访问tomcat,现象,首页空白,前端报错,net::ERR_INCOMPLETE_CHUNKED_ENCODING https://pic1.zhimg.com/80/v2-55ef161fe7f7c8d8b6b853e13dd9de8c_720w.png 原因:百度报错,和temp缓存文件的权限有关系。 解决方案:使用root启动的nginx,最后在nginx.conf中将第一行的 user root; 注释去掉,前端不出现报错了,首页也正常了。 案例六:使用nginx转发之后,图表加载不出来 现象:使用nginx转发之后,图表加载不出来 https://pic4.zhimg.com/80/v2-4d32d6c014331fdfbf51b3628fcde425_720w.png 原因:负载均衡策略选错了 解决方案:upstream FR .com { }中添加了ip_hasp;解决了图表加载不出来的问题。 案例七:nginx转发端口丢失,导致平台访问不到 现象:访问不了平台 https://pic4.zhimg.com/80/v2-d48068c318838e2dfad9eb5d2e96798a_720w.png 原因:nginx配置有问题,导致转发端口丢失 解决方案:在nginx的配置中,location中加上这个参数:proxy_set_header Host $host:$server_port 即可。 案例八:nginx反向代理导致微信集成移动端无法访问 现象:微信集成移动端访问不到页面,报错The plain HTTP request was sent to HTTPS port 原因:https被读取成了http 解决:在nginx反向代理里加入重定向,在server下的端口监控下给配置文件nginx.conf添加语句proxy_redirect http:// https://;给配置文件nginx.conf添加语句(示例如下):proxy_redirect http://12.99.215.240:9080/ https://moboatest.nbcb.com.cn:11180/; 参考:https://blog.csdn.net/u010391029/article/details/50395680 注:添加语句后需重启nginx才能生效 案例九:nginx配置短域名后serverName参数获取不到域名 现象:使用了nginx,导致在报表里面使用serverName参数获取不到域名,获取到的是nginx配置的短域名 解决:可以使用js获取域名,location.host,参考:通过JS获取当前页面URL网址信息-https://help.fanruan.com/finereport/doc-view-2175.html 案例十:配置反响代理,直接通过域名访问登录不了工程 环境: 1)做了tomcat下访问ip直接进入op=fs界面的设置,这个参考文档http://help.finereport.com/doc-view-806.html; 2)做了域名设置; 3) Nginx反向代理设置,参考文档http://help.finereport.com/doc-view-2438.html https://pic3.zhimg.com/80/v2-e91011c5789611a5bb29d8192d10e8ac_720w.png https://pic1.zhimg.com/80/v2-32f9371f64b56c706979752abe01a467_720w.png 现象: 不做Nginx反向代理设置,可以直接访问http://bi.doitfintech.com:8080进入报表系统; 加了Nginx反向代理设置,无法进入报表系统了; 报错: 113.108.10.16 - - "GET /ReportServer?op=fs HTTP/1.0" "-"302 0 "https://bi.doitfintech.com/" "Wget/1.10.2" "-" 49.76.206.253 - - "GET / HTTP/1.1" "-"200 323 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" "-" 49.76.206.253 - - "GET /ReportServer?op=fs HTTP/1.1" "-"302 0 "https://bi.doitfintech.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" "-" 49.76.206.253 - - "GET /favicon.ico HTTP/1.1" "-"404 1016 "https://bi.doitfintech.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" "-" 原因:设置1中做的tomcat下访问ip直接进入op=fs界面的设置,其中需要写一个a.jsp,就是解决从根路径直接访问项目的,这个jsp做了一个302的重定向,但是nginx这边不管处理或者不处理都不能获取这个302的资源。 解决方案:把a.jsp干掉,让nginx来处理302重定向就可以 编辑于 2021-6-24 15:29
【FR与单点登录】单点登录失败排查
一、单点原理 登录状态是指请求中携带了token,这个token可能在请求头Authorization中 https://pic1.zhimg.com/80/v2-3bd3f27b431c14b93ae0fd40b4da1d2d_720w.png 也可能在cookie中 https://pic4.zhimg.com/80/v2-9cf7dddf67c73dacba962af6a12debf2_720w.png 所以完成单点登录只需要想办法让浏览器在请求自己工程的时候带上token就好了,而对于单点请求,一般都是将token(fine_auth_token)放在cookie中的,也有放在session中的,两者的区别可以自行百度。 常见的单点方式分为两种: 1)前台单点接口:http://localhost:8080/webroot/decision/login/cross/domain?fine_username=XX&fine_password=XX&validity=-2&callback= 2)后台单点接口:com.fr.decision.webservice.v10.login.LoginService#login(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String) 二、排查步骤说明 1、首先确认是否单点成功 前台单点:直接访问前台单点请求看是否成功 https://pic1.zhimg.com/80/v2-953d11eee7bc8098d17a6f4cbb177d09_720w.png 后台单点:看请求中是否有Set-Cookie,如果有一般都是正常的 https://pic1.zhimg.com/80/v2-fda3c1a696160029a1024e08b314ce72_720w.png 如果前台单点或后台单点请求都正常,但是依然单点有问题,可能是环境存在问题 2、浏览器问题 如何判断是不是浏览器的问题呢?换个浏览器(内核不同)测试下单点效果,如果换个浏览器单点可以了,说明是浏览器的问题。 注:测试单点的时候,最好是清除缓存后再进行操作,避免缓存影响导致判断出现错误。 举例:新版谷歌有samsite的问题,且新版的edge也用了谷歌内核 补充一下,如何判断cookie是否为httponly呢?一般登录成功后就会将登录信息存入cookie,这时打开浏览器的控制器就能看到,如图。 https://pic1.zhimg.com/80/v2-dd146a920da5a5a8b1aa3b9bb88c1b66_720w.png 直接强制从cookie中读取所有token,在finedb的fine_conf_entity表中添加字段FSConfig.loginConfig.tokenFromCookie 或 ServerConfig.tokenFromCookie(具体见下图对应jar包时间),值设置为true,重启工程即可。 不同jar包版本(2021年为例)的操作方案: https://pic4.zhimg.com/80/v2-963e7f12db120564f22b4c5016c83d4b_720w.png 3、工程设置 a)安全防护 1)如果使用跨域 iframe 的方式嵌入报表,出现无法访问的情况,请关闭 Security Headers 高级设置中的「点击劫持攻击防护」按钮。 2)单点登录时若报跨域的问题,请关闭 Security Headers 高级设置中的「内容嗅探攻击防护」按钮。 b)用户异常 1)平台用户被禁用如果平台用户被禁用了,会导致前台单点不能正常登录,但后台单点不受影响。 2)用户名密码错误这个问题多见于OA集成,即系统用户名需与平台用户名保持一致,且平台用户要处于正常状态(能登录,未被禁用),出问题时可以在代码中加些调试,把结果alert出来,便于判断) 注:如果用户被禁用,只会影响前台单点不能正常登录,后台单点是不受影响的,只要数据库里有这个用户,后台照样能单点成功。 补充:如果说单点登陆的是用户A,实际显示的是用户B之类的问题,这个时候就可以拿到用户的token(获取方法见原理部分),去https://jwt.io/这个网站解析一下,就可以看到token里的用户信息,来确认说的是不是对的。 https://pic1.zhimg.com/80/v2-9875cb38082b8492a1b3ede8ebdf85cd_720w.png c) 9.0 session过期 1)现象:访问一段时间出现单点登录页面 2)处理思路: 1.区分概念:报表session与应用session报表session存放的是访问报表的相关信息,如访问的是不是同一个模板等,应用的session存放的是request请求等一些共享信息,两者是完全独立,不是一个概念 2.出现单点登录页面,说明应用登录session失效(或者理解为过期),9.0是根据tomcat的session超时判断的(未开启心跳场景下) 知识点:报表开启心跳设置,访问报表和fs平台时会一直触发请求,从而一直更新tomcat session时间,session永不超时 https://pic1.zhimg.com/80/v2-71a62580eed30181e84777f8cbe5b842_720w.png 3.回到用户场景,用户在登录自己系统时同步单点到fr,再未访问报表场景下,单点会在30min失效,因此需要调整tomcat 超时时间设置tomcat session 超时设置方式: 在conf/web.xml中 30 这里是以分钟为单位的,默认是30min,按照用户需求,可以将这边修改大一些,比如12H;注:10.0已设置seesion超时时长30min 4、代码问题 在排除了上述问题之后,我们可能就需要去检查一下代码了。 a)前台单点以ajax跨域单点为例,http://localhost:8080/webroot/decision/login/cross/domain?fine_username=XX&fine_password=XX&validity=-2&callback= 首先需要去检查地址有没有误,包括: https错写成http,反之亦然 工程名webroot未修改成实际的工程名 网络不通(请求被拦截、ip、端口写错,决策平台安全限制等等) 可以直接在浏览器访问单点地址,看下返回值,确认下有没有问题。 b)后台单点 以cas单点为例,一般可能出问题的是web.xml,因为需要修改成实际的地址,对照着文档一步步检查设置就行。 1)cas集群 因为集群状态下session无法保持,如果在集群环境下使用了单机的cas 方案,可能会导致单点失败。 原因:前端携带的sessionid会因为集群负载均衡的原因一直变动,比如client1 向会话中写入user信息,表明单点成功,这个时候的sessionid假设为sessionId1,但是下个请求可能会请求到client2,这个时候client2根据sessionid1拿不到session,他就会生成一个新的session,同时将你的sessionId变为sessionId2,然后下个请求可能又到client1,就这样一直循环... 方案:https://help.fanruan.com/finereport/doc-view-2867.html 在自己并不清楚的情况下,如何快速判断当前使用的cas集群方案或是单机方案呢? 可以根据登录之后的cookie中是否存在cas_login_ticket来判断,存在则说明是集群下的cas方案,否则是单机。 https://pic1.zhimg.com/80/v2-fda3c1a696160029a1024e08b314ce72_720w.png 2)cas登出cas server会发出一个下线请求,工程中cas相关的filter会拦截判断是不是登出请求,是的话则与sessionlistener 配合清除会话中的token相关信息,对于用本地生成的证书和域名,jdk是无法解析和信任的,所以请求无法发出,需要将客户端的的证书导入服务器使用的jdk。 5、特殊情况 还有一些不太常规的单点失败的问题,比如特殊的环境等等,如: 1)oa登录页跳转过快导致单点请求取消 现象:用户在自己的OA系统的登录的同时调用单点登录请求,然后页面跳转到用户OA的主页(也可能是其他页面,涉及到到页面跳转),再去访问平台发现还是会跳转到登录页。 原因:请求都是异步的,在执行单点的同时进行OA的登录操作然后跳转页面,有些浏览器会中断全部的请求导致无法写cookie。 方案:在单点登录这个请求结束之后再执行OA系统的登录操作 2)工程间session冲突 几个工程用的同一个域名,而在同一个tomcat下部署的工程 sessionid 和path默认都是一样的,所以如果同时出现写操作,工程间会出现覆盖的现象:即同一个Tomcat启动的放在webapps目录下且使用默认配置的两个工程,A操作会话可能会影响B工程,通过虚拟目录的方式单独设置下cookieSessionPath,使两个工程的session独立即可。 https://pic1.zhimg.com/80/v2-b951af884dcced37dbd93fe2f652e767_720w.png 编辑于 2021-6-23 14:54
【FR与Tomcat】Tomcat启动慢排查
一、问题描述 (1)问题现象:tomcat启动比较慢。 (2)简单说明:tomcat的启动慢一般都是跟工程大小以及工程里面jar大小有关系,目前lib里面的jar越大,启动速度越慢。 二、排查步骤说明 2.1确认问题 确认是tomcat问题还是FR工程问题(详细排查过程见2.2),在确认之前,可以进行tomcat和工程的瘦身。瘦身步骤:删去tomcat的log日志和工程里面的以下文件: logs:工程日志 webroot/logs:埋点文件 webroot/cubes:埋点文件 webroot/WEB-INF/assets/temp_attach:缓存 webroot/WEB-INF/assist/clouds:云端运维数据包临时存放目录 webroot/WEB-INF/schedule:定时调度结果文件 webroot/WEB-INF/treasures:云端运维数据包文件 通过上面的瘦身工作,如果没有解决,就分开启动排查是否具体由哪个导致。 2.2日志检查 通过刚才的瘦身,如果没有解决问题,新出来的日志一般可能有关键信息,可以对日志进行分析,通过对日志等级和日志里面关键词的检查进行排查,根据关键词。常见的有JDK内存、本身JDK的版本、JVM参数。 2.3数据库性能检查 2.3.1 finedb太大导致启动慢客户那边数据库的性能也会有这方面影响,可以用小工具检查是否数据库稳定,如果finedb太大,可以帮助客户迁移外接数据库。 2.3.2 外置数据库导致启动慢外置数据库驱动不匹配时也可能影响工程启动速度,可以和客户确认外置数据库类型版本与之使用的驱动版本是否匹配。 2.4打堆栈 如果上面的方法都没有用,就需要打堆栈,通过详细的堆栈分析,查找相应的对应原因,比较典型的堆栈分析可以参考4.1 三、详细排查 3.1 确认问题 首先先确认是否是启动慢还是启动失败的问题的问题,这个时候可以从日志入手,因为从前端是看不出来的。在日志里看一下启动的日志,找一下启动结束的标识日志,发现找不到。那说明启动慢或者说启动卡住了。 https://pic4.zhimg.com/80/v2-8d89f7add30271203d8d04e0362ab043_720w.png 出现上面信息,就说明是启动完成,不属于启动失败的问题 3.2 检查tomcat 测试是否是工程问题导致的还是tomcat本身问题,可以将工程移开然后进行测试看时间是多少,如果时间特别长,可以确认是tomcat的问题,针对tomcat问题,一般问题集中在于一下几个方面: (1)域名解析导致的,一般都是检查/etc/hosts文件中没有ipv4和ipv6地址映射,这种一般是加上相关映射即可。详细看案例分析一 (2)tomcat的JVM内存导致的,有一种是xms和xmx设置的一样大导致了启动比较慢,一般可以设置xmx四分之一,调整以后重启,即可解决。 (3)tomcat本身的logs文件大小,一般把这部分删掉然后重启就可以解决 (4)https://blog.csdn.net/njchenyi/article/details/46641141 相关案例,随机数导致的tomcat启动慢和卡住,具体分析可以看该文章,一般都是添加JVM参数就可以解决。-Djava.security.egd=file:/dev/urandom (5)JDK问题,如果是openJDk可以通过更换成oracle JDK尝试解决。 3.3检查工程问题 通过刚才测试,如果是工程本身的问题,一般有以下几个方面 (1)finedb太大,导致的工程启动慢,一般需要迁移数据库。迁移的数据库的性能也会影响到tomcat启动慢的现象 (2)检查tomcat日志本身,看是否有明显报错。根据报错查找原因,顺便检查其日志本身的等级,如果是debug可以调整成error,并且去日志文件夹检查日志的大小,看是否因为日志本身导致的卡顿,如果太大可以备份删去。 (3)查看performance、logdb、logdbcopy文件夹,有的时候文件过大对启动以及报表预览等都会有影响,如果太大,可以直接备份删去。 (4)通过这些测试,删去以后还是速度慢的话,就可以打堆栈进行处理检查了。使用 /usr/java/jdk1.7.0_79/bin/ cd到java的bin目录下,如果不知道java路径,可使用java -verbose 查看路径使用jstack打堆栈,jstack -l $pid > /home/bjev/1.txt 输出1.txt的路径要为为可读可写的目录。 四、典型案例 4.1 线程分析-地址解析导致 1、通过打堆栈分析线程:查看对应堆栈当中,大量线程解析本地地址的线程,一直没有释放。 https://pic1.zhimg.com/80/v2-1905b4ba120a6590fb60650078a10be6_720w.png 一旦看到上面这种大量繁忙线程,并且有inet6Address字眼基本上就是/etc/hosts需要配置本地域名解析。具体操作方法: linux:生产环境 执行hostname获取主机名. https://pic1.zhimg.com/80/v2-cb6b00d5c2c3d15e9325397d4cf26e52_720w.png 检查/etc/hosts文件中是否有ipv4和ipv6地址映射 https://pic4.zhimg.com/80/v2-cb6b00d5c2c3d15e9325397d4cf26e52_720w.png 发现没有hostname;ipv4和ipv6的都加上查出来的主机名,改完了之后 ping一下这个主机名, 能通说明改好了;重启一下工程服务,访问速度就正常了。 window环境: 1、首先找到host文件:C:\Windows\System32\drivers\etc然后cmd运行hostname https://pic4.zhimg.com/80/v2-23c66d639ac14b14bc2ba8d19fd846ec_720w.png 2、打开host文件:加入主机名即可 https://pic1.zhimg.com/80/v2-1eb7d052da269a3ec4750263d500a58b_720w.png 路径一般都是上图路径,具体设置跟linux一样 4.2堆栈分析-取数导致 根据上述方法打完堆栈以后可以上传该网站进行分析:https://fastthread.io/ 可以先关注线程堵塞,看是否有堵塞线程,一般堵塞线程伴随着cpu内存低,点开堵塞线程,下面的线程是因为报表关闭的时候,等待取数导致的,通过抓取关键词判断堵塞的基本信息 "pool-56-thread-10" #669 prio=5 os_prio=0 tid=0x00007fa7f4005800 nid=0x3ab2c waiting for monitor entry java.lang.Thread.State: BLOCKED (on object monitor)at com.fr.web.core.ReportSessionIDInfor.clearPageSet(Unknown Source) - waiting to lock (a com.fr.web.core.ReportSessionIDInfor)at com.fr.web.core.TemplateSessionIDInfo.release(Unknown Source) at com.fr.web.core.ReportSessionIDInfor.release(Unknown Source) at com.fr.web.core.SessionPoolManager.processCloseSession(Unknown Source)at com.fr.web.core.SessionPoolManager.access$200(Unknown Source) at com.fr.web.core.SessionPoolManager$5.run(Unknown Source)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748) 4.3 两种繁忙线程导致的卡顿 4.3.1 线程分析-取数导致取数线程等待数据库返回数据,线程没事做,cpu利用率很低。这个线程状态是Runnable的,从socket缓存区读取数据。主要的特征就是依赖了外部api DruidPooledStatement.executeQuery,如果这种线程比较多,就是取数太慢,可以查看数据库 是否正常。这种一般cup会比较低 "pool-43-thread-1893" #4977 prio=5 os_prio=0 tid=0x00007f624950e000 nid=0x130b7 runnable java.lang.Thread.State: RUNNABLEat java.net.SocketInputStream.socketRead0(Native Method)at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)at java.net.SocketInputStream.read(SocketInputStream.java:171)at java.net.SocketInputStream.read(SocketInputStream.java:141)at com.sap.db.rte.comm.BasicSocketComm.receiveData(BasicSocketComm.java:494)at com.sap.db.rte.comm.BasicSocketComm.receive(BasicSocketComm.java:582)at com.sap.db.rte.comm.JdbcCommunication.execute(JdbcCommunication.java:116)at com.sap.db.jdbc.ConnectionSapDB.execute(ConnectionSapDB.java:867)at com.sap.db.jdbc.ConnectionSapDB.execute(ConnectionSapDB.java:820)at com.sap.db.jdbc.StatementSapDB.sendCommand(StatementSapDB.java:898)at com.sap.db.jdbc.StatementSapDB.sendSQL(StatementSapDB.java:947)at com.sap.db.jdbc.StatementSapDB.execute(StatementSapDB.java:256)at com.sap.db.jdbc.StatementSapDB.executeQuery(StatementSapDB.java:399)at com.sap.db.jdbc.trace.Statement.executeQuery(Statement.java:184)at com.fr.third.alibaba.druid.pool.DruidPooledStatement.executeQuery(DruidPooledStatement.java:140)at com.fr.data.core.db.dialect.base.key.create.executequery.DialectExecuteQueryKey.execute(Unknown Source)at com.fr.data.core.db.dialect.base.key.create.executequery.DialectExecuteQueryKey.execute(Unknown Source)at com.fr.data.core.db.dialect.AbstractDialect.execute(Unknown Source)at com.fr.data.core.db.dialect.DefaultDialect.executeQuery(Unknown Source)at com.fr.data.impl.AbstractDBDataModel$1.call(Unknown Source)at com.fr.data.impl.AbstractDBDataModel$1.call(Unknown Source)at java.util.concurrent.FutureTask.run(FutureTask.java:266)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745) 4.3.2 线程分析-非IO导致的问题 还有一种就是不涉及IO操作(数据库访问和redis访问都可以认为是IO操作,IO操作会导致cpu空闲)的繁忙线程导致卡顿,下面也有案例分析,下满这个便是该线程一直在scanAttributeValue,导致的卡顿,也是抓关键词查找具体内容分析卡顿因素 "Timer-7" #109 daemon prio=5 os_prio=0 tid=0x00007f8d7cba1000 nid=0x13b4 runnable java.lang.Thread.State: RUNNABLEat com.fr.third.javax.xml.stream.XMLScanner.scanAttributeValue(XMLScanner.java:548)at com.fr.third.javax.xml.stream.XMLNSDocumentScannerImpl.scanAttribute(XMLNSDocumentScannerImpl.java:499)at com.fr.third.javax.xml.stream.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:298)at com.fr.third.javax.xml.stream.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:1121)at com.fr.third.javax.xml.stream.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:133)at com.fr.third.javax.xml.stream.XMLReaderImpl.next(XMLReaderImpl.java:358)at com.fr.third.javax.xml.stream.XMLEventReaderImpl.nextEvent(XMLEventReaderImpl.java:56)at com.fr.stable.xml.XMLableReader.readXMLObject(Unknown Source) 对你有帮助的话,可以点赞+关注+收藏,更多知识分享持续更新~ 编辑于 2021-6-22 14:15
【帆软FR】父模板和子模板传值
一、描述 应用场景:超链接传参是一个重要的功能场景,其中一个应用就是想要填出的子模板对话框,填写值之后关闭对话框给父模板赋值。 二、示例 2.1 子模板参数面板控件给父模板的参数面板赋值 给子模板的按钮添加点击事件: https://pic2.zhimg.com/80/v2-cdbe5ae968852226525243482370f157_720w.png var bm = this.options.form.getWidgetByName("area").getValue(); alert(bm);var form = window.parent._g().parameterEl; //拿取当前页面的父窗口(即获取参数面板界面) //给父页面写值 form.getWidgetByName("text").setValue(bm); window.parent.FR.closeDialog(); //确定获取值后,关闭取消父窗口的对话框 window.parent.FR.destroyDialog(); 2.2子模板参数面板控件给父模板的单元格赋值 给子模板的按钮添加点击事件: https://pic1.zhimg.com/80/v2-688ec44b1d7a7ddaf7235076596dae91_720w.png var form = window.parent.contentPane; var bm = this.options.form.getWidgetByName("area").getValue();//拿取当前页面的父窗口(即获取填报界面) form.setCellValue(0,0,bm); window.parent.FR.closeDialog(); //确定获取值后,关闭取消父窗口的对话框 window.parent.FR.destroyDialog(); 2.3子模板单元格控件给父模板的参数面板控件赋值 给子模板的单元格按钮添加点击事件: https://pic4.zhimg.com/80/v2-cb65fd7a80c933cffff41d2e8ac107fe_720w.png var bm = _g().parameterEl.getWidgetByName("area").getValue(); alert(bm); var form = window.parent._g().parameterEl; //拿取当前页面的父窗口(即获取参数面板界面) //给父页面写值 form.getWidgetByName("text").setValue(bm); window.parent.FR.closeDialog(); //确定获取值后,关闭取消父窗口的对话框 window.parent.FR.destroyDialog(); 三、 效果查看 3.1子模板参数面板控件给父模板的参数面板赋值 https://pic1.zhimg.com/80/v2-5d6378b535520f8f77e76e60ea143f04_720w.gif 3.2子模板参数面板控件给父模板的单元格赋值 https://pic2.zhimg.com/80/v2-e71819ac671f8629ba82cf9aeac129db_720w.gif 3.3子模板单元格控件给父模板的参数面板控件赋值 https://pic4.zhimg.com/80/v2-954b98c0cb78500f0bc505b87cb6aad6_720w.gif 对你有帮助的话,可以点赞+关注+收藏,更多知识分享持续更新~ 编辑于 2021-6-21 14:20
【帆软FR】JS实现网页框之间联动
一、描述场景:网页框嵌入子页面,想要多个子页面之间相互传参实现联动的效果;场景1:子页面1点击下拉框能够联动到子页面2里面筛选过滤数据,实现实时查询的效果;场景2:子页面1点击单元格实现传参到子页面2效果。二、示例2.1 网页框子页面控件联动思路:先获取子页面1控件的值,然后传递给当前父页面(即网页框1),然后再传参给子页面2,实现传参联动的效果,具体JS如下:ar aa=contentPane.getWidgetByName("ID");var ID=aa.getValue();//alert(ID)var iframe = window.parent._g().getWidgetByName('rHIframe1');iframe.setValue("${servletURL}?viewlet=表2.cpt&op=write&ID="+ID);注意:以前旧的jar可能存在使用如下语法去获取父页面元素的方法parent.document.getElementById('RHIFRAME1');//获取父网页框表2的ID,2021.4.26之后的jar这里的ID就是随机生成的数字,就无法获取到元素,只能使用获取组件名字方式去获取网页框。2.2 网页框子模板超链联动思路:直接在JavaScript脚本里面获取单元格值,然后获取父页面网页框去赋值给子页面2联动。//var parent = window.parent;//var iframe = parent.document.getElementById('RHIFRAME1');var iframe = window.parent._g().getWidgetByName('rHIframe1');iframe.setValue("${servletURL}?viewlet=表2.cpt&ID="+ID);三、效果查看PC端效果如下:注:移动端不支持对你有帮助的话,可以点赞+关注+收藏,更多知识分享持续更新~附件模版.zip (5.87 K) 编辑于 2021-9-19 22:31
【帆软FR】鼠标点击、悬浮炫彩效果
一、描述 1.1 应用场景:想要页面随意点击的时候页面能够弹出炫彩的字体,并且希望鼠标悬浮的时候背景能够动态变化,大屏展示的时候效果炫酷。 1.2 功能介绍:鼠标点击炫彩效果是无论是cpt还是frm模板,页面展示的时候鼠标任意点击不仅不影响页面功能使用,还能够弹出炫彩的字体;鼠标悬浮炫彩效果多应用于大屏动态背景的效果,当鼠标不悬浮在屏幕上面的时候背景是动态变化的,鼠标悬浮在页面上时有汇聚的效果,通过演示这个模板,能够熟练掌握这一系列的相关需求。 二、示例 2.1 鼠标点击炫彩字体提示效果1、在模板web属性添加加载结束事件,如下代码:代码解释:a数组里面存储的是每次点击循环展示的内容,css里面写的是一些样式设置。var a_idx = 0; jQuery(document).ready(function ($) { $("body").click(function (e) { console.log("xxxxxx") var a = new Array("❤富强❤", "❤民主❤", "❤文明❤", "❤和谐❤", "❤自由❤", "❤平等❤", "❤公正❤", "❤法治❤", "❤爱国❤", "❤敬业❤", "❤诚信❤", "❤友善❤"); var $i = $("").text(a); a_idx = (a_idx + 1) % a.length; var x = e.pageX, y = e.pageY; $i.css({ "z-index": 999999999999999999999999999999999999999999999999999999999999999999999, "top": y - 20, "left": x, "position": "absolute", "font-weight": "bold", "color": "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")" //Math.random()返回介于 0(包含) ~ 1(不包含) 之间的一个随机数 }); $("body").append($i); $i.animate({ "top": y - 180, "opacity": 0 }, 1500, function () { $i.remove(); }); }); });2.2 动态背景、鼠标悬浮粒子汇聚效果1、在模板web属性添加加载结束事件,如下代码:代码解释:主要是看return里面返回的信息是悬浮背景粒子的透明度、颜色以及粒子的个数设置。function() { function o(w, v, i) { return w.getAttribute(v) || i } function j(i) { return document.getElementsByTagName(i) } function l() { var i = j("script"), w = i.length, v = i; return { l: w, z: o(v, "zIndex", 0), o: o(v, "opacity", 0.8),//粒子的透明度 c: o(v, "color", "13,100,273"),//粒子的颜色设置 n: o(v, "count", 300)//粒子的个数 } } function k() { r = u.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, n = u.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight } function b() { e.clearRect(0, 0, r, n); var w = .concat(t); var x, v, A, B, z, y; t.forEach(function(i) { i.x += i.xa, i.y += i.ya, i.xa *= i.x > r || i.x < 0 ? -1 : 1, i.ya *= i.y > n || i.y < 0 ? -1 : 1, e.fillRect(i.x - 0.5, i.y - 0.5, 1, 1); for (v = 0; v < w.length; v++) { x = w; if (i !== x && null !== x.x && null !== x.y) { B = i.x - x.x, z = i.y - x.y, y = B * B + z * z; y = x.max / 2 && (i.x -= 0.03 * B, i.y -= 0.03 * z), A = (x.max - y) / x.max, e.beginPath(), e.lineWidth = A / 2, e.strokeStyle = "rgba(" + s.c + "," + (A + 0.2) + ")", e.moveTo(i.x, i.y), e.lineTo(x.x, x.y), e.stroke()) } } w.splice(w.indexOf(i), 1) }), m(b) } var u = document.createElement("canvas"), s = l(), c = "c_n" + s.l, e = u.getContext("2d"), r, n, m = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(i) { window.setTimeout(i, 1000 / 45) }, a = Math.random, f = { x: null, y: null, max: 20000 }; u.id = c; u.style.cssText = "position:fixed;top:0;left:0;z-index:" + s.z + ";opacity:" + s.o; j("body").appendChild(u); k(), window.onresize = k; window.onmousemove = function(i) { i = i || window.event, f.x = i.clientX, f.y = i.clientY }, window.onmouseout = function() { f.x = null, f.y = null }; for (var t = , p = 0; s.n > p; p++) { var h = a() * r, g = a() * n, q = 2 * a() - 1, d = 2 * a() - 1; t.push({ x: h, y: g, xa: q, ya: d, max: 6000 }) } setTimeout(function() { b() }, 100) } (); 三、 效果查看 3.1鼠标点击炫彩字体提示cpt效果如下: https://pic1.zhimg.com/80/v2-9ae5e905742243aa6bc09dcae66a6320_720w.gif 3.2 动态背景、鼠标悬浮粒子汇聚效果展示 https://pic1.zhimg.com/80/v2-bd578a1dc5204b1ee33872f691602e6c_720w.gif 移动端不支持 对你有帮助的话,可以点赞+关注+收藏,更多知识分享持续更新~
【帆软FR】图片放大镜、缩小镜效果
一、描述 展示商品图片的细节时,预览的时候想要等比例的放大、缩小展示所在图片的区域细节。 二、实现思路 2.1 页面元素原图、大图片、小图片、悬浮的元素(放大镜缩小镜) 2.2 放大/缩小的原理通过监控鼠标移入、移出、在原图片上移动,获取在图片的位置,定位大/小图片的相应位置。 onmouseover鼠标移入 onmouseout鼠标移出 onmousemove鼠标移动 三、示例 3.1 模板页面设置通过超链接设置动态参数确定图片放大还是缩小 https://pic4.zhimg.com/80/v2-abbe80633c2c0bfb4f2d182cbab8d095_720w.png 3.2 添加初始化后事件 https://pic1.zhimg.com/80/v2-43f9960a547eb8eadabe3ad0064076bb_720w.png js代码: setTimeout(function(){ var objSmallBox = document.getElementById("small-box"); var objFloatBox = document.getElementById("float-box"); var objBigBox = document.getElementById("big-box"); var objBigBoxImage = objBigBox.getElementsByTagName("img"); var objsmallerBox = document.getElementById("smaller-box"); var objsmallerBoxImage = objsmallerBox.getElementsByTagName("img"); //鼠标移入,悬浮元素显示,参数a为1大图片显示,参数a为0小图片显示 objSmallBox.onmouseover = function () { objFloatBox.style.display = "block" if(a==1) { objBigBox.style.display = "block" } if(a==0){ objsmallerBox.style.display = "block" } } // 鼠标移出,悬浮元素、大图片、小图片隐藏 objSmallBox.onmouseout = function () { objFloatBox.style.display = "none" objBigBox.style.display = "none" objsmallerBox.style.display = "none" } objSmallBox.onmousemove = function (ev) { // 鼠标在图片移动,定位取鼠标的位置 var _event = ev || window.event; //兼容多个浏览器的event参数模式 // left为鼠标的x轴-小图片距离浏览器页面的左边距-悬浮元素的宽度/2 var left = _event.clientX - objSmallBox.offsetLeft - objFloatBox.offsetWidth / 2; // top鼠标的Y轴-小图片距离浏览器页面的上边距-悬浮元素的高度/2 var top = _event.clientY - objSmallBox.offsetTop - objFloatBox.offsetHeight / 2; //定义悬浮元素的移动范围 if (left < 0) { left = 0; } else if (left > (objSmallBox.offsetWidth - objFloatBox.offsetWidth)) { left = objSmallBox.offsetWidth - objFloatBox.offsetWidth; } if (top < 0) { top = 0; } else if (top > (objSmallBox.offsetHeight - objFloatBox.offsetHeight)) { top = objSmallBox.offsetHeight - objFloatBox.offsetHeight; } objFloatBox.style.left = left + "px"; objFloatBox.style.top = top + "px"; //悬浮元素距离原图的左边距/(原图片的宽度 - 悬浮元素的宽度)=大图片距离BigBox的左边距/(BigBox的宽度-大图片的宽度) //宽度比例系数=left / (objSmallBox.offsetWidth - objFloatBox.offsetWidth) //高度的比例系数=top / (objSmallBox.offsetHeight - objFloatBox.offsetHeight) var percentX = left / (objSmallBox.offsetWidth - objFloatBox.offsetWidth); var percentY = top / (objSmallBox.offsetHeight - objFloatBox.offsetHeight); if(a==1) { objBigBoxImage.style.left = -percentX * (objBigBoxImage.offsetWidth - objBigBox.offsetWidth) + "px"; objBigBoxImage.style.top = -percentY * (objBigBoxImage.offsetHeight - objBigBox.offsetHeight) + "px"; } if(a==0) { objsmallerBoxImage.style.left = -percentX * (objsmallerBoxImage.offsetWidth - objsmallerBox.offsetWidth) + "px"; objsmallerBoxImage.style.top = -percentY * (objsmallerBoxImage.offsetHeight - objsmallerBox.offsetHeight) + "px"; } } },100); 3.3 引入css样式 https://pic3.zhimg.com/80/v2-6c4cf356b7a9dec5e3d3a1dffab0c682_720w.png 四、 效果查看 https://pic2.zhimg.com/80/v2-f1dd37f5714a7da27fe7df6874674829_720w.gif 编辑于 2021-6-19 22:28 编辑于 2021-6-19 22:29 编辑于 2021-6-19 22:30
【帆软FR】新增自定义字体(以LED字体为例)
一、描述1、常见问题(1)linux系统字体安装方法:https://blog.csdn.net/u011606175/article/details/81006932 可能导致的现象:导出图表显示不了中文,但是单元格可以显示中文 (2)字体检测是否缺失:https://help.fanruan.com/finereport/doc-view-4063.html?source=4 可能的现象:预览、导出、打印报表时,出现字体效果和设计的效果不一致 (3)字体扩展插件:自带宋体( 字体包为 SimSun.ttc ),如果要使用其他字体则需要手动扩展,见https://help.fanruan.com/finereport/doc-view-1423.html?source=4可能的现象:Linux 系统里预览,会出现行高列宽计算不正确,导出打印字体错位等现象。这是由于 Linux 系统下缺少报表内使用的相应字体导致的 (4)性能优化插件:绘图支持,增加WEB-INF/fonts下字体自动加载系统引擎,不需要安装字体到操作系统也可以让java绘图支持自定义字体,https://help.fanruan.com/finereport/doc-view-2612.html?source=4 2、LED字体展示效果 https://pic1.zhimg.com/80/v2-156f75afc29446d63244d8841335ed1b_720w.png 二、实现思路 1、新增字体存放路径(1)本地的系统字体,如win https://pic3.zhimg.com/80/v2-8ac22872d3e729f0c58474eecdab38da_720w.jpg (2)jdk中放字体,如... java-8u171\jdk171\jre\lib\fonts https://pic1.zhimg.com/80/v2-e8dbe1378a12c07aa3d20ebd84542164_720w.png (3)性能优化插件:绘图支持,增加WEB-INF/fonts下字体自动加载系统引擎,不需要安装字体到操作系统也可以让java绘图支持自定义字体 https://pic1.zhimg.com/80/v2-cc1d39435a493393e05a603a4f99706b_720w.png 2、CSS引入外部字体 (1)应用场景:由于文本形式的内容依赖本地系统字体,可以使用CSS引入外部字体,替换原本字体样式,如Symbol (2)解压LED.zip,将以下三个文件放到工程中指定目录: https://pic2.zhimg.com/80/v2-b503b8548fba4c7d24b827c08f5978ea_720w.png (3)修改stylesheet.css内容 https://pic1.zhimg.com/80/v2-221b3d2e89325ea061aa3b8e8c282003_720w.png (4)参考jssetTimeout(function() { $('').appendTo('head'); }, 200); //css链接地址根据实际放的位置更改 或者 function dynamicLoadCss(url) { var head = document.getElementsByTagName('head'); var link = document.createElement('link'); link.type='text/css'; link.rel = 'stylesheet'; link.href = url; head.appendChild(link); } dynamicLoadCss("/webroot/help/LED/液晶数字字体.css"); https://pic1.zhimg.com/80/v2-2b7629bc98d4593e1eec6ec2efe603e8_720w.png (5)使用方法:使用修改过的字体为symbol https://pic4.zhimg.com/80/v2-467b7521fbbfe3b60df23ca122538502_720w.png 三、注意事项 1、字体乱码问题:https://kms.fineres.com/pages/viewpage.action?pageId=95851206 2、转换ttf格式字体格式:https://www.fontke.com/tool/fontface 3、注意字体版权问题 对你有帮助的话,可以点赞+关注+收藏,更多知识分享持续更新~ 编辑于 2021-6-16 22:38 编辑于 2021-6-17 09:10
【帆软FR】多复现框下动态列处理方案
一、描述 在多个复选框影响下的动态列处理,如图所示 https://pic2.zhimg.com/80/v2-89102663cfc42fdb66ed2a55926f73cf_720w.png 二、sql参数处理 主要问题在于,如果是多参数框情况下,走多参数处理的话,如果有一个为空,可能会出现查询里SELECT 订单ID ,单价,FROM S订单明细 limit 5类似这样的sql语句,导致最后执行的有问题。 1.方案一一个是在sql里处理,sql里处理的话,其实主要就是针对多逗号的情况,其实就是和为空查询全部的思路类似,可以走if判断处理,例如${if(b==',',"",b)}与之配套的控件设置,和参数接收如图所示 https://pic1.zhimg.com/80/v2-d7c6dc963eb7ad04b62aec285b12066a_720w.png https://pic1.zhimg.com/80/v2-d9d8cb3e1087dc367e24275ffbec9fb4_720w.png 这是一个思路,可以在接收时候判断处理,如果为特定情况不返回内容,从而实现不会多逗号的情况。 2.方案二同样是sql参数处理,也可以走外面汇总后,再放入sql里,控件设置如图所示 https://pic4.zhimg.com/80/v2-50065660e13b8d6cbcd1406212192247_720w.png 先汇总处理,然后再返回给sql里,也能实现正常查询 三、共享数据集 关联数据集方案处理的话,因为要分情况读取对应sql,所以适用于情况比较少的情况,比如多个复选框不能同时选择,互斥的情况下,可以用关联数据集先建立复选框对应数目的数据集,如 https://pic4.zhimg.com/80/v2-95012ebcf73c01157b037e6e76f3f426_720w.png 然后建立关联数据集 https://pic4.zhimg.com/80/v2-5736909267eeaf1e60f5c5a3ad79f0af_720w.png 在关联这边可以走公式执行不同的数据集即可。 编辑于 2021-6-16 22:26 编辑于 2021-6-17 09:10
【帆软FR】nginx实现报表读写分离
一、背景 经常出现导入大数量时一个单节点CPU升高,导致整个系统查询慢; 进行大数据量填报时,填报涉及二次计算的时CPU也会升高,这个时候再做其他的操作就会出现卡的现象。对此,使用nginx读写分离的方式,将填报提交走一个节点,预览查询走另外一个节点来避免出现一台节点压力过大的情况,根据实际情况可以调整节点的权重。 二、实现思路 将报表填报和预览分别在不同节点上面实现,实现读写分离的效果;nginx里面使用$request_method = "POST"判断是否是post请求,如果是post请求设置请求的节点,如果不是post走另外一个节点; upstream 里面配置正常请求的节点,与post请求节点分开使用。 if ($request_method = "POST"){ proxy_pass http://122.9.83.61:8080; } 三、操作步骤 3.1 搭建好集群之后单独对nginx进行如下配置:nginx具体配置如下: #用户或者用户组 默认为nobody #user root; worker_processes auto; error_log logs/error.log; events { #每个worker_processes的最大连接数,Windows服务器无论这里设置多大实际都只有1024 #并发数是 worker_processes 和 worker_connections 的乘积 worker_connections 1024; } http { #设定mime类型,类型由mime.type文件定义 include mime.types; #默认文件类型,默认为text/plain default_type application/octet-stream; #日志格式 log_format main '$remote_addr - $remote_user "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $upstream_addr'; #access_log确定了Nginx是否保存访问日志,将这个设置为关闭可以降低磁盘IO而提升速度 access_log off; #access_log logs/access.log main; #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件, #对于普通应用,必须设为 on, #如果用来进行下载等应用磁盘IO重负载应用,可设置为 off, #以平衡磁盘与网络I/O处理速度,降低系统的uptime. sendfile on; #tcp_nopush on; #http长连接(client nginx)超时时间,请求完成之后连接保持的时间 keepalive_timeout 65s; #types_hash_max_size越小,消耗的内存就越小,但散列key的冲突率可能上升 types_hash_max_size 2048; #开启gzip压缩 #gzip on; #gzip_disable "MSIE ."; #设定请求缓冲 client_header_buffer_size 512k; large_client_header_buffers 4 512k; #允许用户最大上传数据大小,根据业务需求调整上传文件大小限制 client_max_body_size 100M; upstream FR.com { server 122.9.83.61:8081 max_fails=15 fail_timeout=300s; #server 122.9.83.61:8080 max_fails=15 fail_timeout=300s; keepalive 300; #其它server参数说明: #down 标记服务器挂掉 #backup 备份服务器,当主服务器(例如上面的95和96)不可用时才加入服务器; #weight=number 权重,默认为1 #内置负载均衡策略有ip hash、轮询、加权轮询(设置server的weight值) #ip_hash; #↓====================主动健康检查模块配置====================↓# ## interval:向后端发送的健康检查包的间隔,单位ms。 ## fall(fall_count): 如果连续失败次数达到fall_count,服务器就被认为是down ## rise(rise_count): 如果连续成功次数达到rise_count,服务器就被认为是up。 ## timeout: 后端健康请求的超时时间,单位ms。 ## type:健康检查包的类型,现在支持tcp、udp、http类型 #check interval=2000 rise=5 fall=10 timeout=10000 type=http; # 检查请求, 7-16之前的persist版本,只能使用 /webroot/decision/system/info HTTP; #check_http_send "GET /webroot/decision/system/health HTTP/1.0\r\n\r\n"; # 检查请求 #check_http_expect_alive http_2xx http_3xx; #该指令指定HTTP回复的成功状态,默认认为2XX和3XX的状态是健康的。 #↑====================主动健康检查模块配置====================↑# } upstream WBS.com { server 122.9.83.61:38888 max_fails=15 fail_timeout=300s; server 122.9.83.61:38888 max_fails=15 fail_timeout=300s; #这里必须使用ip_hash ip_hash; } server { listen 80; server_name 122.9.83.61; #nginx默认不转发带下划线的header,比如请求的header中有_device_这个header,转发到负载服务器时默认会丢弃 #可以在http或者http -> server这两个上下文中加入一条属性 underscores_in_headers on; location / { #对于HTTP代理,proxy_http_version指令应该设置为“1.1”,同时“Connection”头的值也应被清空(如下proxy_set_header Connection "") proxy_http_version 1.1; #定义转发到的服务器(组) proxy_pass http://FR.com; #设置nginx转发时转发到下一个服务器的条件,此处设置将未成功请求(proxy_next_upstream定义的40x, 50x等)传递到下一步进行处理 # 失败尝试说明:50x和429在此配置会被当作fail,error,timeout并 invalid_header无论配置与否都被认为fail,http_403 and http_404配置与否都不是fail。 # error:与后端服务器建立连接、传递请求、读取请求头发生的错误 # timeout:与后端服务器建立连接、传递请求、读取请求头超时,设置在proxy_next_upstream_timeout和proxy_next_upstream_tries(默认值都是0) # invalid_header:服务器返回非法或者为空 proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent; proxy_redirect off; #请求头的一些设置,语法proxy_set_header ; #$host为请求的主机名称(即nginx代理服务器), $server_port为主机端口(即nginx端口),如果有外网映射,这里应改写 外网地址:外网端口 形式(不要带协议) proxy_set_header Host $host:$server_port; #这里$remote_addr客户端ip地址 proxy_set_header X-Real-IP $remote_addr; #这里$proxy_add_x_forwarded_for是代理层级,如果由多层代理,这里就写client,proxy1,proxy2,这里应该是client即客户端ip proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #与后端服务器的连接不需要保持 proxy_set_header Connection ""; #NGINX会缓冲来自代理服务器的响应。响应存储在内部缓冲区中,并且在收到整个响应之前不会发送到客户端。 proxy_connect_timeout 75; #读取超时,默认60s,如果在超时时间内服务器未返回任何数据,视为超时。如果没有大数据量计算或导出的模板,则建议配置不超过100s,如果有大数据量计算或导出的模板,则根据最长耗时的模板时间进行配置。 proxy_read_timeout 400; #写入超时,默认60s,如果在超时时间内服务器未收到数据表示超时,视为超时。如果没有大数据量计算或导出的模板,则建议配置不超过100s,如果有大数据量计算或导出的模板,则根据最长耗时的模板时间进行配置。 proxy_send_timeout 400; add_header backendIP $upstream_addr; add_header backendCode $upstream_status; if ($request_method = "POST"){ proxy_pass http://122.9.83.61:8080; } } #定义404页面 #error_page 404 /404.html; # redirect server error pages to the static page /50x.html #定义50x页面 error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { #此处为websocket端口,如果是集群部署,FineReport工程为38889,FineBI工程为48889 listen 38889; server_name localhost; location / { proxy_http_version 1.1; proxy_pass http://WBS.com; proxy_connect_timeout 75; proxy_read_timeout 400; proxy_send_timeout 400; #升级目标为$http_upgrade 值实际为websocket proxy_set_header Upgrade $http_upgrade; #Connection设置升级 proxy_set_header Connection "upgrade"; } } } 四、效果查看 如下所示是预览的时候走的get请求,走的是8081节点; 在nginx里面加入如下配置,能够在前端看到请求的地址;add_header backendIP $upstream_addr; add_header backendCode $upstream_status; https://pic4.zhimg.com/80/v2-d0fd14dabedba73097fbbdc325a3a3f1_720w.png 2.如下是post请求走的是8080节点 https://pic1.zhimg.com/80/v2-0e0aa3f5510047a25710e17dddadd199_720w.png 编辑于 2021-6-15 20:32 编辑于 2021-6-17 09:11
【帆软FR】js实现分类汇总
一、场景描述1、目前有层级结构的数据可以通过将数据集转换为树数据集,然后结合下拉树或者视图树控件来展示,但是控件本身功能有限,无法在展示层级结构的同时满足填报计算+提交的效果 2、此类场景问题可以通过获取相邻单元格层级然后循环计算上下格数据,达到一个实时计算的效果。从基本的二层联动逻辑上出发,可以逐渐实现多层级自动计算效果,具体效果如下: 多级联动计算效果:https://pic4.zhimg.com/v2-ffc10dc55514294ab16c73d433bed5fb_b.jpg 二、二级联动1、计算思路 (1)获取当前单元格值和对应层级的值,并用设置参数jj,公式值为len(value("测试表",1)),也就是获取到表的行数var location = this.options.location; //获取当前控件的位置 var cr = FR.cellStr2ColumnRow(location); var col = cr.col; //列号 var ro = cr.row; //行号 //获取当前单元格的数据 var score_obj = contentPane.getWidgetByCell(FR.columnRow2CellStr({ col: col, row: ro })); var score=Number(score_obj.getValue()); //获取当前层级 var rank_obj = contentPane.getWidgetByCell(FR.columnRow2CellStr({ col: col-1, row: ro })); var rank=Number(rank_obj.getValue()); (2)关键计算逻辑:以当前单元格为起始,先向上检索层级,如果检索到层级为1,也就是当前的父层级就停止,将经过的子层级数据相加;然后向下检索层级,如果检索到层级为1,也将经过的子层级相加,最终两者之和会赋值给父层级。//循环检索计算 var sum1=score; var ii=ro; //向下检索并求和 for (var i = 1; i < jj-ii+1 ;i++) { var rank1=Number(contentPane.getWidgetByCell(FR.columnRow2CellStr({col:col-1,row: ro+i})).getValue()); var score1=Number(contentPane.getWidgetByCell(FR.columnRow2CellStr({col:col,row: ro+i})).getValue()); sum1=sum1+score1; if(rank1
个人成就
内容被浏览111,394
加入社区5年243天
返回顶部