首页
Search
1
解决 docker run 报错 oci runtime error
49,608 阅读
2
WebStorm2025最新激活码
28,204 阅读
3
互点群、互助群、微信互助群
23,060 阅读
4
常用正则表达式
21,664 阅读
5
罗技鼠标logic g102驱动程序lghub_installer百度云下载windows LIGHTSYNC
20,036 阅读
自习室
互通有无
搞钱日记
养生记
包罗万象
Search
标签搜索
职场副业
职业发展
副业赚钱
后端开发
内容创作
微服务
分布式系统
效率提升
DevOps
技能提升
流量变现
性能优化
云原生
高并发
编程学习
深度学习
人工智能
架构设计
机器学习
前端开发
loong
累计撰写
3,206
篇文章
累计收到
4
条评论
首页
栏目
自习室
互通有无
搞钱日记
养生记
包罗万象
页面
搜索到
3206
篇与
的结果
2019-08-07
MYSQL数据表设计及使用规范
实际工作中数据库设计需要注意的具体操作问题。表设计1.库名、表名、字段名必须使用小写字母,“_”分割,且名称长度不超过12个字符并且要做到见名知意。2.建议使用InnoDB存储引擎。3.存储精确浮点数必须使用DECIMAL替代FLOAT和DOUBLE。4.建议使用UNSIGNED存储非负数值。5.建议使用INT UNSIGNED存储IPV4。6.整形定义中不添加长度,比如使用INT,而不是INT(4)。7.使用短数据类型,比如取值范围为0-80时,使用TINYINT UNSIGNED。8.不建议使用ENUM类型,使用TINYINT来代替。9.尽可能不使用TEXT、BLOB类型。VARCHAR(N),N表示的是字符数不是字节数,比如VARCHAR(255),可以最大可存储255个汉字,需要根据实际的宽度来选择N。10.VARCHAR(N),N尽可能小,因为MySQL一个表中所有的VARCHAR字段最大长度是65535个字节,进行排序和创建临时表一类的内存操作时,会使用N的长度申请内存。11.表字符集选择UTF8。12.使用VARBINARY存储变长字符串。13.存储年使用YEAR类型,存储日期使用DATE类型,存储时间(精确到秒)建议使用TIMESTAMP类型,因为TIMESTAMP使用4字节,DATETIME使用8个字节。14.建议字段定义为NOT NULL。15.将过大字段拆分到其他表中。16.禁止在数据库中使用VARBINARY、BLOB存储图片、文件等。索引1.索引名称必须使用小写,非唯一索引必须按照“idx_字段名称_字段名称[_字段名]”进行命名,唯一索引必须按照“uniq_字段名称_字段名称[_字段名]”进行命名。2.索引中的字段数建议不超过5个。3.单张表的索引数量控制在5个以内。4.唯一键由3个以下字段组成,并且字段都是整形时,使用唯一键作为主键。5.没有唯一键或者唯一键不符合4中的条件时,使用自增(或者通过发号器获取)id作为主键。6.唯一键不和主键重复。7.索引字段的顺序需要考虑字段值去重之后的个数,个数多的放在前面。8.ORDER BY,GROUP BY,DISTINCT的字段需要添加在索引的后面。9.使用EXPLAIN判断SQL语句是否合理使用索引,尽量避免extra列出现:Using File Sort,UsingTemporary。10.UPDATE、DELETE语句需要根据WHERE条件添加索引。11.不建议使用%前缀模糊查询,例如LIKE “%weibo”。12.对长度过长的VARCHAR字段建立索引时,添加crc32或者MD5 Hash字段,对Hash字段建立索引。13.合理创建联合索引(避免冗余),(a,b,c)相当于 (a) 、(a,b) 、(a,b,c)。14.合理利用覆盖索引。15.SQL变更需要确认索引是否需要变更并通知DBA。SQL语句1.SQL语句中IN包含的值不应过多。2.UPDATE、DELETE语句不使用LIMIT。3.WHERE条件中必须使用合适的类型,避免MySQL进行隐式类型转化。4.SELECT语句只获取需要的字段。5.SELECT、INSERT语句必须显式的指明字段名称,不使用SELECT *,不使用INSERTINTO table。6.使用SELECT column_name1, column_name2 FROM table WHERE[condition]而不是SELECT column_name1 FROM table WHERE[condition]和SELECT column_name2 FROM table WHERE [condition]。7.WHERE条件中的非等值条件(IN、BETWEEN、<、8.避免在SQL语句进行数学运算或者函数运算,容易将业务逻辑和DB耦合在一起。9.INSERT语句使用batch提交(INSERT INTO tableVALUES,,……),values的个数不应过多。10.避免使用存储过程、触发器、函数等,容易将业务逻辑和DB耦合在一起,并且MySQL的存储过程、触发器、函数中存在一定的bug。11.避免使用JOIN。12.使用合理的SQL语句减少与数据库的交互次数。13.不使用ORDER BY RAND,使用其他方法替换。14.建议使用合理的分页方式以提高分页的效率。15.统计表中记录数时使用COUNT(*),而不是COUNT(primary_key)和COUNT(1)。16.禁止在从库上执行后台管理和统计类型功能的QUERY。散表1.每张表数据量建议控制在5000w以下。2.可以结合使用hash、range、lookup table进行散表。3.散表如果使用md5(或者类似的hash算法)进行散表,表名后缀使用16进制,比如user_ff。4.推荐使用CRC32求余(或者类似的算术算法)进行散表,表名后缀使用数字,数字必须从0开始并等宽,比如散100张表,后缀从00-99。5.使用时间散表,表名后缀必须使用特定格式,比如按日散表user_20110209、按月散表user_201102。
2019年08月07日
5,192 阅读
0 评论
75 点赞
2019-08-07
MYSQL读写分离之--MYSQL主从复制、主主复制、双主多从配置
MySQL 主从复制原理: 从库生成两个线程,一个I/O线程,一个SQL线程; i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中; 主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog; SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;MySQL 主从复制主要用途:1.读写分离 在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。2.数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换一、如何配置MYSQL的主从复制?1. 两台数据库服务器,IP分别为 192.168.216.128 和 192.168.216.129,在服务器上装MYSQL(我的配置版本为5.5.56)2. 打开 192.168.216.128 服务器上的MYSQL的配置文件 /etc/my.cnf (路径根据自己服务器的情况来看),将其中的 server-id 设为1(默认为1,总之两台服务器要设置为不同的ID),然后重启MYSQL服务3. 打开 192.168.216.129 服务器上的MYSQL的配置文件 /etc/my.cnf (路径根据自己服务器的情况来看),将其中的 server-id 设为2(默认为1),然后重启MYSQL服务4. 设 192.168.216.128 为主服务器,那么在主服务器上加一个从服务器可以登录的用户,语句如下:1GRANT REPLICATION SLAVE ON *.* TO 'sally'@'192.168.216.129' IDENTIFIED BY 'ilovesally';FLUSH PRIVILEGES 建好后,在192.168.216.129 服务器上执行以下语句1mysql -h 192.168.216.128 -usally -pilovesally 然后试一下可不可以连上,如果可以,则正确,如果连不上,看一下什么原因,是否是防火墙的原因,如果是则去配置防火墙的规则。5. 以上完成后在主服务器上执行以下语句,查询master的状态show master status; 可以看到以上结果,这儿只需要看 File 和 Position,其它的两个分别是白名单和黑名单,意思为同步哪几个数据库和不同步哪几个数据库,可自行根据需求进行设置。记录了前两个字段后,在从库上执行以下语句:CHANGE MASTER TO MASTER_HOST='192.168.216.128', MASTER_USER='sally', MASTER_PASSWORD='ilovesally', MASTER_LOG_FILE='mysql-bin.000020', MASTER_LOG_POS=1441;6. 执行完毕后,在从库上继续执行如下语句:slave start; show slave status\G; 这样,查看从服务器的状态,如果状态中的用红线标出来两个参数的值都为YES,那证明配置已经成功,否则可以检查一下具体问题出现在什么地方。 这样,就算配置完成了。在主库中新建数据库,新建一张表,插几条数据,到从库上查询一下看是否已经同步过来。 如果失败,可以从以下几个方面去排查问题:1.首先试一下主从服务器相互之间是否 PING 得通2.试一下远程连接是否正确,如果连不上,则有可能是网卡不一致、防火墙没有放行 3306 端口3.server-id 是否配成一致4.bin-log 的信息是否正确 二、如何配置MYSQL的主主复制? 上面说了主从复制的配置方法,现在接着上面的配置继续,然后实现双主复制,让以上的两个服务器互为主从。1. 在主服务器上配置 /etc/my.cnf 文件,配置如下:auto_increment_increment=2 #步进值auto_imcrement。一般有n台主MySQL就填n auto_increment_offset=1 #起始值。一般填第n台主MySQL。此时为第一台主MySQL binlog-ignore=mysql #忽略mysql库【我一般都不写】 binlog-ignore=information_schema #忽略information_schema库【我一般都不写】 配置之后重启MYSQL服务2.在从服务器上配置 /etc/my.cnf 文件,配置如下auto_increment_increment=2 #步进值auto_imcrement。一般有n台主MySQL就填n auto_increment_offset=2 #起始值。一般填第n台主MySQL。此时为第二台主MySQL binlog-ignore=mysql #忽略mysql库【我一般都不写】 binlog-ignore=information_schema #忽略information_schema库【我一般都不写】 配置之后重启MYSQL服务3. 在从服务器上添加一个主服务器可以访问的用户,命令如下:GRANT REPLICATION SLAVE ON *.* TO 'sally1'@'192.168.216.128' IDENTIFIED BY 'ilovesally'; FLUSH PRIVILEGES 建好后,在192.168.216.128 服务器上执行以下语句mysql -h 192.168.216.129 -usally1 -pilovesally 如果可以连上,则进行下一步,连不上的话,参考上面进行问题排查。4. 因为要互为主从,所以现在从服务器也是master ,所以也要查看一下状态show master status; 查到相应的信息后,在原来的主服务器上执行以下命令(因为现在它现在也是另一台的从服务器)CHANGE MASTER TO MASTER_HOST='192.168.216.129', MASTER_USER='sally1', MASTER_PASSWORD='ilovesally', MASTER_LOG_FILE='mysql-bin.000021', MASTER_LOG_POS=1457;5. 执行完毕后,在原主库上继续执行如下语句:start slave; show slave status\G; 同上,如果出现如下画面,则证明配置成功。6. 在两台服务器的MYSQL中分别进行一些建库、建表、插入、更新等操作,看一下另一台会不会进行同步,如果可以则证明主主配置成功,否则还是上面的排错方法,进行错误排查。 三、如何配置MYSQL的双主多从? 现在已经是双主配置了,但是如果要进行读写分离,那么我们要再增加N台从库,如何做呢?非常简单,按如下操作即可:新增加一台数据库服务器,192.168.216.130,数据库配置均与前两台相同2. 确定一下要将哪一台当作自己的主服务器,我们姑且设 192.168.216.128 为主服务器3. 在第三台服务器中编辑 /etc/my.cnf ,将其 server-id 设为 3(保证与前两个不一样即可),然后重启MYSQL服务4. 在主服务器中,增加一条用户记录,用于当前服务器对主库对的连接,代码如下:GRANT REPLICATION SLAVE ON *.* TO 'farrow'@'192.168.216.130' IDENTIFIED BY 'ilovesally'; FLUSH PRIVILEGES;5. 在 192.168.216.130 服务器上测试是否可以连接到主库mysql -h 192.168.216.130 -ufarrow -pilovesally 如果可以连上,则可以进行下一步,否则根据上面的提示排查问题。6. 在 192.168.216.130 服务器上查询 master 当前状态 看到相关信息后,我们执行如下操作:CHANGE MASTER TO MASTER_HOST='192.168.216.128', MASTER_USER='sally', MASTER_PASSWORD='ilovesally', MASTER_LOG_FILE='mysql-bin.000020', MASTER_LOG_POS=1441;7. 执行完毕后,我们查询一下当前服务器的状态start slave; show slave status; 如果状态如下,则说明配置正确 如果此处有问题,参考上面所提排查并解决问题。8. 此时我们在 192.168.216.128 上建库、建表、插入、更新、删除数据,在 另外两台上分别进行查看,发现均已经同步。但是如果我们在 192.168.216.129 上做相应的操作,则发现只有 192.168.216.128 上进行了相应的同步,而 192.168.216.130 上的数据并未同步。这是为什么呢?因为我们设置的主库是 192.168.216.128,所以在 192.168.216.129 进行数据操作的时候并未同步,这显然不符合我们的需求,那么,我们要怎么修改呢?非常简单,在互为主从的两台服务器的配置文件中均加入以下语句:log-slave-updates=on 加上后将两台服务器的MYSQL重启,然后再进行测试,发现数据已经可以同步了。如果要再多加一些从服务器,和以上类似,现在我们做的是双主一从,我们可以再加N台从服务器,配置也是一样的。 至此,MYSQL主从复制、主主复制、双主多从配置我们均已经搞定。 Mysql 主从复制是mysql 高可用,高性能的基础,有了这个基础,mysql 的部署会变得简单、灵活并且具有多样性,从而可以根据不同的业务场景做出灵活的调整。
2019年08月07日
9,408 阅读
0 评论
57 点赞
2019-08-02
前端学习视频教程入门级、angular、node、React、vue、微信小程序开发实战视频教程
提取码:9p2u 前端入门视频教程,angular视频教程,node视频学习教程,React视频教程,vue视频教程,小程序视频教程。 从入门到常见前端框架的视频教程都有,建议针对性选择学习。包含内容:1.7天搞定Node.js微信公众号开发2.7天培训课-掌握跨平台app开发3.[Web前端开发]----前端全套20174.angular5.node6.React7.vue8.基础到高阶9.前端小白入门系列课程完整版10.微信小程序开发实战
2019年08月02日
11,754 阅读
0 评论
32 点赞
2019-07-30
Python人工智能机器学习课程
提取码:py2k Python , 是一种面向对象的解释型计算机程序设计语言,具有丰富和强大的库,Python 已经成为继JAVA,C++之后的的第三大语言。 特点:简单易学、免费开源、高层语言、可移植性强、面向对象、可扩展性、可嵌入型、丰富的库、规范的代码等。资源包含:
2019年07月30日
11,974 阅读
0 评论
20 点赞
2019-07-30
Docker从入门到实践
提取码:idku
2019年07月30日
5,897 阅读
0 评论
0 点赞
2019-07-26
nginx 通过外网服务器泛域名配置映射到内网端口或者泛地址
nginx 通过外网服务器泛域名配置映射到内网端口或者泛地址。配置示例如下:server { listen 80; server_name *.i.weitip.com; index index.php index.html index.htm default.php default.htm default.html; root /www/wwwroot/weitip.com/frps; location / { # 泛域名开始配置 if ( $host ~* (.*)\.(.*)\.(.*)\.(.*) ) { set $domain $1; #获取当前的 域名前缀 } resolver 114.114.114.114; set $url "http://$domain.weitip.com:8080"; proxy_pass $url; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } access_log /www/wwwlogs/frps.weitip.com.log; error_log /www/wwwlogs/frps.weitip.com.error.log; }
2019年07月26日
5,021 阅读
0 评论
32 点赞
2019-07-17
阿里巴巴开源镜像提供的 packagist 镜像服务 阿里云 Composer 全量镜像
全局配置(推荐)所有项目都会使用该镜像地址:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/取消配置:composer config -g --unset repos.packagist项目配置仅修改当前工程配置,仅当前工程可使用该镜像地址:composer config repo.packagist composer https://mirrors.aliyun.com/composer/取消配置:composer config --unset repos.packagist调试composer 命令增加 -vvv 可输出详细的信息,命令如下:composer -vvv require alibabacloud/sdk
2019年07月17日
5,120 阅读
0 评论
10 点赞
2019-07-10
Windows下搭建虚拟机和Laravel开发环境配置VirtualBox+Vagrant+Homestead
方法一:前提条件:Windows 用户,你可能需要启用硬件虚拟化(VT-x)。这通常需要通过 BIOS 来启用它。如果你在一个 UEFI 系统上使用的是 Hyper-V,你需要关闭 Hyper-V 才能启用 VT-x下载安装最新版: VirtualBox 和 Vagrant1·首先将Homestead文件夹放入到当前用户目录之下2·然后 使用git命令工具3·cd 切换到Homestead目录下4·将virtualbox.box离线文件放入指定目录上5·执行 vagrant box add laravel/homestead 加上离线文件的路径virtualbox.box进行安装6·初始化:bash init.sh7·安装好之后打开Homestead文件夹打开Homestead.yaml文件进行修改配置:ip: “192.168.10.10”memory: 2048cpus: 3provider: virtualboxauthorize: ~/.ssh/id_rsa.pubkeys:– ~/.ssh/id_rsafolders:– map: F:/htdocs/Laravelto: /home/vagrant/Code/Laravelsites:– map: laravel.appto: /home/vagrant/Code/Laravel/publicdatabases:– homestead8·保存之后,加入hosts文件配置:192.168.10.10 laravel.app9·生成密钥:ssh-keygen10·vagrant up开启虚拟机11·vagrant ssh 进入到虚拟机系统上关闭虚拟机:vagrant halt查看vagrant常用命令:vagrant 方法二:1·你首先要确定你有个好的 terminal [ 终端:cmder 或 Git 的git bash ] . 注意windows的cmd不能用(个人推荐用Git bash)2·下载和安装 [ virtualbox ] 和 [ vagrant ]前者为系统装载用的,后者为系统控制用的3·如果你要使用 homestead 就必须要有个virtualbox.box的文件 ,官方 Laravel 下载这个文件的这个命令为vagrant box add laravel/homestead 但是因为中国的对外国网络资源的限制,你要下载这个文件可能会需要不少的时间,因此 , 在这我们拥有两个选择的余地选择一 : 当你使用官方下载命令时,你的终端会显示这个文件的源地址复制https://atlas.hashicorp.com/laravel/boxes/homestead/,然后按 ctrl +c 退出,然后用的喜欢的下载软件下载,最好是用最新版的,因为会有各种问题.选择二 : phphub上的 virtualbox.box好了 , 现在我假设你已经拥有这个文件,现在来用我们的方法添加 virtualbox.box . 打开你的ide(代码编译器) ,一般为 Sublime Text 和 Atom ,为何要提编译器呢 , 因为下面的步骤可能会需要其中一个的编译器 , 创建一个名为homestead.json的文件 , 输入以下内容{“name”: “laravel/homestead”,“versions”:[{“version”: “1.0.1”,“providers”: [{“name”: “virtualbox”,“url”: “D:/box/virtualbox.box” //你下载的virtualbox.box在电脑系统上的位置}]}]}打开的 IDE (编译器) 先不要保存,点击开始菜单或 win 快捷键 , 在搜索栏处输入你的terminal ( 终端 ) , 点击鼠标右键以管理员身份运行,一般会跳转到 : C:\Users\windows的账户名>然后回到 IDE (编译器) 保文件到C:\Users\windows的账户名这个目录下 , 并且命名为 homestead.json , 然后再回到terminal ( 终端 ) 输入一下代码 :C:\Users\windows的账户名> vagrant box add homestead.json C:\Users\windows的账户名> vagrant box add homestead.json==> box: Loading metadata for box 'homestead.json'box: URL: file://C:/Users/windows的账户名/homestead.json==> box: Adding box 'laravel/homestead' (v1.0.1) for provider: virtualboxbox: Downloading: "D:/box/virtualbox.box" //你下载的virtualbox.box在电脑上的位置box: Progress: 100% (Rate: 129M/s, Estimated time remaining: --:--:--)==> box: Successfully added box 'laravel/homestead' (v1.0.1) for 'virtualbox'!然后继续 在terminal ( 终端 ) 输入.C:\Users\windows的账户名> ssh-keygen -t rsa -C "
[email protected]
"说明 : 这个命令是创建 Homestead 连接秘匙 , 因为我们是在本机上运行的所以不需要密码之类的 , 一直按回车就行C:\Users\windows的账户名> ssh-keygen -t rsa -C "
[email protected]
"Generating public/private rsa key pair.Enter file in which to save the key (/c/Users/windows的账户名/.ssh/id_rsa):Created directory '/c/Users/windows的账户名/.ssh'.Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /c/Users/windows的账户名/.ssh/id_rsa.Your public key has been saved in /c/Users/windows的账户名/.ssh/id_rsa.pub.The key fingerprint is:SHA256:UTmPEezFQK0XUa5Km2lGnqOBgtCo5rwGGWCX8CaTN6g
[email protected]
key's randomart image is:+---[RSA 2048]----+| .. . o=*.o. ||..+o .= =. ||o=.= .. B .. ||oo= . .+ o. ||Eo. S o.. ||+. . . + * ||o.. . . . @ ||+. . = . ||.+. . |+----[SHA256]-----+5·现在继续 在terminal ( 终端 ) 输入.git clone https://github.com/laravel/homestead.git Homestead说明 : 这个命令是 下载 Homestead 目录,里面包含了Homestead 的配置文件C:\Users\windows的账户名> git clone https://github.com/laravel/homestead.git HomesteadCloning into 'Homestead'...remote: Counting objects: 1623, done.rRemote: Total 1623 (delta 0)eceiving objects: 99% (1, reused 0 (delt607/1623), 244a 0), pack-reuse.01 KiB | 13.00d 1623 KiB/sReceiving objects: 100% (1623/1623), 252.22 KiB | 13.00 KiB/s, done.Resolving deltas: 100% (958/958), done.Checking connectivity... done.现在让我们来看看文件是否现在成功了,在 在terminal ( 终端 ) 输入 : C:\Users\windows的账户名> lsHomestead/ //我其他文件夹就没写了,只要看到了这个文件夹你就算是把 Homestead 的配置文件下载下来了然后继续 在terminal ( 终端 ) 输入 C:\Users\windows的账户名 > cd HomesteadC:\Users\windows的账户名\Homestead >C:\Users\windows的账户名\Homestead > bash init.sh //初始化 .homestead 目录说明 : 这个bash init.sh 命令会创建一个 .homestead目录这个目录位于C:\Users\windows的账户名\ 这个目录下这个.homestead目录里有一个 Homestead.yaml 文件很多人windows启动Homestead失败都是因为这个配置文件的关系6·注意 !!!现在这个步骤很重要好了现在用 IDE(代码编译器) 打开目录地址 C:\Users\windows的账户名\ .homestead\Homestead.yaml , 你会看到如下代码|---| ip: "192.168.10.10"|memory: 2048|cpus: 1|provider: virtualbox||authorize: ~/.ssh/id_rsa.pub||keys:| - ~/.ssh/id_rsa||folders:| - map: ~/Code //这个是你的项目的地址,例如D:\随便\项目的目录 1| to: /home/vagrant/Code //这个是homestead系统的地址 2| //其实这就是windows和hometead两个系统共享一个文件夹,难懂一点的话叫||映射||sites: //__这个是你的项目| - map: homestead.app 这个是你项目要设定在你的浏览器上的地址 //需要设定C host文件| to: /home/vagrant/Code/Laravel/public //这里的Laravel其实就是D:\随便\项目的目录\Laravel||databases:| - homestead||# blackfire:|# - id: foo|# token: bar|# client-id: foo|# client-token: bar||# ports:|# - send: 50000|# to: 5000|# - send: 7777|# to: 777|# protocol: udp将以上的代码修改成以下的代码|—|ip: “192.168.10.10”|memory: 2048|cpus: 1|provider: virtualbox||authorize: ~/.ssh/id_rsa.pub||keys:| – ~/.ssh/id_rsa||folders:| – map: D:\随便\项目的目录 //当启动时会自动转换成D:/随便/项目的目录,这个是正确的| to: /home/vagrant/Code||sites: //看到这你可以看到为什么是sites,而不是site| – map: aimiliya.local 这个是你在hosts设定的网站地址| to: /home/vagrant/Code/king/public 这里的king是你设定的D:\随便\项目的目录\king|| – map: lamu.local| to: /home/vagrant/Code/lamu/public|| – map: leimu.local| to: /home/vagrant/Code/leimu/public|||databases:| – homestead||# blackfire:|# – id: foo|# token: bar|# client-id: foo|# client-token: bar||# ports:|# – send: 50000|# to: 5000|# – send: 7777|# to: 777|# protocol: udp|提醒 : IDE(代码编译器) 记得保存 .警告 : 以上代码为最基础的Homestead配置 ,你要进行开启其他功能最好阅读或参考 Laravel 和 vagrant官方文档举例 : 例如在 folders 下面填写 type:“nfs” , 这对于windows 来说是错误的 , 对于 mac 来说却是成功的 , 原因vagrant不支持对 windows 开启 nfs ,具体参考 synced-folders .7 .好了现在回到 terminal ( 终端 ) 启动吧,输入 vagrant up注意 : 在你以后重新启动Homestead .即 : vagrant up都必须在 Homestead 这个目录下启动C:\Users\windows的账户名\Homestead> vagrant upBringing machine 'default' up with 'virtualbox' provider...==> default: Checking if box 'laravel/homestead' is up to date...==> default: Clearing any previously set forwarded ports...==> default: Clearing any previously set network interfaces...==> default: Preparing network interfaces based on configuration...default: Adapter 1: natdefault: Adapter 2: hostonly==> default: Forwarding ports...default: 80 (guest) => 8000 (host) (adapter 1)default: 443 (guest) => 44300 (host) (adapter 1)default: 3306 (guest) => 33060 (host) (adapter 1)default: 5432 (guest) => 54320 (host) (adapter 1)default: 22 (guest) => 2222 (host) (adapter 1)==> default: Running 'pre-boot' VM customizations...==> default: Booting VM...==> default: Waiting for machine to boot. This may take a few minutes...default: SSH address: 127.0.0.1:2222default: SSH username: vagrantdefault: SSH auth method: private key==> default: Machine booted and ready!==> default: Checking for guest additions in VM...default: The guest additions on this VM do not match the installed version ofdefault: VirtualBox! In most cases this is fine, but in rare cases it candefault: prevent things such as shared folders from working properly. If you seedefault: shared folder errors, please make sure the guest additions within thedefault: virtual machine match the version of VirtualBox you have installed ondefault: your host and reload your VM.default:default: Guest Additions Version: 5.0.20default: VirtualBox Version: 5.1==> default: Setting hostname...==> default: Configuring and enabling network interfaces...==> default: Mounting shared folders...default: /vagrant =>C:/Users/windows的账户名/Homesteaddefault: /home/vagrant/Code => D:/随便/项目的目录 //当你没看到这条信息请返回你的Homestead.yaml设定==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`==> default: flag to force provisioning. Provisioners marked to run always will still run.好了,这算启动成功了,但是配置成功了吗?还不能确定的,输入 vagrant ssh 登入homesteadC:\Users\windows的账户名\Homestead> vagrant sshWelcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-22-generic x86_64)*Documentation: https://help.ubuntu.com/vagrant@homestead:~$ //当看到这个说明登入成功了vagrant@homestead:~$ ls //查看下一级目录 ,有Code,可以安心Codevagrant@homestead:~$ cd Codevagrant@homestead:~/Code$ ls //当看到king了,你可以彻底放心了,配置成功了king提醒 :如果你启动了 Homestead , 你发觉你的配置文件 Homestead.yaml :想要修改 , 可以的使用命令:vagrant up –provision ,此命令必须在Homestead 启动后使用,此命令作用为更新Homestead.yaml的修改8·最后要在浏览器上显示你的网页你必须设定对应的hosts .hosts文件所在在目录:C:\Windows\System32\drivers\etc\hosts 先hosts拖到桌面,然后修改成:|# Copyright (c) 1993-2009 Microsoft Corp.|#|# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.|#|# This file contains the mappings of IP addresses to host names. Each|# entry should be kept on an individual line. The IP address should|# be placed in the first column followed by the corresponding host name.|# The IP address and the host name should be separated by at least one|# space.|#|# Additionally, comments (such as these) may be inserted on individual|# lines or following the machine name denoted by a ‘#’ symbol.|#|# For example:|#|# 102.54.94.97 rhino.acme.com # source server|# 38.25.63.10 x.acme.com # x client host||# localhost name resolution is handled within DNS itself.|# 127.0.0.1 localhost|# ::1 localhost||192.168.10.10 aimiliya.local|192.168.10.10 lamu.local|192.168.10.10 leimu.local然后把刚复制到桌面而且修改好的hosts文件的拖回C:\Windows\System32\drivers\etc\hosts覆盖.注意:直接修改是不行的
2019年07月10日
4,550 阅读
0 评论
1 点赞
2019-07-10
PHP经典面试题汇总(六)
六十一·写出一个函数实现字符串翻转?方法一:strrev();方法二:$str = "abcdefg"; function show($str){ for ($i=strlen($str); $i>= 0; $i--) { $str2 .= $str{$i}; } return $str2; } echo @show($str);六十二.在hello.txt文件前面追加字符串,往前面写数据?$str = "h1\n"; $file = 'hello.txt'; $get = file_get_contents($file); file_put_contents($file,$str .=$get);六十三.判断用户ip地址是否在192.168.1.100~192.168.1.150范围内?方法一:$ip = "192.167.1.110"; $x = ip2long($ip); $ip1 = "192.168.1.100"; $min = ip2long($ip1); $ip2 = "192.168.1.150"; $max = ip2long($ip2); if($x > $max || $x < $min){ exit("ip不在范围内"); } echo "ip符合要求";方法二:$ip = "192.168.1.120"; echo $pos = strrpos($ip,'.')+1; $ipleft = substr($ip,0,$pos); $ipright = substr($ip,$pos); if($ipleft != "192.168.1."){ exit("ip不在范围内"); } if($ipright >150 || $ipright <100){ exit("ip不在范围内"); } echo "ip符合要求";六十四·请将2维数组按组 name的长度进行重新排序,按照顺序将id赋值(从1开始)?$arr = array( array('id' => 0,'name' => '323444'), array('id' => 0,"name" => 'sgegesssssg'), array('id' => 0,'name' => '这是字符串'), array('id' => 0,'name' => '101928ss323sssgee323'), array('id' => 0,'name' => 'slkgjeoge'), array('id' => 0,'name' => '32'), array('id' => 0,'name' => '1019283'), ); foreach ($arr as $val) { $long[] = strlen($val['name']); } array_multisort($long,$arr); foreach ($arr as $key => &$val) { $val['id'] = $key+1; } echo "
2019年07月10日
6,344 阅读
0 评论
3 点赞
2019-07-10
PHP经典面试题汇总(五)
五十一·用php写出显示客户端ip与服务器ip的代码?$_SERVER['SERVER_ADDR']; $_SERVER['REMOTE_ADDR']; gethostbyname("www.mobanw.com");五十二·include,require,include_once,require_once的区别 ?1·include一个文件存在错误的话,那么程序不会中端,而是继续执行,并显示一个警告错误,require一个文件存在错误的话,那么程序就会中断执行了,并显示致命错误。2·include有返回值,而require没有。3·include_once()会先检查要导入的档案是不是已经在该程序中的其它地方被导入过了,如果有的话就不会再次重复导入。4·include_once(),require_once()会先检查目标文件的内容是不是在之前就已经导入过了,如果是的话,便不会再次重复导入同样的内容五十三·如何修改session的生存时间?方法1:将php.ini中的session.gc_maxlifetime设置为9999重启apache方法2:session_start(); //保存一天,session的过期时间是有cookie决定的 $lifetime = 24*3600; setcookie(session_name(),session_id(),time()+$lifetime,'/');五十四·写出发帖数最多的十个人的名字的sql语句?,利用下表:members(id,username,posts,pass,email)select username,count(id) from members group by username order by count(id) desc limit 10;五十五·请说明php中传值和传引用的区别,什么时候传值什么时候传引用?按值传递:函数范围内对值的任何改变在函数外部都会被忽略,外部不会改变。按引用传递:函数范围内对值的任何改变在函数外部也能反应出这些修改,外部也可以改变。优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递则不需要复制值,对于性能提高很有好处。五十六·在php中error_reporting这个函数的作用是什么?设置错误级别,错误信息回报。错误级别有以下五种:E_ALL,E_PARSE,E_ERROR,E_WARNING,E_NOTICE五十七·msyql_fetch_row(),mysql_fetch_assoc(),mysql_fetch_array()之间有什么区别?msyql_fetch_row()是从结果取出1行索引数组,作为枚举。mysql_fetch_assoc()获取的是关联数组msyql_fetch_array()获取的是关联和索引混合的数组mysql_num_rows($result)取得查询结果集总数五十八·$a=”abcdef”;请打印出$a中第一个字母?echo $a{0}或者echo substr($a,0,1);五十九·写出正则匹配js标签?$str = <<<scriptscript; preg_match_all('/
2019年07月10日
5,958 阅读
0 评论
0 点赞
2019-07-10
PHP经典面试题汇总(四)
三十九·请使用 php编写程序,读取出www.baidu.com的首页的网页内容,并存入字符串$str?方法一:$url ="http://www.baidu.com"; $str = file_get_contents($url); echo $str;方法二:$fp = fopen("http://www.baidu.com",'r'); $str = ''; while(!feof($fp)){ echo $str.=fread($fp,'1024'); }请用php将上题中读出来的网页内容的<title>标签的值解析出来?header("Content-type:text/html;charset=utf-8"); $url ="http://www.baidu.com"; $str = file_get_contents($url); preg_match('/<title>(.+)<\/title>/',$str,$ms); echo $ms[1];四十·通过php函数循环遍历出文件夹下的所有目录的文件,写出程序?$dir = "zt"; function dirList($dir){ $arr = scandir($dir); foreach($arr as $file){ if($file !='.' && $file !='..'){ $path = $dir."/".$file; if(is_dir($path)){ dirList($path); }else{ echo "<p>{$path}</p>"; } } } } dirList($dir);四十一·linux打印出一个文件夹下的所有目录和文件,编写shell脚本?vi tree.sh #! /bin/bash tree chomd 777 tree.sh四十二·什么是数据库索引,主键索引,唯一索引的区别,索引的缺点是什么?数据库索引就相当于一本书的目录,就是给数据库中的每张表建立索引,便于检索提高select 效率,加快搜索速度主键索引就是给每张表的主键设置索引,唯一索引就是给每张表的唯一值字段设置索引,主键索引本身就内置唯一索引,一旦在列里加唯一索引,列里的值就不能重复,主键索引在检索中比唯一索引快,一个表只能有一个主键索引,一个表可以有多个唯一索引,索引的缺点是建立索引需要增加存储空间,空间利用率低,并且数据发生变化时会改变索引资源消耗较大。四十三·数据库设计时,常遇到的性能瓶颈有哪些,常有的解决方案是?1·查询速度慢,避免全盘扫描,因为全盘扫描会导致大量的磁盘I/O操作,用sphinx来解决,和添加索引。2·读写过于频繁,使用读写分离操作。3·数据库压力大,采用分布式数据库负载均衡来解决。4·memcache缓存。5·链接数据库使用pdo,或者mysqli,预处理缓存字段。6·尽量使用MyISAM。7·建议表的列不要过多,要适当的多用些表。四十四·通过js实现页面的前进和后退操作?<a href="javascript:window.history.go(1)">前进</a> <a href="javascript:window.history.go(-1)">后退</a>四十五·浏览器ie和非ie浏览器的区分,区别是什么?<script> var val = navigator.userAgent; if(val.search('MSIE')>=0){ alert('ie浏览器'); }else{ alert('非ie浏览器'); } </script>四十六·设定网站的用户数量在千万级,但是活跃用户的数量只有1%,如何通过优化数据库提高活跃用户的访问速度?1·分区。(分活跃用户表和非活跃用户表)2·分表。(人为分表,需要在php写一段路由层,判断是活跃用户,或者非活跃用户)3·索引优化四十七·ajax技术利用了什么协议,简述一下ajax的工作机制?利用http协议工作原理:1·先通过浏览器内置的XMLHttpRequest类产生一个ajax对象,2·调用ajax对象open方法建立一个与某一个脚本发生通讯的链接3·设定好传输方式get/post,还要确定是异步还是同步,默认是异步4·调用ajax的send方法发送请求,发起对php文件的请求5·通过给ajax绑定状态检测事件,当状态码为4,并且服务器响应码为200时则获取php文件的响应数据。<script> function showHint(str) { var xmlhttp; if (str.length==0) { document.getElementById("txtHint").innerHTML=""; return; } if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp=new XMLHttpRequest(); } else { // IE6, IE5 浏览器执行代码 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("txtHint").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","/try/ajax/gethint.php?q="+str,true); xmlhttp.send(); } </script>四十八·利用php打印出前一天的时间格式是2017-8-10 22:21:50?echo date('Y-n-d H:i:s',strtotime('-1 day'));四十九·echo ,print ,print_r的区别是什么?1·echo 和print是语言结构,print_r是函数2·echo 可以有多个参数,print,print_r只能有一个参数3·print()只能打印简单的数据类型变量的值(int ,string)print_r()可以打印出复杂类型变量的值(数组,对象)echo 可以输出一个或者多个字符串五十·能够使html和php分离开使用的模板引擎?Smarty,template,thinkphp,laravel,yii
2019年07月10日
6,059 阅读
0 评论
1 点赞
2019-07-10
PHP经典面试题汇总(三)
二十一·写出数据类型(int char varchar datetime text)的意思,varchar 和char的区别?int数字类型,char固定长度字符串,varchar实际(可变)长度字符串,datetime日期时间类型,text文本类型char长度是固定的,不管你存储的数据是多少他都会都固定的长度。而varchar则处可变长度但他要在总长度上加1字符,这个用来存储位置,由于某种原因char 固定长度,所以在处理速度上要比varchar快速很多,但是对费存储空间,所以对存储不大,但在速度上有要求的可以使用char类型,反之可以用varchar类型来实例二十二·MyISAM和InnoDB的基本区别?innoDB支持事务机制、存储过程、行级锁定,MyISAM不支持,MyISAM在增删改查中速度快于InnoDB,作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,如果数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是首选,InnoDB不支持FULLTEXT类型的索引,InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可二十三·客户端禁用了cookie,怎么实现session技术共享多个页面?方法一.通过session获取session_id进行传值:a.php页面(设置session) session_start(); header("Content-type:text/html;charset=utf-8"); $user = $_SESSION['name'] = 'zhangsan'; echo $sid = session_id(); $sname = session_name(); echo ""; print_r($user); echo ""; echo "cookie"; b.php页面(接收session) if(isset($_GET['PHPSESSID'])){ session_id($_GET['PHPSESSID']); } session_start(); echo session_id(); echo ""; print_r($_SESSION); echo "";方法二.或者php.ini 配置选项,里面有一个session.use_trans_sid=0设置为1(在herf action header会自动添加SID,但是js跳转不会自动增加); 重启apache可以生效二十四·isset()和empty()的区别,对不同数据的判断结果?isset()是判断变量是否存在,是否定义empty()是判断变量的值是否为空二十五·如何在页面之间传递变量?get,post,ajax,curl,cookie,session二十六·写出匹配url的正则表达式?$url = "https://www.baidu.com/index.php?id=1&name=user1"; $reg = "/(http|ftp|https):[\/]{2}[a-z]+[.]{1}[a-z\d\-]+[.]{1}[a-z\d]*[\/]*[A-Za-z\d]*[\/]*[A-Za-z\d]* /"; echo preg_match($reg,$url);二十七·请写出常见的排序算法,并用php实现冒泡排序,将数组$a=array()按照从小到大的方式进行排序?function mysort($arr){ for($i=0;$i<count($arr)-1;$i++){ for($j=0;$j
2019年07月10日
5,743 阅读
0 评论
0 点赞
2019-07-10
PHP经典面试题汇总(二)
十一·如何进行防止SQL注入?1·表单尽量用post提交,核心用户验证都用post,表单判断使用get,因为get比post快2·使用$_SERVER[HTTP_REFERER]判断提交表单的源头是否是本机域名$path = $_SERVER['HTTP_REFERER']; $arr = parse_url($path); $arr2= $arr['host']; echo "<pre>"; print_r($arr2);3·php.ini开启addslashes,防止用户输入信息有单引号或者双引号对sql语句带来的破坏性,开启之后会在单双引号之前加反斜杠\’\”4·密码需要设置md5或Sha1加密5·服务器本身的安全(web + mysql)十二·防止盗链?1·服务器上防止盗链:Apache 和Nginx做rewrite基于源来做判断阻止盗链Apache设置防盗链方法:(.htaccess文件)RewriteEngine on RewriteCond %{HTTP_REFERER} !^$ [NC] RewriteCond %{HTTP_REFERER} !linuxidc.cn [NC] RewriteCond %{HTTP_REFERER} !google.com [NC] RewriteCond %{HTTP_REFERER} !baidu.com [NC] RewriteRule .(jpg|gif|png|bmp|swf|jpeg) /image/replace.gif [R,NC,L] RewriteRule ^(.*)$ http://image.linuxidc.cn/image/$1 [L]不是以上网站访问来源就直接转向:RewriteRule .(jpg|gif|png|bmp|swf|jpeg) /image/replace.gif [R,NC,L]Nginx设置防盗链方法:(/usr/local/nginx/conf/nginx.conf文件)location ~ .*\.(jpg|gif|png|bmp|swf|jpeg)$ { expires 30d; valid_referers none blocked *.linuxidc.cn *.google.com *.baidu.com; if ($invalid_referer) { rewrite ^/ ; return 404; } }2·代码防止盗链:$_SERVER[‘HTTP_REFERER’]十三·用php写出一个安全的用户登录系统需要注意哪些方面?1·验证码2·U盾3·动态口令卡4·限制登录次数5·使用数字键盘6·密码不能粘贴7·网址使用ssl,服务器证书https8·注册验证必须要使用php验证9·以post提交给后端php程序十四·使用过哪些php框架,试着描述其优劣点?Thinkphp:ThinkPHP(FCS)是一个轻量级的中型框架,是从Java的Struts结构移植过来的中文PHP开发框架。它使用面向对象的开发结构和MVC模式,并且模拟实现了Struts的标签库,各方面都比较人性化,熟悉J2EE的开发人员相对比较容易上手,适合php框架初学者。 ThinkPHP的宗旨是简化开发、提高效率、易于扩展,其在对数据库的支持方面已经包括MySQL、MSSQL、Sqlite、PgSQL、 Oracle,以及PDO的支持。ThinkPHP有着丰富的文档和示例,框架的兼容性较强,但是其功能有限,因此更适合用于中小项目的开发。优点:1.易于上手,有丰富的中文文档;2.框架的兼容性较强,PHP4和PHP5完全兼容、完全支持UTF8等。3. 适合用于中小项目的开发缺点1.对Ajax的支持不是很好;2.目录结构混乱,需要花时间整理;3.上手容易,但是深入学习较难。Yii:Yii 是一个基于组件的高性能php框架,用于开发大型Web应用。Yii采用严格的OOP编写,并有着完善的库引用以及全面的教程。从 MVC,DAO/ActiveRecord,widgets,caching,等级式RBAC,Web服务,到主题化,I18N和L10N,Yii提供了 今日Web 2.0应用开发所需要的几乎一切功能。事实上,Yii是最有效率的PHP框架之一。优点1·纯OOP2·用于大规模Web应用3·模型使用方便4·开发速度快,运行速度也快。性能优异且功能丰富5·使用命令行工具。缺点:1·对Model层的指导和考虑较少2·文档实例较少3·英文太多4·要求PHP技术精通,OOP编程要熟练!5·View并不是理想view,理想中的view可能只是html代码,不会涉及PHP代码。Lavarel:优点Laravel 的设计思想是很先进的,非常适合应用各种开发模式TDD, DDD 和BDD,作为一个框架,它准备好了一切,composer 是个php 的未来,没有composer,PHP 肯定要走向没落。laravel 最大的特点和优秀之处就是集合了php 比较新的特性,以及各种各样的设计模式,Ioc 容器,依赖注入等。缺点基于组件式的框架,所以比较臃肿CodeIgniter:优点:推崇“简单就是美”这一原则。没有花哨的设计模式、没有华丽的对象结构,一切都是那么简单。几行代码就能开始运行,再加几行代码就可以进行输出。可谓是“大道至简”的典范。 配置简单,全部的配置使用PHP脚本来配置,执行效率高;具有基本的路由功能,能够进行一定程度的路 由;具有初步的Layout功能,能够制作一定程度的界面外观;数据库层封装的不错,具有基本的MVC功能. 快速简洁,代码不多,执行性能高,框架简单,容易上手,学习成本低,文档详细;自带了很多简单好用的library,框架适合小型应用.缺点:本身的实现不太理想。内部结构过于混乱,虽然简单易用,但缺乏扩展能力。 把Model层简单的理解为数据库操作. 框架略显简单,只能够满足小型应用,略微不太能够满足中型应用需要.评价:总体来说,拿CodeIgniter来完成简单快速的应用还是值得,同时能够构造一定程度的layout,便于模板的复用,数据操作层来说封装的不 错,并且CodeIgniter没有使用很多太复杂的设计模式,执行性能和代码可读性上都不错。至于附加的library 也还不错,简洁高效。十五·用过哪些版本控制工具?svn subversion 版本控制github 版本控制十六·进制转换?对照表:1 1 1 1 1 1 1 1(二进制)128 64 32 16 8 4 2 1(十进制)例如:(二进制转换为十进制) 101010111 = 1×2^8 + 1×2^6 + 1×2^4 + 1×2^2 + 1×2^1 + 1×2^0 = 256+64+16+4+2+1 = 343(十六进制转换为十进制) 3A5B=3×16^3 + Ax16^2 + 5×16^1 + Bx16^0 = 3×4096 + 10×256 + 80 + 11×1 = 12288+2560+80+11=14939(十六进制转换为二进制) 41=0100 000116进制的1位数代表2进制的4位数(二进制转换为十六进制) 11010110 = B6四个数为一组(1101)= 1×2^3 + 1×2^2 + 1×2^0 = 13=B,(0110)= 1×2^2 + 1×2^1 = B6(十进制转换为二进制) 13=1101余数=被除数-除数*商13/2(商6 余数1),6/2(商3 余数0),3/2(商1 余数1),1/2(商0 余数1)规律:不断除以2,保留余数,商为0时不再除以2,将所有余数倒序排列。(十进制转换为十六进制) 138=8A138/16(商8 余数10 A),8/16(商0 余数8)规律:不断除以16,保留余数,商为0时不再除以16,将所有余数倒序排列。$int = 1+2+"23+4" = 26; ascii码转换: chr(65) == A; ord(A) == 65; $a = array(1=>5,5=>8,22,2=>'8',81); $a[7] == 81 //前一个最大下标加2 $a[6] == 81 //前一个最大下标加1 $a[3] 不存在,空 $a[bar] = 'hello'; $a[bar] 和 $a['bar'] 结果一样hello;位运算:echo 1>>0; // 001 ==>1 echo 2>>1; // 010 ==> 001 => 1 二进制向右移动1位,结果转十进制 echo 3<<2; // 011 ==> 01100 => 1x2^3+1x2^2=12 二进制向左移动2位,结果转十进制echo 可以打印多个参数,print不可以十七·下面能正确输出yellow的结果有哪些:$fruits = array('apple' =>'red','banana' =>'yellow'); echo "A banana is {$fruits[banana]}"; echo "A banana is {$fruits['banana']}"; echo "A banana is $fruits[banana]"; heredoc: $str=<<<str this is string str; echo $str;以上等同于$str=”this is string”;十八·什么是面向对象,主要特征是什么?也就是我们常说的OOP,以对象为中心的程序设计思维或者方式,好处是有两个成员组成,成员属性和成员方法,提高代码重用性,避免代码冗余度三大特征:封装,继承,多态十九·session和cookie的区别是什么,请从协议,产生的原因与作用说明?cookie数据存放在客户端的浏览器上,session数据放在服务器上,cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session,session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE,单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,将登陆信息等重要信息存放为SESSION, 其他信息如果需要保留,可以放在COOKIE中二十·HTTP状态中的200,302,304,403,404,500代码含义?200:成功访问,并返回数据302:重定向304:缓存未过期403:服务器拒绝访问,Apache权限拒绝访问404:访问的页面不存在500:服务器内部错误linux压缩:tar czf text.tar.gz test.phplinux解压:tar xzf test.tar.gz
2019年07月10日
6,695 阅读
0 评论
2 点赞
2019-07-10
PHP经典面试题汇总(一)
一· 用php获取当前时间并打印,打印格式:2017-3-25 22:20:21?echo date('Y-n-d H:i:s'); //月份未满十不补零,二十四小时制 echo date('Y-m-d h:i:s'); //月份未满十补零,十二小时制二· 字符串转数组,数组转字符串,字符串截取,字符串替换,字符串查找的函数分别是什么?1)字符串转数组:$str = 'www.baidu.com'; print_r(str_split($str,3)); print_r(explode(".",$str));2)数组转字符串:$arr = array('aaa','bbb','ccc'); echo implode('',$arr); echo join(' ',$arr);3)字符串截取:$str = "这是一个字符串this is a string!"; echo substr($str,0,4); //截取英文字符串 echo mb_substr($str,0,4,'utf-8'); //按照字符个数截取字符串 echo mb_strcut($str,0,6); //按照字节数截取字符串(中文三个字节为一个中文字)4)字符串替换:$table_change = array('you'=>'her sister','Love' => 'hate'); echo strtr("I Love you",$table_change); //比str_replace快四倍,区分大小写,但是这个函数挺麻烦,不能替换为空,可以替换空白 $bodytag = str_replace("%body%", "black", ""); //区分大小写 echo $bodytag; $str = "linux is very good server for php"; echo preg_replace('/linux|php/','java',$str); //使用正则替换5)字符串查找:$str = "/web/b/c/index.html"; echo strpos($str,'/'); //查找第一个出现的位置,返回位置数 echo strrpos($str,'/'); //查找最后一个出现的位置,返回位置数 $pos = strrpos($str,'/'); echo substr($str,$pos+1); //截取路径里面的文件部分 echo substr($str,0,$pos); //截取路径里面的目录部分 echo basename($str); //获取路径中的文件名 echo dirname($str); //获取路径中的目录 $str = "pap is pbp and pcp or pdp"; preg_match_all('/p.p/',$str,$ms); //正则匹配,返回数组 echo "
2019年07月10日
6,683 阅读
0 评论
5 点赞
2019-07-10
linux定时任务的设置与使用
定时任务命令:1· 定时任务服务提供crontab 命令来设定服务。2· crontab -e //编辑某个用户的cron服务。3· crontab -l //列出某个用户cron服务的详细内容。4· crontab -r //删除每个用户的cron服务。例如:*/1 * * * * php /data/www/cron.php //意思是每分钟执行cron.php50 7 * * * /sbin/service sshd start //意思是每天的7:50开启ssh服务30 7 8 * * ls //意思是每月8号的7:30分执行ls命令分 时 日 月 星期 命令0-59 0-23 1-31 1-12 0-6
2019年07月10日
6,094 阅读
0 评论
1 点赞
2019-07-09
高性能网站架构方案
高性能网站架构方案,用以优化网站响应时间,实现大型网站技术架构方案。无论是电子商务或者其他网站且可使用。一、优化网站响应时间的架构方案: 网站能不能留的住用户,一方面是看内容,另一方面是看响应时间。通常有以下几个方式来降低网站响应时间: 1、减少HTTP请求。包括合并css和javascript。减少图片数量,比如利用css的偏移技术来在一个图片中选择不同的位置内容。利用浏览器的Cache功能,我们可以在头中声明是否被浏览器缓存。 2、动态内容静态化。比如永久生成HTML文件。生成静态文件并设定生存时间,到期后查询新的动态内容进行替换。 3、优化数据库。数据库的性能对于项目整体性能中是重中之重。设计良好的Mysql比乱糟糟的Mysql性能高出N个数量级,更别论再引入NOSQL了,比如Redis,MongoDB。 4、使用负载均衡。将请求合理的分发到更多服务器。 5、使用缓存。把花费时间和资源成本高昂的计算结果取出缓存起来,避免重复计算。比如在Mysql前面挡一层Memcached。比如生成一个文件,使用的时候include进来。再比如PHP中的OPCACHE等。二、压力测试的架构方案: 吞吐率是指单位时间内处理的请求数,单位reqs/s。最大吞吐率是指单位时间内能够处理的最大请求出。模拟足够多的人数和并发请求来测试最大吞吐率的方法叫做压力测试。比如Apache自带的ab(Apache Bench)。ab的参数很多,常用的有请求数(-n),并发用户数(-c),超时时间(-t),长连接(-k),附件一个Cookie(-c name=value)$ab -c 10 -n 1000 http://localhost/三、长连接的架构方案: 每次请求都需要TCP的三次握手,握手完比表示连接正式联通,之后再发送数据。那么,把N个请求,就需要3N次握手,传递N次数据,得到N次响应,总共5N。如果把N个请求合成一个请求,就是3次握手,1次传递数据,1次返回响应,共5次。但是,有时候我们需要上一次响应的返回结果来发送新一轮的请求,在这个时候,合并请求并不好实现,这就需要长连接。使用起来很简单,在头中包含如下:Connection: Keep-Alive 客户端和服务器端都可以设置长连接的最大时间,当两者不统一时以小的一方为准。开启长连接后进行压力测试:$ab -c 10 -n 1000 http://localhost/ 发现提升不止三五倍。本机是提升了8倍的性能。四、提高Mysql的响应速度的架构方案: Handlerocker是日本的一位架构师开发。Mysql的一种插件。Handlerocker实现了绕过Mysql的SQL解析层。在Mysql5.1以上版本可以使用,详情可以查看Mysql手册。这里就不在阐述。五、Mysql主从复制的架构方案: 在分布式部署中,1台主库,N台从库。主库只写,从库只查。主库从库数据需要实现统一,这就是主从复制。优点是: 1、从库备份时,主库可以继续处理更新。 2、优化响应时间。 3、增加健壮性。主库挂了可以切换到从库作为备份。 主从复制的实现过程有三步,1个在主库,2个在从库: 1、主库服务器将用户对数据库更新的操作以二进制格式保存到Binary Log日志文件。然后Binlog Dump线程将Binary Log日志文件传输给从库服务器。 2、从库服务器通过一个I/O线程将主库服务器的Binary Log日志文件中的更新操作复制到一个叫做Relay Log中的中继日志文件中。 3、从库服务器通过另一个SQL线程Relay Log中继日志文件中的操作依次在本地执行,从而实现主从数据库之间数据的同步。 本篇只是简单的列出方案,详细的配置和实现步骤将在另一篇中写到。六、代理的架构方案: 读取内存的速度是读取硬盘的100000-1000000倍。把访问过的页面缓存在内存中,下次直接从内存中读取,可以有效加速。 1、传统代理。客户端发送请求给代理服务器,代理服务器向WEB服务器取到数据并返回给浏览器。代理服务器就是一个有大的存储空间的Cache。 2、反向代理。和传统代理原理类似,只是使用对象不同。传统代理的使用对象是客户端,反向代理的使用对象是服务器。用户通过反向代理访问Web服务器,Web服务器是隐藏起来的。不过用户不关心这些,权把代理服务器当作真实的Web服务器。反向代理有Vamish。七、异步计算的架构方案: 比较耗时的比如将用户上传的文件分发到多台机器,比如裁剪图片,视频转码等。可以使用异步方案。让用户无须等待计算结束而是先行返回结果。代表产品有和Me
2019年07月09日
10,115 阅读
0 评论
2 点赞
2019-07-04
数据结构与算法视频教程
提取码:964a 数据结构:是指相互之间存在一种或多种特定关系的数据元素的集合用计算机存储、组织数据的方式。数据结构分别为逻辑结构、(存储)物理结构和数据的运算三个部分。为什么要学数据结构? 首先,因为数据结构作为计算机专业的专业基础课程,是计算机考研的必考科目之一,如果打算报考计算机专业的研究生,你必须学好它;其次,数据结构是计算机软考、计算机等级考试等相关考试的必考内容之一,想要顺利通过这些考试,你也必须学好它;最后,数据结构还是你打算今后学习计算专业其他课程的基础,如操作系统、编辑原理、数据库管理系统、软件工程、人工智能等。总而言之,你既然已经与计算机接轨就必须掌握好它。如何学习数据结构? 对于初学者来说,数据结构是门概念上比较抽象的课程,不是太容易掌握,需要构思和理解。万事开头难,只要你掌握了学习这门课的方法和技巧,就会变得很容易了。不管学什么,首先应该做好充分的心理准备,建立好自信心,拥有一颗战胜困难的决心,才能不畏惧、不退缩,直至胜利归来。其次,就是最好有C语言基础,这样学起来事半功倍,当然没有C语言基础也行,可以一边学数据结构一边巩固C语言知识。最后,就是多动手!多动手!多动手!重要的事情说三遍!只有亲自动手上机操作或用笔在纸上画画写写才能加深映像,方便理解记忆。
2019年07月04日
11,810 阅读
0 评论
63 点赞
2019-07-04
Apicloud-7天掌握跨平台app开发
提取码:3vag一、APICloud应用设计思想及架构设计【技术讲解】APICloud应用设计思想、UI组成架构、混合渲染原理等【开发实战】根据实际应用的开发需求,进行UI架构设计、功能分解、制定开发计划、云端创建应用、应用配置、编译生成安装包、分析安装包结构、分析APICloud应用代码结构等。二、APICloud页面布局及开发工具使用【技术讲解】APICloud引擎执行流程,应用执行流程;屏幕适配、窗口管理、界面切换、事件交互、界面间通信等API的使用【开发实战】基于实际应用的UI设计图,搭建应用框架、编写首页代码、调用API完成应用主要界面直接的交互,完成应用的第一个静态页面版本。三、APICloud网络通信及数据云使用【技术讲解】平台网络通信相关API的使用,在数据云中根据应用需求设计数据模型及表结构,为应用提供动态数据【开发实战】将应用中的静态数据改为从网络动态获取,使用模板函数来实现布局和数据分离;完成进度提示、下拉刷新、加载更多等。四、数据存储、缓存及资源访问等API的使用【技术讲解】APICloud平台的4种数据存储方式、应用沙箱结构、访问方式、缓存机制等【开发实战】在实际应用中完成登录、注册以及文件下载等功能,通过API存储用户信息,并且管理本地资源,网络图片使用缓存等。五、APICloud模块使用【技术讲解】APICloud的高模块化架构设计、模块扩展机制、模块通用设计原则、模块Store等【开发实战】通过使用模块相关API,在应用中完成第三方登录管理以及阅读功能的实现。六、跨平台应用的性能优化策略【技术讲解】生命周期控制、事件响应、动画效果、网络状态、加载速度、渲染速度等【开发实战】在开发的项目中应用这些策略对应用进行优化;完成应用中的其他功能,输出应用的第一个版本。七、应用管理相关API综合讲解及总结【技术讲解】应用管理相关的控制台操作流程、版本管理、云修复、推送、统计等的实现机制。【开发实战】在应用中完成版本管理、云修复、推送统计等相关功能,升级版本;综合讲解并总结,对开发问题进行集中答疑。
2019年07月04日
11,961 阅读
0 评论
7 点赞
2019-07-02
linux查看与设定别名
1.alias :查看系统中所有的命令别名2.设定别名 alias 别名='原命令'3.删除别名 unalias 别名4.使别名永久生效 vi ~/.bashrc 写入这个文件中即可永久生效 编辑完之后记得使环境变量生效: source .bashrc
2019年07月02日
5,645 阅读
0 评论
1 点赞
2019-07-02
libxml2 configure: error: xml2-config not found. Please check your libxml2 insta
在Linux下,编译安装PHP时报错:libxml2 configure: error: xml2-config not found. Please check your libxml2 installation.但是在Linux下已经安装了libxml2,我通过rpm -qa | grep libxml2就可以查到,那为什么还会提示那个错误呢?应该是libxml2-dev。ubuntu/debian:apt-get install libxml2-devcentos/redhat:yum install libxml2-devel
2019年07月02日
5,159 阅读
0 评论
2 点赞
2019-06-24
Swoole文档中心
PHP的 协程 高性能网络通信引擎,使用C/C++语言编写,提供了多种通信协议的网络服务器和客户端模块。包括: TCP/UDP/UnixSock 服务器端 Http/WebSocket/Http2.0 服务器端 协程 TCP/UDP/UnixSock 客户端 协程 MySQL 客户端 异步 Redis 客户端 协程 Http/WebSocket 客户端 协程 Http2 客户端 AsyncTask 毫秒定时器 协程文件读写 Swoole4支持完整的协程编程模式,可以使用完全同步的代码实现异步程序。PHP代码无需额外增加任何关键词,底层自动进行协程调度,实现异步IO。
2019年06月24日
5,496 阅读
0 评论
2 点赞
2019-06-21
PHP秒杀系统 高并发高性能的极致挑战
提取码:6et5 第1章 课程介绍 秒杀系统在各种网站和应用中经常会用到。本课程从基本的系统设计和基础功能开始教导大家用PHP来设计和实现秒杀系统,并且为海量并发提供更高级的技术方案和实现手段。 1-1 课程导学 1-2 课程目标 1-3 秒杀系统特点 1-4 课程技术分析第2章 系统技术选型分析 本章节需要大家掌握基础的LNMP平台的开发,提供基础的数据封装类,让后续的开发得心应手。我们会讲解到系统环境的技术选型,我们采用的数据库是Mysql,还用到Redis来作为高性能缓存, 为了让大家不拘泥于框架的选择,巩固基础知识,本门课程使用原生PHP的方式来开发。… 2-1 技术选型分析之基础服务 2-2 技术选型分析之CDN 2-3 技术选型分析负载均衡 2-4 开发环境准备 2-5 MySQL封装类 2-6 Redis封装类 2-7 调试封装类(上) 2-8 调试封装类(下)第3章 系统设计 有一个好的系统设计,整个系统也就成功了一半。本章节会从项目功能、流程、活动表的设计、商品信息表的设计、日志问答订单表及页面交互设计等多个维度去讲解如何设计一个既能满足当前又能兼顾未来,有统一的标准,也有灵活扩充的系统。 3-1 系统设计之项目基本功能 3-2 系统设计之项目流程 3-3 数据库设计-活动信息表 3-4 数据库设计-商品信息表 3-5 数据库设计-日志问答订单信息表 3-6 系统设计之交互和页面设计第4章 秒杀功能开发 本章节就是实打实的进入到代码编写和讲解的环节了,本节课我们会完成 商品页面开发、商品的状态控制、商品秒杀逻辑的实现及数据处理逻辑的实现。 4-1 商品页面开发-服务端代码 4-2 商品页面开发–模版代码 4-3 商品的几种状态控制 4-4 秒杀逻辑控制器 4-5 数据逻辑处理(上) 4-6 数据逻辑处理(下)第5章 秒杀后台功能管理 本章节系统讲解后台管理功能,从活动管理、商品上下线管理、商品管理、订单管理等多方面入手,让秒杀随时可控。 5-1 活动信息管理 5-2 活动上下线信息管理 5-3 商品信息管理 5-4 活动订单管理 5-5 活动参与日志管理第6章 单商品秒杀(理论篇) 本章节重点讲解单产品的秒杀。从单个商品的秒杀开始,我们会讲解不同规模的秒杀如万次、百万次、过亿次秒杀系统要如何考虑和实现。以及讲解对单商品在不同的秒杀量级下,会遇到的问题和困难,分别有哪些要注意的地方和改进的方法。 6-1 单商品特点 6-2 单商品万次秒杀 6-3 单商品百万次秒杀 6-4 单商品过亿次秒杀第7章 组合商品秒杀(理论篇) 前面章节我们讲解到单商品秒杀会遇到的问题及应对措施,本章节会重点讲解由单商品升级到组合商品更复杂的关联关系时,我们又会面临的问题以及应对策略。 7-1 组合商品特点 7-2 组合商品万次秒杀 7-3 组合商品百万次秒杀 7-4 组合商品过亿次秒杀第8章 优化单机性能(实战篇) 单机性能上去了,集群才有可能处理更多请求,整体系统才能快起来。从本章节我们会从页面访问速度、接口访问速度、数据处理速度、代码逻辑的细节地方入手,来优化我们的单机性能,从交互策略的调整上,改善秒杀系统的性能,从而应对更大的并发量。 8-1 提高页面访问速度–gzip 8-2 提高页面访问速度–合并和压缩 8-3 提高页面访问速度–缓存和CDN 8-4 提高秒杀接口速度 8-5 提高秒杀接口速度–astatus 8-6 提高秒杀接口速度–前端调用 8-7 提高数据处理速度 8-8 提高数据处理速度-代码改造(一) 8-9 提高数据处理速度-代码改造(二) 8-10 章节总结第9章 分布式方案 灵活的分布式方案是我们对过亿次秒杀有从容应对的基本底气。本章节则从接入层、数据层,来设计服务器集群架构,以助于我们把系统有机会可以部署和扩充到更大规模的服务器上,让更多的服务器资料来帮助我们抗住更大的并发。 9-1 分布式方案–多个接入层服务器 9-2 选购和部署服务器 (上) 9-3 选购和部署服务器(下) 9-4 分布式方案–多WEB服务器单数据中心 9-5 在服务器上部署秒杀系统 9-6 分布式方案–多WEB服务器多数据中心 9-7 LVS的部署和使用 9-8 分布式方案–服务器规模预估 9-9 中控服务的功能和实现 (上) 9-10 中控服务的功能和实现 (下) 9-11 秒杀系统的压力测试(一) 9-12 秒杀系统的压力测试(二) 9-13 秒杀系统的压力测试 (三)第10章 拒绝黄牛刷单 秒杀系统存在的一个很大的挑战就是黄牛刷单的存在!一个黄牛可怕,可怕的是黄牛后面的机器人黑客手段。本章节会从问答验证、触点验证、行为分析等方面,带领大家讲解如何阻断机器人的刷单。 10-1 机器人无法猜测的问答式验证码-原理篇(上) 10-2 机器人无法猜测的问答式验证码-原理篇(下) 10-3 机器人无法猜测的问答式验证码-代码
2019年06月21日
13,997 阅读
0 评论
88 点赞
2019-06-21
PHP开发高可用高安全App后端
提取码:br73 高安全授权码 sign算法登录场景 access_user_token算法token 唯一性支持API 一次性请求支持高可用restful api开发全过程web登录和APP登录一同簇APP本地时间和服务器时间一致性解决方案不可预知的API内部异常解决方案APP版本升级解决方案利用七牛云解决图片处理基础服务能力基础类库的封装部分php设计模式的穿透部分模块提供多种解决方案最后选择最优的方案php+ajax实现异步数据交互APP端异常、性能监控以及定位解决方案多种APP调试方案(编辑器调试APP,手机调试APP)TP5核心模板引擎vendor下核心类库的安装分析核心框架类库的内核如何编写接口文档系统效果后台模块APP模块部分视频截图:
2019年06月21日
12,527 阅读
0 评论
79 点赞
2019-06-21
微信小程序商城构建全栈应用
提取码:xgku 微信小程序商城构建全栈应用课程目录:第1章 前言:不同的时代,不同的Web第2章 环境,工具与准备工作第3章 模块,路由与获取请求参数第4章 构建验证层第5章 REST与RESTFul第6章 AOP与全局异常处理第7章 数据库访问与ORM第8章 专题、分类、商品详情接口编写第9章微信登陆与令牌第10章 微信支付第11章前端部分:前端框架构建与令牌管理第12章 购物车第13章 实现微信支付、购买商品流程与用户历史订单+第14章 CMS与CORS跨域第15章 小程序部署流程与TP5在生产环境中的优化
2019年06月21日
15,030 阅读
0 评论
269 点赞
2019-06-20
Swoole实战打造高性能直播平台
提取码:w0bv 该课程包含Swoole入门到图文聊天室实战的课程内容,讲得很全面细致,只要动手跟着边学边敲代码,很容易就能上手,所有视频本人均看过,视频画面和音质清晰。1. 课程介绍 欢迎大家来到swoole的课程!本章主要是介绍了swoole的一些特性,以及使用场景,并且分享了swoole在其他公司的一些案例,最后重点讲解了swoole学习的一些准备工作。2. PHP 7 源码安装 很多工作好几年的PHPer对源码编译安装并不是很了解,其实这种情况是非常可怕的。本章我会教大家如何通过源码安装PHP7,并且简化PHP执行命令。最后重点讲解了源码安装踩到的坑,让您在源码编译安装过程中少走很多弯路。3. 源码编译安装swoole Swoole的安装方式有2种:傻瓜式安装和源码编译安装!本章节我将带领大家通过源码编译安装Swoole扩展,让大家真正去理解Swoole的安装方式和参数设置。最后让PHP支持Swoole,然后开启第一个swoole程序!4. 玩转网络通信引擎 本章重点介绍了TCP UDP HTTP websocket通信引擎。在swoole http server中会带领大家对比传统的http,并教大家如何配置swoole http让他支持静态资源的访问;同时详细讲解如何使用Swoole websocket轻松解决客户端和服务器端长连接难题;使用Swoole提供了异步task任务完美解决实际工作中面临的耗时的场景,本章会特别细…5. 异步非堵塞IO场景PHP+Crontab做定时任务是很常见的案例,但是Crontab只能精确到分钟级,Swoole的毫秒定时器能轻松精确到更细的力度。本章详细讲解了毫秒定时器、异步文件读和写、异步Mysql、以及异步Redis并且每一个场景都结合案例来讲解,让小伙伴轻轻松松的理解这些场景;最后为了让Swoole支持异步Redis 课程中还教大家如何源码编译安装6. 进程、内存、协程原生的PHP不支持多线程,多进程支持的也不是很好。Swoole提供了很好的多进程处理方案。课程中详细的讲解了进程,并且通过一个场景来分析Swoole进程的使用场景,让小伙伴对Swoole进程有新的认知;在多进程中子进程和子进程以及子进程和主进程如何共享数据?课程中通过内存来引入这个话题,并详细讲解了Swoole table模块。7. 赛事直播—登录模块 前面学习完Swoole后,我们就开始正式进入到实战项目阶段!项目框架我们采用Thinkphp 5.0 ,项目中的静态页面是单独部署在一个模块的,所有他的数据都是通过Ajax获取后端数据;做到前后端分离;登录案例中我们使用到了swoole http的特性,登录方式我们采用手机号+短信验证码的方式进行登录并且将数据存储到Redis中。8. 赛事直播 – 直播模块 本章我们会实现赛事节目列表页面; 赛事直播页 赛事数据页;在赛事直播的页面中由于客户端和服务器端必须是要保持一个长久的连接,这样后端有新的直播数据的时候页面才能实时的呈现,这个地方我们用到的就是swoole里面websocket并且还会结合异步task任务来处理响应的内容,赛事的内容我们支持图片+文字;课程中还会讲解开…9. 赛事直播 – 聊天室模块 本章我会带领大家利用Swoole websocket等知识点实现聊天室模块!聊天室模块是指每个登录的用户可以实时的和其他用户一起聊天,畅游比赛心得,同时我们会使用swoole的特性来获取在线的用户数。10. 系统监控和性能优化模块 系统的稳定运行是每个工程师必须要深度考虑的问题,一个系统如果线上运作不稳定,无论你技术方案多么先进你的系统也是不靠谱系统;课程中利用Linux+Swoole+PHP监控平台的稳定性,为服务保驾护航;面对高流量实时在线的用户如何提升系统服务性能 本课程给大家带来干货内容,结合自身7年大型互联网工作经验毫无保留的教大家…
2019年06月20日
12,662 阅读
0 评论
26 点赞
2019-06-19
秒数转换为日时分秒格式
秒数转换为日时分秒格式PHP版:/** * 秒数转换天时分秒 */ protected function formatTime($second){ $day = floor($second/(3600*24)); $second = $second%(3600*24); $hour = floor($second/3600); $second = $second%3600; $minute = floor($second/60); $second = $second%60; $str = ''; if ($day>0){ $str .= $day.'天'; } if ($hour>0){ $str .= $hour.'小时'; } if ($minute>0){ $str .= $minute.'分'; } if ($second>0){ $str .= $second.'秒'; } return $str; }JS版://秒数转换天时分秒 function formatTime(mss) { var days = parseInt(mss / (60 * 60 * 24)); var hours = parseInt((mss % (60 * 60 * 24)) / (60 * 60)); if (nowHour !== hours) { window.location.reload(); } var minutes = parseInt((mss % (60 * 60)) / 60); var seconds = (mss % 60); var str = ''; if (days>0){ str += days + " 天 "; } if (hours>0){ str += hours + " 小时 "; } if (minutes>0){ str += minutes + " 分钟 "; } if (seconds>0){ str += seconds + " 秒 "; } return str; }
2019年06月19日
4,949 阅读
0 评论
1 点赞
2019-06-17
解决: g++: internal compiler error: Killed (program cc1plus)
g++: internal compiler error: Killed (program cc1plus)Please submit a full bug report,在centos7编译php7的时候遇到的问题,记录一下。 主要原因是内存不足, 使用的渣渣配置1核1M,临时使用交换分区来解决吧。sudo dd if=/dev/zero of=/swapfile bs=64M count=16sudo mkswap /swapfilesudo swapon /swapfile用完之后得还回去:sudo swapoff /swapfilesudo rm /swapfile
2019年06月17日
8,202 阅读
0 评论
4 点赞
2019-06-15
VC15运行库32/64位
提取码:umog php5.3、5.4和apache都是用vc9编译,电脑必须安装vc9运行库才能运行。php5.5、5.6是vc11编译,如用php5.5、5.6必须安装vc11运行库。php7.0、7.1是vc14编译,如用php7.0、7.1及以上版本必须安装vc14运行库。Visual C++ Redistributable Package是安装 Visual C++ 库的运行时组件。以上安装VC++系统运行库必须是32位的
2019年06月15日
5,933 阅读
0 评论
48 点赞
2019-06-14
php使用unlink删除文件时失败的原因
在做网站的文件上传功能时,遇到了不能删除文件的问题。 我采用的方案是用户先上传到服务器,服务器再上传到阿里云的OSS,中间会有一个把图片临时存储到服务器的过程。使用php的@unlink(删除指定文件)方法时发现了删除失败的问题,很是疑惑。 开始以为是路径名写错了,后来确认路径没有错误并且是绝对路径。删除失败的原因是图片仍然被进程占用,以至于删除失败。 所以想要成功执行unlink操作,我们最好手动释放下文件对象,避免因为被其他线程或进程占用而导致删除失败,小呆萌如下:public function upload() { //获取上传文件 $file = $this->request->file('file'); if ($file) { // 移动文件到 uploads 目录下 $info = $file->rule('date')->move(ROOT_PATH . 'public' . DS . 'uploads'); if ($info) {//文件上传到服务器成功->接下来上传到OSS $filePath = ROOT_PATH . 'public' . DS . 'uploads/' . $info->getSaveName(); $oss = new Oss(); $result = $oss->putObject($filePath); if ($result) { //上传到OSS成功 unset($info);//解除图片的进程占用 @unlink($filePath); return success(['avatar' => $result['fileSrc']], '头像更新成功'); } } } }
2019年06月14日
6,864 阅读
0 评论
52 点赞
2019-06-13
mysql 根据经纬度计算距离并排序
mysql 根据经纬度计算距离并排序。计算公式是这样的: Lng1表示A点纬度和经度,Lat2 Lng2 表示B点纬度和经度a = Lat1 – Lat2为两点纬度之差 b = Lng1 -Lng2 为两点经度之差6378.137为地球半径,单位为公里计算出来的结果单位为公里SELECT *, ( 2 * 6378.137 * ASIN( SQRT( POW( SIN( PI() * (111.86141967773438 - lng) / 360 ), 2 ) + COS(PI() * 33.07078170776367 / 180) * COS(lat * PI() / 180) * POW( SIN( PI() * (33.07078170776367 - lat) / 360 ), 2 ) ) ) ) AS juli FROM `area` ORDER BY juli ASC LIMIT 0, 20;PHP计算经纬度方法:/** * @desc 根据两点间的经纬度计算距离 * @param float $lat 纬度值 * @param float $lng 经度值 */ function getDistance($lat1, $lng1, $lat2, $lng2) { $earthRadius = 6367000; $lat1 = ($lat1 * pi() ) / 180; $lng1 = ($lng1 * pi() ) / 180; $lat2 = ($lat2 * pi() ) / 180; $lng2 = ($lng2 * pi() ) / 180; $calcLongitude = $lng2 - $lng1; $calcLatitude = $lat2 - $lat1; $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2); $stepTwo = 2 * asin(min(1, sqrt($stepOne))); $calculatedDistance = $earthRadius * $stepTwo; return round($calculatedDistance); }
2019年06月13日
10,366 阅读
0 评论
146 点赞
2019-06-10
QQ推送服务,QQ群管,QQ定时提醒,QQ机器人
QQ推送服务,无需挂机,无需技术运维,通过api接口即可推送qq消息以及QQ消息接口回调,可以实现QQ推送服务,QQ机器人,qq定时推送,QQ群管,QQ定时提醒等功能。 可以用于消息通知、订单通知、个人收款码支付通知审核等场景。 通过后台可以添加定时推送任务,设置执行循环计划、推送内容、接收QQ号即可定时接收到设置好的消息推送。 零技术门槛,点点鼠标即可,若上述功能不能满足您的需求,可联系QQ进行定制开发。服务名称:QQ推送费用:基础版免费服务描述:通过api接口/或后台定时的方式推送qq消息到指定qq。应用场景:qq消息通知、qq验证码、qq定时提醒、新订单提醒、qq群通知、qq群消息同步、git更新群通知等等。立即开通
2019年06月10日
8,121 阅读
0 评论
156 点赞
2019-06-06
软著申请资料模板示例及申请地址
提取码:x2ur 点击以上链接下载软件著作权申请的资料模板以及表格填写说明等资料。中国版权登记系统:http://apply.ccopyright.com.cn/cpcc/column_list_bqdj.jsp软件著作权即软件开发者、软件所有者对软件享有发表权,使用权等权利,但是享有权利前应到相关部门进行登记申报,看是否符合法定的要求。 请使用IE浏览器,否则提交著作权登记申请的时候可能会遇到无法提交的问题。
2019年06月06日
13,363 阅读
0 评论
203 点赞
2019-05-17
常用银行sql表(含银行标识)及银行logo
提取码:94th 常用银行sql表(含银行标识)及银行logoCREATE TABLE `bank` ( `id` int(11) NOT NULL AUTO_INCREMENT, `bank_name` varchar(20) NOT NULL COMMENT '银行名称', `bank_code` varchar(11) NOT NULL COMMENT '银行标识码', PRIMARY KEY (`id`), KEY `bank_name` (`bank_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2019年05月17日
16,254 阅读
0 评论
158 点赞
2019-05-17
通过酷Q实现qq机器人,实现qq客服、定时推送qq消息、群管理等功能
通过酷Q实现qq机器人,实现qq客服、定时推送qq消息、群管理等功能。方式:1.windows下载酷Q并安装http-api插件。 下载地址:https://pan.baidu.com/s/1qY55zp62.直接使用docker,通过wine运行在linux系统上。$ docker pull richardchien/cqhttp:latest $ mkdir coolq # 用于存储酷 Q 的程序文件 $ docker run -ti --rm --name cqhttp-test \ -v $(pwd)/coolq:/home/user/coolq \ # 将宿主目录挂载到容器内用于持久化酷 Q 的程序文件 -p 9000:9000 \ # noVNC 端口,用于从浏览器控制酷 Q -p 5700:5700 \ # HTTP API 插件开放的端口 -e COOLQ_ACCOUNT=123456 \ # 要登录的 QQ 账号,可选但建议填 -e CQHTTP_POST_URL=http://example.com:8080 \ # 事件上报地址 -e CQHTTP_SERVE_DATA_FILES=yes \ # 允许通过 HTTP 接口访问酷 Q 数据文件 richardchien/cqhttp:latest其中,CQHTTP_POST_URL、CQHTTP_SERVE_DATA_FILES 是用于配置插件运行的,格式为「CQHTTP_ + 插件配置项的大写」,具体的配置项,见 配置。然后访问 http://注意,默认情况下,容器启动时会检查是否已经存在 config 目录,如果不存在,则会将 CQHTTP_ 开头的环境变量写入到配置文件中;如果 config 目录存在,即不是首次启动,则不会做任何修改。因此,你可以在容器运行时手动修改配置文件,重启容器后仍然有效,这和旧版本的行为不一样!如果你要让容器每次启动时都使用环境变量重新创建配置文件,以保持插件行为和容器启动命令的一致性,可以设置环境变量 FORCE_ENV 的值为 true。完成上述配置后即可通过调用api完成qq的发送消息及qq群管理等功能,剩下的具体的业务逻辑使用自己熟悉的语言去实现即可。详细的接口文档:https://richardchien.gitee.io/coolq-http-api/附点餐小呆萌代码:/** * 接收事件上报 * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function receive(){ try{ $getData = input('post.') ? : file_get_contents('php://input'); if (!empty($getData['group_id']) && (int)$getData['group_id'] == $this->groupId) { if ($this->userId = $this->getGroupUserid()){ $content = $getData['raw_message'] ? : $getData['message']; //分离酷q的前置数据与内容文本 preg_match('/(.*[CQ:]{3}.*[]]{1})(.*)/u', $content, $arr); if (!empty($arr[1]) && !empty($arr[2])){ //提取前置数据中被@的qq号 preg_match('/(.*[CQ:at,qq=]{9})([0-9]{5,11})([]]{1})/u', $arr[1], $arr1); if (!empty($arr1[2]) && (int)$arr1[2] == 167114078){ //来到这里证明是被at了,取得纯文本内容进行下一步处理 $tasks = db("group_task") ->whereTime('create_time', 'today') ->select(); if (count($tasks)>=2){ preg_match_all("/([周]{1})([一二三四五六日]{1}).{0,3}([a-cA-C]{1}|[\u{4e0d}]{1}[\u{70b9}]{1})/u", $arr[2],$arr8); $dateArr = $this->getLastSevenDays(); if (!empty($arr8[2])) { //有选项 $data = []; //获取任务id与时间的对应数组,用于判断用户输入的时间有没有任务 $taskArr = array_column($tasks, 'id', 'time'); foreach ($arr8[2] as $key => $value) { $data[strtotime($dateArr[$this->changeDateType($value)])] = $arr8[3][$key]; if (!empty($taskArr[strtotime($dateArr[$this->changeDateType($value)])])){ $taskId = $taskArr[strtotime($dateArr[$this->changeDateType($value)])]; $this->order($taskId, $arr8[3][$key]); }else{ $this->sendGroup($this->groupId, "{$this->groupUserInfo['user_name']}周{$value},没有可点套餐。"); } } }else{ //无选项 preg_match('/([不]{1}[点]{1})/u', $arr[2],$arr2); preg_match('/([A-Ca-c])/u', $arr[2], $arr3); if (!empty($arr2[0]) && $arr2[0] == "不点" || !empty($arr3[0]) && in_array(ucfirst($arr3[0]), ['A', 'B', 'C'])){ $lists = []; $listsNote = []; foreach ($tasks as $v){ $lists[] = "周".$this->changeDateType((int)date("w", $v['time'])); $listsNote[] = "周".$this->changeDateType((int)date("w", $v['time'])) . "-A"; } $msg = "大佬,今天要点" . count($tasks) ."天的餐,你这样我不知道你想点哪一个呀。". PHP_EOL ."今日可点餐有" . implode('、', $lists) . ",点餐请按示例格式回复。". PHP_EOL ."如:" . implode(' ', $listsNote); $this->sendGroup($this->groupId, $msg); } } }else{ if (!empty($tasks[0]['id'])){ preg_match('/([不]{1}[点]{1})/u', $arr[2],$arr2); preg_match('/([A-Ca-c])/u', $arr[2], $arr3); if (!empty($arr2[0]) && $arr2[0] == "不点") { $this->order($tasks[0]['id'], $arr2[0]); exit; }else if (!empty($arr3[0]) && in_array(ucfirst($arr3[0]), ['A', 'B', 'C'])) { $this->order($tasks[0]['id'], ucfirst($arr3[0])); exit; }else { //$this->sendGroup($this->groupId, "不要@我,大佬不给我说话!"); exit; } } } } } } exit; } }catch (\Exception $e){ Log::write("Receive message:".$e->getMessage()); } } /** * 发送消息 * 多行内容部分记得urlencode * @param bool $toUserId * @param bool $content */ public function send($toUserId = false, $content = false){ if ($toUserId && $content){ $content = urlencode($content); $url = "http://127.0.0.1:5701/send_private_msg?user_id={$toUserId}&message={$content}"; file_get_contents($url); } } /** * 发送群消息 * @param bool $groupId * @param bool $message */ public function sendGroup($groupId = false, $message = false){ if ($groupId && $message){ $message = urlencode($message); $url = "http://127.0.0.1:5701/send_group_msg?group_id={$groupId}&message={$message}"; file_get_contents($url); } } /** * 获取群用户id * @return bool|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ private function getGroupUserid(){ $userModel = db('group_user'); $userInfo = $userModel->where(['qq'=>$this->params['user_id']])->find(); if (isset($userInfo['id'])){ if ((int)$userInfo['status']!=1) return false; $this->groupUserInfo = $userInfo; return $userInfo['id']; } $userParam = $this->params['sender']; $userInfo = [ 'qq' => $userParam['user_id'], 'user_name' => $userParam['nickname'], 'age' => $userParam['age'], 'sex' => $this->getSex($userParam['sex']), 'create_time' => time(), 'update_time' =>time() ]; $this->groupUserInfo = $userInfo; return $userModel->insertGetId($userInfo) ? : false; } private function order($taskId='', $type=''){ try { $type = ucfirst($type); $task = db("group_task") ->find($taskId); if ($task) { $dbModel = db('group_order'); $record = $dbModel ->where([ 'user_id' => $this->userId, 'task_id' => $task['id'] ]) ->find(); $msg = "{$this->groupUserInfo['user_name']},"; if ($record) { $result = $dbModel->update([ 'id' => $record['id'], 'task_id' => $task['id'], 'type' => $this->changeOrderType($type), 'update_time' => time() ]); $msg .= "更新点餐成功,"; } else { $result = $dbModel->insert([ 'user_id' => $this->userId, 'task_id' => $task['id'], 'type' => $this->changeOrderType($type), 'create_time' => time() ]); $msg .= "点餐成功,"; } if ((int)$this->changeOrderType($type) == 9) { $date = $this->changeDateType((int)date("w", $task['time'])); $msg = "{$this->groupUserInfo['user_name']},好的知道了,你周{$date}不点。"; }else if ($result) { $data = json_decode($task['data'], true); $msg .= "您点的是:{$type}餐,【{$data[$type]}】。"; }else{ $msg = "哦吼,点餐失败,系统出错了。"; } $this->sendGroup($this->groupId, $msg); }else{ $this->sendGroup($this->groupId, "{$this->groupUserInfo['user_name']},还没到点餐时间,到时间会通知你的,认真上班吧。"); } }catch (\Exception $e){ $this->sendGroup($this->groupId, "卡bug了,错误信息:".$e->getMessage().'line:'.$e->getLine()); } } /** * 添加点餐任务 * @return mixed */ public function add_task(){ if (request()->isPost()){ $content = input('post.content'); //提取文本中的日期 preg_match_all("'\d{1,2}月\d{1,2}'", $content,$arr1); $time = empty($arr1[0][0]) ? time() : strtotime(date('Y') . '/' . str_replace(['月'], '/', $arr1[0][0])); $dbModel = db("group_task"); $where = [ 'time' => $time ]; $check = $dbModel->where($where) ->find(); if ($check){ $date = date('Y年m月d日', $time); $this->error("{$date},该日期已存在订餐任务,不能重复添加!"); } preg_match_all('/([A-Za-z#].+)/u', $content,$arr); if (!empty($arr[1])) { $result = []; foreach ($arr[1] as $v){ $v = preg_replace("/(\s|\ \;| |\xc2\xa0)/","",$v); $data = explode('餐',$v); if (!empty($data[0]) && in_array($data[0], ['A', 'B', 'C']) && !empty($data[1])) { $result[$data[0]] = $data[1]; } } if (count($result)>=3) { $data = [ 'time' => $time, 'data' => json_encode($result, JSON_UNESCAPED_UNICODE), 'content' => $content, 'create_time' => time() ]; $dbModel->insert($data); $this->success('添加点餐任务成功!'); } } $this->error('添加任务失败!'); exit; } return $this->fetch(); } /** * 推送qq消息 */ public function push_message(){ if (request()->isPost()) { $content = input('post.content'); $this->sendGroup($this->groupId, $content); //$this->sendGroup($this->groupId, "来活了,老铁们,开始点餐啦,A、B、C随便选,不点的回复不点,点餐时需要先@小助手,否则不管用哦,点餐12点准时结束,过时不候。"); $this->success("推送成功!"); } return $this->fetch(); } /** * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function views(){ $userModel = db('group_user'); $day = input("param.day") ? : (date('d')); $startTime = strtotime(date("Y-m-{$day} 00:00:00")); $task = db("group_task") ->where(['time'=> $startTime]) ->find(); $data = empty($task['id'])? [] : $userModel->alias('u') ->field("u.id,u.user_name,o.type,o.create_time") ->join("group_order o", "o.task_id = {$task['id']} and o.user_id = u.id", 'LEFT') ->where(['u.status' => 1]) ->order("o.type asc") ->select(); $result = $this->array_group_by($data, 'type'); $notChoose = isset($result['']) ? implode(',', array_column($result[''], 'user_name')) : ''; $this->assign('not_choose', $notChoose); ksort($result); $record = []; $msg = []; foreach ($result as $k => $v){ if (!empty((int)$k) && in_array((int)$k, [1,2,3])){ $num = count($v); $msg[] = $this->changeOrderType($k) ." {$num}份"; $record[$k] = $num; } } $info = '云商项目开发部: '.implode(', ', $msg) . " 共计:".array_sum($record) . "份"; foreach ($data as $k => &$v){ if (!empty($v['type']) && in_array((int)$v['type'], [1, 2, 3])){ $v['status'] = 1; }else{ $v['status'] = ''; } $v['type'] = $this->changeOrderType($v['type']); if ($v['create_time']){ $v['create_time'] = date('Y-m-d H:i:s', $v['create_time']); } } krsort($msg); if (request()->isPost()){ $result = [ 'code' => 0, 'data' => $data ]; echo json_encode($result); exit; } if ($task){ $task = json_decode($task['data'], true); } $days = date('t', strtotime('Y-m')) + 1 ; $this->assign('days', $days); $this->assign('day', $day); $this->assign('task', $task); $this->assign('data', $data); $this->assign('info', $info); return $this->fetch(); } /** * @return mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function view_month(){ $days = date('t', strtotime('2019-03')); $userModel = db('group_user'); $orderModel = db('group_order'); $month = input("param.month") ? : date('m'); if (request()->isPost()){ $startTime = strtotime(date("Y-{$month}-1")); $endTime = strtotime(date("Y-m-d", strtotime("last day of this month", strtotime(date("Y-{$month}-d"))))); $data = $userModel ->field("id,user_name") ->where(['status' => 1]) ->select(); foreach ($data as &$v){ $results = $orderModel->alias('o')->field("t.time") ->join('group_task t', "t.id = o.task_id", "LEFT") ->where([ 'o.user_id' => $v['id'], 't.time' => ['between', [$startTime, $endTime]], 'o.type' => ['IN', [1,2,3]] ])->select(); $v['type'] = "午餐"; $timeArr = array_column($results, 'time'); for ($i=1;$i 0, 'data' => $data ]; echo json_encode($result); exit; } $this->assign('months', [1,2,3,4,5,6,7,8,9,10,11,12]); $this->assign('month', $month); return $this->fetch(); } public static function array_group_by($arr, $key) { $grouped = []; foreach ($arr as $value) { $grouped[$value[$key]][] = $value; } if (func_num_args() > 2) { $args = func_get_args(); foreach ($grouped as $key => $value) { $parms = array_merge([$value], array_slice($args, 2, func_num_args())); $grouped[$key] = call_user_func_array('array_group_by', $parms); } } return $grouped; } /** * 点餐结束,推送点餐情况 * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function push_order_result(){ if (!empty($this->params['token']) && $this->params['token'] == $this->push_token) { $task = db("group_task") ->whereTime('create_time', 'today') ->select(); if ($task) { $userModel = db('group_user'); $msg = '今日点餐时间结束,点餐情况如下:'.PHP_EOL; foreach ($task as $v){ $orderDate = date('Y年m月d日', $v['time']); $msg .= "用餐时间:{$orderDate}".PHP_EOL; $data = $userModel->alias('u') ->field("u.id,u.user_name,o.type,o.create_time") ->join('group_order o', "o.user_id = u.id and task_id = {$v['id']}", 'LEFT') ->where(['u.status' => 1]) ->select(); $orderData = json_decode($v['data'], true); foreach ($data as $vo){ if (!empty($vo['type']) && in_array((int)$vo['type'], [1,2,3])){ $type = $this->changeOrderType($vo['type']); $msg .= "{$vo['user_name']} : {$type}餐 【{$orderData[$type]}】".PHP_EOL; }else{ $msg .= "{$vo['user_name']} : 不点".PHP_EOL; } } $result = $this->array_group_by($data, 'type'); $typeMsg = []; $record = []; foreach ($result as $k => $v){ if (!empty((int)$k) && in_array((int)$k, [1,2,3])){ $num = count($v); $typeMsg[$k] = $this->changeOrderType($k) ." {$num}份"; $record[$k] = $num; } } ksort($typeMsg); $msg .= PHP_EOL."{$orderDate} 云商项目开发部: ".implode(', ', $typeMsg) . " 共计:".array_sum($record) . "份".PHP_EOL; } $this->sendGroup($this->groupId, $msg); } } } /** * 开饭前推送今天的点餐情况 * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ public function push_today_order(){ if (!empty($this->params['token']) && $this->params['token'] == $this->push_token) { $task = db("group_task") ->whereTime('time', 'today') ->find(); if ($task){ $userModel = db('group_user'); $orderDate = date('m月d日', $task['time']); $msg = "下班开饭,{$orderDate}点餐情况如下,请对号入座:".PHP_EOL; $data = $userModel->alias('u') ->field("u.id,u.user_name,o.type,o.create_time") ->join('group_order o', "o.user_id = u.id and task_id = {$task['id']}", 'LEFT') ->where(['u.status' => 1]) ->select(); $orderData = json_decode($task['data'], true); foreach ($data as $vo){ if (!empty($vo['type']) && in_array((int)$vo['type'], [1,2,3])){ $type = $this->changeOrderType($vo['type']); $msg .= "{$vo['user_name']} : {$type}餐 【{$orderData[$type]}】".PHP_EOL; }else{ $msg .= "{$vo['user_name']} : 不点".PHP_EOL; } } //$msg .= PHP_EOL."你喜欢岁月静好,其实现实是大江奔流。"; $this->sendGroup($this->groupId, $msg); } } } /** * 获取未来7天分别是周几 * @param bool $time * @return array */ public function getLastSevenDays($time = false){ if (!$time) $time = time(); $data = []; for ($i=0;$i<7;$i++){ $data[date('w', $time)] = date('Y-m-d 00:00:00', $time); $time += 60*60*24; } return $data; } /** * 把中文的周几转换为数字并对应php date()方法 * @param string $date * @return bool|int */ public function changeDateType($date = ''){ $result = false; if (is_int($date)){ switch ($date){ case 1: $result = '一'; break; case 2: $result = '二'; break; case 3: $result = '三'; break; case 4: $result = '四'; break; case 5: $result = '五'; break; case 6: $result = '六'; break; case 0: $result = '日'; break; } }else{ if (empty($date)) return $result; switch ($date){ case '一': $result = 1; break; case '二': $result = 2; break; case '三': $result = 3; break; case '四': $result = 4; break; case '五': $result = 5; break; case '六': $result = 6; break; case '日': $result = 0; break; } } return $result; }
2019年05月17日
7,741 阅读
0 评论
46 点赞
2019-05-11
centos 搭建Nginx 负载均衡
搭建Nginx 负载均衡一、安装如下环境yum -y install make gcc gcc-c++ gcc-g77 flex bison file libtool libtool-libs autoconf kernel-devel libjpeg libjpeg-devel libpng libpng-devel libpng10 libpng10-devel gd gd-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glib2 glib2-devel bzip2 bzip2-devel libevent libevent-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel gettext gettext-devel ncurses-devel gmp-devel pspell-devel unzip libcap lsof编译pcre的包tar zxf pcre-8.31.tar.gzcd pcre-8.31./configuremake && make installuseradd -s /sbin/nologno -g nginx -M nginxtar zxf nginx-1.10.2.tar.gzcd nginx-1.10.2./configure –prefix=/usr/local/nginx –sbin-path=/usr/local/nginx/bin/nginx –conf-path=/usr/local/nginx/conf/nginx.conf –error-log-path=/var/log/nginx/error.log –http-log-path=/var/log/nginx/access.log –pid-path=/var/run/nginx/nginx.pid –lock-path=/var/lock/nginx.lock –user=nginx –group=nginx –with-http_ssl_module –with-http_flv_module –with-http_stub_status_module –with-http_gzip_static_module –http-client-body-temp-path=/var/tmp/nginx/client/ –http-proxy-temp-path=/var/tmp/nginx/proxy/ –http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ –http-uwsgi-temp-path=/var/tmp/nginx/uwsgi –http-scgi-temp-path=/var/tmp/nginx/scgi –with-pcremakemake install/usr/local/nginx/bin/nginx –t./nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory 解决prce的问题 #find / -name libpcre.so*/usr/local/lib/libpcre.so.1.0.1/usr/local/lib/libpcre.so/usr/local/lib/libpcre.so.1/lib64/libpcre.so.0.0.1/lib64/libpcre.so.0出现了这么多结果。我们安装的PCRE库的位置在/usr/local/pcre中,我们就用这个位置vim /etc/ld.so.conf在尾行加入/usr/local/binroot@mail2 bin]# ldconfig#/usr/local/nginx/bin/nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful 这就正常了启动nginx/usr/local/nginx/bin/nginxvim /usr/local/nginx/conf/nginx.conf在最后面的大括号前面添加一行include /usr/local/nginx/conf.d/*.conf;建立这个目录mkdir /usr/local/nginx/conf.dvim /usr/local/nginx/conf.d/lkq.confupstream backend{server 192.168.236.150:80 weight=1;server 192.168.236.151:80 weight=2;#ip_hash;}server{listen 80;server_name www.lkq.com;location ~ ^/*{proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_buffering off;proxy_pass http://backend;}}haproxy+nginx实现高可用负载均衡Keepalived 的作用是检测web服务器的状态,如果有一台web服务器死机,或工作出现故障,Keepalived将检测到,并将有故障的web服务器从系统中剔除, 当web服务器工作正常后Keepalived自动将web服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的 web服务器。HAProxy 提供高可用性、负载均衡以及基于 TCP 和 HTTP 应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案。HAProxy 特别适用于那些负载特大的 web 站点, 这些站点通常又需要会话保持或七层处理。HAProxy 运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整 合进您当前的架构中, 同时可以保护你的 web 服务器不被暴露到网络上。系统环境: CenOS 6.5x86_64 Desktop install 将selinux and iptables 设置为disabled图1 为基本的架构图:图2 为IP地址分配。主要用途IPHaproxy+keepalived_master192.168.236.143Haproxy+keepalived_backup192.168.236.192Webser1192.168.236.150Webser2192.168.236.151一:安装过程,在两台HA机器上分别keepalived:#ln -s /usr/src/kernels/2.6.18-128.el5-i686/ /usr/src/linux http://www.keepalived.org/software/ keepalived 的下载地址。版本的话自己可以选择一下版本。楼主选择的版本是1.2.23的版本 [root@mail2 keepalived-1.2.23]# ./configure –sysconf=/etc [root@mail2 keepalived-1.2.23]# make && make install [root@mail2 keepalived-1.2.23]# ln –s /usr/local/sbin/keepalived /sbin [
[email protected]
]#cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak [
[email protected]
]# ln -s /etc/init.d/keepalived /etc/rc.d/rc3.d/S99keepalived [
[email protected]
]# ln -s /etc/init.d/keepalived /etc/rc.d/rc5.d/S99keepalived二、修改配置文件Director server 1 的配置文件[root@Lserver-1 keepalived]# cat keepalived.confMaster :! Configuration File for keepalived vrrp_script chk_http_port { script "/etc/keepalived/check_haproxy.sh" ######设置了一个keepalived一个脚本 interval 2 weight 2 global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state MASTER ###keepalived 的主 interface eth0 virtual_router_id 51 priority 150 #####keepalived 一个ID 号 备的ID一定要小于主的ID advert_int 1 authentication { auth_type PASS auth_pass 1111 } track_script { chk_http_port } virtual_ipaddress { 192.168.236.230 ######一个VIP地址 } } }BACKUP:! Configuration File for keepalived vrrp_script chk_http_port { script "/etc/keepalived/check_haproxy.sh" #####一个keepalived的脚本同主一样 interval 2 weight 2 global_defs { router_id LVS_DEVEL } vrrp_instance VI_1 { state BACKUP ####为keepalived 的backup 备节点 interface eth0 virtual_router_id 51 priority 120 ####### keepalived 的一个ID号,一定要小于主节点 advert_int 1 authentication { auth_type PASS auth_pass 1111 } track_script { chk_http_port } virtual_ipaddress { 192.168.236.230 ##同主 } } }三、Master 主机上:####这里是一个控制haproxy的一个启动脚本 #vi /etc/keepalived/check_haproxy.sh #!/bin/bash A=`ps -C haproxy --no-header | wc -l` if [ $A -eq 0 ];then /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg echo "haproxy start" sleep 3 if [ `ps -C haproxy --no-header | wc -l`-eq 0 ];then /etc/init.d/keepalived stop echo "keepalived stop" fi fiBackup 备机上:#!/bin/bash A=`ip a | grep 192.168.236.230 | wc -l` B=`ps -ef | grep haproxy | grep -v grep| awk '{print $2}'` if [ $A -gt 0 ];then /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg else kill -9 $B fi#两台机器分别执行:chmod 755 /etc/keepalived/check_haproxy.sh四、haproxy的安装(主备都一样):yum -y install pcre pcre-devel wget https://fossies.org/linux/misc/haproxy-1.7.5.tar.gz tar xf haproxy-1.7.5.tar.gz cd haproxy-1.7.5 make TARGET=linux26 ARCH=x86_64 PREFIX=/usr/local/haproxy USE_PCRE=1 make install PREFIX=/usr/local/haproxy #cd/usr/local/haproxy/ #mkdir conf #mkdir logs#vi haproxy.cfgglobal log 127.0.0.1 local0 log 127.0.0.1 local1 notice #log loghost local0 info maxconn 4096 # chroot /usr/share/haproxy chroot /usr/local/haproxy uid 99 gid 99 daemon #debug #quiet defaults log global mode http option httplog option dontlognull retries 3 #redispatch maxconn 2000 option redispatch stats uri /haproxy stats auth admin:admin frontend www bind *:80 acl web hdr(host) -i www.lkq.com ####这里是通过域名访问的。如果域名为这个则通过。 use_backend webserver if web backend webserver #webserver作用域 mode http balance roundrobin option httpchk /index.html server s1 192.168.236.151:80 weight 3 check ###这两条记录为后端的两台WEB服务器 server s2 192.168.236.150:80 weight 3 check五、:先主后从,两台机器上都分别启动:/etc/init.d/keepalivedstart (如果之前没有启动haproxy,这条命令会自动把haproxy启动)[root@Rserver-1 conf]# ps -ef |grep haproxy nobody 14766 1 0 19:13 ? 00:00:01 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg root 16034 8237 0 19:56 pts/2 00:00:00 grep haproxy [root@Rserver-1 conf]# ps -ef |grep keepalived root 16016 1 0 19:56 ? 00:00:00 keepalived -D root 16018 16016 0 19:56 ? 00:00:00 keepalived -D root 16019 16016 0 19:56 ? 00:00:00 keepalived -D root 16102 8237 0 19:56 pts/2 00:00:00 grep keepalived [root@Rserver-1 conf]#六、再两台HA上分别执行ip addr list |grep 192.168.23master:[root@Rserver-1 conf]# ip addr list |grep 192.168.236 inet 192.168.236.143/24 brd 192.168.236.255 scope global eth0 inet 192.168.236.230/32 scope global eth0 [root@Rserver-1 conf]#Backup:[root@Lserver-1 keepalived]# ip addr list |grep 192.168.236 inet 192.168.236.192/24 brd 192.168.236.255 scope global eth0 [root@Lserver-1 keepalived]#七、停掉主上的haproxy,3秒后keepalived会自动将其再次启动[root@Rserver-1 conf]# killall haproxy [root@Rserver-1 conf]# ps -ef |grep haproxy nobody 14766 1 0 19:13 ? 00:00:02 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/conf/haproxy.cfg root 16826 8237 0 20:01 pts/2 00:00:00 grep haproxy八、停掉主的keepalived,备机马上接管服务Master:[root@Rserver-1 conf]# /etc/init.d/keepalived stop [root@Rserver-1 conf]# ip addr list|grep 192.168.236 inet 192.168.236.143/24 brd 192.168.236.255 scope global eth0 [root@Rserver-1 conf]#Backup:[root@Lserver-1 keepalived]# ip addr list|grep 192.168.236 inet 192.168.236.192/24 brd 192.168.236.255 scope global eth0 inet 192.168.236.230/32 scope global eth0 [root@Lserver-1 keepalived]#
2019年05月11日
12,199 阅读
0 评论
14 点赞
2019-04-10
mysql优化之thread_cache_size
1、mysql服务器的线程数查看方法:show global status like 'Thread%';Threads_created:创建过的线程数,如果发现Threads_created值过大的话,表明MySQL服务器一直在创建线程,这也是比较耗资源,可以适当增加配置文件中thread_cache_size值2、优化参数thread_cache_sizethread_cache_size:当客户端断开之后,服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁(前提是缓存数未达上限)即可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能。thread_cache_size大小的设置:如果是短连接,适当设置大一点,因为短连接往往需要不停创建,不停销毁,如果大一点,连接线程都处于取用状态,不需要重新创建和销毁,所以对性能肯定是比较大的提升。对于长连接,不能保证连接的稳定性,所以设置这参数还是有一定必要,可能连接池的问题,会导致连接数据库的不稳定性,也会出现频繁的创建和销毁,但这个情况比较少,如果是长连接,可以设置成小一点,一般在50-100左右。物理内存设置规则:通过比较Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。(-->表示要调整的值) 根据物理内存设置规则如下: 1G ---> 8 2G ---> 16 3G ---> 32 >3G ---> 64查询thread_cache_size设置show global status like'thread_cache_size';优化方法:1、mysql> set global thread_cache_size=162、编辑/etc/my.cnf 更改/添加thread_concurrency = 163、mysql kill线程mysqladmin start slave stop slave kill某个连接到mysqlServer的线程
2019年04月10日
6,063 阅读
0 评论
49 点赞
2019-03-29
解决 docker run 报错 oci runtime error
在部署新服务器运行docker镜像的时候遇到了报错,记录下解决方法。docker 启动容器报错:Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "process_linux.go:258: applying cgroup configuration for process caused \"Cannot set property TasksAccountingdocker 是通过 yum install docker安装的,搜了一把,原来是因为linux与docker版本的兼容性问题。那就卸载旧版本安装最新版试试。0.通过uname -r命令查看你当前的内核版本uname -r1.使用 root 权限登录 Centos。确保 yum 包更新到最新。sudo yum update2.卸载旧版本(如果安装过旧版本的话)sudo yum remove docker docker-common docker-selinux docker-engine3.安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的sudo yum install -y yum-utils device-mapper-persistent-data lvm24.设置yum源sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo5.可以查看所有仓库中所有docker版本,并选择特定版本安装yum list docker-ce --showduplicates | sort -r6.安装dockersudo yum install docker-ce7.启动并加入开机启动sudo systemctl start dockersudo systemctl enable docker8.验证安装是否成功(有client和service两部分表示docker安装启动都成功了) docker version 经过以上一通操作,pull 一下镜像再执行docker run命令,问题解决。
2019年03月29日
49,608 阅读
0 评论
951 点赞
2019-03-11
内部类-非静态内部类|静态内部类|匿名内部类
内部类-非静态内部类|静态内部类|匿名内部类package com.weitip.oop; /** * Created by IntelliJ IDEA. * User: loong * Date: 2019/3/11 * Time: 15:35 * Description: com.weitip.oop **/ public class InnerClass { public static void main(String[] args) { Outer.Inner inner = new Outer().new Inner(); inner.show(); Outer.Inner2 inner2 = new Outer.Inner2(); inner2.show(); } } class Outer{ private int age = 20; class Inner{ int age = 999; public void show(){ int age = 999999; System.out.println("外部类属性age:" + Outer.this.age); System.out.println("内部类属性age:" + this.age); System.out.println("局部变量age:" + age); } } static class Inner2{ public static void show() { System.out.println("内部静态类被调用"); } } }package com.weitip.oop; /** * Created by IntelliJ IDEA. * User: loong * Date: 2019/3/11 * Time: 16:01 * Description: com.weitip.oop **/ public class AnonymousInnerClass { public static void test(AA a){ a.aa(); } public static void main(String[] args) { AnonymousInnerClass.test(new AA(){ @Override public void aa() { System.out.println("匿名内部类被调用"); } }); } } interface AA{ void aa(); }
2019年03月11日
1,977 阅读
0 评论
0 点赞
2019-03-02
Beyond Compare 4 代码对比工具
提取码:bh69
2019年03月02日
4,786 阅读
0 评论
4 点赞
2019-03-02
vmware 12 虚拟机
提取码:9fb5 VMware是功能最强大的虚拟机软件,用户可以在虚拟机同时运行各种操作系统,进行开发、测试、演示和部署软件,虚拟机中复制服务器、台式机和平板环境,每个虚拟机可分配多个处理器核心、主内存和显存。
2019年03月02日
4,492 阅读
0 评论
1 点赞
2019-03-02
【数据库可视化】navicat120_premium安装包以及破解补丁
提取码:ojh3 第一步:检测电脑是否已经安装了:Microsoft Visual C++ 2017 Runtime,若没有,请安装!安装很简单,分别点击图中的两个可执行文件,安装即可。(一定要确保已经安装了这两个文件。) 第二步:下载、安装Navicat Premium 12.0.18,版本一定要是12.0.18安装步骤:双击安装文件navicat120_premium_cs_x64(1).exe点击“下一步”。 选择“我同意”,点击“下一步”。 选择安装目录,点击“下一步”。 点击“下一步”。 继续点击“下一步”。 点击“安装”,稍等片刻,便会弹出“安装成功”提示。Navicat Premium 12.0.18安装成功!(再次声明:必须是12.0.18版本) 第三步:破解Navicat Premium 12.0.18解压破解文件:Navicat Premium 12 破解补丁,得到下面的目录:根据自己安装Navicat Premium 12.0.18的位数,和想要的语言字体,选择对应的文件。我选择的“简体中文64位”,打开:看到这两个文件:payload.bin、 version.dll,把这两个文件复制粘贴到,Navicat Premium 12.0.18的安装目录下:复制粘贴成功之后,打开Navicat Premium,点击“帮助”/“help”,点击“关于”/“about”,弹出下方页面:“未激活”字样消失,破解成功!!!!
2019年03月02日
6,204 阅读
0 评论
82 点赞
2019-03-02
【Git GUI】TortoiseGit 64位 小乌龟
提取码:g1jr 1 TortoiseGit简介tortoiseGit是一个开放的git版本控制系统的源客户端,支持Winxp/vista/win7.该软件功能和git一样不同的是:git是命令行操作模式,tortoiseGit界面化操作模式,不用记git相关命令就可以直接操作,读者可根据自己情况选择安装 2 TortoiseGit下载 当前最新稳定版本是2.6.0,下面就以该版本为例说明下载和安装。进入2.6.0.0之后可看到包含32位和64位的软件安装包下载,以及各种语言安装包,根据自己的系统选择对应的安装包,笔者主机是win7 64位。就以64位为例语言包下载安装根据个人习惯,默认是英文(推荐),需要中文的下载语言包安装即可 3 TortoiseGit安装安装顺序:先安装程序包,然后安装语言包(LanguagePack).安装说明:因为TortoiseGit 只是一个程序壳,必须依赖一个 Git Core,所以安装前请确定已完成git安装和配置下面以64位版本为演示3.1 安装程序包双击TortoiseGit-2.6.0.0-64bit.msi,弹出安装导向页面 一路Next> 即可,配置均选择默认 点击Install 点击Finish,如果以前有老版本,则选择覆盖,关闭旧程序并尝试重启即可 3.2 安装语言包如果想使用英文版本的该工具,不想使用中文版本的,则该模块操作可忽略双击TortoiseGit-LanguagePack-2.6.0.0-64bit-zh_CN.msi,弹出安装导向 点击下一步,安装完成后,点击完成 4 TortoiseGit配置4.1 常规配置先选择一个本地的目录,作为git项目存放的目录,方便管理。本文选择: E:\project\clear-project,建议:路径中不要包含中文 在空白处点击鼠标右键, 选择 --> TortoiseGit --> Settings, 弹出配置界面(当TortoiseGit安装完成后,鼠标右键点击后,默认出现 TortoiseGit 相关选项) 点击General,在页面中选择Language下拉框,选择“中文(简体)中华人名共和国”,然后点击应用,确定关闭对话框(当然也可以继续使用英文) 如果使用英文:该步骤和下一步骤可直接跳过在空白处再次点击鼠标右键,可以看到弹出菜单中已经变成中文. 原来的 Settings 变成 设置; Clone 变为 克隆,点击设置(S),再次弹出配置界面配置右键菜单. 在设置对话框中,点选左边的"右键菜单",如果右边的复选框有默认勾选,全部去掉,,这样右键菜单显得比较干净 点击左边Git,配置相关信息,配置好后保存退出 ①因为当前还没有本地项目,所以 “编辑本地 .git/config(L)” 按钮处于灰色不可用状态,如果在某个本地Git项目下打开配置对话框,那么这个按钮就可用,然后就可以编辑此项目的一些属性。 ②点击 “编辑全局 .git/config(O)”按钮,会使用记事本打开全局配置文件,在全局配置文件中,在后面加上下面的内容: [user] name = jinqi email =
[email protected]
signingkey = lht&123456 [credential] helper = store 则当你推送项目到Gitlab等在线仓库时,会记住你输入的用户名和密码(这里不是用户的姓名和Email),这里用户名和密码就是注册gitlab的用户名和密码 name: 注册gitlab的账号,如: jinqi signingkey: 注册gitlab的密码: ********* Email: 是联系邮箱,给别人联系时使用 4.2 秘钥配置前面已经提到TortoiseGit只是一个壳,除软件的常规配置(语言包、用户信息等),还需要像git一样生成、配置秘钥信息开始-->TortoiseGit-->PuTTYgen,进入PuTTY Key Generator 点击Generate,生成的过程中 注意:生成时鼠标要不停划过进度条,不然进度条会一直不动! 先点击Save private key把私有的密钥存起来,记住存储的位置,后面会用到 把生成出来的public Key复制粘贴到Gitlab上面,配置SSH key Gitlab配置成功后,邮箱会收到邮件 打开:开始-->TortoiseGit-->Pageant,打开以后右下角会有图标,双击点开蓝屏幕电脑那个图标 说明:使用TortoiseGit进行和远端输出项目时,Pageant必须启动且添加了对应的私钥。否则会报错 添加前面生成的private key.ppk,也就是私钥。然后关闭 5 TortoiseGit使用示例以克隆verify-center项目为例,举例验证TortoiseGit配置正确注意:克隆代码之前确保有相关的项目代码权限(master、developer、reporter),如无权限,请求项目具有master权限的同事帮忙分配权限登录gitlab,获取SSH 链接地址 在本地目标下载目录下,右键-->TortoiseGit(T)-->克隆,粘贴SSH 链接地址到URL,点击确定 确认项目已从gitlab上克隆到本地
2019年03月02日
5,412 阅读
0 评论
26 点赞
2019-03-02
ThinkPHP5.1完全开发手册
https://www.kancloud.cn/manual/thinkphp5_1/353946 ThinkPHP是一个快速、简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,自2006年诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简代码的同时,尤其注重开发体验和易用性,并且拥有众多的原创功能和特性,为WEB应用和API开发提供了强有力的支持。
2019年03月02日
6,371 阅读
0 评论
9 点赞
2019-02-17
PHP7新特性
PHP7中也增加了一些新的语法,这些语法的使用也能对提高性能有帮助。1.标量参数类型声明 现在支持字符串(string)、整型(int)、浮点数(float)、及布尔型(bool)参数声明,以前只支持类名、接口、数组及Callable两种风格:强制转换模式(默认)与严格模式。<?php function sum(int ...$numbers){ var_dump($numbers); return array_sum($numbers); } echo sum("18","9984");运行结果如下: 以string类型传入的值会被强制转换为int类型,若类型转换失败会抛出错误。2.返回类型声明<?php function test():array { return [456,996]; } var_dump(test());运行结果:若返回值类型不为预设类型则报错:<?php function test():array { return 666; } var_dump(test());3.??运算符 ?? 用于替代需要isset的场合,这是一个语法糖。<?php $id = isset($_GET['id']) ? $_GET['id'] : null; $id = $_GET['id'] ?? null; 这两种写法是等效的。4.比较运算符 就是看两个表达式值的大小,三种关系: = 返回0、< 返回-1、 > 返回 1<?php echo 1 2; //-1 echo 1 1; //0 echo 2 1; //15.define支持定义数组类型的值 php 5.6已经支持CONST 语法定义数组类的常量,PHP7中支持define语法。"lili", "age"=>18]); var_dump(human);6.匿名类write();7.增加了整除函数 intdiv 对除法结果取整<?php echo intdiv(10,3); //输出3小结:性能提升:PHP 7要比PHP 5.6快两倍;全面一致的64位支持;新增了空接合操作符(??)。
2019年02月17日
5,785 阅读
0 评论
13 点赞
2019-02-17
PHP生成随机标识
用于微信小程序接口开发中生成3rd_session。/*** 生成随机标识*@param$len*@returnmixed|string*/public functionrandomFromDev($len) { $fp= @fopen('/dev/urandom','rb'); $result=''; if($fp!==FALSE) { $result.= @fread($fp,$len); @fclose($fp); }else{ trigger_error('Can not open /dev/urandom.'); } if(empty($result))$result= md5(mt_rand(111111111,999999999));//兼容 $result= base64_encode($result);// convert from binary to string $result= strtr($result,'+/','-_');// remove none url chars returnsubstr($result,0,$len);}
2019年02月17日
5,566 阅读
0 评论
4 点赞
2019-02-16
商品sku匹配及属性可选状态
最近在做商品sku的时候遇到了一些困惑,记录一下,以备日后会看。 先说一说需求: 1.根据选中的SKU,显示对应的SKU图片,没有选中的SKU时,默认展示SPU商品图,单击放大预览; 2.每个属性下属性值有多个时,默认不选,只有一个时,默认选中; 3.后台没有设置SKU时,则无属性值展示; 4.选中交互:选中某一个属性下属性值时,检查其他属性的属性值,哪些不能组合为一个SKU,不能组合的属性值只读,原选中的则取消选中。 已上就是给出的文字需求,在需求讨论的时候产品定了调调,通过既定的属性去确定一个sku,即所有未选择的属性假定一个初始值。一听心里乐了,所有选中的属性都已知,排序之后再匹配不就是轻松确定sku了嘛,美滋滋。/** * 获取商品sku属性(初始默认选中,已经被否了呀) */ public function goods_sku_version_1 (){ $goodsId = $this->post['goods_id'] or $this->response(201, 'goods_id不能为空'); $catId = mall_database_execute('goods') ->where(['goods_id' => $goodsId, 'is_on_sale'=> 1, 'is_delete' => 0]) ->getField('goods_type') or $this->response(208, '商品不存在'); //构建查询条件 $where = ['gs.goods_id'=> $goodsId]; $attrArr = []; if (!empty($this->post['attr_id'])){ $attrArr = explode(',', $this->post['attr_id']); sort($attrArr); //升序 $where['gs.attr_id_arr'] = implode(',', $attrArr); } //获取sku信息 $this->rows['info'] = mall_database_execute('goods_sku')->alias('AS gs') ->where($where) ->find() or $this->response(208, 'sku不存在'); if (empty($this->post['attr_id'])) $attrArr = explode(',', $this->rows['info']['attr_id_arr']); //获取顶级sku列表 $this->rows['attribute'] = mall_database_execute('goods_sku_list')->alias('AS gsl') ->field('ga.attr_id, ga.attr_type, ga.attr_name, gsl.attr_values_arr') ->join(mall_database_table('goods_attribute').' AS ga ON ga.attr_id = gsl.attr_id', 'LEFT') ->where([ 'gsl.goods_id' => $goodsId, 'gsl.status' => 1 ]) ->select() ? : ''; if (!empty($this->rows['attribute'])){ //通过二定一待,确定sku foreach ($this->rows['attribute'] as $k=>&$v){ $newAttrArr = $attrArr; $newAttrArr[$k] = '%'; $str = implode(',', $newAttrArr); $v['option'] = mall_database_execute('goods_sku') ->field('goods_sku_id,attr_id_arr,status' ) ->where([ 'goods_id' => $goodsId, 'attr_id_arr' => ['LIKE', $str] ]) ->select(); if (!empty($v['option'])){ foreach ($v['option'] as &$vo){ $newAttrArr = explode(',', $vo['attr_id_arr']); $attrInfo = mall_database_execute('goods_attribute') ->field('attr_id, attr_type, attr_name') ->where([ 'attr_id' => $newAttrArr[$k] ]) ->find(); unset($vo['attr_id_arr']); $vo = array_merge($attrInfo, $vo); } } } } $this->response(); } 本以为这样就完事了,结果没过多久需求就改了,不假定每个属性的初始值,根据用户当前选择动态匹配sku,GG。这个方案一开始没想明白的点在于,基于用户当前选择,推算所有属性的节点是否还有可选的可能(可用sku),之前想到过这一层面,想着偷懒完成需求即可,便没有深究。/** * 基于用户当前属性选择状态,获取sku,及推算每个属性的可选状态 */ public function goods_sku(){ $goodsId = $this->post['goods_id']; //检测商品是否存在 mall_database_execute('goods') ->where(['goods_id' => $goodsId, 'is_on_sale'=> 1, 'is_delete' => 0]) ->getField('goods_id') or $this->response(208, '商品不存在'); $where = [ 'goods_id' => $goodsId, 'status' => 1 ]; //获取所有可选sku的属性组合 $allSkuLists = array_column(mall_database_execute('goods_sku') ->field('attr_id_arr') ->where($where) ->select(), 'attr_id_arr'); $this->rows['sku_num'] = count($allSkuLists); if (!empty($this->post['attr_id'])){ $attrArr = explode(',', $this->post['attr_id']); foreach ($attrArr as &$vv){ if ($vv == '') $vv = '%'; } $where['old_id_arr'] = ['LIKE', implode(',', $attrArr)]; } //查询一个当前用户选择状态下满足条件的组合(先这样,等产品出了可能组合排序规则再完善) $this->rows['info'] = mall_database_execute('goods_sku') ->field('goods_sku_id,price,goods_number,attr_value,goods_thumb') ->where($where) ->find() ? : ''; if ($this->rows['info']['goods_thumb']) $this->rows['info']['goods_thumb'] = change_file_path($this->rows['info']['goods_thumb']); //获取规格 $attribute = mall_database_execute('goods_sku_list')->alias('AS gsl') ->field('ga.attr_id, ga.attr_type, ga.attr_name, gsl.attr_values_arr') ->join(mall_database_table('goods_attribute').' AS ga ON ga.attr_id = gsl.attr_id', 'LEFT') ->where([ 'gsl.goods_id' => $goodsId, 'gsl.status' => 1 ]) ->order('attr_type asc, attr_id asc') ->select(); if (!empty($attribute)){ //遍历获取所有规格的属性,并假定每种属性都不可选 foreach ($attribute as $k=>&$v){ $v['option'] = mall_database_execute('goods_attribute') ->field('attr_id,attr_type,attr_name,2 as status') ->where([ 'attr_id' => ['IN', $v['attr_values_arr']], 'status' => 1 ]) ->order('attr_id asc') ->select(); unset($v['attr_values_arr']); if (!empty($allSkuLists)){ //遍历所有属性判断基于用户选择状态下属性是否有可选方案 foreach ($v['option'] as &$vo){ //获取用户当前选择 $checkSku = explode(',', $this->post['attr_id']); //把当前属性与用户选择进行组合 $checkSku[$k] = $vo['attr_id']; //遍历所有可能的组合列表,查找是否有匹配当前的组合 foreach ($allSkuLists as $vov){ //判断条件:如果我有的你都有那就对了 $intersect = array_intersect($checkSku, explode(',', $vov)); asort($intersect); asort($checkSku); //序列化后做比较 if (implode(',', $intersect) == implode(',', array_filter($checkSku))) $vo['status'] = '1'; } } } } } $this->rows['attribute'] = $attribute ? : ''; $this->response(); }附上表结构:CREATE TABLE `fd_goods_sku` ( `goods_sku_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `goods_id` int(11) NOT NULL, `old_id_arr` varchar(255) NOT NULL DEFAULT '' COMMENT '没排序之前的id组合', `attr_id_arr` varchar(255) NOT NULL DEFAULT '0' COMMENT '属性id', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1正常,2失效', `price` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '售价,单位分', `goods_number` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '库存', `attr_value` varchar(255) NOT NULL DEFAULT '' COMMENT '商品自定义属性', `goods_thumb` varchar(255) NOT NULL DEFAULT '', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`goods_sku_id`), KEY `goods_id` (`goods_id`,`goods_sku_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2208 DEFAULT CHARSET=utf8mb4 COMMENT='商品sku表'; CREATE TABLE `fd_goods_sku_list` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `goods_id` int(10) unsigned NOT NULL, `attr_id` varchar(255) NOT NULL DEFAULT '' COMMENT '属性id', `attr_values_arr` varchar(255) NOT NULL DEFAULT '' COMMENT '属性值id', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1正常,2失效', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=599 DEFAULT CHARSET=utf8mb4 COMMENT='商品已选属性表'; 以上仅作记录,如大神们有更好方案请不吝赐教。
2019年02月16日
13,092 阅读
0 评论
35 点赞
2019-01-15
http状态码一览表
http状态码一览表1**:请求收到,继续处理2**:操作成功收到,分析、接受3**:完成此请求必须进一步处理4**:请求包含一个错误语法或不能完成5**:服务器执行一个完全有效请求失败 100——客户必须继续发出请求101——客户要求服务器根据请求转换HTTP协议版本 200——交易成功201——提示知道新文件的URL202——接受和处理、但处理未完成203——返回信息不确定或不完整204——请求收到,但返回信息为空205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件206——服务器已经完成了部分用户的GET请求 300——请求的资源可在多处得到301——删除请求数据302——在其他地址发现了请求数据303——建议客户访问其他URL或访问方式304——客户端已经执行了GET,但文件未变化305——请求的资源必须从服务器指定的地址得到306——前一版本HTTP中使用的代码,现行版本中不再使用307——申明请求的资源临时性删除 400——错误请求,如语法错误401——请求授权失败402——保留有效ChargeTo头响应403——请求不允许404——没有发现文件、查询或URl405——用户在Request-Line字段定义的方法不允许406——根据用户发送的Accept拖,请求资源不可访问407——类似401,用户必须首先在代理服务器上得到授权408——客户端没有在用户指定的饿时间内完成请求409——对当前资源状态,请求不能完成410——服务器上不再有此资源且无进一步的参考地址411——服务器拒绝用户定义的Content-Length属性请求412——一个或多个请求头字段在当前请求中错误413——请求的资源大于服务器允许的大小414——请求的资源URL长于服务器允许的长度415——请求资源不支持请求项目格式416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求 500——服务器产生内部错误501——服务器不支持请求的函数502——服务器暂时不可用,有时是为了防止发生系统过载503——服务器过载或暂停维修504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长505——服务器不支持或拒绝支请求头中指定的HTTP版本
2019年01月15日
4,631 阅读
0 评论
0 点赞
2019-01-11
docker 部署PHP+ nginx环境
首先push 两个镜像docker pull php:7.2.3-fpm docker pull nginx然后启动一个php docker run --name phpfpm -d -v /root/app:/app php:7.2.3-fpm说明一下 –name 是容器的名字 phpfpm-v 是/root/app 是本机的地址/app 是容器内部的存储位置然后再启动一个nginx docker run --name nginx_server -d -p 80:80 --link phpfpm:phpfpm -v /root/conf/nginx.conf:/etc/nginx/nginx.conf --volumes-from phpfpm nginx— link phpfrpm:phpfpm 是容器之间建立关系–volumes-from phpfpm 就是把/root/app:/app 也会导入到 容器中/app 目录 -v /root/conf/nginx.conf 导入到 /etc/nginx/nginx.conf 宿主机 的nginx.conf 的导入到/etc/nginx/nginx.conf 中 连接PHP的配置如下: location ~ .php$ { root /app; fastcgi_pass phpfpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name; include fastcgi_params; }nginx配置文件如下:user root root; worker_processes auto; error_log /tmp/nginx_error.log crit; pid /tmp/nginx.pid; worker_rlimit_nofile 51200; events { use epoll; worker_connections 51200; multi_accept on; } http { include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 512; client_header_buffer_size 32k; large_client_header_buffers 4 32k; client_max_body_size 50m; sendfile on; tcp_nopush on; keepalive_timeout 60; tcp_nodelay on; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on; server { listen 80; server_name www.bt.cn; index index.html index.htm index.php; root /app; #error_page 404 /404.html; location ~ .php$ { root /app; fastcgi_pass phpfpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name; include fastcgi_params; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /\. { deny all; } access_log /tmp/access.log; } }
2019年01月11日
15,662 阅读
0 评论
40 点赞
2019-01-09
PHP Warning: file_get_contents failed to open stream解决办法
file_get_contents函数在获得远程文件时提示Warning: file_get_contents failed to open stream,希望例子能够帮助到各位,希望例子能够帮助到大家。在做项目时用 file_get_contents 来获取数据,php 报错 PHP Warning: file_get_contents failed to open stream: no suitable wrapper could be found.最后用了curl来获取数据!今天百度了一下!找到了解决办法!先拷贝过来!系统:centos 6.5在错误日志中,php报的错误是Warning: file_get_contents() [function.file-get-contents]: http:// wrapper is disabled in the server configuration by allow_url_fopen=0failed to open stream: no suitable wrapper could be found此警告说服务器阻止访问远程文件,修改php.ini把allow_url_fopen = Offallow_url_include = Off改成allow_url_fopen = Onallow_url_include = On重启php-fpm或者重启web服务。如果还是无法解决 的话windows下处理方法:c:\windows\php.iniextension=php_openssl.dll 把前的;去掉,重启iis服务。linux下处理方法:/etc/php.iniextension=php_openssl.dll 把前的;去掉,重启apache服务。 如果上面问题没能解决我的问题,我们可以如下测试。 $context = stream_context_create(array('http'=>array('ignore_errors'=>true)));$contents = file_get_contents($url, FALSE, $context);可以请求时,忽略错误。可以解决警告信息
2019年01月09日
6,514 阅读
0 评论
3 点赞
2018-10-29
静默运行bat批处理文件
#静默运行@echo offif "%1" == "h" goto beginmshta vbscript:createobject("wscript.shell").run("""%~nx0"" h",0)(window.close)&&exit:beginREM@echo OFFcolor 0aTitle frp启动工具 by loongMode con cols=109 lines=30:STARTECHO.Echo ==========================================================================ECHO.Echo frp客户端启动工具ECHO.Echo ==========================================================================Echo.echo.echo.frpc.exe -c frpc.iniPAUSEgoto TUNNEL
2018年10月29日
5,606 阅读
0 评论
62 点赞
1
...
63
64
65