首页 文章 精选 留言 我的

精选列表

搜索[互动课堂],共7846篇文章
优秀的个人博客,低调大师

杨老师课堂之JavaWeb项目架构之NFS文件服务器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kese7952/article/details/81013750 NFS简介 NFS(Network File System)即网络文件系统。 主要功能:通过网络(局域网)让不同的主机系统之间可以共享文件或目录。 主要用途:NFS网络文件系统一般被用来存储共享视频,图片,附件等静态资源文件。 NFS存储服务 无NFS文件共享存储 当用户A通过互联网上传文件时,经过负载均衡,随机或者定向分配到某个节点。但是当用户B去下载这个文件的时候,并不确定会向哪个节点发送请求,这样会导致用户存在一定几率下载不到的情况。 NFS_A.png 有NFS文件共享存储 当用户A通过互联网上传文件时,经过负载均衡,无论发送到哪个节点都会被存储到NFS文件服务器。但是当用户B去下载这个文件的时候,任何节点都可以读取NFS文件服务器的文件。 NFS_B.png NFS服务的优缺点 优点 简单容易上手 方便部署非常快速,维护十分简单 节省本地存储空间将常用的数据存放在一台服务器可以通过网络访问 缺点 在高并发下NFS效率/性能有限 NFS的数据是明文的,对数据完整性不做验证 多台机器挂载NFS服务器时,连接管理维护麻烦 容易发生单点故障,如果服务端宕机,所有客户端将不能访问 客户端没用用户认证机制,且数据是通过明文传送,安全性一般(一般建议在局域网内使用) RPC工作流程 170621082430983.png NFS支持的功能非常多,不同的功能会有不同的服务来完成,很多服务都需要监听在一些端口,其中的很多端口并不是固定的。这些服务在启动时,都需要向rpcbind服务注册一个端口,rpcbind服务随机选取一个未被使用的端口予以分配。rpcbind服务监听在111端口,所以rpcbind的主要功能就是指定每个RPC service对应的port number,并且通知给客户端,让客户端连接到正确的端口上去。 客户端向NFS服务器端请求的步骤: 首先用户访问网站程序,由程序在NFS客户端上发出存取NFS文件的请求,这是NFS客户端的RPC服务就不通过网络向NFS服务器端的RPC服务的111端口发出NFS文件存取功能的查询请求,包括要实现的什么功能。 NFS服务器端的RPC服务找到对应的已注册的NFS端口,通知NFS客户端的RPC服务。 此时NFS客户端获取到正确的端口,并与NFS联机存取数据。 NFS客户端把数据存取成功后,返回给客户端程序,告知用户存取结果。 注意:由于rpc service在启动时需要向rpcbind注册端口,所以rpcbind要先启动。另外若rpcbind重新启动,原来注册的数据也会不见,因此一但rpcbind重新启动,让所管理的服务因为需要重新启动以重新向rpcbind注册。 NFS服务器端配置 NFS服务器:192.168.1.180 检查并安装NFS [root@iZ2ze74fkxrls31tr2ia2fZ ~]# rpm -qa rpcbind nfs-utils nfs-utils-1.3.0-0.48.el7_4.1.x86_64 rpcbind-0.2.0-42.el7.x86_64 如果没有,安装 NFS 服务器所需的软件包,实际上需要安装两个包nfs-utils(nfs服务主程序)和rpcbind(rpc主程序), 不过当使用yum安装nfs-utils时会把rpcbind一起安装上。 yum install -y nfs-utils 配置说明 /etc/sysconfig/nfs #NFS的主配置文件 /etc/exports #配置共享目录的文件 /etc/exports的配置格式: nfs共享目录 nfs客户端地址1(参1,参2…..) 客户端地址2(参1,参2…) 说明: nfs共享目录:为nfs服务器要共享的实际目录,绝对目录。注意权限问题。 nfs客户端地址:为nfs服务器授权可以访问的客户端的地址,可以是单独的ip地址或主机名,域名。也可以是整个网段。 授权整个网段:eg:10.0.0.0/24 文件配置实例说明: /data/fileserver 192.168.1.190(rw,sync,no_root_squash) 若服务器端对/etc/exports文件进行了修改,可以通过exportfs命令重新加载服务而不需要重启服务。若重启服务需要重新向prcbind注册,而且对客户端的影响也很大,所以尽量使用exportfs命令来使配置文件生效。 exportfs: exportfs -ar #重新导出所有的文件系统 exportfs -r #导出某个文件系统 exportfs -au #关闭导出的所有文件系统 exportfs -u #关闭指定的导出的文件系统 相关参数 (man exports) A. 选项:选项用来设置输出目录的访问权限、用户映射等。 设置输出目录只读:ro 设置输出目录读写:rw B. 用户映射选项 all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody); no_all_squash:与all_squash取反(默认设置); root_squash:将root用户及所属组都映射为匿名用户或用户组(默认设置); no_root_squash:与rootsquash取反; anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx); anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户,并指定该匿名用户组账户为本地用户组账户(GID=xxx); C. 其它选项 secure:限制客户端只能从小于1024的tcp/ip端口连接nfs服务器(默认设置); insecure:允许客户端从大于1024的tcp/ip端口连接服务器; sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性; async:将数据先保存在内存缓冲区中,必要时才写入磁盘; wdelay:检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认设置); no_wdelay:若有写操作则立即执行,应与sync配合使用; subtree:若输出目录是一个子目录,则nfs服务器将检查其父目录的权限(默认设置); no_subtree:即使输出目录是一个子目录,nfs服务器也不检查其父目录的权限,这样可以提高效率; 启动NFS服务端上nfs服务 1、先为rpcbind和nfs做开机启动: systemctl enable rpcbind.service systemctl enable nfs-server.service 2、然后分别启动rpcbind和nfs服务: systemctl start rpcbind.service systemctl start nfs-server.service 查看服务是否启动 [root@iZ2ze74fkxrls31tr2ia2fZ ~]# rpcinfo -p program vers proto port service 100000 4 tcp 111 portmapper 100000 3 tcp 111 portmapper 100000 2 tcp 111 portmapper 100000 4 udp 111 portmapper 100000 3 udp 111 portmapper 100000 2 udp 111 portmapper 100024 1 udp 47426 status 100024 1 tcp 35379 status 100005 1 udp 20048 mountd 100005 1 tcp 20048 mountd 100005 2 udp 20048 mountd 100005 2 tcp 20048 mountd 100005 3 udp 20048 mountd 100005 3 tcp 20048 mountd 100003 3 tcp 2049 nfs 100003 4 tcp 2049 nfs 100227 3 tcp 2049 nfs_acl 100003 3 udp 2049 nfs 100003 4 udp 2049 nfs 100227 3 udp 2049 nfs_acl 100021 1 udp 53046 nlockmgr 100021 3 udp 53046 nlockmgr 100021 4 udp 53046 nlockmgr 100021 1 tcp 38280 nlockmgr 100021 3 tcp 38280 nlockmgr 100021 4 tcp 38280 nlockmgr 使用exportfs查看本机上已经共享的目录: exportfs NFS客户端配置 NFS客户端:192.168.1.190 安装nfs,并启动服务。 yum install -y nfs-utils systemctl enable rpcbind.service systemctl start rpcbind.service 客户端不需要启动nfs服务,只需要启动rpcbind服务。 检查 NFS 服务器端是否有目录共享 showmount -e 192.168.1.180 挂载远程服务 mount -t nfs 192.168.1.180:/data/fileserver /data/itstyle 查看挂载 df -h 开机挂载,编辑/etc/fstab vim /etc/fstab 加入以下内容: # 设备文件 挂载点 文件系统类型 mount参数 dump参数 fsck顺序 192.168.1.180:/data/fileserver /data/itstyle nfs defaults,_netdev 0 0 _netdev明确说明这是网络文件系统,避免网络启动前挂载出现错误。 保存后,重新挂载 /etc/fstab 里面的内容。 mount -a 作者: 杨校 出处: https://blog.csdn.net/kese7952 分享是快乐的,也见证了个人成长历程,文章大多都是工作经验总结以及平时学习积累,基于自身认知不足之处在所难免,也请大家指正,共同进步。 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 如有问题, 可邮件(397583050@qq.com)咨询。

