首页 文章 精选 留言 我的

精选列表

搜索[文档解析],共10000篇文章
优秀的个人博客,低调大师

AAC ADTS流解析总结

这里列出Android里将aac编码器输出的音频帧加上ADTS头的代码: + int tmpFd; + tmpFd = ::open("/data/src.aac", O_WRONLY | O_APPEND ); + if ( tmpFd < 0 ) { + LOGE("No dump decode file %s",strerror(errno)); + } + else + { + unsigned char adts_hdr[7] = {0xff, 0xf9, 0x5c, 0x80, 0x00,0x1f, 0xfc}; + + adts_hdr[3] = 0x80 | ((mConfig->inputBufferCurrentLength >> 11) & 3); + adts_hdr[4] = (mConfig->inputBufferCurrentLength >> 3) & 0xff; + adts_hdr[5] = ((mConfig->inputBufferCurrentLength & 7) << 5) | 0x1f; + + ::write(tmpFd,adts_hdr, 7); + ::write(tmpFd,(const char *)mConfig->pInputBuffer , mConfig->inputBufferCurrentLength); + ::close(tmpFd); + } AAC参考知识: http://blog.csdn.net/axdc_qa_team/article/details/4271043 (除协议外,非常详细的文章) http://blog.csdn.net/jay100500/article/details/52955232 (adts协议) http://blog.csdn.net/leixiaohua1020/article/details/11822537 //aac header http://yeyingxian.blog.163.com/blog/static/344712420134485613752/ https://wiki.multimedia.cx/index.php?title=MPEG-4_Audio 本文转自 曾永刚 51CTO博客,原文链接:http://blog.51cto.com/zyg0227/1952766

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

Handler的解析和使用

1.handler为android中多线程间通信的一种机制, @1android中只允许在UI线程(主线程)操作或改变UI,其他线程不能操作UI。 @2其他线程有刷新UI的需要,所以得告诉UI线程,这时候就用到Handler,在handeMessage方法中处理消息。 @3handler可以定义在主线程也可以定义在其他线程,作用不一样。 @4与handler执行相关的类:Handler,Message,MessageQueue,Looper UI线程:主线程,创建时会自动初始化一个Looper对象,也会创建一个消息队列 Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。 Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。 MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。 Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。 Thread:线程,负责调度整个消息循环,即消息循环的执行场所。 2.handler的使用 @1用在主线程 ---1-定义Handler对象,重写handleMessage方法,在方法里面处理消息,更新UI privateHandlermHanlder=newHandler(){ publicvoidhandleMessage(android.os.Messagemsg){ numberAdapter=newBlackNumberAdapter(getApplicationContext(),mList,mBnd); lv_blacknum.setAdapter(numberAdapter); }; }; ---2-在其他 线程发送消息,有时需要自己定义消息对象 mHanlder.sendEmptyMessage(BLACKNUM_PREPARED); @2handler定义在子线程,需要自己创建Looper对象 ----流程: ====1.调用Looper.prepare()为当前线程创建Looper对象,此时会自动创建MessageQueue消息队列;2.创建Handler对象,重写handleMessage方法;3.调用Looper.loop()方法启动Looper消息循环 本文转自lzwxx 51CTO博客,原文链接:http://blog.51cto.com/13064681/1943367

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

Ubuntu环境变量解析

在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /etc/environment:在登录时操作系统使用的第二个文件,系统在读取你自己的profile前,设置环境文件的环境变量 ~/.profile:在登录时用到的第三个文件是.profile文件,每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件. /etc/bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取. ~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取. 当你登录并且登录shell是bash时,bash首先执行/etc/profile文件中的命令(如果该文件存在),然后它顺序寻找 ~ /.bash_profile,~/.bash_login或~/.profile文件,并执行找到的第一个可读文件中的命令.当登录bash退出时,它 将执行~/.bash_logout文件中的命令. 当启动一个交互的bash时,它将执行~/.bashrc文件中的命令(如果该文件存在并且可读).当非交互地启动以运行一个shell脚本时,bash将查找bash_env环境变量,确定执行文件的名称. 本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/4474154.html,如需转载请自行联系原作者

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

深度解析阿里云存储

国际知名调研机构Gartner近日公布了2017年全球云计算云存储魔力象限,阿里云的云存储强势崛起成为这一核心领域的前四名。 图1 2017年Gartner全球云存储魔力象限图 在去年首次进入Gartner魔力象限即取得了不错的位置之后,今年阿里云存储再次强势进入公共云存储魔力象限,紧跟Google成为公共云存储厂商中在利基象限中最接近领导者象限的公共云存储厂商,而领导者象限中目前只有AWS和Azure。 图2 2016年Gartner全球云存储魔力象限图 作为国内市场排名第一的云厂商的云存储产品系列,取得这样的成绩也并不是水涨船高的结果。首先从整体评估上来说,Gartner的评估方法并不依赖母体厂商的品牌和占有率,而是客观的从云存储类型(对象,块,文件)和冷热存储,全球数据中心的位置、技术成熟度、市场策略、市场份额、服务承诺和SLA

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

Android 使用SAX解析XML

