首页 文章 精选 留言 我的

精选列表

搜索[热点技术征文第五期Sora],共10007篇文章
优秀的个人博客,低调大师

Android第五期 - 更新自己的apk本地与网络两种方法

首先是本地: ParseXmlService部分: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package com.szy.update; import java.io.InputStream; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** *@authorcoolszy *@date2012-4-26 *@bloghttp://blog.92coding.com */ public class ParseXmlService { public HashMap<String,String>parseXml(InputStreaminStream) throws Exception { HashMap<String,String>hashMap= new HashMap<String,String>(); //实例化一个文档构建器工厂 DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance(); //通过文档构建器工厂获取一个文档构建器 DocumentBuilderbuilder=factory.newDocumentBuilder(); //通过文档通过文档构建器构建一个文档实例 Documentdocument=builder.parse(inStream); //获取XML文件根节点 Elementroot=document.getDocumentElement(); //获得所有子节点 NodeListchildNodes=root.getChildNodes(); for ( int j= 0 ;j<childNodes.getLength();j++) { //遍历子节点 NodechildNode=(Node)childNodes.item(j); if (childNode.getNodeType()==Node.ELEMENT_NODE) { ElementchildElement=(Element)childNode; //版本号 if ( "version" .equals(childElement.getNodeName())) { hashMap.put( "version" ,childElement.getFirstChild().getNodeValue()); } //软件名称 else if (( "name" .equals(childElement.getNodeName()))) { hashMap.put( "name" ,childElement.getFirstChild().getNodeValue()); } //下载地址 else if (( "url" .equals(childElement.getNodeName()))) { hashMap.put( "url" ,childElement.getFirstChild().getNodeValue()); } } } return hashMap; } } UpdateManager部分: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 package com.gaoxiaotongctone.update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import com.gaoxiaotongctone.R; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources.NotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; public class UpdateManager{ /*下载中*/ privatestaticfinalintDOWNLOAD=1; /*下载结束*/ privatestaticfinalintDOWNLOAD_FINISH=2; /*保存解析的XML信息*/ HashMap<String,String>mHashMap; /*下载保存路径*/ privateStringmSavePath; /*记录进度条数量*/ privateintprogress; /*是否取消更新*/ privatebooleancancelUpdate=false; privateContextmContext; /*更新进度条*/ privateProgressBarmProgress; privateDialogmDownloadDialog; privateHandlermHandler=newHandler(){ @Override publicvoidhandleMessage(Messagemsg){ switch(msg.what){ //正在下载 caseDOWNLOAD: //设置进度条位置 mProgress.setProgress(progress); break; caseDOWNLOAD_FINISH: //安装文件 installApk(); break; default: break; } }; }; publicUpdateManager(Contextcontext){ this.mContext=context; } /** *检测软件更新 * *@throwsIOException *@throwsNotFoundException */ publicvoidcheckUpdate()throwsNotFoundException,IOException{ newThread(newRunnable(){ @Override publicvoidrun(){ //TODOAuto-generatedmethodstub try{ if(isUpdate()){ //显示提示对话框 Looper.prepare(); showNoticeDialog(); Looper.loop(); Log.d("消息","有新版本"); }else{ //Toast.makeText(mContext,R.string.soft_update_no, //Toast.LENGTH_LONG).show(); Log.d("消息","已是最新版本"); } }catch(NotFoundExceptione){ //TODOAuto-generatedcatchblock //Toast.makeText(UpdateManager.this,"QQ空间",2).show(); e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }).start(); } /** *检查软件是否有更新版本 * *@return *@throwsIOException */ privatebooleanisUpdate()throwsIOException{ //获取当前软件版本 intversionCode=getVersionCode(mContext); //把version.xml放到src,然后获取文件信息 InputStreaminStream= ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml"); InputStreaminStream=urlConn.getInputStream(); //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlServiceservice=newParseXmlService(); try{ mHashMap=service.parseXml(inStream); }catch(Exceptione){ e.printStackTrace(); } if(null!=mHashMap){ intserviceCode=Integer.valueOf(mHashMap.get("version"));//String.valueOf("serviceCode"+"---"+serviceCode) //Toast.makeText(UpdateManager.this,'',Toast.LENGTH_SHORT).show(); Log.i("-----serviceCode",""+serviceCode); Log.i("-----versionCode",""+versionCode); //版本判断 if(serviceCode>versionCode){ returntrue; } }else{ Log.i("-----null==mHashMap","null==mHashMap"); } returnfalse; } /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext){ intversionCode=0; try{ //获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode=context.getPackageManager().getPackageInfo( "com.gaoxiaotongctone",0).versionCode; }catch(NameNotFoundExceptione){ e.printStackTrace(); } returnversionCode; } /** *显示软件更新对话框 */ privatevoidshowNoticeDialog(){ //构造对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_update_title); builder.setMessage(R.string.soft_update_info); //更新 builder.setPositiveButton(R.string.soft_update_updatebtn, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //显示下载对话框 showDownloadDialog(); } }); //稍后更新 builder.setNegativeButton(R.string.soft_update_later, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); } }); DialognoticeDialog=builder.create(); noticeDialog.show(); } /** *显示软件下载对话框 */ privatevoidshowDownloadDialog(){ //构造软件下载对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_updating); //给下载对话框增加进度条 finalLayoutInflaterinflater=LayoutInflater.from(mContext); Viewv=inflater.inflate(R.layout.sotfupdate_progress,null); mProgress=(ProgressBar)v.findViewById(R.id.update_progress); builder.setView(v); //取消更新 builder.setNegativeButton(R.string.soft_update_cancel, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //设置取消状态 cancelUpdate=true; } }); mDownloadDialog=builder.create(); mDownloadDialog.show(); //现在文件 downloadApk(); } /** *下载apk文件 */ privatevoiddownloadApk(){ //启动新线程下载软件 newdownloadApkThread().start(); } /** *下载文件线程 */ privateclassdownloadApkThreadextendsThread{ @Override publicvoidrun(){ try{ //判断SD卡是否存在,并且是否具有读写权限 if(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)){ //获得存储卡的路径 Stringsdpath=Environment.getExternalStorageDirectory() +"/"; mSavePath=sdpath+"download"; URLurl=newURL(mHashMap.get("url")); //创建连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); conn.connect(); //获取文件大小 intlength=conn.getContentLength(); //创建输入流 InputStreamis=conn.getInputStream(); Filefile=newFile(mSavePath); //判断文件目录是否存在 if(!file.exists()){ file.mkdir(); } FileapkFile=newFile(mSavePath,mHashMap.get("name")); FileOutputStreamfos=newFileOutputStream(apkFile); intcount=0; //缓存 bytebuf[]=newbyte[1024]; //写入到文件中 do{ intnumread=is.read(buf); count+=numread; //计算进度条位置 progress=(int)(((float)count/length)*100); //更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if(numread<=0){ //下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } //写入文件 fos.write(buf,0,numread); }while(!cancelUpdate);//点击取消就停止下载. fos.close(); is.close(); } }catch(MalformedURLExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } //取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** *安装APK文件 */ private void installApk(){ Fileapkfile= new File(mSavePath,mHashMap.get( "name" )); if (!apkfile.exists()){ return ; } //通过Intent安装APK文件 Intenti= new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse( "file://" +apkfile.toString()), "application/vnd.android.package-archive" ); mContext.startActivity(i); } } MainActivity.java部分: 1 2 3 4 5 6 7 8 9 @Override public void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); UpdateManagermanager= new UpdateManager(MainActivity. this ); manager.checkUpdate(); } 别忘了xml中给权限。 version.xml部分: 1 2 3 4 5 < update > < version >2</ version > < name >彩通科技</ name > < url >http://imp.ctone.net/Frame/ctone.apk</ url > </ update > 网络链接UpdateManager.java部分: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 package com.gaoxiaotongctone.update; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import com.gaoxiaotongctone.R; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources.NotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; public class UpdateManager{ /*下载中*/ privatestaticfinalintDOWNLOAD=1; /*下载结束*/ privatestaticfinalintDOWNLOAD_FINISH=2; /*保存解析的XML信息*/ HashMap<String,String>mHashMap; /*下载保存路径*/ privateStringmSavePath; /*记录进度条数量*/ privateintprogress; /*是否取消更新*/ privatebooleancancelUpdate=false; privateContextmContext; /*更新进度条*/ privateProgressBarmProgress; privateDialogmDownloadDialog; privateHandlermHandler=newHandler(){ @Override publicvoidhandleMessage(Messagemsg){ switch(msg.what){ //正在下载 caseDOWNLOAD: //设置进度条位置 mProgress.setProgress(progress); break; caseDOWNLOAD_FINISH: //安装文件 installApk(); break; default: break; } }; }; publicUpdateManager(Contextcontext){ this.mContext=context; } /** *检测软件更新 * *@throwsIOException *@throwsNotFoundException */ publicvoidcheckUpdate()throwsNotFoundException,IOException{ newThread(newRunnable(){ @Override publicvoidrun(){ //TODOAuto-generatedmethodstub try{ if(isUpdate()){ //显示提示对话框 Looper.prepare(); showNoticeDialog(); Looper.loop(); Log.d("消息","有新版本"); }else{ //Toast.makeText(mContext,R.string.soft_update_no, //Toast.LENGTH_LONG).show(); Log.d("消息","已是最新版本"); } }catch(NotFoundExceptione){ //TODOAuto-generatedcatchblock //Toast.makeText(UpdateManager.this,"QQ空间",2).show(); e.printStackTrace(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } } }).start(); } /** *检查软件是否有更新版本 * *@return *@throwsIOException */ privatebooleanisUpdate()throwsIOException{ //获取当前软件版本 intversionCode=getVersionCode(mContext); //把version.xml放到网络上,然后获取文件信息 URLurl=newURL("http://imp.ctone.net/Frame/version.xml"); HttpURLConnectionurlConn=(HttpURLConnection)url.openConnection(); InputStreaminStream=urlConn.getInputStream(); //解析XML文件。由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlServiceservice=newParseXmlService(); try{ mHashMap=service.parseXml(inStream); }catch(Exceptione){ e.printStackTrace(); } if(null!=mHashMap){ intserviceCode=Integer.valueOf(mHashMap.get("version"));//String.valueOf("serviceCode"+"---"+serviceCode) //Toast.makeText(UpdateManager.this,'',Toast.LENGTH_SHORT).show(); Log.i("-----serviceCode",""+serviceCode); Log.i("-----versionCode",""+versionCode); //版本判断 if(serviceCode>versionCode){ returntrue; } }else{ Log.i("-----null==mHashMap","null==mHashMap"); } returnfalse; } /** *获取软件版本号 * *@paramcontext *@return */ privateintgetVersionCode(Contextcontext){ intversionCode=0; try{ //获取软件版本号,对应AndroidManifest.xml下android:versionCode versionCode=context.getPackageManager().getPackageInfo( "com.gaoxiaotongctone",0).versionCode; }catch(NameNotFoundExceptione){ e.printStackTrace(); } returnversionCode; } /** *显示软件更新对话框 */ privatevoidshowNoticeDialog(){ //构造对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_update_title); builder.setMessage(R.string.soft_update_info); //更新 builder.setPositiveButton(R.string.soft_update_updatebtn, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //显示下载对话框 showDownloadDialog(); } }); //稍后更新 builder.setNegativeButton(R.string.soft_update_later, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); } }); DialognoticeDialog=builder.create(); noticeDialog.show(); } /** *显示软件下载对话框 */ privatevoidshowDownloadDialog(){ //构造软件下载对话框 AlertDialog.Builderbuilder=newBuilder(mContext); builder.setTitle(R.string.soft_updating); //给下载对话框增加进度条 finalLayoutInflaterinflater=LayoutInflater.from(mContext); Viewv=inflater.inflate(R.layout.sotfupdate_progress,null); mProgress=(ProgressBar)v.findViewById(R.id.update_progress); builder.setView(v); //取消更新 builder.setNegativeButton(R.string.soft_update_cancel, newOnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); //设置取消状态 cancelUpdate=true; } }); mDownloadDialog=builder.create(); mDownloadDialog.show(); //现在文件 downloadApk(); } /** *下载apk文件 */ privatevoiddownloadApk(){ //启动新线程下载软件 newdownloadApkThread().start(); } /** *下载文件线程 */ privateclassdownloadApkThreadextendsThread{ @Override publicvoidrun(){ try{ //判断SD卡是否存在,并且是否具有读写权限 if(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)){ //获得存储卡的路径 Stringsdpath=Environment.getExternalStorageDirectory() +"/"; mSavePath=sdpath+"download"; URLurl=newURL(mHashMap.get("url")); //创建连接 HttpURLConnectionconn=(HttpURLConnection)url .openConnection(); conn.connect(); //获取文件大小 intlength=conn.getContentLength(); //创建输入流 InputStreamis=conn.getInputStream(); Filefile=newFile(mSavePath); //判断文件目录是否存在 if(!file.exists()){ file.mkdir(); } FileapkFile=newFile(mSavePath,mHashMap.get("name")); FileOutputStreamfos=newFileOutputStream(apkFile); intcount=0; //缓存 bytebuf[]=newbyte[1024]; //写入到文件中 do{ intnumread=is.read(buf); count+=numread; //计算进度条位置 progress=(int)(((float)count/length)*100); //更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if(numread<=0){ //下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } //写入文件 fos.write(buf,0,numread); }while(!cancelUpdate);//点击取消就停止下载. fos.close(); is.close(); } }catch(MalformedURLExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } //取消下载对话框显示 mDownloadDialog.dismiss(); } }; /** *安装APK文件 */ private void installApk(){ Fileapkfile= new File(mSavePath,mHashMap.get( "name" )); if (!apkfile.exists()){ return ; } //通过Intent安装APK文件 Intenti= new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse( "file://" +apkfile.toString()), "application/vnd.android.package-archive" ); mContext.startActivity(i); } } 附效果图: 好好学习,好好活着。 附件:http://down.51cto.com/data/2364560 本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1429384,如需转载请自行联系原作者

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