优秀的个人博客,低调大师

杭电建新型教学实训平台,引入阿里云云效走进高校课堂

阿里云云效是阿里巴巴新近推出的基于 Work Like Allibaba 理念的一站式企业协同研发云平台,其源于阿里巴巴多年先进的管理理念和工程实践,提供从“需求->开发->测试->发布->运维->运营”端到端的协同服务和研发工具支撑。 阿里云云效不但可以助力广大企业高效提升研发效能与优化工作流程,在高校校园同样具有广泛的应用场景。 此次杭州电子科技大学计算机学院引入阿里云效,将就高校教学实践与研发协同工具的对接展开探索。阿里云效将为《软件过程与管理》、《WEB应用程序设计》、《WEB前端开发技术》等一系列课程的改革和运行提供全部平台资源和技术支持,并将基于试点成果在未来教育场景下展开更加全面和深入的探索。

优秀的个人博客,低调大师

酷炫的Android交互动画和视觉效果:高仿音悦台播放页面

新版的音悦台 APP 播放页面交互非常有意思,可以把播放器往下拖动,这个页面透明渐变,然后到底部可以左右拖动关闭播放器,然后点击视频列表有个页面弹出来的效果,十分炫酷,于是我自己动手实现了这个交互炫酷的播放器页面。 1.废话不多说,直接演示实现效果 1.1.点击某个视频,然后手指上下拖动,播放器做尺寸比例的渐变,视频相关信息做透明度渐变 1.2.播放器只有在底部的时候,才能左右拖动,此时播放器做透明度渐变,拖动一定范围可以关闭播放器;然后它只有在原始位置的一小段距离内可以往上拖动 1.3.点击视频列表的时候,若是上次视频是左右拖动关闭的话,会有个弹起播放页面的效果;若是返回键和返回箭头则无效果 2.实现的思路讲解 毫无疑问,需要自定义一个容器,然后处理它的触摸事件,对它的子 View 进行不同的处理。触摸事件的处理使用 ViewDragHelper 是再适合不过了,然后你需要实现容器 onMeasure 和 onLayout,由于使用了 ViewDragHelper,有些坑在代码解析的时候就会讲解。 播放页面是用新的 Activity 还仅仅是当前 Activity 的View的问题,由于播放器缩小到底部的时候,用户是可以滑动视频列表的,所以我个人认为就是在当前 Activity 放置一个自定义容器即可,因此为了效率考虑你可以用 ViewStub 来懒加载处理,这里方便演示我就直接 View 的形式了。 3.代码解析 3.1.需要的变量 3.2.初始化做 ViewDragHelper 的初始化,然后 post 拿到两个子 View,这里强制规定只能有两个子元素 3.3. ViewDragHelper 的回调需要做的事情比较多,在 mFlexView 拖动的时候需要同时设置 mFlexView 和 mFollowView 的相应变化效果,在 mFlexView 释放的时候需要处理关闭或收起等效果 3.4.接下来是处理测量和定位,我们实现的排列效果类似 LinearLayout 垂直排列的效果,这里被 measureChildWithMargins 的 heightUse 摆了一道;onLayout 的时候在位置缓存不为空的时候直接定位是因为 ViewDragHelper 在处理触摸事件子元素在做一些平移之类的,若是有元素更新了 UI 会导致重新 Layout,例如我的播放器在更新时间的 TextView 时就会如此,因此在 FlexCallback 的 onViewPositionChanged 方法记录位置,在重新 Layout 时恢复位置即可,这个也坑了好久 3.5.触摸事件的处理,由于缩放不会影响 mFlexView 真实宽高,ViewDragHelper 仍然会阻断 mFlexView 的真实宽高的区域,所以这里判断手指是否落在 mFlexView 视觉上的范围内,在才去调 ViewDragHelper 的 shouldInterceptTouchEvent 方法 3.6.在 computeScroll 中,若是 mIsClosing 为 true,即关闭的整个平移执行完毕了,通知回调事件 3.7.容器实现了,接下来我们继承 YytLayout 实现播放器页面的组合控件即可,再封装一些常用的方法,这里使用的是大名鼎鼎的 Ijkplayer 实现的播放器,屏蔽了 IjkVideoView 的触摸事件自己处理了;顺带一提,为了实现播放器 Controller 跟随拖动缩放的效果,放弃了常用的 PopupWindow 实现的思路,IjkController 直接是添加到 IjkVideoView 中的,要不弹窗实现跟随播放器太麻烦了 /** *CreatedbyOubowuon2016/12/2717:32.<p> *仿音悦台播放页面的具体实现,组合控件的形式 */ publicclassYytPlayerextendsYytLayout{ privateIjkControllermIjkController; privateIjkVideoViewmIjkVideoView; privateImageViewmIvAvatar; privateTextViewmTvName; privateTextViewmTvTime; privateTextViewmTvTitle; privateTextViewmTvDesc; privateRecyclerViewmYytRecyclerView; privateVideoListAdaptermVideoListAdapter; publicYytPlayer(Contextcontext,AttributeSetattrs){ super(context,attrs); init(context,attrs); } privatevoidinit(Contextcontext,AttributeSetattrs){ //继承YytLayout并且通过merge标签减少层级来实现组合控件 LayoutInflater.from(context).inflate(R.layout.yyt_player,this,true); setOnLayoutStateListener(newOnLayoutStateListener(){ @Override publicvoidonClose(){ setVisibility(View.INVISIBLE); mIjkVideoView.release(true); } }); mIjkVideoView=(IjkVideoView)findViewById(R.id.ijk_player_view); finalintscaledTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop(); mIjkVideoView.setOnTouchListener(newOnTouchListener(){ floatmDownX=0; floatmDownY=0; booleanmClickCancel; @Override publicbooleanonTouch(Viewv,MotionEventevent){ floatx=event.getX(); floaty=event.getY(); switch(event.getAction()){ caseMotionEvent.ACTION_DOWN: mDownX=x; mDownY=y; break; caseMotionEvent.ACTION_MOVE: if(Math.abs(mDownX-x)>scaledTouchSlop||Math.abs(mDownY-y)>scaledTouchSlop){ mClickCancel=true; } break; caseMotionEvent.ACTION_UP: if(!mClickCancel&&Math.abs(mDownX-x)<=scaledTouchSlop&&Math.abs(mDownY-y)<=scaledTouchSlop){ //点击事件偶尔失效,只好这里自己解决了 if(isHorizontalDragEnable()){ expand(); }else{ mIjkVideoView.toggleMediaControlsVisibility(); } } mClickCancel=false; break; caseMotionEvent.ACTION_CANCEL: mClickCancel=false; break; } returntrue; } }); mIvAvatar=(ImageView)findViewById(R.id.iv_avatar); mTvName=(TextView)findViewById(R.id.tv_name); mTvTime=(TextView)findViewById(R.id.tv_time); mTvTitle=(TextView)findViewById(R.id.tv_title); mTvDesc=(TextView)findViewById(R.id.tv_desc); mVideoListAdapter=newVideoListAdapter(); mVideoListAdapter.setOnItemClickCallback(newOnItemClickCallback(){ @Override publicvoidonClick(Viewview,intposition){ intpos=(Integer)view.getTag(); VideoSummarysummary=mVideoListAdapter.getData().get(pos); playVideo(mVideoListAdapter.getData(),summary); } }); mYytRecyclerView=(RecyclerView)findViewById(R.id.yyt_recycler_view); GridLayoutManagergridLayoutManager=newGridLayoutManager(context,2,LinearLayoutManager.VERTICAL,false); mYytRecyclerView.setLayoutManager(gridLayoutManager); mYytRecyclerView.setNestedScrollingEnabled(false); mYytRecyclerView.addItemDecoration(newVideoListItemDecoration(context)); mYytRecyclerView.setAdapter(mVideoListAdapter); } //播放视频 privatevoidplayVideo(Stringpath,Stringname){ try{ if(mIjkController==null){ IjkMediaPlayer.loadLibrariesOnce(null); IjkMediaPlayer.native_profileBegin("libijkplayer.so"); mIjkController=newIjkController(mIjkVideoView,name); mIjkController.setOnViewStateListener(newIjkController.OnViewStateListener(){ @Override publicvoidonBackPress(){ stop(); } }); mIjkVideoView.setMediaController(mIjkController); mIjkVideoView.setOnPreparedListener(newIMediaPlayer.OnPreparedListener(){ @Override publicvoidonPrepared(IMediaPlayermp){ mIjkVideoView.start(); } }); mIjkVideoView.setOnErrorListener(newIMediaPlayer.OnErrorListener(){ @Override publicbooleanonError(IMediaPlayermp,intwhat,intextra){ Toast.makeText(getContext(),"视频播放出错了╮(╯Д╰)╭",Toast.LENGTH_SHORT).show(); returntrue; } }); }else{ //重新设置视频名字 mIjkController.setVideoName(name); } //设置这个TextureView播放器缩放就正常了 mIjkVideoView.setRender(IjkVideoView.RENDER_TEXTURE_VIEW); //因为每次setRender都会移除view再添加,为了缩放效果这里控制器是添加到IjkVideoView中的,所以这里也要重新添加才能在IjkVideoView的最上面 mIjkController.updateControlView(); //显示加载条 mIjkController.showProgress(); //播放视频 mIjkVideoView.setVideoURI(Uri.parse(path)); }catch(UnsatisfiedLinkErrore){ e.printStackTrace(); Toast.makeText(getContext(),"你的CPU是"+Build.CPU_ABI+",当前播放器使用的编译版本"+BuildConfig.FLAVOR+"不匹配!",Toast.LENGTH_LONG).show(); } } /** *显示布局,并且播放视频 * *@paramdata视频列表,用于播放页面下面的列表布局 *@paramsummary播放的视频信息 */ publicvoidplayVideo(List<VideoSummary>data,VideoSummarysummary){ //拿到数据,设置到播放的布局的相关信息 Glide.with(getContext()).load(summary.mTopicImg).transform(newGlideCircleTransform(getContext())).into(mIvAvatar); mTvName.setText(summary.mTopicName); mTvTime.setText(summary.mPtime); mTvTitle.setText(Html.fromHtml(summary.mTitle)); if(summary.mDescription.isEmpty()){ mTvDesc.setText(summary.mTopicDesc); }else{ mTvDesc.setText(Html.fromHtml(summary.mDescription)); } //设置YytLayout可见,并且展开 setVisibility(View.VISIBLE); expand(); mVideoListAdapter.setData(data); mVideoListAdapter.setItemWidth(mYytRecyclerView.getWidth()/2); mVideoListAdapter.notifyDataSetChanged(); //播放视频 playVideo(summary.mMp4HdUrl==null?summary.mMp4Url:summary.mMp4HdUrl,summary.mTitle); } //开始播放 publicvoidstart(){ if(mIjkVideoView!=null&&!mIjkVideoView.isPlaying()){ mIjkVideoView.start(); } } //暂停播放 publicvoidpause(){ if(mIjkVideoView!=null&&mIjkVideoView.isPlaying()){ mIjkVideoView.pause(); } } //停止播放 publicvoidstop(){ setVisibility(View.INVISIBLE); if(mIjkVideoView!=null){ mIjkVideoView.release(true); } } publicbooleanisShowing(){ returngetVisibility()==VISIBLE; } } 4.总结 说难也不难,就是各种抠细节需要脑洞,各位不妨看到好玩的交互自己打开脑洞一下,接下来可能要实现下 UC 浏览器播放器的效果,感觉也是非常有意思。 作者:oubowu 来源:51CTO

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册