项目的结构 首先新建一个book_info.xml的xml文件,结构如下: <?xml version= "1.0" encoding= "UTF-8" ?> <books> <catalog>Computer</catalog> <book> <country>USA</country> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <price> 10.90 </price> </book> <book> <country>UK</country> <title>Hide your heart</title> <artist>Bonnie Tyler</artist> <price> 9.90 </price> </book> <book> <country>USA</country> <title>Greatest Hits</title> <artist>Dolly Parton</artist> <price> 9.90 </price> </book> </books> BookItem.java 代表一本书的信息,代码如下: package com.example.utility; public class BookItem { public String name; public String title; public String artit; public String price; public BookItem() { } public String getName() { return name; } public void setName(String countryName) { this .name = countryName; } public String getTitle() { return title; } public void setTitle(String title) { this .title = title; } public String getArtist() { return artit; } public void setArtist(String artit) { this .artit = artit; } public String getPrice() { return price; } public void setPrice(String price) { this .price = price; } } BookFeed代表所有书的信息,代码如下: package com.example.utility; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; public class BookFeed { private String catalog; private List<BookItem> bookList; private int itemcount; public BookFeed() { bookList = new Vector<BookItem>( 0 ); } public int addBookItem(BookItem item) { itemcount++; bookList.add(item); return itemcount; } public BookItem getBookItem( int location) { return bookList.get(location); } public List<BookItem> getAllBooks() { return bookList; } public String getCatalog() { return catalog; } public void setCatalog(String catalog) { this .catalog = catalog; } public List<BookItem> getBookList() { return bookList; } public void setBookList(List<BookItem> bookList) { this .bookList = bookList; } public List GetAllBooks() { List<Map<String, String>> data = new ArrayList<Map<String,String>>() ; int size = bookList.size(); for ( int i = 0 ; i < size; i++) { HashMap<String, String> bookItemHashMap = new HashMap<String, String>(); bookItemHashMap.put( "title" , bookList.get(i).getTitle()); bookItemHashMap.put( "price" , bookList.get(i).getPrice()); data.add(bookItemHashMap); } return data; } } BookHand.java package com.example.utility; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import android.R.integer; public class BookHandle extends DefaultHandler { BookFeed bookFeed; BookItem bookItem; final int Book_Country = 1 ; final int Book_Title = 2 ; final int Book_Artist = 3 ; final int Book_Price = 4 ; int curState = 0 ; public BookHandle() { } public BookFeed getBookFeed() { return bookFeed; } @Override public void startDocument() throws SAXException { bookFeed = new BookFeed(); bookItem = new BookItem(); } @Override public void endDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (localName.equals( "books" )) { curState = 0 ; return ; } if (localName.equals( "book" )) { bookItem = new BookItem(); return ; } if (localName.equals( "country" )) { curState = Book_Country; return ; } if (localName.equals( "title" )) { curState = Book_Title; return ; } if (localName.equals( "artist" )) { curState = Book_Artist; return ; } if (localName.equals( "price" )) { curState = Book_Price; return ; } curState = 0 ; } @Override public void endElement(String uri, String localName,String qName) throws SAXException { if (localName.equals( "book" )) { bookFeed.addBookItem(bookItem); return ; } } @Override public void characters( char [] ch, int start, int length) throws SAXException { String str = new String(ch,start,length); switch (curState) { case Book_Country: bookItem.setName(str); curState = 0 ; break ; case Book_Title: bookItem.setTitle(str); curState = 0 ; break ; case Book_Artist: bookItem.setArtist(str); curState = 0 ; break ; case Book_Price: bookItem.setPrice(str); curState = 0 ; break ; default : return ; } } } MainActiviyt.java public class MainActivity extends Activity { public BookFeed feed; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); feed = getFeed(); showList(); } private void showList() { // TODO Auto-generated method stub ListView lView = (ListView) this .findViewById(R.id.listView1); if (feed == null ) { Log.i( "Custom Message" , "feed is null" ); return ; } SimpleAdapter adapter = new SimpleAdapter( this , feed.GetAllBooks(), android.R.layout.simple_list_item_2, new String[]{ "title" , "price" }, new int []{android.R.id.text1, android.R.id.text2}); lView.setAdapter(adapter); } public BookFeed getFeed() { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader reader = parser.getXMLReader(); BookHandle handle = new BookHandle(); reader.setContentHandler(handle); InputSource iSource = new InputSource( this .getClassLoader().getResourceAsStream( "book_info.xml" )); reader.parse(iSource); return handle.getBookFeed(); } catch (ParserConfigurationException e) { // TODO: handle exception e.printStackTrace(); } catch (SAXException e) { // TODO: handle exception e.printStackTrace(); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } return null ; } } 效果图: 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/archive/2013/03/18/2966020.html,如需转载请自行联系原作者

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

Android Fragment使用全解析

Fragment的使用可谓是老生常谈了~~~ 1、概述 自API 11引入Fragment之后,Fragment可谓风靡一时,现在大部分项目都或多或少的用到了Fragment,其更轻量级,更加适用屏幕,更加方便UI设计等优势。说了这么多什么是Fragment呢? Fragment:碎片,碎片是一个应用程序的用户界面和行为能够被放置在一个活动上。在其核心,它代表了一个特定的操作或界面,运行在一个更大的活动上。代表界面是因为可作为View在布局中进行使用,代表特定操作是因为包含生命周期可进行逻辑操作。简言之,Fragment就是一个带生命周期的组件。(若有问题恳请指正!) Fragment的特点: 生命周期必须依赖于Activity,当Activity被销毁,所有的碎片将被摧毁。(自己曾经踩坑) 轻量级,轻量切换。 方便处理平板、Phone的界面差异。 2、继承结构和生命周期 继承结构: Fragment直接继承Object,有四个直接子类,我个人对它的子类使用甚少。 生命周期: Fragment的生命周期在图上标注的很清楚了就不赘述了。该图是很久之前收藏的,已忘记原出处,在此感谢原作者! 3、基本使用 1).静态使用 静态使用就是Fragment相当于控件一样在布局中使用。 TestFragment.java 继承Fragment重写onCreateView方法 /** *Createdbymagicon2016年9月27日. */ publicclassTestFragmentextendsFragment{ @Override publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer, BundlesavedInstanceState){ Viewview=inflater.inflate(R.layout.fragment_main,container); ImageViewimg=(ImageView)view.findViewById(R.id.img); img.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ Toast.makeText(getActivity(),"这是一个fragment",Toast.LENGTH_SHORT).show(); } }); returnview; } } fragment_main.xml <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/img"/> </RelativeLayout> MainActivity.java 里面其实什么也没干。 /** *Createdbymagicon2016年9月27日. */ publicclassMainActivityextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } activity_main.xml <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/id_fragment" android:layout_width="match_parent" android:layout_height="match_parent" class="com.magic.test_fragment.TestFragment"/> </RelativeLayout> 使用 fragment 标签添加碎片,通过class指定碎片的完整类名。 运行效果: 2).动态使用 动态使用就是向Fragment布局容器中动态添加、替换、移除、隐藏、显示Fragment。 CommonFragment.java /** *Createdbymagicon2016年9月27日.通用Fragment */ @SuppressLint("ValidFragment") publicclassCommonFragmentextendsFragment{ Stringdesc; publicCommonFragment(Stringdesc){ super(); this.desc=desc; } @Override publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer, BundlesavedInstanceState){ Viewview=inflater.inflate(R.layout.fragment_common,container,false); TextViewtev=(TextView)view.findViewById(R.id.tev); System.out.println(desc); tev.setText(desc); returnview; } } 通过构造方法传递数据的形式向TextView上设置内容。 fragment_common.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tev" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textColor="@color/mainOrange"/> </LinearLayout> MainActivity.java /** *Createdbymagicon2016年9月27日.底部tab+fragment */ publicclassMainActivityextendsActivityimplementsOnClickListener{ TextViewtev_tab1,tev_tab2,tev_tab3,tev_tab4; //fragment事务类 FragmentTransactionft; //fragment CommonFragmenttabFragment1,tabFragment2,tabFragment3,tabFragment4; @SuppressLint("CommitTransaction") @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); initView(); ft=getFragmentManager().beginTransaction(); tabFragment1=newCommonFragment("Tab1"); //替换 ft.replace(R.id.container,tabFragment1); //提交 ft.commit(); } //初始化控件 privatevoidinitView(){ tev_tab1=(TextView)findViewById(R.id.tev_tab1); tev_tab2=(TextView)findViewById(R.id.tev_tab2); tev_tab3=(TextView)findViewById(R.id.tev_tab3); tev_tab4=(TextView)findViewById(R.id.tev_tab4); tev_tab1.setOnClickListener(this); tev_tab2.setOnClickListener(this); tev_tab3.setOnClickListener(this); tev_tab4.setOnClickListener(this); } @Override publicvoidonClick(Viewv){ FragmentTransactionft=getFragmentManager().beginTransaction(); switch(v.getId()){ caseR.id.tev_tab1: ft.replace(R.id.container,tabFragment1); break; caseR.id.tev_tab2: if(tabFragment2==null){ tabFragment2=newCommonFragment("Tab2"); } ft.replace(R.id.container,tabFragment2); break; caseR.id.tev_tab3: if(tabFragment3==null){ tabFragment3=newCommonFragment("Tab3"); } ft.replace(R.id.container,tabFragment3); break; caseR.id.tev_tab4: if(tabFragment4==null){ tabFragment4=newCommonFragment("Tab4"); } ft.replace(R.id.container,tabFragment4); break; } //提交 ft.commit(); } } activity_main2.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/mainTextBlack" android:orientation="horizontal"> <TextView android:id="@+id/tev_tab1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="Tab1" android:textColor="@color/white"/> <TextView android:id="@+id/tev_tab2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="Tab2" android:textColor="@color/white"/> <TextView android:id="@+id/tev_tab3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="Tab3" android:textColor="@color/white"/> <TextView android:id="@+id/tev_tab4" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="Tab4" android:textColor="@color/white"/> </LinearLayout> </LinearLayout> 通过 FrameLayout 标签创建Fragment的容器,底部四个Tab添加监听事件用于动态更换FrameLayout容器中的Fragment。 运行效果: 4、相关类及主要方法 FragmentManager碎片管理器,抽象类,具体实现在Android-support-v4.jar中的FragmentManagerImpl类中。 //获取FragmentManager对象 FragmentManagermanager=getFragmentManager(); FragmentTransaction碎片事务类,抽象类,具体实现在BackStackRecord类中。添加、删除、替换等操作其实最终的实现还是在FragmentManagerImpl类中。 //获取FragmentTransaction对象 FragmentTransactiontransaction=manager.beginTransaction(); //添加fragment transaction.add(); transaction.add(containerViewId,fragment,tag); //将被添加到容器的现有fragment替换 transaction.replace(); //删除一个现有的fragment transaction.remove(); //保存当前fragment数据,避免视图重绘 transaction.hide(); //显示以前隐藏的fragment transaction.show(); //这两个方法会触发fragment中的onHiddenChanged(booleanhidden)回调 //显示之前数据实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryView和onCreateView transaction.addToBackStack(null); //事务提交 transaction.commit(); Fragment 碎片类 Fragmentfragment=newFragment(); //返回此fragment当前关联的Activity fragment.getActivity(); //设置数据 fragment.setArguments(newBundle()); //获取数据 fragment.getArguments(); //返回与该fragment作用的FragmentManager fragment.getFragmentManager(); //获取标签名 fragment.getTag(); //当隐藏状态改变的时候回调 //onHiddenChanged(true); 有兴趣大家可以去Read The Fucking Source,反正我看的比较头大……. 5、其它 未完待续…… 本文作者:佚名 来源:51CTO

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

