月度归档: 2021 年 7 月

  • Docker-compose常用命令

    莫小安

    Docker-compose常用命令

    1.github地址:https://github.com/TodorText/lnmp.git

    这个是根据laradock精简的lnmp,并且摘除了从容器挂载数据卷

    2.命令

    docker-compose –help你会看到如下这么多命令

    build               Build or rebuild servicesbundle              Generate a Docker bundle from the Compose fileconfig              Validate and view the Compose filecreate              Create servicesdown                Stop and remove containers, networks, images, and volumesevents              Receive real time events from containersexec                Execute a command in a running containerhelp                Get help on a commandimages              List imageskill                Kill containerslogs                View output from containerspause               Pause servicesport                Print the public port for a port bindingps                  List containerspull                Pull service imagespush                Push service imagesrestart             Restart servicesrm                  Remove stopped containersrun                 Run a one-off commandscale               Set number of containers for a servicestart               Start servicesstop                Stop servicestop                 Display the running processesunpause             Unpause servicesup                  Create and start containersversion             Show the Docker-Compose version information

    3.常用命令

    docker-compose up -d nginx                     构建建启动nignx容器

    docker-compose exec nginx bash            登录到nginx容器中

    docker-compose down                              删除所有nginx容器,镜像

    docker-compose ps                                   显示所有容器

    docker-compose restart nginx                   重新启动nginx容器

    docker-compose run –no-deps –rm php-fpm php -v  在php-fpm中不启动关联容器,并容器执行php -v 执行完成后删除容器

    docker-compose build nginx                     构建镜像 。        

    docker-compose build –no-cache nginx   不带缓存的构建。

    docker-compose logs  nginx                     查看nginx的日志 

    docker-compose logs -f nginx                   查看nginx的实时日志

    docker-compose config  -q                        验证(docker-compose.yml)文件配置,当配置正确时,不输出任何内容,当文件配置错误,输出错误信息。 

    docker-compose events –json nginx       以json的形式输出nginx的docker日志

    docker-compose pause nginx                 暂停nignx容器

    docker-compose unpause nginx             恢复ningx容器

    docker-compose rm nginx                       删除容器(删除前必须关闭容器)

    docker-compose stop nginx                    停止nignx容器

    docker-compose start nginx                    启动nignx容器

  • git同步远程已删除的分支和删除本地多余的分支

    使用 git branch -a 可以查看本地分支和远程分支情况 

    但远程分支(红色部分)删除后,发现本地并没有同步过来。

    一. 同步本地的远程分支

    查看本地分支和追踪情况:

    git remote show origin

    可以发现红框中的分支是远程分支已被删除的分支,根据提示可以使用 git remote prune 来同步删除这些分支。

    运行命令:

    git remote prune origin

    再次查看分支情况:

     发现红色部分的远程分支已经同步,远程删除的分支,本地也已经不见了。

    二. 删除本地多余分支

    git branch -D feature/chatfix

    本地多余分支已删除

    三.删除远程分支

    git branch --delete --remotes <remote>/<branch>

    git push origin --delete release/3.2.6

  • Composer 国内加速,修改镜像源

    如何修改镜像源

    可以使用阿里巴巴提供的 Composer 全量镜像 https://mirrors.aliyun.com/composer/

    a). 配置只在当前项目生效
    
    
    composer config repo.packagist composer https://mirrors.aliyun.com/composer/
    
     取消当前项目配置
    composer config --unset repos.packagist
    b). 配置全局生效
    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
    
     取消全局配置
    composer config -g --unset repos.packagist
  • 正确地使用Redis的SETNX实现锁机制

    setNX,是set if not exists 的缩写,也就是只有不存在的时候才设置, 设置成功时返回 1 , 设置失败时返回 0 。可以利用它来实现锁的效果,但是很多人在使用的过程中都有一些问题没有考虑到。
    例如某个查询数据库的接口因为请求量比较大所以加了缓存,并设定缓存过期后刷新。当并发量比较大并且缓存过期的瞬间,大量并发请求会直接查询数据库导致雪崩。如果使用锁机制来控制只有一个请求去更新缓存就能避免雪崩的问题。下面是很多人下意识想到的加锁方法

    $rs = $redis->setNX($key, $value);
    if ($rs) {//处理更新缓存逻辑
    // ......
    //删除锁
    $redis->del($key);
    }

      通过 setNX 获取锁,如果成功了则更新缓存然后删除锁。其实这里有一个严重的问题:如果更新缓存的时候因为某些原因意外退出了,那么这个锁就不会被删除而一直存在,以至于缓存再也得不到更新。为了解决这个问题有人可能会想到给锁设置一个过期时间,如下

    1234 $redis->multi();$redis->setNX($key, $value);$redis->expire($key, $ttl);$redis->exec();

      因为 setNX 不具备设置过期时间的功能,所以要借助 Expire 来设置,同时需要使用 Multi/Exec 来确保请求的原子性,以免 setNX 成功了 Expire 却失败了。这样还有问题:当多个请求到达时,虽然只有一个请求的 setNX 可以成功,但是任何一个请求的 Expire 却都可以成功,这就意味着即便获取不到锁也可以刷新过期时间,导致锁一直有效,还是解决不了上面的问题。显然 setNX 满足不了需求,Redis从 2.6.12 起,SET 涵盖了 SETEX 的功能, SET 本身又包含了设置过期时间的功能,所以使用 SET 就可以解决上面遇到的问题

    1234567 $rs  $redis ->set( $key $value array ( 'nx' 'ex' =>  $ttl )); if ( $rs ) { //处理更新缓存逻辑 // ...... //删除锁 $redis ->del( $key ); }

      到这一步其实还是有问题的,如果一个请求更新缓存的时间比锁的有效期还要长,导致在缓存更新过程中锁就失效了,此时另一个请求就会获取到锁,但前一个请求在缓存更新完毕的时候,直接删除锁的话就会出现误删其它请求创建的锁的情况。所以要避免这种问题,可以在创建锁的时候需要引入一个随机值并在删除锁的时候加以判断

    123456789 $rs  $redis ->set( $key $random array ( 'nx' 'ex' =>  $ttl )); if ( $rs ) { //处理更新缓存逻辑 // ...... //先判断随机数,是同一个则删除锁 if ( $redis ->get( $key ) ==  $random ) { $redis ->del( $key ); } }
  • mysql 备份

    备份所有数据库:
    
    mysqldump -uroot -p --all-databases > /backup/mysqldump/all.db
    备份指定数据库:
    
    mysqldump -uroot -p test > /backup/mysqldump/test.db
    备份指定数据库指定表(多个表以空格间隔)
    
    mysqldump -uroot -p  mysql db event > /backup/mysqldump/2table.db
    备份指定数据库排除某些表
    
    mysqldump -uroot -p test --ignore-table=test.t1 --ignore-table=test.t2 > /backup/mysqldump/test2.db
    
     授权:
     grant all privileges on *.* to 'root'@'%' identified by '6NbAFQBE';
     grant all privileges on *.* to 'dbmanager'@'%' identified by '6NbAFQBE';
     FLUSH PRIVILEGES;
    
    导出全部数据库
    mysqldump -uroot -p --all-databases > sqlfile.sql

    三、还原命令

    3.1 系统行命令

    mysqladmin -uroot -p create db_name 
    mysql -uroot -p  db_name < /backup/mysqldump/db_name.db
    
    注:在导入备份数据库前,db_name如果没有,是需要创建的; 而且与db_name.db中数据库名是一样的才可以导入。
    

    3.2 soure 方法

    mysql > use db_name
    mysql > source /backup/mysqldump/db_name.db
  • think-swoole应用-微服务之RPC远程调用通信实战

    RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。

    解决问题:
    解决分布式系统中,服务之间的调用问题。
    远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。

    Think-Swoole中已经实现了的基于TCP的PRC,这样我们使用传统型框架也可以做简单的分布式架构应用了。

    一、配置服务端
    1,修改 config/swoole.php

        'rpc'        => [
            'server' => [
                'enable'   => true,
                'port'     => 9000,
                'services' => [
                    \app\rpc\service\UserService::class            ],
            ],
            'client' => [
            ],
        ],

    2,新增rpc目录结构如下:

    3,定义接口抽象方法

    <?php// +----------------------------------------------------------------------// | najing [ 通用后台管理系统 ]// +----------------------------------------------------------------------// | Copyright (c) 2020 http://www.najingquan.com ;All rights reserved.// +----------------------------------------------------------------------// | Author: 救火队队长namespace app\rpc\interfaces;interface UserInterface{
        public function add($name);}

    4,实现接口方法

    <?php// +----------------------------------------------------------------------// | najing [ 通用后台管理系统 ]// +----------------------------------------------------------------------// | Copyright (c) 2020 http://www.najingquan.com ;All rights reserved.// +----------------------------------------------------------------------// | Author: 救火队队长namespace app\rpc\service;use app\rpc\interfaces\UserInterface;class UserService implements UserInterface{
        public function add($name)
        {
            return "您要新增的用户名是:{$name}";
        }}

    服务端的操作就已经完成。 可以开启swoole 命令 php think swoole start

    二、配置客户端
    1,修改 config/swoole.php

    
    
    
    
    'rpc'        => [
            'server' => [
                'enable'   => false,
                'port'     => 9000,
                'services' => [  
                ],
            ],
            'client' => [
                'userservice'=>[
                     //RPC服务端的ip地址
                    'host' => '127.0.0.1',
                     //RPC服务端的端口
                    'port' => 9000
    
                ]
            ],
        ],

    2,生成RPC服务接口

    php think rpc:interface

    会在app目录下生成一个rpc.php的文件,它就是RPC服务接口文件
    文件内容大致:

    
    
    
    
    <?php/**
     * This file is auto-generated.
     */declare(strict_types=1);namespace rpc\contract\userservice;interface UserInterface{
        public function add($name);}return ['userservice' => ['rpc\contract\userservice\UserInterface']];

    注意return中就是每个服务接口的命名空间;在控制器中使用该命名空间实例对象就可以调用

    3,Controller调用

    
    
    
    
    <?php// +----------------------------------------------------------------------// | najing [ 通用后台管理系统 ]// +----------------------------------------------------------------------// | Copyright (c) 2020 http://www.najingquan.com ;All rights reserved.// +----------------------------------------------------------------------// | Author: 救火队队长namespace app\controller;use app\BaseController;use rpc\contract\userservice\UserInterface;class User extends BaseController{
        public function add(UserInterface $user)
        {
           echo $user->add("救火队队长");
        }}

    4,浏览器访问客户端Controller
    6 收藏 点击回复

  • php替换html里面的图片相对路径地址为绝对路径

    /**
     * 替换html里面的图片相对路径地址为绝对路径
     * @param  string $content 请求html内容
     * @param  array  $prefix 绝对url地址
     */
    function pregReplaceImg2($content,$prefix)
    {
        $contentAlter = preg_replace_callback('/(<[img|IMG].*?src=[\'\"])([\s\S]*?)([\'\"])[\s\S]*?/i', function($match)use($prefix){
            if(strstr($match[2], 'http://') == false && strstr($match[1], 'https://') == false)
                return $match[1].$prefix.$match[2].$match[3];
            else
                return $match[1].$match[2].$match[3];
        } , $content);
        return $contentAlter;
    }
  • java中逗号分隔的字符串和List相互转换

    1、将逗号分隔的字符串转换为List

    String str = "a,b,c"; 
    
    List<String> result = Arrays.asList(str.split(","));

    2、将List转换为逗号分隔的字符串

    (1) 利用Guava的Joiner

    List<String> list = new ArrayList<String>(); 
    list.add("a"); 
    list.add("b"); 
    list.add("c"); 
    
    String str = Joiner.on(",").join(list); 

    (2)利用Apache Commons的StringUtils

    List<String> list = new ArrayList<String>(); 
    list.add("a"); 
    list.add("b"); 
    list.add("c"); 
    
    String str = StringUtils.join(list.toArray(), ",");