首页 文章 精选 留言 我的

精选列表

搜索[运维监控平台],共10000篇文章
优秀的个人博客,低调大师

java版spring cloud+spring boot+redis社交电子商务平台-SSO单点登录之OAuth2.0登录认证

之前写了很多关于spring cloud的文章,今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一、oauth中的角色 client:调用资源服务器API的应用 Oauth 2.0 Provider:包括Authorization Server和Resource Server (1)Authorization Server:认证服务器,进行认证和授权 (2)Resource Server:资源服务器,保护受保护的资源 user:资源的拥有者 二、下面详细介绍一下Oauth 2.0 Provider Authorization Server: (1)AuthorizationEndpoint:进行授权的服务,Default URL: /oauth/authorize (2)TokenEndpoint:获取token的服务,Default URL: /oauth/token Resource Server: OAuth2AuthenticationProcessingFilter:给带有访问令牌的请求加载认证 三、下面再来详细介绍一下Authorization Server: 一般情况下,创建两个配置类,一个继承AuthorizationServerConfigurerAdapter,一个继承WebSecurityConfigurerAdapter,再去复写里面的方法。 主要出现的两种注解: 1、@EnableAuthorizationServer:声明一个认证服务器,当用此注解后,应用启动后将自动生成几个Endpoint:(注:其实实现一个认证服务器就是这么简单,加一个注解就搞定,当然真正用到生产环境还是要进行一些配置和复写工作的。) /oauth/authorize:验证 /oauth/token:获取token /oauth/confirm_access:用户授权 /oauth/error:认证失败 /oauth/check_token:资源服务器用来校验token /oauth/token_key:如果jwt模式则可以用此来从认证服务器获取公钥 以上这些endpoint都在源码里的endpoint包里面。 2、@Beans:需要实现AuthorizationServerConfigurer AuthorizationServerConfigurer包含三种配置: ClientDetailsServiceConfigurer:client客户端的信息配置,client信息包括:clientId、secret、scope、authorizedGrantTypes、authorities (1)scope:表示权限范围,可选项,用户授权页面时进行选择 (2)authorizedGrantTypes:有四种授权方式 Authorization Code:用验证获取code,再用code去获取token(用的最多的方式,也是最安全的方式) Implicit: 隐式授权模式 Client Credentials (用來取得 App Access Token) Resource Owner Password Credentials (3)authorities:授予client的权限 这里的具体实现有多种,in-memory、JdbcClientDetailsService、jwt等。 AuthorizationServerSecurityConfigurer:声明安全约束,哪些允许访问,哪些不允许访问 AuthorizationServerEndpointsConfigurer:声明授权和token的端点以及token的服务的一些配置信息,比如采用什么存储方式、token的有效期等 client的信息的读取:在ClientDetailsServiceConfigurer类里面进行配置,可以有in-memory、jdbc等多种读取方式。 jdbc需要调用JdbcClientDetailsService类,此类需要传入相应的DataSource. 下面再介绍一下如何管理token: AuthorizationServerTokenServices接口:声明必要的关于token的操作 (1)当token创建后,保存起来,以便之后的接受访问令牌的资源可以引用它。 (2)访问令牌用来加载认证 接口的实现也有多种,DefaultTokenServices是其默认实现,他使用了默认的InMemoryTokenStore,不会持久化token; token存储方式共有三种分别是:(1)InMemoryTokenStore:存放内存中,不会持久化 (2)JdbcTokenStore:存放数据库中 (3)Jwt: json web token 授权类型: 可以通过AuthorizationServerEndpointsConfigurer来进行配置,默认情况下,支持除了密码外的所有授权类型。相关授权类型的一些类: (1)authenticationManager:直接注入一个AuthenticationManager,自动开启密码授权类型 (2)userDetailsService:如果注入UserDetailsService,那么将会启动刷新token授权类型,会判断用户是否还是存活的 (3)authorizationCodeServices:AuthorizationCodeServices的实例,auth code 授权类型的服务 (4)implicitGrantService:imlpicit grant (5)tokenGranter: endpoint的URL的配置: (1)AuthorizationServerEndpointsConfigurer的pathMapping()方法,有两个参数,第一个是默认的URL路径,第二个是自定义的路径 (2)WebSecurityConfigurer的实例,可以配置哪些路径不需要保护,哪些需要保护。默认全都保护。 自定义UI: (1)有时候,我们可能需要自定义的登录页面和认证页面。登陆页面的话,只需要创建一个login为前缀名的网页即可,在代码里,设置为允许访问,这样,系统会自动执行你的登陆页。此登陆页的action要注意一下,必须是跳转到认证的地址。 (2)另外一个是授权页,让你勾选选项的页面。此页面可以参考源码里的实现,自己生成一个controller的类,再创建一个对应的web页面即可实现自定义的功能。 下面梳理一下授权获取token流程: (1)端口号换成你自己的认证服务器的端口号,client_id也换成你自己的,response_type类型为code。 localhost:8080/uaa/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com(2)这时候你将获得一个code值:http://www.baidu.com/?code=G0C20Z (3)使用此code值来获取最终的token: curl -X POST -H “Cant-Type: application/x-www-form-urlencoded” -d ‘grant_type=authorization_code&code=G0C20Z&redirect_uri=http://www.baidu.com’ “http://client:secret@localhost:8080/uaa/oauth/token” 返回值: {“access_token”:“b251b453-cc08-4520-9dd0-9aedf58e6ca3”,“token_type”:“bearer”,“expires_in”:2591324,“scope”:“app”} (4)用此token值来调用资源服务器内容(如果资源服务器和认证服务器在同一个应用中,那么资源服务器会自己解析token值,如果不在,那么你要自己去做处理) curl -H “Authorization: Bearer b251b453-cc08-4520-9dd0-9aedf58e6ca3” “localhost:8081/service2(此处换上你自己的url)” 四、Resource Server:保护资源,需要令牌才能访问 在配置类上加上注解@EnableResourceServer即启动。使用ResourceServerConfigurer进行配置: (1)tokenServices:ResourceServerTokenServices的实例,声明了token的服务 (2)resourceId:资源Id,由auth Server验证。 (3)其它一些扩展点,比如可以从请求中提取token的tokenExtractor (4)一些自定义的资源保护配置,通过HttpSecurity来设置 使用token的方式也有两种: (1)Bearer Token(https传输方式保证传输过程的安全):主流 (2)Mac(http+sign) 如何访问资源服务器中的API? 如果资源服务器和授权服务器在同一个应用程序中,并且您使用DefaultTokenServices,那么您不必太考虑这一点,因为它实现所有必要的接口,因此它是自动一致的。如果您的资源服务器是一个单独的应用程序,那么您必须确保您匹配授权服务器的功能,并提供知道如何正确解码令牌的ResourceServerTokenServices。与授权服务器一样,您可以经常使用DefaultTokenServices,并且选项大多通过TokenStore(后端存储或本地编码)表示。 (1)在校验request中的token时,使用RemoteTokenServices去调用AuthServer中的/auth/check_token。 (2)共享数据库,使用Jdbc存储和校验token,避免再去访问AuthServer。 (3)使用JWT签名的方式,资源服务器自己直接进行校验,不借助任何中间媒介。 五、oauth client 在客户端获取到token之后,想去调用下游服务API时,为了能将token进行传递,可以使用RestTemplate.然后使用restTemplate进行调用Api。 注: scopes和authorities的区别: scopes是client权限,至少授予一个scope的权限,否则报错。 authorities是用户权限。 以上是我从网上找到的一篇写的不错的博客,希望可以帮助大家快速了解OAuth2.0,下一篇文章我们正式介绍OAuth2.0在当前框架中的使用。 从现在开始,我这边会将近期研发的spring cloud微服务云架构的搭建过程和精髓记录下来,帮助更多有兴趣研发spring cloud框架的朋友,大家来一起探讨spring cloud架构的搭建过程及如何运用于企业项目。

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