HBase - 建表语句解析

像所有其他数据库一样,HBase也有表的概念,有表的地方就有建表语句,而且建表语句还很大程度上决定了这张表的存储形式、读写性能。比如我们熟悉的MySQL,建表语句中数据类型决定了数据的存储形式,主键、索引则很大程度上影响着数据的读写性能。虽然HBase没有主键、索引这些概念,但在HBase的世界里,有些东西和它们一样重要! 废话不说,直接奉上一条HBase建表语句,来为各位看官分解剖析: create 'NewsClickFeedback',{NAME=>'Toutiao',VERSIONS=>1,BLOCKCACHE=>true,BLOOMFILTER=>'ROW',COMPRESSION=>'SNAPPY',TTL => ' 259200 '},{SPLITS => ['1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']} 上述建表语句表示创建一个表名为“NewsClickFeedback”的表,该表只包含一个列簇“Toutiao”。接下来重点讲解其他字段的含义以及如何正确设置。Note:因为篇幅有限本文并不讲解具体的工作原理,后续会有相关专题对其进行分析。 VERSIONS 数据版本数,HBase数据模型允许一个cell的数据为带有不同时间戳的多版本数据集,VERSIONS参数指定了最多保存几个版本数据,默认为1。假如某个用户想保存两个历史版本数据,可以将VERSIONS参数设置为2,再使用如下Scan命令就可以获取到所有历史数据: scan 'NewsClickFeedback',{VERSIONS => 2} BLOOMFILTER 布隆过滤器,优化HBase的随机读取性能,可选值NONE|ROW|ROWCOL,默认为NONE,该参数可以单独对某个列簇启用。启用过滤器,对于get操作以及部分scan操作可以剔除掉不会用到的存储文件,减少实际IO次数,提高随机读性能。Row类型适用于只根据Row进行查找,而RowCol类型适用于根据Row+Col联合查找,如下: Row类型适用于:get ‘NewsClickFeedback’,’row1′ RowCol类型适用于:get ‘NewsClickFeedback’,’row1′,{COLUMN => ‘Toutiao’} 对于有随机读的业务,建议开启Row类型的过滤器,使用空间换时间,提高随机读性能。 COMPRESSION 数据压缩方式,HBase支持多种形式的数据压缩,一方面减少数据存储空间,一方面降低数据网络传输量进而提升读取效率。目前HBase支持的压缩算法主要包括三种:GZip | LZO | Snappy,下面表格分别从压缩率,编解码速率三个方面对其进行对比: Snappy的压缩率最低,但是编解码速率最高,对CPU的消耗也最小,目前一般建议使用Snappy TTL 数据过期时间,单位为秒,默认为永久保存。对于很多业务来说,有时候并不需要永久保存某些数据,永久保存会导致数据量越来越大,消耗存储空间是其一,另一方面还会导致查询效率降低。如果设置了过期时间,HBase在Compact时会通过一定机制检查数据是否过期,过期数据会被删除。用户可以根据具体业务场景设置为一个月或者三个月。示例中TTL => ‘259200’设置数据过期时间为三天 IN_MEMORY 数据是否常驻内存,默认为false。HBase为频繁访问的数据提供了一个缓存区域,缓存区域一般存储数据量小、访问频繁的数据,常见场景为元数据存储。默认情况,该缓存区域大小等于Jvm Heapsize * 0.2 * 0.25 ,假如Jvm Heapsize = 70G,存储区域的大小约等于3.2G。需要注意的是HBase Meta元数据信息存储在这块区域,如果业务数据设置为true而且太大会导致Meta数据被置换出去,导致整个集群性能降低,所以在设置该参数时需要格外小心。 BLOCKCACHE 是否开启block cache缓存,默认开启。 SPLITS region预分配策略。通过region预分配,数据会被均衡到多台机器上,这样可以一定程度上解决热点应用数据量剧增导致系统自动split引起的性能问题。HBase数据是按照rowkey按升序排列,为避免热点数据产生,一般采用hash + partition的方式预分配region,比如示例中rowkey首先使用md5 hash,然后再按照首字母partition为16份,就可以预分配16个region。 本文转载自:http://hbasefly.com 原文链接

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