【征文】使用 WorkBuddy 优化老旧 PHP 门户网站项目实操分享

手上维护一套多年前开发的 PHP 传统门户网站,项目年代久、代码缺少规范,没有完善注释,存在 SQL 拼接风险、前端页面加载慢、冗余代码多等一系列问题。日常改需求、排查 BUG、做性能优化耗费大量精力。近期我使用 WorkBuddy 辅助梳理老 PHP 项目、代码审计、性能优化以及安全漏洞排查。本文记录完整实操流程、踩坑经验,以及如何合理使用模型控制积分消耗。

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

【AWS征文】如何利用 AWS CloudFront 给您的站点全站安全加速

如何给你的站点加速,如何做到静态资源动态资源同时加速,本文将详细为你介绍 AWS CloudFront,并且如何利用 CloudFront 为您的站点加速,以及使用 CloudFront 的注意事项。 CloudFront 是什么 现在越来越多的产品开始走出国内,迈向全球。现在移动互联网越来越火热,大家都是通过官方网站去浏览产品的特性,那么我们就需要为产品建立一个全球化的网站,把产品介绍推送给全球用户。那么如何才可以让全球的用户以最快的速度打开站点呢?我们知道,全球的网络传输依托于光纤,而光的速度是不变的,距离服务器越远的用户延迟注定会越高,经过的路由也会越多多,速度也会越慢。 如何克服困难,给用户一个好的体验,AWS 云服务中哪个产品可以帮助我们实现?我们需要了解一下 AWS CloudFront,CloudFront 是什么,拥有什么功能,相比于其他的 CDN 服务,又有什么优势呢,我们后面一一解答。 CloudFront 是 AWS 推出的 CDN 服务,可以对网站资源进行缓存加速。我们通常理解的 CDN 就是对静态资源加速,静态资源会分发到 AWS 全球的边缘节点,用户就近访问所需要的资源。那么针对动态资源怎么办?这个我们也不用担心,AWS 拥有非常庞大的基础设施,利用这些基础设施,CloudFront 同样可以对动态资源加速,比如我们的 PHP、ASP 等动态资源。这里的加速并不是把这些资源分发的全球,而是让用户的流量最快进入 AWS 的骨干网。骨干网依托于 AWS 的基础设施,骨干网由 AWS 自己维护,拥有高速带宽,智能路由,AWS 会制定最优的路由策略,让用户的请求最快稳定的到达源站。 那么废话不多说,我们下面看看如何设定,让我们的站点推向全球吧。 准备站点 我这次以一个 wordpress 站点做演示,我们不需要破坏站点的任何结构,就可以实现全站加速,静态资源缓存到全球边缘节点,请求动态资源通过 AWS 骨干网动态路由到源站。 CloudFront 虽然说可以加速第三方站点,但是为了最好的效果,非常推荐把站点放在 AWS 的服务中,这次我们把站点放置在 EC2 上面进行测试。 我 EC2 的系统是 Amazon Linux 2,环境是用 LNMP 一键安装包创建的,关于 LNMP 的使用方式我这里不再介绍,一台 EC2 可以部署多个虚拟主机网站,默认我们的 EC2 只提供 HTTP 的服务,如果需要 HTTPS 的话,那我们把证书挂载 ALB 或者 CloudFront。 我们从最开始指导大家如何一步步操作,最终配置完成 CloudFront 实现全站加速。 查看默认站点 默认域名是直接解析到 EC2 的,使用的是 HTTP 请求访问,我们查看一下效果。 配置 ALB 启用 HTTPS 虽然说 CloudFront 可以直接为网站加速,但是那需要我们准备两个域名,一个加速域名,一个源站域名,弄起来比较复杂,我们借助 ALB 中间这个工具,只负责一个域名就可以了,管理起来非常简单,关于 ALB 的配置,我这里也不再介绍,大家看我配置好的效果吧。 当我们使用 HTTPS 访问的时候,发现很多连接都被浏览器 blocked 掉了,那么这是为什么呢? 我们首先就是要解决这个 HTTPS 的问题,不然使用 CloudFront 会有同样的问题,我们首先了解一下目前的架构情况。 虽然用户使用的 HTTPS 发起请求,但是在经过 ALB 之后,转换成 HTTP 请求源站的 wordpress,wordpress 其实并不知道用户使用的 HTTPS 请求的,发现过来的请求是 HTTP,于是 wordpress 构建的 document 里面嵌入的是 HTTP 的资源链接,返回给浏览器之后,浏览器因为一些安全的设定,会 blocked 这些 HTTP 的资源请求,这也就导致了我们的站点不能正常展示,顺便说一下,我使用的是 Chrome 浏览器,其他浏览器是否会 blocked 大家可以去试一下。 那么如何解决这个问题呢?打个不恰当的比如,我们要“欺骗” wordpress,让它认为我们是用 HTTPS 请求的,其实也就是给 wordpress 做个设置,不管用户使用什么协议请求,都给客户端返回 HTTPS,那么我们需要给 wordpress 的配置文件wp-config.php增加下面一段内容。 if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) $_SERVER['HTTPS']='on'; 然后我们再次请求,看到 HTTPS 已经可以正常访问。 配置 CloudFront 创建 Distribution 打开 CloudFront 控制台,创建一个 WEB Distribution,因为很多小伙伴并不清楚站点的结构,不知道哪些目录是静态资源,哪些目录是动态资源,如果默认直接都缓存的话,那会产生很多问题,比如无法登陆,无法提交信息等。所以我们换个思路去操作,那就是我们先全站动态加速,不进行任何缓存,然后再去检查哪些目录是静态文件,在设置规则,对这些目录的文件进行缓存,初次创建,那大家就按照我下面的参数设置吧。 注意:表格里面没有写的,选择默认即可。 Parameter Value Origin Domain Name AuroraMigrationTask Origin Protocol Policy HTTP Only Allowed HTTP Methods GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE Cache Based on Selected Request Headers All Forward Cookies All Query String Forwarding and Caching Forward all, cache based on all Alternate Domain Names wp.wzlinux.com SSL Certificate Custom SSL Certificate,域名证书在 us-east-1 区域申请 查看效果 然后我们创建分发,在修改域名解析之前,我们测试一下站点现在全球的延时情况,目前网站所在区域为爱尔兰。 可以看到除了欧洲区域,其他地域延迟都比较高,现在我们修改域名解析指向 CloudFront Domain Name,然后再测试一下延迟情况。 使用 CDN 之后,我们可以看到海外的延迟明显降了下来,因为大陆防火墙的原因,下降没有那么明显,不过也比之前好多了。 我们继续浏览器访问一下,又发现了很多链接没有返回 https,所以被 blocked 了,这是为什么,我们继续分析一下现在的架构图。 前面用户访问 ALB 使用的 HTTPS,用户的请求协议其实透过请求头通过 ALB 传递到了后端服务器,现在访问 ALB 变成了 HTTP,虽然用户访问 CDN 使用的 HTTPS,CloudFront 没有把请求头没有传到后端,所以后端一直以为是用 HTTP 访问的,导致返回的链接被浏览器 blocked。那这种情况该怎么办呢?既然请求协议没有传递到后端,那我们可以在 CloudFront 上面添加请求头X-Forwarded-Proto。 打开我们创建好的 distribute,选择 Origins and Origin Groups,编辑添加 Origin Custom Headers。 等待生效,本以为这样就可以了,但是还是不行,后来了解到 ALB 会更换请求头X-Forwarded-Proto,因为 ALB 看到 CloudFront 使用的 HTTP 请求的,所以即便我们在 CloudFront 上面添加请求头,也是会被 ALB 重置,那么我们只有从 wordpress 上面去下手解决问题了。 应该还记得我们前面对 wordpress 添加的一个配置,里面有一个 if 判断条件,我们可以去掉这个条件,让 wordpress 不管用户使用什么请求,都返回给用户 HTTPS 的链接。那我们就这样做,把之前的配置修改如下: $_SERVER['HTTPS']='on'; 因为我们是全站动态加速,所以看到缓存结果没有命中,这是正常的,那下面我们来针对站点进行缓存优化,毕竟不进行缓存,那 CDN 和咸鱼又有什么区别呢? 优化缓存 我们打开开发者模式,多访问几个页面,查看一下静态资源都在什么路径下面,比如我找到的几个静态资源URL 地址如下: https://wp.wzlinux.com/wp-content/uploads/2020/07/mp53182456_1452216795463_2.jpeg https://wp.wzlinux.com/wp-includes/css/dist/block-library/style.min.css?ver=5.4.2 https://wp.wzlinux.com/wp-includes/js/wp-embed.min.js?ver=5.4.2 https://wp.wzlinux.com/wp-content/themes/twentytwenty/style.css?ver=1.2 https://wp.wzlinux.com/wp-content/themes/twentytwenty/assets/js/index.js?ver=1.2 你们找到的 URL 可能比我多,不同的主题 URL 会有些不同,我们就拿着几个为例子进行设置一下,可以大胆一点,我们对整个目录进行缓存,我们整理的路径有如下几个。 wp-content/uploads/* wp-includes/css/* wp-includes/js/* wp-content/themes/twentytwenty/* 如果有什么问题,我们可以再针对具体情况调整,那下面我们就开始优化缓存吧。 打开 Distribution,选择创建 Behaviors,把上面的路径填写在 Path Pattern 里面,因为我们后端服务是虚拟主机,需要我们把 Host 这个 Request Header 传递过去,加入白名单中,其他选择默认即可: 按照这样的模式,我们把其他几个路径也填写好。 然后我们再去请求站点,查看我们进行缓存的一些文件是否缓存命中。 目前看来一切正常了,大家可以慢慢完善需要缓存的内容。还等什么,给你的站点去做全站加速吧! 注意:因为我们开启了 HTTPS 访问,所以遇到了一些问题,本文一一解释了问题的原因以及如何解决办法,如果你不需要 HTTPS,那整个过程会更加简单。 欢迎大家扫码关注,获取更多信息

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

