首页
留言
动态
归档
推荐
音乐
工具
Search
1
Emby公益服-上万部电影电视剧免费看
61,628 阅读
2
openwrt-docker部署lxk0301京东自动签到脚本
12,510 阅读
3
QuantumultX-京东签到撸京东豆
10,841 阅读
4
LXK0301京东签到脚本-自动提交互助码
9,294 阅读
5
微信-域名被封监测以及自动更换被封域名
8,981 阅读
随便写写
科学上网
Web开发
瞎折腾
Search
标签搜索
quantumultx
laravel
openwrt
laravel nova
laradock
telegram
薅羊毛
google adsense
jd_scripts
京东签到
ubuntu
oh-my-zsh
web开发环境
nginx
工具
shadowsocks shadowsocksR
RBAC
权限管理
内网穿透
Python
orzlee
累计撰写
44
篇文章
累计收到
595
条评论
首页
栏目
随便写写
科学上网
Web开发
瞎折腾
页面
留言
动态
归档
推荐
音乐
工具
搜索到
15
篇与
Web开发
的结果
2019-01-22
Laravel 5.7 Broadcast + laravel echo 实现 WebSocket C/S 实时通信
前言 laravel Broadcast 平时项目中接触得比较少,最近公司年会活动需要做一个抽奖项目。要求用一太手机控制其他在抽奖页面的用户同时开始抽奖以及显示抽奖结果。提出项目需求时第一个想到的就是WebSocket,相对于使用AJAX轮询请求来说,WebSocket的实时性要高出不少,而且AJAX轮询请求服务器有太多不必要的请求,对于搞开发的来说这种不必要的请求就应该避免,不做多余操作。以前在项目中使用的WebSocket,也是抽奖项目,但是不是基于laravel框架,这次项目确实动力十足。 实现流程 使用laravel Broadcast广播系统(使用Redis) 触发Broadcast广播事件 laravel-echo-server 通过Redis收听到Broadcast广播事件 laravel-echo-server 使用socket.io下发给laravel-echo laravel-echo接收事件对象 实现步骤 配置 在app.php中启用广播系统服务提供者 /* * Application Service Providers... */ ... App\Providers\BroadcastServiceProvider::class, ... 修改.env中BROADCAST_DRIVER配置位置redis ... BROADCAST_DRIVER=redis ... laravel redis客户端扩展: 查看database.php中redis['client'] 如果使用predis请安装composer包 composer require predis/predis 如果使用phpredis就需要自己编译PHP的reids扩展。 phpredis效率要高于predis,按自己项目需求取舍 自定义配置文件config/lottery.php: 在该项目中使用的是扩展包开发,配置文件中有些命名空间应该修改为自己对应的,可以先定义,看完文章后再回过头来就明白了。 return [ /* * 频道名称 */ 'channel_name' => env('LOTTERY_CHANNEL_NAME','sweepstakes'), /* * 路由路径 */ 'route' => 'lottery', /* * 控制器 */ 'controller' => \Lijianmin\Lottery\Contollers\LotteryController::class, /* * 频道验证 */ 'broadcast' => \Lijianmin\Lottery\Broadcasting\LotteryChannel::class, /* * 缓存 */ 'cache' => [ 'prefix' => 'lottery-cache', 'expiration_time' => 5, //默认过期时间,小时 'redis_cache_db' => env('REDIS_CACHE_DB',1), ], ]; 注册广播事件 项目中事件包括 活动开始、入场、抽奖开始、开奖。 由于合作开发,我将它写出扩展包,定制接口方便对接。 首先创建出所需事件,如果不需要扩展包开发可以: php artisan make:event event-name 或者 在app/Providers/EventServiceProvider.php成员变量$listen内追加: /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'App\Events\EventName' => [ 'App\Listeners\ListenserName', ], ... ]; ... 然后执行生成事件命令 php artisan event:generate 事件注册完毕后需要实现Illuminate\Contracts\Broadcasting\ShouldBroadcast接口,需要实现broadcastOn方法,该方法返回一个频道或者一个频道数组。broadcastAs方法自定义广播名称,我希望还是自己定义,不然后面laravel-echo会很尴尬: use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class ActivityStart implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public $option; public function __construct($option = []) { $this->option = $option; } public function broadcastOn() { return new PresenceChannel(config('lottery.channel_name')); } public function broadcastAs(){ return 'activityStart'; } } config('lottery.channel_name')应该修改为自己定义的频道名称,或者也可以像orzlee一样使用配置文件定义,方便修改。 每个事件都需要创建对应的文件,如果只是为了通知前端可以不需要事件处理器。 对于频道分为三种: Channel-普通频道。 PrivateChannel-私有频道,需要自定义授权认证。 PresenceChannel-类似于私有频道,但是比私有频道更加高级。 频道授权 首先自己创建一个频道: php artisan make:channel LotteryChannel 在routes/channels.php中添加频道(主要是频道授权验证): Broadcast::channel(config('lottery.channel_name'),config('lottery.broadcast')); 实现授权验证方法: PrivateChannel私有频道只需要返回true或者false,PresenceChannel频道在验证成功就需要返回一个用户信息数组,验证失败返回false或者null。 class LotteryChannel { ... /** * Authenticate the user's access to the channel. * * @param \App\User $user * @return array|bool */ public function join() { if(\Auth::check()){ $user = \Auth::user(); return [ 'user' => [ 'id' => $user->id, 'name' => $user->names, ], 'isLotteryDraw' => $this->lotteryService->isLotteryDraw() ]; } return false; } } 搭建laravel-echo-server服务: 安装最新版NodeJS和npm(如果已经安装可以跳过): curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - sudo apt-get install -y nodejs ##如果需要指定版本修改链接中的数字即可 curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - 进入项目目录执行: 先把需要安装的一次性装完,orzlee已经写成command,部署服务器一行命令就全部安装好了 npm install -g laravel-echo-server npm i --save socket.io-client npm i --save laravel-echo npm install 初始化laravel-echo-server: 按实际情况填写,选错了也不要紧,到时候在修改 laravel-echo-server init 项目下会生成laravel-echo-server.json配置文件: 注意authHost,devMode,port,protocol几个重要参数就好了。 { "authHost": "http://127.0.0.1:8000", "authEndpoint": "/broadcasting/auth", "clients": [], "database": "redis", "databaseConfig": { "redis" : {}, "sqlite": { "databasePath": "/database/laravel-echo-server.sqlite" } }, "devMode": true, "host": null, "port": "6001", "protocol": "http", "socketio": {}, "sslCertPath": "", "sslKeyPath": "", "sslCertChainPath": "", "sslPassphrase": "", "subscribers": { "http": true, "redis": true }, "apiOriginAllow": { "allowCors": false, "allowOrigin": "", "allowMethods": "", "allowHeaders": "" } } 启动laravel-echo-server: laravel-echo-server start 前端laravel-echo对接 修改resources/js/bootstrap.js(5.6文件在public目录下): 默认内容是注释了的,而且使用的是pusher,说实话pusher是付费服务,而且服务器都在国外,对国内实在是不友好。有想法的可以去了解下,每天有免费请求限制,主要是用于开发调试。 /** * Echo exposes an expressive API for subscribing to channels and listening * for events that are broadcast by Laravel. Echo and event broadcasting * allows your team to easily build robust real-time web applications. */ import Echo from 'laravel-echo' window.io = require('socket.io-client'); // window.Pusher = require('pusher-js'); window.Echo = new Echo({ broadcaster: 'socket.io', host: window.location.hostname + ':6001' }); 其实做完这一步就可以打包编译NodeJS了: prod代表生产环境,如果还需要调试可以使用dev或者watch,watch模式文件改动会自动编译。 npm run prod 前端页面配置事件监听: 注意监听事件名称,如果在上文中使用了broadcastAs命名事件名称,那么只需要在名称前加入.就好了,不然你需要把命名空间以.分割,例如:App.Lottery.ActivityStart,实在是太罗嗦了。 <!-- Scripts --> <script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script> <script src="{{ asset('js/app.js') }}"></script> <script> let lottery_server = Echo.join('{{ config('lottery.channel_name') }}'); lottery_server.here(function (users) { //本来使用私有频道,但是找了半天也没有找到连接成功的事件才改用`PresenceChannel`频道, //在`here`事件会在连接成功返回所有当前频道的用户信息 console.log(e) }); lottery_server.joining(function (user) { //新用户加入频道返回用户信息 console.log(e) }); lottery_server.listen('.activityStart', (e) => { //活动开始 console.log('activityStart',e); }); lottery_server.listen('.admission', (e) => { //入场,其实这个事件在`PresenceChannel`频道下已经多此一举了 console.log('admission',e); }); lottery_server.listen('.newcomerAdmission', (e) => { //新用户加入,这个也是多余的 console.log('newcomerAdmission',e); }); lottery_server.listen('.lottery', (e) => { //摇奖事件 console.log('lottery',e); }); lottery_server.listen('.lotteryResult', (e) => { //摇奖结果事件 console.log('lotteryResult',e); }); </script> 到此整个前对接已经完成。 后端事件触发 其实最简单的就是后端。例如用户入场,用户登陆后触发AdmissionEvent事件,在定义事件时构造函数中设定前端所需的参数,数组也好对象也好,都会传给前端。 发送入场事件: event(new AdmissionEvent()); 每个事件我都会在构造函数中添加option数组,除了必须传递的参数以外方便附加其他参数。 结语 像这种类似于C/S模式开发要考虑的情况非常多,用户已经入场,关闭浏览器再次入场情况,首先名单不能重复添加,已中奖用户在入场时必须实时传递,在开奖状态中用户离开页面,然后在进入页面也应该保持前端正在开奖的效果,所以开奖状态要实时传递。还有很多很多需要考虑的问题,然后经过不停的测试。在年会上需要开31个奖,真是心惊胆战的,测试是还是有些问题的,还好在年会上没有出大漏子(真心不是后端问题,前端开奖结果效果问题),包括后端都去调试前端开奖动画效果,真心累。自从写好laravel-echo部署上线,真的没有出现过问题,还是很稳定的。测试时,最多30多台手机,活动开始之前有个图片遮罩,活动开始事件触发全部向上拉开遮罩,真的很壮观。多台手机之间延迟非常小,体验很不错,年会现场效果也是非常棒。
2019年01月22日
5,277 阅读
0 评论
0 点赞
2018-12-18
laravel nova 权限管理工具
前言 前几个月一直在折腾laravel nova,不得不说它的扩展性非常强。laravel nova packages每天都会有很多新鲜的扩展包,生态很好。spatie laravel-permission是非常不错的Role-based access control RBAC扩展包,orzlee在laravel 5.3就在使用了,这里主要说说spatie laravel-permission的laravel nova权限管理工具。 Larval nova packages 目前有三款laravel nova packages包是基于spatie laravel-permission开发的,功能上大同小异,各有特色。 1. vyuldashev/nova-permission: 这是最早出现基于spatie laravel-permission的laravel nova packages。支持自定义资源,本地化支持。 orzlee一开始也是使用的这款扩展包,但是没几天我就发现了一个问题,因为laravel nova的Relationships并不会调用spatie laravel-permission自带的权限或角色附加、分离方法,所以在给用户添加权限时不会触发权限缓存更新。这就必须等待缓存过期或者手动清理缓存。 这个问题一直没有解决,orzlee也关注了Issues:Cache not invalidated on attaching a role or permission to user好长一段时间,然而并没有进展。最后还是提问者重新创建了一个新的包insenseanalytics/laravel-nova-permission。 2. insenseanalytics/laravel-nova-permission: 这款包主要是使用ForgetCachedPermissions中间件来判断当前路由是否为附加或分离请求(attach,detach),然后过滤出附加或分离权限的请求,执行缓存清除。 分离时没有问题,但是附加在路由判断上有点问题。orzlee在测试的时候发现附加怎么也无法清除缓存,经过调试发现url没有匹配到。 class ForgetCachedPermissions { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * * @return \Illuminate\Http\Response */ public function handle($request, $next) { $response = $next($request); if ($request->is('nova-api/*/detach') || $request->is('nova-api/*/*/attach/*')) { ##作者判断了attach,但是orzlee的请求路由为:http://127.0.0.1:8000/nova-api/admins/1/attach-morphed/permissions $permissionKey = (Nova::resourceForModel(app(PermissionRegistrar::class)->getPermissionClass()))::uriKey(); if ($request->viaRelationship === $permissionKey) { app(PermissionRegistrar::class)->forgetCachedPermissions(); } } return $response; } } orzlee已经向作者提交Issues了。 orzlee在给作者RP包语言本地化时有一个权限搜索翻译的功能没有被作者合并。作者觉得使用自定义资源功能让用户自行实现,这样也不错,不过度化设计。 权限是由开发者添加,而使用的时候基本上是管理员在操作。现在添加权限是一个搜索选择器,管理员需要给某个用户或管理员添加权限就必须搜索。权限在添加时为了多语言化必用标识,管理员在搜索时按照本地化语言搜索会方便很多。 orzlee还是把实现方法分享出来吧: GuardFilterHandelTrait主要功能是按guard_name过滤掉不属于附加用户的权限,防止多guard_name权限混乱。 use Laravel\Nova\Http\Requests\NovaRequest; trait GuardFilterHandelTrait { /** * Override the applyFilters method to add the guard_name condition when filtering * * @param \Laravel\Nova\Http\Requests\NovaRequest $request * @param \Illuminate\Database\Eloquent\Builder $query * @param array $filters * * @return \Illuminate\Database\Eloquent\Builder */ protected static function applyFilters(NovaRequest $request, $query, array $filters) { $query = parent::applyFilters($request, $query, $filters); if ($model = head($request->__memoized)) { $guard_name = $model->guard_name ?? self::getGuardForModel(get_class($model)); $query->where('guard_name', $guard_name); } return $query; } /** * @param string model * * @return string|null */ public static function getGuardForModel(string $model) { return collect(config('auth.guards')) ->map(function ($guard) { return config("auth.providers.{$guard['provider']}.model"); })->search($model); } } PermissionSearchTranslationTrait搜索权限时会按照本地化语言反向找出对应权限。 trait PermissionSearchTranslationTrait { use GuardFilterHandelTrait; /** * Override the applyFilters method,title field translation */ public function title() { return __('laravel-nova-permission::permissions.display_names.'.$this->name); } /** * Rewrite the applySearch method to apply translation field search * * @param \Illuminate\Database\Eloquent\Builder $query * @param string $search * @return \Illuminate\Database\Eloquent\Builder */ protected static function applySearch($query, $search) { return $query->where(function ($query) use ($search) { if (is_numeric($search) && in_array($query->getModel()->getKeyType(), ['int', 'integer'])) { $query->orWhere($query->getModel()->getQualifiedKeyName(), $search); } $model = $query->getModel(); $connectionType = $query->getModel()->getConnection()->getDriverName(); $likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like'; $trans_search = array_keys(preg_grep("/$search/",array_dot(__('laravel-nova-permission::permissions.display_names')))); foreach (static::searchableColumns() as $column) { $qualify_column = $model->qualifyColumn($column); foreach ($trans_search as $t_search){ $query->orWhere($qualify_column, $likeOperator, '%'.$t_search.'%'); } $query->orWhere($qualify_column, $likeOperator, '%'.$search.'%'); } }); } } 自定义Role & Permission资源(注意命名空间替换成自己项目对应的): use App\Traits\Resources\GuardFilterHandelTrait; use \Insenseanalytics\LaravelNovaPermission\Role as BaseRole; class Role extends BaseRole { use GuardFilterHandelTrait; } use App\Traits\Resources\PermissionSearchTranslationTrait; use \Insenseanalytics\LaravelNovaPermission\Permission as BasePermission; class Permission extends BasePermission { use PermissionSearchTranslationTrait; } 按照作者文档自定义角色和权限类: // in app/Providers/NovaServiceProvider.php public function tools() { return [ // ... \Insenseanalytics\LaravelNovaPermission\LaravelNovaPermission::make() ->roleResource(CustomRole::class) ->permissionResource(CustomPermission::class), ]; } 如果你还没有发布语言文件请执行: php artisan vendor:publish --provider="Insenseanalytics\LaravelNovaPermission\NovaPermissionServiceProvider" 创建自己本地化语言文件,例如在项目路径./resources/lang/vendor/laravel-nova-permission/创建一个zh-CN文件夹,复制en中的所有文件到zh-CN,然后自己翻译。display_names就是权限name对应的本地化翻译。 'display_names' => [ 'test' => '测试', 'delete' => '删除', 'edit' => '编辑', 'create' => '创建', ], 现在应该支持本地化权限搜索了。或者可以直接使用包jianminlee/laravel-nova-filter。 该包还支持基于laravel nova的权限验证,非常方便,在nova资源中使用PermissionsBasedAuthTrait Trait,然后定义一个静态变量: class YourNovaResource extends Resource { use \Insenseanalytics\LaravelNovaPermission\PermissionsBasedAuthTrait; public static $permissionsForAbilities = [ 'viewAny' => 'view products', 'view' => 'view products', 'create' => 'create products', 'update' => 'update products', 'delete' => 'delete products', 'restore' => 'restore products', 'forceDelete' => 'forceDelete products', 'addAttribute' => 'add product attributes', 'attachAttribute' => 'attach product attributes', 'detachAttribute' => 'detach product attributes', ]; .... } 详细文档可以取项目地址查看。insenseanalytics/laravel-nova-permission 3. DigitalCloud/nova-permission-tool: 今天刚刚发布的的,该包根据资源自动生成对应权限,听上去高大上,但是会多出不少多余的权限。因为我们的资源不一定会实现所有功能,到时候添加权限就会眼花缭乱了。orzlee认为还是自定义的好。 作者还自定义角色和权限的字段,在操作上体验好很多。凡是都有两面性,如果项目比较大(权限多)的情况下体验就可想而知了。 结语 这三款包都各有特色,同一功能的包就有这么多,这些还都只是基于spatie laravel-permission的,还有其他作者自己实现的权限管理工具。回过头来,还是得靠自己,工具再多也不一定都适合自己的项目,好好学Vue吧!
2018年12月18日
5,681 阅读
0 评论
0 点赞
2018-12-05
frp内网穿透
前言 在项目中经常涉及到需要验证域名的API开发,这些API开发需要在线调试。通常我们可以解析域名到本地,但是国内运营商封端口、无外网ip,线上调试又相对麻烦。frp是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。让它实现内网穿透,域名解析到服务器,让服务器通过其他端口访问本地web服务,轻松实现API调试。 安装使用 搭建frp服务需要一台服务器,基本无配置要求。 下载frp(frp发布地址): wget https://github.com/fatedier/frp/releases/download/v0.21.0/frp_0.21.0_linux_amd64.tar.gz 解压tar.gz: tar -zxvf frp_0.21.0_linux_amd64.tar.gz 编辑服务端配置文件: cd frp_0.21.0_linux_amd64 nano frps.ini 如果不许要其他功能,frps.ini保留下面三行即可(端口可自行更改) ############### [common] bind_port = 4443 ##frp服务端口 vhost_http_port = 80 ##http协议访问端口 启动服务: ./frps -c ./frps.ini 后台运行可以使用tmux工具,安装使用可以看orzlee的另一篇文章tmux强大的终端复用软件 客户端(windows) windows 32位 windows 64位 包含服务端和客户端。 编辑客户端配置文件: 解压zip后进入目录,编辑frpc.ini(推荐编辑器Sublime Text)。 [common] server_addr = x.x.x.x ###服务端ip地址或域名 server_port = 4443 ###服务端端口 [web] type = http ###http https local_port = 8000 ###本地web服务访问端口 custom_domains = www.yourdomain.com ###服务器域名地址 启动客户端: ./frpc -c ./frpc.ini 现在通过浏览器访问 http://www.yourdomain.com 即可访问到处于内网机器上的 web 服务。 结语 有了内网穿透,对于验证域名的API开发要省事不少,本地调试修改代码都非常方便,提高开发效率。而部署frp比较简单,当然还有更多功能,可以看看中文文档。
2018年12月05日
3,350 阅读
0 评论
1 点赞
2018-11-23
Ubuntu 搭建LNMP+redis+composer环境
前言 作为开发者,orzlee觉得必须得会搭建开发与生产环境,光靠集成环境是不行的,并不是所有公司都用集成环境。特别是用久了集成环境居然忘了最基本的环境搭建,这可不行。老老实实自己装,虽然麻烦,但是利大于弊。 Nginx orzlee已经写过一篇关于Ubuntu 安装nginx的文章,这里就不再重复了。 MySql 在Ubuntu环境下,直接使用linux packages安装就好了。 当前最新版为Mysql5.7,推荐安装5.7版本,相对于以往版本添加了新功能: 3倍更快的性能 InnoDB 相关改进 新的优化器 多源复制 GIS 相关改进 原生 JSON 支持 orzlee觉得最大的亮点就是支持原生JSON。 相关文档 ##更新源和升级已安装的库、软件、依赖等等 apt update && apt upgrade sudo apt install mysql-server-5.7 mysql-client-5.7 在安装途中会要求输入两次密码(第二次是确认密码)。 安装完成之后可以尝试连接mysql: mysql -uroot -p 然后输入你安装时候的密码。 出现如下界面表示安装完成: 输入exit退出mysql。 有些情况无法设置mysql密码,并且默认密码为空,这种情况是mysql验证方式问题。 连接mysql查询 select Host,User,plugin from mysql.user where User='root'; 一般都是 unix_socket 或者 auth_socket; 修改密码验证方式 update mysql.user set plugin='mysql_native_password'; 修改密码 update mysql.user set authentication_string=password('123qwe') where user='root' and Host = 'localhost'; 刷新权限 flush privileges; mysql8.0用上面修改密码不好使,使用 caching_sha2_password 加密方式(默认),使用 mysql_native_password 加密方式会出现如下错误!!! The user specified as a definer ('mysql.infoschema'@'localhost') does not exist ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'very_strong_password'; FLUSH PRIVILEGES; PHP 安装PHP7.2,也推荐使用linux packages安装,包括之后安装扩展更新等等都可以使用linux packages来安装。 首先安装第三方源,添加源过程中会要求按一次回车 sudo apt install software-properties-common sudo add-apt-repository ppa:ondrej/php sudo apt update 安装PHP7.2 sudo apt install php7.2 php7.2-fpm php -v 安装PHP7.2模块 sudo apt install php-pear php7.2-curl php7.2-dev php7.2-gd php7.2-mbstring php7.2-zip php7.2-mysql php7.2-xml sudo service php7.2-fpm restart 如果以后需要安装其他模块也可以直接安装 apt update sudo apt install example-model sudo service php7.2-fpm restart composer 作为PHP的包管理工具,它对于PHP来说当然必不可少。 sudo apt install curl git zip unzip cd ~ curl -sS https://getcomposer.org/installer| php sudo mv composer.phar /usr/local/bin/composer redis 安装编译和测试依赖 sudo apt install build-essential tcl 下载redis 创建一个工作目录,下载redis并且解压缩 sudo mkdir ~/work cd ~/work curl -O http://download.redis.io/redis-stable.tar.gz tar xzvf redis-stable.tar.gz 编译安装 cd redis-stable make make test sudo make install 配置redis 4.1 创建一个配置文件目录 sudo mkdir /etc/redis 4.2 移动示例配置文件到/etc/redis。 sudo cp ~/work/redis-stable/redis.conf /etc/redis/redis.conf 4.3 编辑redis配置文件 sudo nano /etc/redis/redis.conf ## 如果只是希望本地使用,建议去掉#号注释 bind 127.0.0.1 ## 将 supervised no 改为 supervised systemd ## 将 dir 改为 dir /var/lib/redis ##或者你可以选择其他目录 nano保存修改退出 保存 Ctrl+o 确认修改 Enter 退出 Ctrl+x 4.4 配置系统单元文件 sudo nano /etc/systemd/system/redis.service 添加如下内容: [Unit] Description=Redis In-Memory Data Store After=network.target # [Service] User=redis #指定用户 --删除注释 Group=redis ##指定用户组 --删除注释 ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf ExecStop=/usr/local/bin/redis-cli shutdown Restart=always # [Install] WantedBy=multi-user.target 切记删除标记注释,不然无法启动redis 4.5 设置redis用户、用户组和目录 sudo adduser --system --group --no-create-home redis sudo mkdir /var/lib/redis # 创建目录 sudo chown redis:redis /var/lib/redis # 设置/var/lib/redis用户和组 sudo chmod 770 /var/lib/redis # 调整权限 测试redis 5.1 启动redis sudo systemctl start redis 5.2 查看状态 systemctl status redis 如果正常会输出: ● redis.service - Redis Server Loaded: loaded (/etc/systemd/system/redis.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2016-05-11 14:38:08 EDT; 1min 43s ago Process: 3115 ExecStop=/usr/local/bin/redis-cli shutdown (code=exited, status=0/SUCCESS) Main PID: 3124 (redis-server) Tasks: 3 (limit: 512) Memory: 864.0K CPU: 179ms CGroup: /system.slice/redis.service └─3124 /usr/local/bin/redis-server 127.0.0.1:6379 5.3 测试实例 5.3.1 连接redisredis-cli 127.0.0.1:6379> ping # 返回 PONG 5.3.2 存入数据127.0.0.1:6379> set test "working!" # 返回 ok 5.3.3 获取数据127.0.0.1:6379> get test # 返回 "working!" 127.0.0.1:6379> exit 多测试几次,在退出后再次进入获取test值是否正常。 5.3.4 多次测试无误后重启redis127.0.0.1:6379> sudo systemctl restart redis 开机启动redis sudo systemctl enable redis 结语 其实虽然手动搭建Web环境略显繁琐,但是每次搭建都会有新收获。熟能生巧,而且在linux上敲命令的感觉真的很爽,如果命令都熟悉了就会觉得超过控制鼠标的输入效率。集成环境解决了一部分问题,但是也带来新的问题,世上的问题都是这样,在解决问题的同时,也会随之出现一个或多个新的问题,只是问题的大小而已。
2018年11月23日
2,135 阅读
0 评论
1 点赞
2018-11-23
Ubuntu 安装nginx
前言 开发期间经常需要搭建环境,网上也有很多集成环境,但是我还是推荐自己搭建。做开发的还是需要最基础的技能,开发人员不愿意折腾,难道让用户去折腾吗? nginx nginx是轻量级但非常强大的异步框架Web服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势,官方测试支持五万个并发连接。了解更多信息前往维基百科-Nginx。 安装 安装方法分为两种,编译安装和linux packages安装。linux packages安装非常方便,但是如果需要第三方扩展还是非常麻烦的。 编译安装 从Nginx news下载最新的安装包(当然也可以下载其他版本的安装包). wget http://nginx.org/download/nginx-1.15.6.tar.gz 解压安装包 tar -zxvf nginx-1.15.6.tar.gz 进入文件夹 cd nginx-1.15.6 安装编译工具和依赖库 apt install build-essential apt install libpcre3-dev zlib1g-dev libssl-dev 编译安装 ./configure --prefix=/usr --conf-path=/etc/nginx --user=www-data --group=www-data make sudo make install 安装完成后配置文件在/etc/nginx目录下,执行文件在/usr/sbin目录下。 可以在编译时指定模块,方便扩展(以下是apt安装nginx配置参数): ##安装依赖 apt install libxml2 libxml2-dev libxslt1-dev libgdchart-gd2-xpm libgdchart-gd2-xpm-dev libgeoip-dev ##配置 ./configure --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module 如果找不到nginx的话,配置下环境变量: nano /etc/profile ##末尾加入 export PATH="$PATH:/usr/share/nginx/sbin" 恢复/etc/nginx/目录方法: sudo apt purge nginx-common apt install nginx-common 更多./configure配置信息可以去nginx configure查看,相关文档nginx documentation。 从linux packages安装 直接安装会安装比较老旧的版本。 sudo apt install nginx 安装nginx-signing.key For Debian/Ubuntu, in order to authenticate the nginx repository signature and to eliminate warnings about missing PGP key during installation of the nginx package, it is necessary to add the key used to sign the nginx packages and repository to the apt program keyring. Please download this key from our web site, and add it to the apt program keyring with the following command: 对于Debian / Ubuntu,为了验证nginx存储库签名并在安装nginx包期间消除有关丢失PGP密钥的警告,有必要将用于签署nginx包和存储库的密钥添加到apt程序密钥环。请从我们的网站下载此密钥,并使用以下命令将其添加到apt程序密钥环: wget http://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key 添加官方源 echo "deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx">> /etc/apt/sources.list echo "deb-src http://nginx.org/packages/mainline/ubuntu/ trusty nginx">> /etc/apt/sources.list 更新源并安装nginx apt update apt install nginx 至此,nginx就安装完成了,配置文件在/etc/nginx目录下。 配置 如果nginx主进程使用root运行,那么nginx 将会调用 setuid()/setgid() 去设置 user/group。如果 group 没有特别指定,那么 nginx 会使用 user 相同的名称设置 group。默认为 nobody nogroup 或者安装nginx的时候在 ./configure 指定的 --user=USER 和 --group=GROUP 由于是linux packages安装,安装好nginx之后首先需要修改nginx user。 nano /etc/nginx/nginx.conf ##指定user为www-data user www-data; nano保存修改退出 保存 Ctrl+o 确认修改 Enter 退出 Ctrl+x 重启nginx sudo service nginx restart 新站点 个人喜欢使用配置域名命名配置文件www.example.com。 新建一个配置文件 nano /etc/nginx/conf.d/www.example.com.conf ###内容 server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/web_site/public; ##修改为自己站点目录 index index.php index.html index.htm; server_name server_domain_or_IP ##修改为自己的域名(www.example.com example.com); location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri /index.php =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 每次创建新的站点配置文件,或者修改配置文件都要养成好习惯。先测试,再重载,特别是线上环境。 nginx -t nginx -s reload 现在可以去浏览器测试自己的站点是否配置正确,正常访问了。 结语 orzlee以前也使用Apache,那时候还在用C#开发,接触PHP的后才慢慢转向nginx。同行中也有不少在使用Apache,其实都各有优缺点。个人觉得nginx比Apache要简单,性能方面nginx要优于Apache。orzlee服务器主要使用Ubuntu 16.04。
2018年11月23日
3,057 阅读
0 评论
1 点赞
1
2