LinkedIn架构演化历史解析

LinkedIn 创建于 2003 年,主要目标是连接你的个人人脉以得到更好的的工作机会。上线第一周只有 2700 个会员,之后几年,LinkedIn 的产品、会员、服务器负载都增长非常快。 今天,LinkedIn 全球用户已经超过 3.5 亿。我们每天每秒有上万个页面被访问,移动端流量已占到 50% 以上。所有这些接口请求都从后台获取,达到每秒上百万级。 那么,我们是怎么做到的呢? 早些年 – Leo LinedIn 开始跟很多网站一样,只有一台应用服务做了全部工作。这个应用我们给它取名叫“Leo”。它包含了所有的网站页面(JAVA Servlets),还包含了业务逻辑,同时连接了一个轻量的 LinkedIn 数据库。 哈!早年网站的形态-简单实用 会员图表 第一件要做的是管理会员与会员间的社交网络。我们需要一个系统来图形化遍历用户之间连接的数据,同时又驻留内存以达到有效和高性能。从这个不同的需 求来看,很明显我们需要可以独立可扩展的 Leo。一个独立的会员图示化系统,叫“云”的服务诞生了 – LinkedIn 的第一个服务。为了让图表服务独立于 Leo,我们使用了 Java RPC 用来通讯。 也大概在这期间我们也有搜索服务的需求了,同时会员图表服务也在给搜索引擎-Lucene 提供数据。 复制只读数据库 当站点继续增长,Leo 也在增长,增加了角色和职责,同时自然也增加了复杂度。负载均衡的多实例 Leo 运转起来了。但新增的负载也影响了 LinkedIn 的其它关键系统,如会员信息数据库。 一个通常的解决方案是做垂直扩展 – 即增加更多的 CPU 和内存!虽然换取了时间,但我们以后还要扩展。会员信息数据库受理了读和写请求,为了扩展,一个复制的从数据库出现了,这个复制从库, 是会员主库的一个拷贝,用早期的 databus 来保证数据的同步(现在开源了)。从库接管了所有的读请求,同时添加了保证从库与主库一致的逻辑。 当主-从架构工作了一段时间后,我们转向了数据库分区 当网站开始看起来越来越多流量,我们的应用服务 Leo 在生产环境经常宕机,排查和恢复都很困难,发布新代码也很困难,高可用性对 LinkedIn 至关重要,很明显我们要“干掉”Leo,然后把它拆分成多个小功能块和无状态服务。 面向服务的架构 – SOA 工程师从分解负担 API 接口和业务逻辑的微服务开始,如搜索、个人信息、通讯及群组平台,然后是展示层分解,如招募功能和公共介绍页。新产品和新服务都放在 Leo 之外了,不久,每个功能区的垂直服务栈完成了。 我们构建了从不同域抓取数据模型的前端服务器,用于表现层展示,如生成 HTML(通过 JSPs)。我们还构建了中间层服务提供 API 接口访问数据模型及提供数据库一致性访问的后端数据服务。到 2010 年,我们已经有超过 150 个单独的服务,今天,我们已经有超过 750 个服务。 因为无状态,可以直接堆叠新服务实例及用硬件负载均衡实现扩展。我们给每个服务都画了警戒红线,以便知道它的负载,从而制定早期对策和性能监控。 缓存 LinkedIn 可预见的增长,所以还需要进一步扩展。我们知道通过添加更多缓存可以减少集中压力的访问。很多应用开始使用如 memcached/couchbase 的中间层缓存,同时在数据层也加了缓存,某些场景开始使用 useVoldemort 提供预结果生成。 又过一了段时间,我们实际上去掉了很多中间层缓存,中间层缓存数据往往来自多个域,但缓存只是开始时对减少负载有用,但更新缓存的复杂度和生成图表变得更难于把控。保持缓存最接近数据层将降低潜在的不可控影响,同时还允许水平扩展,降低分析的负载。 Kafka 为了收集不断增长的数据,LinkedIn 开始了很多自定义的数据管道来流化和队列化数据,例如,我们需要把数据保存到数据仓库、我们需要发送批量数据到 Hadoop 工作流以分析、我们从每个服务聚合了大量日志、我们跟踪了很多用户行为,如页面点击、我们需要队例化 InMail 消息服务、我们要保障当用户更新个人资料后搜索的数据是最新的等等。 当站点还在增长,更多定制化管道服务出现了,因网站需要可扩展,单独的管道也要可扩展,有些时候很难取舍。解决方案是使用 kafka,我们的分布式发布-订阅消息平台。Kafka 成为一个统一的管道服务,根据提交的日志生成摘要,同时一开始就很快速和具有可扩展性。它可以接近于实时的访问所有数据源,驱动了 Hadoop 任务,允许我们构建实时的分析,广泛的提升了我们站点监控和告警的能力,同时支持将调用可视化。今天,Kafka 每天处理超过 5 亿个事件。 反转 扩展可从多个维度来衡量,包括组织结构。2011 年晚些时候,LinkedIn 内部开始一个创新,叫”反转”(Inversion)。我们暂停了新功能开发,允许所有的开发部门集中注意力提升工具和布署、基础架构及实用性开发。这对 于今天敏捷开发新的可扩展性产品很有帮助。 近几年 – Rest.li 当我们从 Leao 转向面向服务的架构后,之前基于 JAVA 的 RPC 接口,在团队中已经开始分裂了,并且跟表现层绑得太死,这,只会变得更坏。为了搞定这个问题,我们开发了一套新的 API 模型,叫 Rest.li,它是一套以数据为中心的架构,同时保证在整个公司业务的数据一致性且无状态的 Restful API。 基于 HTTP 的 JSON 数据传递,我们新的 API 最终很容易支持到非 java 编写的客户端,LinkedIn 今天依然主要用 Java,但同时根据已有的技术分布也利用了 Python、Ruby、Node.js 和C++。脱离了 RPC,同时也让我们从前端表现层及后端兼容问题解耦,另外, 使用了基于动态发现技术(D2)的 Rest.li,我们每个服务层 API 获得了自动负载均衡、发现和扩展的能力。 今天,LinkedIn 所有数据中心每天已经有超过 975 个 Rest.li 资源和超过千亿级 Rest.li 调用。 Rest.li R2/D2 技术栈 超级块 面向服务的架构对于域解耦和服务独立扩展性很有帮助,但弊端是,大都我们的应用都需要很多不同类型的数据,按序会产品数百个延伸的调用。这就是通常 说的“调用线路图”,或伴随着这么多延伸调用的“扇出”(fan-out)。例如,任何个人信息页都包含了远不止于相册、连接、群组、订阅、关注、博客、 人脉维度、推荐这些。调用图表可能会很难管理,而且只会把事件搞得越来越不规则。 我们使用了”超级块”的概念 – 一个只有单一 API 接口的群组化后台服务。这样可以允许一个小组去优化一个“块”,同时保证每个客户端的调用情况可控。 多数据中心 作为一个会员快速增长的全球化公司,我们需要将数据中心进行扩展,我们努力了几年来解决这个问题,首先,从两个数据中心(洛杉矶和芝加哥)提供了公 共个人信息,这表明,我们已经可以提供增强的服务用来数据复制、不同源的远程调用、单独数据复制事件、将用户分配到地理位置更近的数据中心。 我们大多的数据库运行在 Espresso(一个新的内部多用户数据仓库)。Espresso 支持多个数据中心,提供了主-主的支持,及支持复杂的数据复制。 多个数据中心对于高可用性具有不可思议的重要性,你要避免因单点故障不仅只导致某个服务失效,更要担心整个站点失效。今天,LinkedIn 运行了 3 个主数据中心,同时还有全球化的 PoPs 服务。 我们还做了哪些工作? 当然,我们的扩展故事永远不止这么简单。我们的工程师和运维团队这些年做了不计其数的工作,主要包括这些大的初创性的: 这些年大多关键系统都有自己的丰富的扩展演化历史,包括会员图表服务(Leo 之外的第一个服务),搜索(第二个服务),新闻种子,通讯平台及会员资料后台。 我们还构建了数据基础平台支持很长一段时间的增长,这是 Databus 和 Kafka 的第一次实战,后来用 Samza 做数据流服务,Espresso 和 Voldemort 作存储解决方案,Pinot 用来分析系统,以及其它自定义解决方案。另外,我们的工具也进步了,如工程师可自动化布署这些基础架构。 我们还使用 Hadoop 和 Voldemort 数据开发了大量的离线工作流,用以智能分析,如“你可能认识的人”,“相似经历”,“感觉兴趣的校友”及“个人简历浏览地图”。 我们重新考虑了前端的方法,加了客户端模板到混合页面(个人中心、我的大学页面),这样应用可以更加可交互,只要请求 JSON 或部分 JSON 数据。还有,模板页面通过 CDN 和浏览器缓存。我们也开始使用了 BigPipe 和 Play 框架,把我们的模型从线程化的服务器变成非阻塞异步的。 在代码之外,我们使用了 Apache 的多层代理和用 HAProxy 做负载均衡,数据中心,安全,智能路由,服务端渲染,等等。 最后,我们继续提升服务器的性能,包含优化硬件,内存和系统的高级优化,利用新的 JRE。 下一步是什么 LinkedIn 今天仍在快速增长,仍然有大量值得提升的工作要做,我们正在解决一些问题,看起来只解决了一部分 – 快来加入我们吧! 来源:51CTO

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