Android 分享两个你学习android 平台开发必须碰到的几个知识点的组件【天气预报、日期】View 组件

本篇文章将分享两个VIEW组件,一个天气组件和一个日期组件,这两个组件本来是一个App Widget 后来,我看着好玩,将他们弄成一个VIEW的组件,可以像使用Windows Phone 7 的用户控件一样拖放到你想要的项目中。本篇将演示这两个组件的编写过程,工程文件如下: 包名介绍: com.terry.weather 程序的入口包 com.yaomei.adapter 天气预报组件使用到的数据源 com.yaomei.model 天气预报使用到的模型包 com.yaomei.util 获取天气信息的工具包 com.yaomei.widget 天气预报组件、日期组件的存放位置 从包名可以看出,编写一个天气预报所需要的代码量比编写一个日期VIEW所需要的代码量要多得多 ,那么我们先把天气预报的一些实现思路跟大家讲讲。 首先,本实例使用的天气预报是一个可以自己国际化的天气组件VIEW,可以看上图,将所需要的URL都放入ANDROID 自己的国际化文件夹里面,比如中文的话就这样写: < string name ="googleWeatherApi" > <![CDATA[ http://www.google.com/ig/api?hl=zh-cn&weather= ]]> </ string > 那么是英语环境的就只需要在默认的VALUES里面的string.xml这样写即可: < string name ="googleWeatherApi" > <![CDATA[ http://www.google.com/ig/api?hl=en&weather= ]]> </ string > 这是本篇一个要注意的一点,另外还有需要注意的是,这个天气组件提供可供用户选择更新频率,这里比如我们使用3个小时更新一次,那么当用户退出程序时,再打开是否还要再去Google 上面读天气呢?答案是NO,因为既然用户选择了更新频率,那么在一定的时间内,我们最好不要自动去更新,除非用户自己点击更新才去执行。那么要如何得到之前的数据呢? 这里使用到的是SharePreference 将一些天气的信息保存进去,连同天气的图片也一并保存。保存天气图片是将google 天气的图片使用Base64转成字符串,然后保存进Sharepreference ,如果更新频率条件未满足则进去SharePrference 将天气预报数据取出来 。因为Android 并未提供将图片转成字符串的API,这里使用到的是apache 的一个Jar包,可在这里下载:点击这里 思路上面给出了,下面给出天气预报组件VIEW的核心代码,其他附属代码可在后面的附件下载得到,代码如下: package com.yaomei.widget; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.apache.commons.codec.binary.Base64; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Bitmap.CompressFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.text.Html; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.terry.weather.R; import com.yaomei.adapter.weatherAdapter; import com.yaomei.model.WeatherMdoel; import com.yaomei.util.strHelpeUtil; public class WeatherView extends LinearLayout{ private static final StringHour_COMPARE = " hour_compare " ; private static final StringDAY_OF_WEEK = " day_of_week " ; private static final StringLOW = " low " ; private static final StringHIGH = " high " ; private static final StringCONDITION = " condition " ; private static final StringIMAGE = " image " ; private static final StringDATE_COMPARE = " date_compare " ; private static final StringCITYNAE_SHARE = " cityNameShare " ; private ImageViewiv_weather; private TextViewtv_state,tv_position,tv; WeatherMdoelmodel; private List < WeatherMdoel > weatherList = null ; GridViewgv; Timertimer; Handlerhandler = new Handler(){ public void handleMessage(Messagemsg){ if (msg.arg1 == 1 ){ if (weatherList.size() > 0 ){ gv .setAdapter( new weatherAdapter(getContext(), weatherList)); init(); } else { Toast.makeText(getContext(), " 查询不到数据 " , 1000 ).show(); } // msg.recycle(); } }; }; /** *自动加载天气 */ private boolean autoLoad = false ; public boolean getAutoLoad(){ return autoLoad; } public void setAutoLoad( boolean isLoad){ this .autoLoad = isLoad; } /** *城市名称 */ private StringcityName = "" ; public StringgetCityName(){ return cityName; } public void setCityName(StringcityName){ this .cityName = cityName; } /** *设置每几小时更新一次 */ private int updateHour; public int getUpdateHour(){ return updateHour; } public void setUpdateHour( int hour){ this .updateHour = hour; } public WeatherView(Contextcontext){ this (context, null ); // TODOAuto-generatedconstructorstub } public WeatherView(Contextcontext,AttributeSetattrs){ super (context,attrs); int resouceID = - 1 ; TypedArraytyedArray = context.obtainStyledAttributes(attrs, R.styleable.WeatherView); int N = tyedArray.getIndexCount(); for ( int i = 0 ;i < N;i ++ ){ int attr = tyedArray.getIndex(i); switch (attr){ case R.styleable.WeatherView_AutoLoad: setAutoLoad(tyedArray.getBoolean( R.styleable.WeatherView_AutoLoad, false )); break ; case R.styleable.WeatherView_CityName: resouceID = tyedArray.getResourceId( R.styleable.WeatherView_CityName, 0 ); setCityName(resouceID > 0 ? tyedArray.getResources().getText( resouceID).toString():tyedArray .getString(R.styleable.WeatherView_CityName)); break ; case R.styleable.WeatherView_UpdateHour: setUpdateHour(tyedArray.getInteger( R.styleable.WeatherView_UpdateHour, 3 )); break ; } } Viewview = LayoutInflater.from(getContext()).inflate( R.layout.weather_layout, this ); tv = (TextView)view.findViewById(R.id.tv_temperature); gv = (GridView)view.findViewById(R.id.grid); iv_weather = (ImageView)view.findViewById(R.id.iv_weather); tv_state = (TextView)view.findViewById(R.id.tv_state); tv_position = (TextView)view.findViewById(R.id.tv_position); timer = new Timer(); if (getAutoLoad()){ startLoadWeather(); } tyedArray.recycle(); } /** *开始加载 */ public void startLoadWeather(){ timer.schedule( new TimerTask(){ @Override public void run(){ SharedPreferencesshare = getContext().getSharedPreferences( " weather " ,Activity.MODE_PRIVATE); long time = System.currentTimeMillis(); final CalendarmCalendar = Calendar.getInstance(); mCalendar.setTimeInMillis(time); StringtempDate = mCalendar.get(Calendar.YEAR) + " - " + mCalendar.get(Calendar.MONTH) + " - " + mCalendar.get(Calendar.DAY_OF_MONTH); if (share.contains(DATE_COMPARE)){ if (share.getString(CITYNAE_SHARE, "" ).equals(cityName)){ int time_cop = mCalendar.get(Calendar.HOUR) - share.getInt(Hour_COMPARE, 0 ); Stringdate = share.getString(DATE_COMPARE, "" ); if (time_cop >= getUpdateHour() || ! date.equals(tempDate)){ saveWeatherList(mCalendar.get(Calendar.HOUR), tempDate); } else if (time_cop < getUpdateHour()){ weatherList = new ArrayList < WeatherMdoel > (); for ( int i = 0 ;i < 4 ;i ++ ){ WeatherMdoelmodel = new WeatherMdoel(); model.setWeek(share.getString(DAY_OF_WEEK + i, "" )); model.setLowTemp(share.getString(LOW + i, "" )); model .setHighTemp(share.getString(HIGH + i, "" )); model.setConditions(share.getString(CONDITION + i, "" )); Stringimage = share.getString(IMAGE + i, "" ); byte []base64Bytes = Base64.decodeBase64(image .getBytes()); ByteArrayInputStreambais = new ByteArrayInputStream( base64Bytes); model.setImageUrl( "" ); model .setImageDrawable(Drawable .createFromStream(bais, " weather_image " )); weatherList.add(model); } } } else { saveWeatherList(mCalendar.get(Calendar.HOUR),tempDate); } } else { saveWeatherList(mCalendar.get(Calendar.HOUR),tempDate); } // 把必要的操作放在于线程中执行,不阻塞UI if (handler.hasMessages( 1 )) handler.obtainMessage().recycle(); else { Messagemsg = handler.obtainMessage(); msg.arg1 = 1 ; msg.sendToTarget(); } } }, 0 ,getUpdateHour() * 3600 * 1000 ); } /** *第一次或者另外重新加载 */ void saveWeatherList( int hour,Stringday){ weatherList = new ArrayList < WeatherMdoel > (); weatherList = strHelpeUtil.searchWeather(Html.fromHtml( getContext().getResources() .getString(R.string.googleWeatherApi)).toString(), getCityName()); SharedPreferences.EditorshareEditor = getContext() .getSharedPreferences( " weather " ,Activity.MODE_PRIVATE).edit(); shareEditor.clear(); int i = 0 ; for (WeatherMdoelmodel:weatherList){ shareEditor.putString(DAY_OF_WEEK + i,model.getWeek()); shareEditor.putString(LOW + i,model.getLowTemp()); shareEditor.putString(HIGH + i,model.getHighTemp()); shareEditor.putString(CONDITION + i,model.getConditions()); /** *将图片存入 */ ByteArrayOutputStreambaos = new ByteArrayOutputStream(); ((BitmapDrawable)strHelpeUtil.loadImage(model.getImageUrl())) .getBitmap().compress(CompressFormat.JPEG, 50 ,baos); StringImageBase64 = new String(Base64.encodeBase64(baos .toByteArray())); shareEditor.putString(IMAGE + i,ImageBase64); i ++ ; } shareEditor.putString(DATE_COMPARE,day); shareEditor.putInt(Hour_COMPARE,hour); shareEditor.putString(CITYNAE_SHARE,cityName); shareEditor.commit(); } /** *初始化组件信息 */ void init(){ model = weatherList.get( 0 ); iv_weather.setImageDrawable(model.getImageUrl() == "" ? model .getImageDrawable():strHelpeUtil.loadImage(model .getImageUrl())); tv_state.setText(model.getConditions()); tv_position.setText(getCityName()); tv.setText(getContext().getResources().getString(R.string.temp_format, model.getLowTemp(),model.getHighTemp())); } /** *释放对象 */ public void releaseTimer(){ timer.cancel(); weatherList = null ; } } 学习这个类,你能够学到的知识点为:为应用程序添加属性,编写组件,SharePreference 的使用,Timer和Handler 异步处理UI等知识点。 日期VIEW显示VIEW组件,是一个显示当前系统时间的组件,当第一次运行时,得到当前的秒数在以60秒减去当前秒,得到第一次运行时下一次运行需要的秒数,当这一次更新完毕后,下一次每次60秒更新一次时间,这个组件也是以分更新UI的操作,学习本类,你可以学到两个Handler 是如何协作处理UI,代码如下: package com.yaomei.widget; import java.util.Calendar; import java.util.Date; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; import com.terry.weather.R; import com.yaomei.util.strHelpeUtil; public class DateView extends FrameLayout{ private TextViewtv_date_time,tv_week,tv_date; int second; Handlerhandler = new Handler(){ public void handleMessage(android.os.Messagemsg){ init(); handler.sendMessageDelayed(handler.obtainMessage(), 60 * 1000 ); }; }; public DateView(Contextcontext){ this (context, null ); } public DateView(Contextcontext,AttributeSetattrs){ super (context,attrs); // this.setBackgroundDrawable(getContext().getResources().getDrawable( // R.drawable.date_background)); Viewview = LayoutInflater.from(getContext()).inflate( R.layout.date_layout, this ); tv_date_time = (TextView)view.findViewById(R.id.tv_date_time); tv_week = (TextView)view.findViewById(R.id.tv_week); tv_date = (TextView)view.findViewById(R.id.tv_date); init(); final Calendarcalendar = Calendar.getInstance(); second = calendar.get(Calendar.SECOND); handler.sendMessageDelayed(handler.obtainMessage(), ( 60 - second) * 1000 ); } void init(){ java.text.DateFormatdf = new java.text.SimpleDateFormat( " HH:mm " ); tv_date_time.setText(df.format( new Date())); tv_week.setText(strHelpeUtil.getWeekOfDate( new Date())); strHelpeUtilstr = new strHelpeUtil(getContext()); tv_date.setText(str.toString()); } } 上篇运行效果如下: 由于没有为其提供背景颜色,使用的同学可以自己为它们加上一个好看的背景颜色,效果会更加。 上面的天气组件,其实可以使用AsyncTask也是起到同样的效果,AsyncTask使用起来会觉得优雅一点,这里也顺便把一些AsyncTask在使用上一些注意事项跟大家谈一谈: 在doInBackground 里面不要直接操作UI,比如设置UI的可见性操作。 在doInBackground 所在的操作只负责帮你得到数据,然后把UI处理都放在onPostExecute 里面。 同时启动几个AsyncTask 注意线程加锁,使用synchronized 必须每次都创建一个新的AsyncTask 对象,否则会提示“ataskcanbeexecutedonlyonce” 的错误信息。 本篇的所有源码下载地址:组件 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/486341,如需转载请自行联系原作者

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

从小数据分析到大数据平台,这十几年来大数据开源技术是如何演进的?

首先,介绍两个使用案例。 第一个是OLTP流程,主要指的是整个商业应用和流程。我们会收集交易数据,在业务过程当中收集数据,比如要销售一些网上产品,可能希望把每一单都能够记录下来。 第二个主要案例是OLAP,主要指的是分析数据,我们让所有收集的数据能够有意义,可以帮助我们生成报告,根据数据分析,进行业务决策。这个应用场景下,我们会把一些数字,比如说收益,将整个数据维度Dimensions以及Measures和数据整合在一起。 Small Data Analytics 在一个小数据里可以做以上两个应用,单个系统都可以应用,非常简单。我们主要做什么呢?我们会像微软表格当中收集数据,之后进行一系列视觉化。 我们提供的解决方案对于小的数据而言主要使用单个系统,这个单个系统主要通过一个系统解决所有的问题和所有的应用场景,而且能够快速提取出关键数据,并且很容易的去创建各种不同的数据展现形式。 在过去几年里,数据一直在快速发展,人们意识到有些解决方案针对小数据已经无效了。数据已经不能够通过一台机器或设备来解决,所以我们需要通过多台设备共同来解决大数据的问题。 当数据快速发展的时候,当时我们确实也存在很多数据解决方案,这些解决方案主要是由IBM等等公司提供。这些解决方案看起来非常并行,是企业数据的解决方案。但是对于这些解决方案存在的问题就是针对专属的数据,要付出高昂的代价解决这些问题。在大数据世界里,很多中小公司也会产生大量的数据,他们无法支付得起高昂的企业解决方案。 The rise of Hadoop 1.history of Hadoop 2003年,谷歌发布了一篇Google GFS论文,论文介绍了如何将GFS系统用于大型的、分布式的、对大量数据进行访问的应用。2004年,谷歌公布了另外一篇关于MapReduce的介绍一种用于大规模数据集(大于1TB)的并行运算编程模型,即MapReduce编程模型。 2005年初,雅虎启动了Nutch项目,同时,Nutch项目的开发者在Nutch上有了一个可工作的MapReduce应用,到当年年中,所有主要的Nutch算法被移植到使用MapReduce和HDFS来运行。 在2006年2月,他们从Nutch转移出来成为一个独立的Lucene子项目,称为Hadoop。大约在同一时间,Doug Cutting加入雅虎。Yahoo提供一个专门的团队和资源将Hadoop发展成一个可在网络上运行的系统。 2008年1月,Hadoop已成为Apache顶级项目,证明它是成功的,是一个多样化、活跃的社区。通过这次机会,Hadoop成功地被雅虎之外的很多公司应用。 今天有很多不同的技术存在于整个大数据的技术空间里,大多数的技术像Hadoop一样都是开源的技术。很多人当他们最开始关注大数据空间的时候,他们觉得太复杂了,他们很难理清每个系统到底做什么的,或者他们应该什么样的系统解决现实存在的问题。 2.Early Open Source Stacks 早期的应用都是直接现将数据存储到数据库中,应用/用户直接/间接从数据库中获取所需数据。 随着数据量的增大,人们开始关注Hadoop进一步替代他们使用的传统方法。Hadoop有两个重要的组成部分,一个是存储引擎,这都是以谷歌HDFS作为依据,一个是数据处理模型MapReduce。Hadoop是一套很灵活的解决方案,它也是最常用的一种数据处理方式。但是它在某些方面表现的比较乏力。 3.Rise of Open Source Data Infrastructure 当一项技术变得被广泛采纳的时候,那么他的局限性也变得众所周知了,Hadoop也不例外,下文罗列了Hadoop的部分缺点 1)、快速查询; 2)、(流式)事件的传递; 3)、流处理; 4)、内存计算 为了解决Hadoop的缺点,许多新的技术被创建出来。 Data Infrastructure Space Today 1.Modern Open Source Stacks 当下的数据处理模型如下图所示: 当我思考当今的大数据现状的时候,大多数技术都会归为四类,第一个是整个传输数据,第二加工数据,第三存储数据,以及数据的问询或分析。现在关于技术有很多不同的领域,因为谈到大数据的时候,人们已经意识到即使简单的问题也需要很多复杂的解决方案,和一种专署的技术,或者大规模的技术才能够解决。比如说从一个位置向另外一个位置进一步传输数据的数据是比较简单的,但对大量数据就是非常复杂的问题了,这些都需要非常先进的技术才能够解决。 所以这四类技术所有的开源的大数据技术都可以归为四类当中的一类技术,很多人都已经开始意识到不同的技术其实可以结合到一起,把它用为一种端对端的技术来对所有的数据进行分析,我会给大家介绍一下四种不同的技术。不同的技术在整个大数据空间如何归为四类当中的其中一类。 这里有很多的不同技术,有很多技术都是彼此竞争关系,我没有时间给大家做逐一赘述,也不能够进一步详细介绍每个技术是什么。但是我希望给大家提供简介,帮助大家了解这些技术是做什么的,以及整个构架是什么样的。 2.Data Delivery 第一类技术是数据传输系统,数据传输系统他们主要负责把事件从一个位置进一步运输到另外一个位置,所以我们可能会产生一些数据的,比如说把数据进一步传到整个数据系统。数据传输系统他们主要专注于短期储存,这些系统通常会和数据流来打交道。这些系统可以分为不同的类别,每个系统都有不同的框架和不同的关键点传输数据。 但是我给大家介绍一下上层的架构,就像kafka,它提供了资源的上分区,把生产数据和消费数据直接分开,现在这个架构是根据分布式逻辑来进行的,你可以把这些数据按照分布的逻辑进行分布,之后从分布式逻辑上来收集数据,这是一个非常好的描述数据的一个方式。 MQ是提取数据的系统,不完全一样,这两个架构有些不同,不同的架构,不同的结构可以产生不同范围,不同规模的表现性能,以提升不同的操作性能。 现在Kafka逐步变成了这个领域的标准。 3.Storage 数据提供系统是怎么工作的呢?它通常把数据提供到其它地方进行进一步的处理,首先可以把数据提供到存储的机制当中,存储机制只是数据库,会存储数据,也可以从这里调用数据。然而现在更普遍的情况是一种专门的储存数据库,可以看到很多的专门的存储数据的系统。 现在最普遍的存储方式是分布式数据存储系统,也就是说把这些数据无限制地放到HDFS系统当中,随时进行提取数据。文件系统和数据提交系统有一些重叠的地方,如果你在Kafka里长时间存储数据的话,你会考虑它是一种存储的方式。但是有些时候这种数据推送,数据提供需要同样的技术。 4.Processing 数据处理的技术是做什么的呢?也就是说它把数据进行变化,让它更简洁,或者把数据进行变形,以便于更容易的处理。在查询和数据处理方面也有一些重合。我们应该这么理解,处理过程是把数据进行变形,输出的数据和输入的数据量是一样大的,查询系统的输出数据比输入数据比较小一些,这在很多的系统里都是这样的。在大数据系统方面你可以看到这些系统不断来增强处理的性能。另外一些系统重点放到查询方面技术的提高。 5.Stream Processing 有两种子类型,关于处理的,第一个流处理,流处理也就是把数据放到一个流的程序当中进行连续处理。首先数据提供到Kafka里,需要先进行流处理,之后才进入存储器进行存储。还有一种就是直接放到查询系统当中,这是两种不同流处理的流程。 有很多不同的流处理的处理器,有很多的开源的流处理的程序,下面这三种是非常流行的处理方式。 6.Batch Processing 现在我要给大家介绍批处理。批处理方式在流处理方面当中不是一种真正的流处理的方式,它只是以批的方式来收集数据,然后把它放到一种特定的构架下面,然后来进行批处理。这是两种不同的架构,两种表现也是不同,它们担心的问题也不一样。通过流处理可以得到非常快速处理的结果。 现在有两个非常流行的技术,他们分别是Hadoop和Spark对大型静态数据集的处理,Hadoop是批处理非常流行的一种技术,但是它有很多的局限。在过去几年当中Spark更加受到大家的欢迎。 Spark的工作方式就是考虑你的处理过程,将它想象成一个过程或者一个舞台,Spark做的就是非常有效地利用内存,每一个计算过程都会输出一个结果,Spark会把这些结果做一个统计,这种工作的方法是迭代式的,而且是非常高效的迭代式。Spark会把所有的数据都进行统一的整理,而且Spark比Hadoop的API更加有优势,所以在过去几年当中,Spark几乎慢慢地变成了批处理的标配。 7.Querying 最后一个环节要说的是查询环节,查询环节目前是最大的一个环节,而且是最先进的一种数据查询。这种查询技术的目的就是为了快速,我们如何来利用查询技术呢?我们要输入一个查询的命令,然后把这个命令进行处理,把输出的数据放到查询环节当中以便用户随时查询,这就需要我们对数据进行预处理,然后把预处理数据放到存储器当中,然后再送到查询处理器当中以便查询。 8.SQL-on-Hadoop 数据的操作语言是SQL,因此很多工具的开发目标自然就是能够在Hadoop上使用SQL。这些工具有些只是在MapReduce之上做了简单的包装。SQL-on-Hadoop工作的原理就是从某些地方提取数据,提取数据可能是分布式处理,把数据放到自己引擎当中,这样就可以控制数据,改变数据,并且创造数据。所以SQL是非常灵活的一种过程,这是它的主要的特点。 很多SQL on Hadoop都支持SQL查询的功能,SQL可以帮助你非常便捷得到想得到的数据。但是缺点是处理速度非常慢,因为中间涉及到一些过程要从HDFS提取数据,处理数据,然后再放到存储器当中。这样就会非常慢,如果需要快速反应的话,这种小的延迟期的操作还需要进一步的提升。所以我们就需要进一步提高优化存储。 9.Key/Value Stores 另一种加速查询速度的方法就是要把资料库进行优化,这样就能够打造一种非常快速的查询的架构。它可以支持非常快速的查找,也可以进行快速的写入,我们有很多时间序列的数据库都有键值存储。 键值存储有两种方式,第一个方式就是预计算,预计算方面要把每个查询命令都进行预测,然后把这些查询命令进行预处理,把数据进行预存储。左边是非常分散的数据,右边根据键入的信息进行分类,这样的话在某种程度上是非常有效的。在你预计算之后查询将变得非常之快,因为它会快速来查询一些映射。 但问题是一些数据库的预计算可能会耗时很长,有些时候预计算会花几个小时才能得到数据,所以提前进行预计算是非常省时的方式。常用的键值存储引擎如下: 以下是在键值存储进行预计算时得到的数据: 从上述的结果我们可以看出,即使是使用了键值存储,在对数据进行查询时依旧很慢。 10.Column stores 另外一个方式就是,也是非常流行的技术,就是范围扫描。关于范围扫描的理念就是主间直是井号,对维度和特性进行分类,这种问题方式关于性能方面的问题。首先需要预计算的时间,这个扫描也是很花时间的。所以现在有些人仍然用键值存储方式加速查询速度,但是今年来突然出现了一种列存储的技术,马上就变得十分流行。你可以存储并且扫描你的数据,然后把这些数据进行列存储,根据查询的关键字,电脑可以快速查询各个列,这样的话你就可以在不同的列当中创造不同的关键字,以及指标。这是性能查询方面非常大的进步。 11.Druid 下面我给大家介绍一下Druid,它是一种列存储的方式,一种交互式操作系统,它会以列的形式来存储数据,它十分擅长于对数据进行并发的读取,而且也可以实现低延时的查询,在事件创建的毫秒内就可以被查询到。 12.面对如此多的选择,我们究竟选择哪一个呢? 现在大数据非常复杂,我们在评价不同技术的时候应该首先考虑的是这个技术是不是真正解决了我们的问题,其次技术是否得到了积极快速的发展,是不是有新技术的加入提升了新的功能。在不同的技术之间可能差别不是很大,我们可以随便选某一种技术来为我所用。但在未来我们可能是会有更加集中化,一体化的技术出现。 现在我要给大家介绍一下未来的发展趋势,在未来几年当中将会出现的一些技术。 我觉得开源大数据项目几乎已经达到了饱和点,可能是大数据当中一旦出现一个问题,大概就会同时出现五个解决这个问题的项目,索引很多问题都可以被快速的解决。 在最近几年中很多人都特别地注重流计算,流计算已经变得越来越流行了,在过去几年当中我们也看到很多人注意到内存计算,因为内存变得越来越便宜,在很多的系统当中内存计算可能会成为大数据处理方面的一个标配。 现在这些大数据的技术还是比较新的技术,还需要一些时间才会出现共同的标准。但是我觉得在不久的将来,我们很快就会出现大数据方面通用的标准。 我不相信有单一的一种技术会解决所有的问题,我觉得有很多不同的数据就需要有很复杂的大数据库来处理。但是我觉得未来的开源大数据的堆栈包括以下几个部分,其中必须要有一个处理单元,要有一个储存单元,当然肯定要有查询单元,没有查询单元就没有快速的目标的实现了。 在数据提交方面,Kafka已经达到了这个标准,对于流处理方面Spark已经成为了标准的工具,我觉得Druid查询方面也做得很好。 所以基础设施的架构也会不断成熟,不断地改善。在我们的架构不断变得稳定之后,会出现很多的应用,我们现在已经看到一些可视化的工具,以及虚拟现实的工具已经应用到了开源数据。 在未来几年当中还会有更多的开源数据。在虚拟现实之外,架构和设施稳定了,可以做很多很酷的事情,比如可以更多研究AR,更多研究深度学习,人工智能,这都是建立基础网络,基础系统上的未来发展,这也是非常流行的趋势。我觉得现在IT社区会变得越来越庞大。 人物名片:Fangjin Yang 是 Druid 项目联合发起人、核心开发者,Imply 联合创始人。Imply 是位于美国旧金山的一家技术创业公司。Fangjin 之前曾在 Metamarkets 和 Cisco 等公司任高级工程师。加拿大滑铁卢大学电气工程专业本科,计算机工程专业硕士。 ====================================分割线================================ 本文转自d1net(转载)

资源下载

更多资源
Mario

Mario

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

腾讯云软件源

腾讯云软件源

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

Sublime Text

Sublime Text

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

WebStorm

WebStorm

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

用户登录
用户注册