php读取excel文件数据的导入和导出
在之前有写过一篇文章讲述了使用PHP快速生成excel表格文件并下载,这种方式生成Excel文件,生成速度很快,但是有缺点是: 1.单纯的生成Excel文件,生成的文件没有样式,单元格属性(填充色,宽度,高度,边框颜色…)不能自定义; 2.生成的文件虽然可以打开,但是兼容性很差,每次打开,都会报一个警告: 今天使用一个第三方的SDK(PHPExcel)实现Excel文件的导入和导出。 准备工作: 1.下载PHPExcel的SDK,下载地址:https://github.com/PHPOffice/PHPExcel。 2.将SDK解压之后的Class文件拷贝到自己的项目。 一.Excel文件读取
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
function excelToArray(){ require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; //加载excel文件 $filename = dirname(__FILE__).'/result.xlsx'; $objPHPExcelReader = PHPExcel_IOFactory::load($filename); $sheet = $objPHPExcelReader->getSheet(0); // 读取第一个工作表(编号从 0 开始) $highestRow = $sheet->getHighestRow(); // 取得总行数 $highestColumn = $sheet->getHighestColumn(); // 取得总列数 $arr = array('A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); // 一次读取一列 $res_arr = array(); for ($row = 2; $row <= $highestRow; $row++) { $row_arr = array(); for ($column = 0; $arr[$column] != 'F'; $column++) { $val = $sheet->getCellByColumnAndRow($column, $row)->getValue(); $row_arr[] = $val; } $res_arr[] = $row_arr; } return $res_arr; } |
或者:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function excelToArray(){ require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; //加载excel文件 $filename = dirname(__FILE__).'/result.xlsx'; $objPHPExcelReader = PHPExcel_IOFactory::load($filename); $reader = $objPHPExcelReader->getWorksheetIterator(); //循环读取sheet foreach($reader as $sheet) { //读取表内容 $content = $sheet->getRowIterator(); //逐行处理 $res_arr = array(); foreach($content as $key => $items) { $rows = $items->getRowIndex(); //行 $columns = $items->getCellIterator(); //列 $row_arr = array(); //确定从哪一行开始读取 if($rows < 2){ continue; } //逐列读取 foreach($columns as $head => $cell) { //获取cell中数据 $data = $cell->getValue(); $row_arr[] = $data; } $res_arr[] = $row_arr; } } return $res_arr; } |
|
1 |
两种方法均可将表格数据转化为数组,然后哦再进行相关的操作就简单了。 二.Excel文件导出
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
/** * 创建(导出)Excel数据表格 * @param array $list 要导出的数组格式的数据 * @param string $filename 导出的Excel表格数据表的文件名 * @param array $indexKey $list数组中与Excel表格表头$header中每个项目对应的字段的名字(key值) * @param array $startRow 第一条数据在Excel表格中起始行 * @param [bool] $excel2007 是否生成Excel2007(.xlsx)以上兼容的数据表 * 比如: $indexKey与$list数组对应关系如下: * $indexKey = array('id','username','sex','age'); * $list = array(array('id'=>1,'username'=>'YQJ','sex'=>'男','age'=>24)); */ function exportExcel($list,$filename,$indexKey,$startRow=1,$excel2007=false){ //文件引入 require_once APP_ROOT.'/Api/excel/PHPExcel.php'; require_once APP_ROOT.'/Api/excel/PHPExcel/Writer/Excel2007.php'; if(empty($filename)) $filename = time(); if( !is_array($indexKey)) return false; $header_arr = array('A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); //初始化PHPExcel() $objPHPExcel = new PHPExcel(); //设置保存版本格式 if($excel2007){ $objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); $filename = $filename.'.xlsx'; }else{ $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel); $filename = $filename.'.xls'; } //接下来就是写数据到表格里面去 $objActSheet = $objPHPExcel->getActiveSheet(); //$startRow = 1; foreach ($list as $row) { foreach ($indexKey as $key => $value){ //这里是设置单元格的内容 $objActSheet->setCellValue($header_arr[$key].$startRow,$row[$value]); } $startRow++; } // 下载这个表格,在浏览器输出 header("Pragma: public"); header("Expires: 0"); header("Cache-Control:must-revalidate, post-check=0, pre-check=0"); header("Content-Type:application/force-download"); header("Content-Type:application/vnd.ms-execl"); header("Content-Type:application/octet-stream"); header("Content-Type:application/download");; header('Content-Disposition:attachment;filename='.$filename.''); header("Content-Transfer-Encoding:binary"); $objWriter->save('php://output'); } |
导出文件,还可以设置模板
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
function exportExcel($list, $filename, $indexKey = array()) { require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/IOFactory.php'; require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel.php'; require_once dirname(__FILE__) . '/Lib/Classes/PHPExcel/Writer/Excel2007.php'; $header_arr = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); //$objPHPExcel = new PHPExcel(); //初始化PHPExcel(),不使用模板 $template = dirname(__FILE__) . '/template.xls'; //使用模板 $objPHPExcel = PHPExcel_IOFactory::load($template); //加载excel文件,设置模板 $objWriter = new PHPExcel_Writer_Excel5($objPHPExcel); //设置保存版本格式 //接下来就是写数据到表格里面去 $objActSheet = $objPHPExcel->getActiveSheet(); $objActSheet->setCellValue('A2', "活动名称:江南极客"); $objActSheet->setCellValue('C2', "导出时间:" . date('Y-m-d H:i:s')); $i = 4; foreach ($list as $row) { foreach ($indexKey as $key => $value) { //这里是设置单元格的内容 $objActSheet->setCellValue($header_arr[$key] . $i, $row[$value]); } $i++; } // 1.保存至本地Excel表格 //$objWriter->save($filename.'.xls'); // 2.接下来当然是下载这个表格了,在浏览器输出就好了 header("Pragma: public"); header("Expires: 0"); header("Cache-Control:must-revalidate, post-check=0, pre-check=0"); header("Content-Type:application/force-download"); header("Content-Type:application/vnd.ms-execl"); header("Content-Type:application/octet-stream"); header("Content-Type:application/download");; header('Content-Disposition:attachment;filename="' . $filename . '.xls"'); header("Content-Transfer-Encoding:binary"); $objWriter->save('php://output'); } |
先弄一个excel模板 然后使用该模板导出数据 from:https://www.jianshu.com/p/f7c07763a16e
View DetailsCentOS6.5将shell脚本设置为服务和开机启动的方法
第一种开机执行命令法: 直接修改/etc/rc.d/rc.local文件 编辑文件/etc/rc.d/rc.local vi /etc/rc.d/rc.local 比如要将zookeeper添加为开机自启动就在最后加上“/usr/local/zookeeper-3.4.5/bin/zkServer.sh start” 配置好之后,重启centos,会发现命令被执行了。前提条件是当前机器环境变量中有java命令即$JAVA_HOME/bin的路径,否则zookeeper也启动不了。 Bash
|
1 2 3 4 5 6 7 8 9 10 11 |
[root@zookeeper ~]# vim /etc/rc.d/rc.local #!/bin/sh # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. touch /var/lock/subsys/local # /usr/local/zookeeper-3.4.5/bin/zkServer.sh start |
第二种服务自启动法: 这次换个jetty吧 1、进入到/etc/rc.d/init.d目录下,新建一个jetty脚本 Bash
|
1 |
vi /etc/rc.d/init.d/jetty |
将以下脚本写入文件中,可以看出这是一个case语句判断,当我们使用"service jetty start"启动服务的时候"start"参数就会变成$1传入下面的脚本,从而做出对应的操作。 # chkconfig: 345 99 99 (这个比较有意思,345代表在设置在那个level中是on的,如果一个都不想on,那就写一个横线"-",比如:chkconfig: – 99 99。后面两个数字当然代表S和K的默认排序号啦,基本都写99,排后面启动安全保险) Bash
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/bash #chkconfig: 345 99 99 #description:jetty server #processname:jetty JETTY_HOME=/app/jetty9_4_8 case $1 in start) su root $JETTY_HOME/bin/jetty.sh start;; stop) su root $JETTY_HOME/bin/jetty.sh stop;; check) su root $JETTY_HOME/bin/jetty.sh check;; restart) su root $JETTY_HOME/bin/jetty.sh restart;; *) echo "require start|stop|check|restart" ;; esac |
2、最后保存jetty文件后别忘了设置文件的执行权限 Bash
|
1 |
chmod +x jetty |
3、至此服务已经创建好了,可以用"service jetty start"来启动jetty了,但我们要设置自启动还需要添加到chkconfig来管理 Bash
|
1 2 3 |
chkconfig --add jetty chkconfig --list jetty |
看到3是启动状态就说明在文本界面启动方式下该服务已经设置为自启动了,5是图形化界面 如果不是启动状态需要用命令开启自启动 Bash
|
1 2 3 |
chkconfig --level 345 jetty on chkconfig --list jetty |
这样就没问题了。 from:https://blog.csdn.net/e_wsq/article/details/79885180
View DetailsCentOS7添加自定义脚本服务
一、CentOS7添加自定义脚本服务说明 在CentOS7下,已经不再使用chkconfig命令管理系统开机自启动服务和条件自定义脚本服务了,而是使用管理unit的方式来控制开机自启动服务和添加自定义脚本服务。在/usr/lib/systemd/system目录下包含了各种unit文件,有service后缀的服务unit,有target后缀的开机级别unit等。这里介绍自定义脚本服务,如果想把自定义的脚本变成服务进程,都需要写对应的service配置文件,这样才能被unit所管理(注意:自定义开机自启动服务的.service配置文件必须放在/usr/lib/systemd/system这个目录下面)。服务类别又分为服务又分为系统服务(system)和用户服务(user)。 系统服务:开机不登陆就能运行的程序(常用于开机自启)。 用户服务:需要登陆以后才能运行的程序。 二、编写.service配置文件说明 1、[unit]区块:设置管理启动顺序与依赖关系 Description=服务描述 给出当前服务的简单描述 Documentation=路径或url 给出文档位置 After=服务.target或服务.service 定义在某些服务之后启动。例如sshd服务启动必须在network.target sshd-keygen.service服务开启之后才能启动,可以使用如下命令查看sshd服务的配置 cat /usr/lib/systemd/system/sshd.service Before=服务.target 定义在某些服务之前启动 Wants=服务.service 弱依赖,表示等号填写服务启动或失败,不影响此配置文件服务的启动 Requires=服务.service 强依赖,表示等号填写服务启动或失败,那么此配置文件的服务将启动失败 注意:如果After、Before、Wants、Requires等号后面需要填写多个服务可以用空格隔开。After和Before字段只涉及启动顺序,不涉及依赖关系。Wants字段与Requires字段只涉及依赖关系,与启动顺序无关,默认情况下是同时启动的。 2、[Service]区块:设置启动行为 •启动命令 ExecStart=命令 定义启动进程时执行的命令 ExecReload=命令 重启服务时执行的命令 ExecStop=命令 停止服务时执行的命令 ExecStartPre=命令 启动服务之前执行的命令 ExecStartPost=命令 启动服务之后执行的命令 ExecStopPost=命令 停止服务之后执行的命令 所有的启动设置之前,都可以加上一个连词号(-),表示"抑制错误",即发生错误的时候,不影响其他命令的执行。例如:ExecStop=-/bin/sh /server/scripts/xx.sh •启动类型 Type字段定义启动类型。它可以设置的值如下: simple(默认值) ExecStart字段启动的进程为主进程 forking ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程(后台运行) oneshot 类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务 dbus 类似于simple,但会等待 D-Bus 信号后启动 notify 类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务 idl 类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合 •重启行为 KillMode字段,定义Systemd如何停止服务,它可以设置的值如下 control-group(默认值) 当前控制组里面的所有子进程,都会被杀掉 process 只杀主进程 mixed 主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号 none 没有进程会被杀掉,只是执行服务的 stop 命令 Restart字段,定义了服务退出后,Systemd的重启方式,它可以设置的值如下 no(默认值) 退出后不会重启 on-success 只有正常退出时(退出状态码为0),才会重启 on-failure 非正常退出时(退出状态码非0),包括被信号终止和超时,才会重启 on-abnormal 只有被信号终止和超时,才会重启 on-abort 只有在收到没有捕捉到的信号终止时,才会重启 on-watchdog 超时退出,才会重启 always 不管是什么退出原因,总是重启 •service区块的其他一些字段 […]
View DetailsShell脚本中cd命令使用
在写shell脚本的时候发现cd切换目录的时候无法切换,代码是下面的。
|
1 2 3 4 5 6 7 |
#!/bin/bash #changedir.sh cd /home/firefox pwd |
我仔细一想,我执行的时候是./changedir.sh来执行的,这样执行的话终端会产生一个子shell,子shell去执行我的脚本,在子shell中已经切换了目录了,但是子shell一旦执行完,马上退出,子shell中的变量和操作全部都收回。回到终端根本就看不到这个过程的变化。那么怎么验证上面的猜想呢?看下面的代码
|
1 2 3 4 5 6 7 8 9 10 11 |
#!/bin/bash #changedir.sh history cd /home/firefox sleep 1 pwd |
首先按照 ./changedir.sh执行,这时候终端没有切换目录,history执行的结果是空的,说明子shell里面没有历史命令(这是肯定的)。然后按照 source changedir.sh执行,这时候就是直接在终端的shell执行脚本了,没有生成子shell,执行的结果就是输出历史命令,并且切换了目录。 from:https://blog.csdn.net/firefoxbug/article/details/7317279
View Detailscentos mysql 命令行下执行 sql 文件
命令行下执行 sql 文件有两种方法 一、第一中方法 (未连接数据库) 不推荐这样使用 因为在密码带有特殊字符时会报错
|
1 |
mysql -h localhost -u username -ppassword < filepath #filepath 为绝对路径 |
二、第二中方法(已链接数据库 当提示符为 mysql> 时) 这里的 yourDatavase 为你的数据库名 filepath 为 sql 文件的绝对路径
|
1 2 |
use yourDatabase; source filepath; |
附: 一、命令行下创建数据库
|
1 |
CREATE DATABASE IF NOT EXISTS yourDatabaseName DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; |
二、命令行下创建数据表 下面的 id、title、author、date 这些字段根据实际需求填写
|
1 2 3 4 5 6 7 |
CREATE TABLE IF NOT EXISTS `yourTableName`( `id` INT UNSIGNED AUTO_INCREMENT, `title` VARCHAR(100) NOT NULL, `author` VARCHAR(40) NOT NULL, `date` DATE, PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
三、删除数据库 yourDatabaseName 为你要删除的数据库名
|
1 |
drop database yourDatabaseName; |
四、删除数据表 yourTableName 为你要删除的数据表名
|
1 |
DROP TABLE yourTableName; |
五、允许远程连接mysql数据库
|
1 2 |
grant all privileges on *.* to 'admin'@'%' identified by '123456' with grant option; flush privileges; |
允许任何ip地址(%表示允许任何ip地址)的电脑用admin帐户和密码(123456)来访问这个mysql server。 注意admin账户不一定要存在。 六、修改表引擎方法
|
1 |
alter table table_name engine=innodb; |
其它数据库操作请自行查询 from:https://blog.csdn.net/ming_xiaoxiami/article/details/81905388
View Details解决linux环境下nohup: redirecting stderr to stdout问题
在生产环境下启动Weblogic时,发现原来好好的nohup信息输出到指定文件中的功能,突然出问题了。现象是控制台输出的信息一部分输出到了我指定的文件,另一部分却输出到了nohup.out,而我是不想让它产生nohup.out文件,不知道是什么原因。 我的启动命令是这样的: nohup bin/startManagedServer.sh myserver htp://192.168.0.1 -Xms2048m -Xmx2048m > logs/myserver.out &现在指行这个命令,会给我产生两个文件,一个中logs/myserver.out,另一个是nohup.out文件。 怎样才能让它不产生nohup.out文件呢。 网上搜了半天,据说好象可以把后面的 “&” 改成 “2>&1 &”,于是把启动命令改成如下: nohup bin/startManagedServer.sh myserver htp://192.168.0.1 -Xms2048m -Xmx2048m > logs/myserver.out 2>&1 &再次执行,问题解决。 解释如下: 2> 表示把标准错误(stderr)重定向,标准输出(stdout)是1。 尖括号后面可以跟文件名,或者是&1, &2,分别表示重定向到标准输出和标准错误。 2> &1 1> &2 2> stderr.log 1> stdout.log from:https://www.xuebuyuan.com/2205812.html?mobile=0
View Detailscentos下查看端口占用情况,杀死进程
阅读目录 第一种:我们知道端口号用下面这种方法 第二种:我们知道服务名称 比如查询tomcat 如何通过pid看端口 window下杀死进程 window下自启 第一种:我们知道端口号用下面这种方法 有时候我们知道某个服务端口正在后台运行,想关掉它。比如说我tomcat是8080端口,在后台运行。怎么关掉它呢? 根据端口查看这个进程的pid
|
1 |
netstat -lnp|grep 8080 #8080请换为你的apache需要的端口 |
查看进程的详细信息
|
1 |
ps 1777 #1777就是上一步得到的pid |
杀掉进程
|
1 |
例如: kill -9 [PID] #-9 表示强迫进程立即停止 |
第二种:我们知道服务名称 比如查询tomcat 根据pid查看进程的详细信息
|
1 |
ps -ef|grep redis |
root 7474 1 0 14:58 ? 00:00:01 /usr/local/redis/redis-4.0.11/src/redis-server 127.0.0.1:6379 root 7794 2175 0 15:30 pts/0 00:00:00 grep --color=auto redis 7474就是pid 如何通过pid看端口
|
1 |
netstat -antup |grep 2711 |
jar类型的项目后台执行
|
1 2 3 4 5 |
nohup java -jar XX.jar >temp.text & //nohup 意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行 //当用 nohup 命令执行作业时,缺省情况下该作业的所有输出被重定向到nohup.out的文件中 //除非另外指定了输出文件。 // 这种方法会把日志文件输入到你指定的文件中,没有则会自动创建 |
window下杀死进程
|
1 2 3 4 |
netstat -ano | findstr 9999 taskkill /f /pid 12612 |
window下自启
|
1 |
%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 放快捷方式 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
1、Windows平台 在windows命令行窗口下执行: 1.查看所有的端口占用情况 C:\>netstat -ano 协议 本地地址 外部地址 状态 PID TCP 127.0.0.1:1434 0.0.0.0:0 LISTENING 3236 TCP 127.0.0.1:5679 0.0.0.0:0 LISTENING 4168 TCP 127.0.0.1:7438 0.0.0.0:0 LISTENING 4168 TCP 127.0.0.1:8015 0.0.0.0:0 LISTENING 1456 TCP 192.168.3.230:139 0.0.0.0:0 LISTENING 4 TCP 192.168.3.230:1957 220.181.31.225:443 ESTABLISHED 3068 TCP 192.168.3.230:2020 183.62.96.189:1522 ESTABLISHED 1456 TCP 192.168.3.230:2927 117.79.91.18:80 ESTABLISHED 4732 TCP 192.168.3.230:2929 117.79.91.18:80 ESTABLISHED 4732 TCP 192.168.3.230:2930 117.79.91.18:80 ESTABLISHED 4732 TCP 192.168.3.230:2931 117.79.91.18:80 ESTABLISHED 4732 2.查看指定端口的占用情况 C:\>netstat -aon|findstr "9050" 协议 本地地址 外部地址 状态 PID TCP 127.0.0.1:9050 0.0.0.0:0 LISTENING 2016 P: 看到了吗,端口被进程号为2016的进程占用,继续执行下面命令: (也可以去任务管理器中查看pid对应的进程) 3.查看PID对应的进程 C:\>tasklist|findstr "2016" 映像名称 PID 会话名 会话# 内存使用 ========================= ======== ================ tor.exe 2016 Console 0 16,064 K P:很清楚吧,tor占用了你的端口。 4.结束该进程 C:\>taskkill /f /t /im tor.exe |
from:https://www.cnblogs.com/coder-lzh/p/8977232.html
View DetailsCentOS查看进程、杀死进程、启动进程等常用命令
关键字: linux 查进程、杀进程、起进程 1.查进程 ps命令查找与进程相关的PID号: ps a 显示现行终端机下的所有程序,包括其他用户的程序。 ps -A 显示所有程序。 ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。 ps -e 此参数的效果和指定"A"参数相同。 ps e 列出程序时,显示每个程序所使用的环境变量。 ps f 用ASCII字符显示树状结构,表达程序间的相互关系。 ps -H 显示树状结构,表示程序间的相互关系。 ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。 ps s 采用程序信号的格式显示程序状况。 ps S 列出程序时,包括已中断的子程序资料。 ps -t<终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。 ps u 以用户为主的格式来显示程序状况。 ps x 显示所有程序,不以终端机来区分。 最常用的方法是ps aux,然后再通过管道使用grep命令过滤查找特定的进程,然后再对特定的进程进行操作。 ps aux | grep program_filter_word,ps -ef |grep tomcat ps -ef|grep java|grep -v grep 显示出所有的java进程,去处掉当前的grep进程。 2.杀进程 使用kill命令结束进程:kill xxx 常用:kill -9 324 Linux下还提供了一个killall命令,可以直接使用进程的名字而不是进程标识号,例如:# killall -9 NAME 3.进入到进程的执行文件所在的路径下,执行文件 ./文件名 附: 这是本人花了两天时间整理得来的,一些最常用的地球人都知道的命令就省去啦!最后提供pdf手册下载 1. 更改档案拥有者 命令 : chown [-cfhvR] [--help] [--version] user[:group] file… 功能 : 更改文件或者文件夹的拥有者 参数格式 […]
View DetailsSpring Boot 容器选择 Undertow 而不是 Tomcat
Spring Boot 内嵌容器Undertow参数设置 配置项:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多 server.undertow.io-threads=16 # 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程 # 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8 server.undertow.worker-threads=256 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可 server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region server.undertow.buffers-per-region=1024 # 是否分配的直接内存(NIO直接分配的堆外内存) server.undertow.direct-buffers=true |
来看看源代码: https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/Undertow.java
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
ioThreads = Math.max(Runtime.getRuntime().availableProcessors(), 2); workerThreads = ioThreads * 8; //smaller than 64mb of ram we use 512b buffers if (maxMemory < 64 * 1024 * 1024) { //use 512b buffers directBuffers = false; bufferSize = 512; } else if (maxMemory < 128 * 1024 * 1024) { //use 1k buffers directBuffers = true; bufferSize = 1024; } else { //use 16k buffers for best performance //as 16k is generally the max amount of data that can be sent in a single write() call directBuffers = true; bufferSize = 1024 * 16 - 20; //the 20 is to allow some space for protocol headers, see UNDERTOW-1209 } |
很显然,Undertow认为它的运用场景是在IO密集型的系统应用中,并且认为多核机器是一个比较容易满足的点,Undertow初始化假想应用的阻塞系数在0.8~0.9之间,所以阻塞线程数直接乘了个8,当然,如果对应用较精确的估测阻塞系数,可以配置上去。 Spring Boot内嵌容器支持Tomcat、Jetty、Undertow。为什么选择Undertow? 这里有一篇文章,时间 2017年1月26日发布的: Tomcat vs. Jetty vs. Undertow: Comparison of Spring Boot Embedded Servlet Containers 1. Setup Spring Boot Application We will use Maven to setup a new project in Eclipse with the appropriate dependencies. We will use the starter parent for this example but the dependencies in a production application will likely be altered to streamline, optimize or customize. 1.1 Setup Spring Boot Dependencies The default embedded servlet container is Tomcat. This version of Spring Web […]
View DetailsSpring Boot :Undertow
Undertow Undertow 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器 Untertow 的特点: 轻量级:它是一个 Web 服务器,但不像传统的 Web 服务器有容器概念,它由两个核心 Jar 包组成,加载一个 Web 应用可以小于 10MB 内存 Servlet3.1 支持:它提供了对 Servlet3.1 的支持 WebSocket 支持:对 Web Socket 完全支持,用以满足 Web 应用巨大数量的客户端 嵌套性:它不需要容器,只需通过 API 即可快速搭建 Web 服务器 默认情况下 Spring Cloud 使用 Tomcat 作为内嵌 Servlet 容器,可启动一个 Tomcat 的 Spring Boot 程序与一个 Undertow 的 Spring Boot 程序,通过 VisualVM 工具进行比较,可看到 Undertow 性能优于 Tomcat 使用 Undertow 添加依赖
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> |
支持 HTTP2
|
1 2 3 4 5 6 7 8 9 10 11 |
// 在@Configuration的类中添加@bean @Bean UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() { UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory(); // 这里也可以做其他配置 factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)); return factory; } |
配置 Undertow
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Undertow 日志存放目录 server.undertow.accesslog.dir # 是否启动日志 server.undertow.accesslog.enabled=false # 日志格式 server.undertow.accesslog.pattern=common # 日志文件名前缀 server.undertow.accesslog.prefix=access_log # 日志文件名后缀 server.undertow.accesslog.suffix=log # HTTP POST请求最大的大小 server.undertow.max-http-post-size=0 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 server.undertow.io-threads=4 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 server.undertow.worker-threads=20 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分 server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region server.undertow.buffers-per-region=1024 # 是否分配的直接内存 server.undertow.direct-buffers=true |
from:https://www.jianshu.com/p/e625b8aa0e80
View Details