android studio lint基本解析

可访问性(accessibility) 1、Image without contentDescription图像没有内容描述 这个是需要对图片进行一个描述,不然会有警告,一般情况下进行统一的标识加入 android:c ontentDescription="@string/abc 正确性(correctness) 2、Attribute unused on older versions 旧版本中未使用的属性 3、Class is not registered in the manifest 类没有在清单中注册 没有注册的activity 4、Duplicate ids across layouts combined with include tags布局中重复的ids与包含标签相结合 引用的布局和父布局包含相同的id 5、Implied locale in date format 使用日期格式的默示语言环境 http://blog.csdn.net/revival_liang/article/details/51812723 时间声明问题 SimpleDateFormat format = new SimpleDateFormat("MM月dd日HH时mm分ss秒");//有报警问题 SimpleDateFormat format = new SimpleDateFormat("MM月dd日HH时mm分ss秒", Locale.getDefault()); 6、Incorrect order of elements in manifest 清单中元素的顺序不正确 有些权限需要写道application之前,示例极光的一个权限 <uses-permission android:name="packagename.permission.JPUSH_MESSAGE" /> 7、Layout Inflation without a Parent 父布局没有膨胀 示例 使用nullView view = inflater.inflate(R.layout.progressbar, null); 正确的使用 第三个参数设置为了true,表示将第一个参数所指定的布局添加到第二个参数的View中 LinearLayout ll = (LinearLayout) findViewById(R.id.ll); LayoutInflater inflater = LayoutInflater.from(this); inflater.inflate(R.layout.linearlayout, ll,true); 8、Missing commit() calls 失踪的commit()调用 一般报错 After creating a FragmentTransaction, you typically need to commit it as well fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.xxxx, new xxxxFragment().newInstance(xxxx),"xxxx"); fragmentTransaction.commit(); 改为(暂未测试效果) fragmentManager.beginTransaction().replace(R.id.xxxx, new xxxxFragment().newInstance(xxxx),"xxxx").commit(); 9、Missing commit() on SharedPreference editor ` SharedPreferences.Editor edit = sp.edit(); edit.putString("isFirstLogin", "0"); edit.commit(); 改为 apply() ` 这两个方法的区别在于: apply没有返回值而commit返回boolean表明修改是否提交成功 apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。 apply方法不会提示任何失败的提示。 由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。 10、Nested scrolling widgets 嵌套滚动窗口小部件 scrollview中嵌套了listview 11、Obsolete Gradle Dependency 过时Gradle依赖 提示android 升级高版本 12、RecyclerView Problems recycleerview的问题 在onBindviewholder方法中不能使用position 应该使用holer.getAdapterPosition()来获取position 有时候在做item换位置时直接使用postiion会发生位置错误 无法获取到变换后的位置 13、ScrollView size validation scrollview大小的验证 ScrollView里的LinearLayout的高度应该使用wrap_content 14、Reference to an id that is not in the current layout 引用不在当前布局内的id 15、Target SDK attribute is not targeting latest version 目标SDK属性不是针对最新版本的 15、Unreachable state in a <selector> In a selector, only the last child in the state list should omit a state qualifier. If not, all subsequent items in the list will be ignored since the given item will match all 在选择器中,只有状态列表中的最后一个子应该省略一个状态限定符。如果没有,则列表中的所有后续项都将被忽略,因为给定的项将匹配所有项 16、Using deprecated resources 过时的方法 17、Using inlined constants on older versions quanxu Internationalization 国际化 18、Hardcoded text 硬编码 https://toutiao.io/posts/572671/app_preview 19、TextView Internationalization java 代码中使用的汉字应使用常量来代替(个人建议) 20、 Bidirectional Text 双向设置 如 :android:paddingLeft="15dp" 需要设置两侧对应android:paddingLeft="15dp" android:paddingRight="15dp" Performance 性能 21、FrameLayout can be replaced with <merge> tag FrameLayout可以替换为<merge>标签 MergeRootFrame 如果FrameLayout是根布局,并且不提供背景或填充等,它通常可以替换为稍微更有效的<merge>标签。请注意,这取决于上下文,因此请确保在继续之前了解<merge>标记的工作原理。 22、Handler reference leaks handle引起程序泄露参考 因为同一个线程下的handler共享一个looper对象,消息中保留了对handler的引用,由于Java在生成内部类的时候,原本没有构造器的内部类会被生成一个带外部类参数的构造器,这个内部类就会持有外部类的隐式引用。Handler其实隐式的持有了Activity的引用,只要有消息在队列中,那么handler便无法被回收,如果handler不是static那么使用Handler的Service和Activity就也无法被回收。这就可能导致内存泄露 http://blog.csdn.net/liangchengfeng/article/details/51999882 23、HashMap can be replaced with SparseArray HashMap可以用SparseArray替换 ` HashMap<Integer, HashMap<String, String>> rightPopCommonList = new HashMap<Integer, HashMap<String, String>>(); 改为 HashMap<Integer, HashMap<String, String>> rightPopCommonList = new new HashMap<>(); ` 24、Inefficient layout weight 低效的权重布局 在 设置权重属性的时候相应的宽高属性应设为0dp 25、Layout hierarchy is too deep 布局层次结构太深 嵌套过多的布局不利于性能。考虑使用更平的布局(比如相对布局或GridLayout)。默认的最大深度为10,但可以使用环境变量androidlintmaxdepth配置 26、Memory allocations within drawing code 绘制代码内的内存分配 Avoid object allocations during draw/layout operations (preallocate and reuse instead) You should avoid allocating objects during a drawing or layout operation. These are called frequently, so a smooth UI can be interrupted by garbage collection pauses caused by the object allocations. The way this is generally handled is to allocate the needed objects up front and to reuse them for each drawing operation. Some methods allocate memory on your behalf (such as Bitmap.create), and these should be handled in the same way. 27、Missing baselineAligned attribute 消失的baselineAligned属性 baselineAligned属性默认为true 这是基准线设置,设置为fale时它的子控件不对齐 当linearlayout为水平时设置为fale 获取更好的性能http://blog.csdn.net/bdmh/article/details/48495583 28、Nested layout weights 嵌套布局权重 避免权重套权重,当一个非零权重的线性布局被嵌套在另一个带有非零权重的线性布局中,那么度量的数量就会呈指数增长。 29、Node can be replaced by a TextView with compound drawables 节点可以用一个带有复合绘图的TextView来替换 让只有图片和文字的一个小布局合并为一个textview 这个视情况。 30、Obsolete layout params 布局中无用的参数 31、Overdraw: Painting regions more than once 过度绘制 一般布局根背景不需要在设置bg了 子布局的背景挡住的父布局造成了过度绘制 32、Static Field Leaks 静态变量泄露 主要是上下文对象不要设置为static 33、Unused resources 无用的资源 34、Useless leaf layout 无用的布局 35、Useless parent layout无用的父布局 36、View Holder Candidates adapter没有重用子布局

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