邀您参与阿里云MaxCompute2.0最佳实践征文活动

DT时代,越来越多的企业应用数据步入云端。与传统Hadoop相比,阿里云大数据计算服务MaxCompute(原名ODPS)向用户提供了完善的数据导入方案以及多种经典的分布式计算模型,能够更快速的解决用户海量数据计算问题,有效降低企业成本,并保障数据安全。 最新推出的MaxCompute 2.0,在高性能方面主要依托于全新的SQL 2.0计算引擎。同时,基于MaxCompute2.0新一代的SQL引擎,MaxCompute显著提升了SQL语言编译过程的易用性与语言的表达能力。在新功能方面提供了非结构化的处理能力,在云上开始使用OSS(开放的对象存储)、OTS(开放的表格存储),MaxCompute对其进一步分析和计算提供了连接性。安全方面,提供了Label字段级别数据访问控制及数据脱敏。用量控制方面,推出了禁止全表扫描FullScan

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

【阿里云MVP第五期】Elastic曾勇:Elasticsearch在智能运维领域的应用

嘉宾介绍 曾勇 阿里云MVP、Elastic开发工程师与布道师,在分布式搜索、高性能、高可用架构、自动化运维等方面积累了超过七年的经验。曾勇是Elasticsearch国内首批用户,自2010年起就开始接触Elasticsearch并投入到生产环境中使用,并编写过一系列的中文处理相关的插件。 智能运维从概念走向应用 人工智能是当前很火热的话题,无AI不科技。在运维领域如何同人工智能结合,业界也正在不断探索。理想的世界里,运维工程师可以悠闲的喝咖啡,所有的运维工作都由机器帮忙搞定。这只存在与概念层面,实际上,落地的应用还需要较长的时间。如何落地,在哪些运维的点上可以尝试人工智能,这就是我们今天讨论的重点。 运维的痛点 运维在一个公司里面人不多,但是事情又特别杂,涉及到很多方面,包括最基本的IT运维,服务器的运维,公司内网等基础设施的监控,安全

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

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

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

WebStorm

WebStorm

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

用户登录
用户注册