经典的 Fork 炸弹解析

Jaromil在2002年设计了最为精简的一个Linux Fork炸弹,整个代码只有13个字符,在shell中运行后几秒后系统就会宕机: :(){:|:&};: 这样看起来不是很好理解,我们可以更改下格式: :() { :|:& }; : 更好理解一点的话就是这样: bomb() { bomb|bomb& }; bomb 因为shell中函数可以省略function关键字,所以上面的十三个字符是功能是定义一个函数与调用这个函数,函数的名称为:,主要的核心代码是:|:&,可以看出这是一个函数本身的递归调用,通过&实现在后台开启新进程运行,通过管道实现进程呈几何形式增长,最后再通过:来调用函数引爆炸弹.因此,几秒钟系统就会因为处理不过来太多的进程而死机,解决的唯一办法就是重启。 Bomb一下 秉着不作不死的心态,我们也来运行一下,于是我将矛头指向云主机,,我使用了国内的一个2G内存的云主机,首先在本地开启两个终端,在一个终端连接云主机后运行炸弹,几秒后再尝试用另外一个终端登录,效果可以看下面Gif图: 看,运行一段时间后直接报出了-bash: fork: Cannot allocate memory,说明内存不足了。并且我在二号终端上尝试连接也没有任何反应。因为是虚拟的云主机,所以我只能通过主机服务商的后台来给主机断电重启。然后才能重新登录: 炸弹危害 Fork炸弹带来的后果就是耗尽服务器资源,使服务器不能正常的对外提供服务,也就是常说的DoS(Denial of Service)。与传统1v1、通过不断向服务器发送请求造成服务器崩溃不同,Fork炸弹有种坐山观虎斗,不费一兵一卒斩敌人于马下的感觉。更吓人的是这个函数是不需要root权限就可以运行的。看到网上有帖子说某些人将个性签名改为Fork炸弹,结果果真有好奇之人中枪,试想如果中枪的人是在公司服务器上运行的话,oh,! 预防方式 当然,Fork炸弹没有那么可怕,用其它语言也可以分分钟写出来一个,例如,python版: import os while True: os.fork() Fork炸弹的本质无非就是靠创建进程来抢占系统资源,在Linux中,我们可以通过ulimit命令来限制用户的某些行为,运行ulimit -a可以查看我们能做哪些限制: ubuntu@10-10-57-151:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 7782 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 7782 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 可以看到,-u参数可以限制用户创建进程数,因此,我们可以使用ulimit -u 20来允许用户最多创建20个进程。这样就可以预防bomb炸弹。但这样是不彻底的,关闭终端后这个命令就失效了。我们可以通过修改/etc/security/limits.conf文件来进行更深层次的预防,在文件里添加如下一行(ubuntu需更换为你的用户名): ubuntu - nproc 20 这样,退出后重新登录,就会发现最大进程数已经更改为20了, 这个时候我们再次运行炸弹就不会报内存不足了,而是提示-bash: fork: retry: No child processes,说明Linux限制了炸弹创建进程。 原文发布时间为:2015-06-24 本文来自云栖社区合作伙伴“Linux中国”

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

weex高性能list解析

weex是alibaba出品的用于移动端跨平台开发界面的框架,类似react-native。而ListView在移动端界面的开发中是非常重要的组件,无论是H5还是react-native都因为ListView的低性能而饱受非议。那么到底是什么样的实现让weex能拥有与众不同的ListView性能呢? List示例 首先,让我们一起来看看weex下如何使用list。 <template> <div> <list class="list"> <refresh class = "refresh-view" display="{{refresh_display}}" onrefresh="onrefresh"> <text if="{{(refresh

资源下载

更多资源
Mario

Mario

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

腾讯云软件源

腾讯云软件源

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

Spring

Spring

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

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册