首页 文章 精选 留言 我的

精选列表

搜索[代码托管平台],共10000篇文章
优秀的个人博客,低调大师

今日头条在消息服务平台和容灾体系建设方面的实践与思考

本篇文章整理自今日头条的沈辉在 RocketMQ 开发者沙龙中的演讲,主要和大家分享一下,RocketMQ 在微服务架构下的实践和容灾体系建设。沈辉是今日头条的架构师,主要负责 RocketMQ 在头条的落地以及架构设计,参与消息系统的时间大概一年左右。 以下是本次分享的议题: 头条的业务背景 为什么选择 RocketMQ RocketMQ 在头条的落地实践 头条的容灾系统建设 业务背景 今日头条的服务大量使用微服务,容器数目巨大,业务线繁多, Topic 的数量也非常多。另外,使用的语言比较繁杂,包括 Python,Go, C++, Java, JS 等,对于基础组件的接入,维护 SDK 的成本很高。 引入 RocketMQ 之前采用的消息队列是 NSQ 和 kafka , NSQ 是纯内存的消息队列,缺少消息的持久性,不落盘直接写到 Go

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

选型宝访谈:如何打造云时代的一体化供应链平台?

写在前面 供应链是现代企业竞争的焦点,线上拼用户和流量,线下拼供应链,已成为许多企业的共识。近年来,在“中国制造”和“电子商务”大发展的带动下,SCM已成为许多企业继ERP之后的新标配。 今天,移动互联网蓬勃发展,云计算、大数据、AI等技术日臻成熟,企业信息系统云端化成为趋势,新技术应用成为常态。在这样的背景下,企业传统的SCM系统该何去何从,成为很多CIO朋友非常关心的话题。 李维良(主持人) 请您先为大家介绍一下,什么是供应链(Supply Chain)和供应链管理?供应链通常包含哪些节点和主体? 许效军(嘉宾) 关于供应链和供应链管理,在很多教科书上,有很多专业的说法。通俗一点来讲,供应链就是围绕核心企业,通过对物流、信息流、资金流的控制,构建的从采购原材料开始,到制成中间产品及最终产品、最后由销售网络把产品送到消费者手中的一个网链。在这个网链中,通常会包含供应商、经销商、物流服务商、最终客户等众多主体。 可以说,供应链是一个企业从端到端,贯穿经营全过程的一个重要职能,而供应链管理就是对整个供应链系统进行计划、协调、操作、控制和优化的各种活动和过程。为供应链管理提供支撑的信息化系统,就是我们常说的SCM(供应链管理系统 Supply Chain Management)。 李维良 进入新时代,为什么传统的SCM需要转型?转型的方向是什么? 许效军 随着经济全球化、互联网化的不断推进,企业的供应链系统也在发生着巨大的变化,比如:供应链进一步拉长、客户订单日益多样化、交货期越来越短、仓库及承运商多而分散等等。竞争的不断加剧、新商业模式的不断出现,使市场变得越来越不可预测,波动成为一种新的常态。 在这样的背景下,传统SCM系统的弊端开始显现:订单、仓储、运输等系统各自为政,缺乏信息共享与协同机制,难以应付激增的海量数据,无法对市场变化做出及时的响应和调整……传统的供应链管理系统越来越力不从心,变革势在必行。 与此同时,移动互联网、云计算、大数据、物联网、人工智能等新技术日益成熟,应用的成本越来越低,这也为供应链管理系统的变革与创新提供了可能。 供应链具有先天的多连接属性,从外部的供应商、经销商到内部的销售、采购、生产、仓储、运输,从货车司机到终端消费者,都是供应链连接的对象。移动+社交、云计算、物联网等技术的普及,使今天的供应链系统可以将这些对象更好地连接起来。传统的物流、资金流、信息流“三流合一”的理念需要升级,今天,通过新技术的应用,可以将供应链中的第四大要素“人”也连接起来,做到“四流合一”。 连接自然会带来海量的数据,而大数据技术可以帮助我们从海量数据中获取价值,从而进一步优化供应链系统。 经过几年的发展和应用,云计算培养了C端市场“On Demand”也就是“按需服务”的能力和习惯,今天,这种消费习惯也延伸到了B端。 不难看出,移动化、云端化、一体化、智能化,都是供应链系统转型的重要方向。新一代SCM正依托新技术,连接包括人在内的更多要素,实现供应链数据的无缝流转,为企业打造应需而变、智慧决策、灵活扩展、快速响应的数字化供应链系统。

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

java版spring cloud+spring boot 社交电子商务平台-Ribbon设计原理

一. Spring集成下的Ribbon工作结构 先贴一张总览图,说明一下Spring如何集成Ribbon的,如下所示: Spring Cloud集成模式下的Ribbon有以下几个特征: 1.Ribbon 服务配置方式 每一个服务配置都有一个Spring ApplicationContext上下文,用于加载各自服务的实例。 和Feign的集成模式 在使用Feign作为客户端时,最终请求会转发成 http://<服务名称>/的格式,通过LoadBalancerFeignClient, 提取出服务标识<服务名称>,然后根据服务名称在上下文中查找对应服务的负载均衡器FeignLoadBalancer,负载均衡器负责根据既有的服务实例的统计信息,挑选出最合适的服务实例。 二、Spring Cloud模式下和Feign的集成实现方式 和Feign结合的场景下,Feign的调用会被包装成调用请求LoadBalancerCommand,然后底层通过Rxjava基于事件的编码风格,发送请求;Spring Cloud框架通过 Feigin 请求的URL,提取出服务名称,然后在上下文中找到对应服务的的负载均衡器实现FeignLoadBalancer,然后通过负载均衡器中挑选一个合适的Server实例,然后将调用请求转发到该Server实例上,完成调用,在此过程中,记录对应Server实例的调用统计信息。 /** * Create an {@link Observable} that once subscribed execute network call asynchronously with a server chosen by load balancer. * If there are any errors that are indicated as retriable by the {@link RetryHandler}, they will be consumed internally by the * function and will not be observed by the {@link Observer} subscribed to the returned {@link Observable}. If number of retries has * exceeds the maximal allowed, a final error will be emitted by the returned {@link Observable}. Otherwise, the first successful * result during execution and retries will be emitted. */ public Observable<T> submit(final ServerOperation<T> operation) { final ExecutionInfoContext context = new ExecutionInfoContext(); if (listenerInvoker != null) { try { listenerInvoker.onExecutionStart(); } catch (AbortExecutionException e) { return Observable.error(e); } } // 同一Server最大尝试次数 final int maxRetrysSame = retryHandler.getMaxRetriesOnSameServer(); //下一Server最大尝试次数 final int maxRetrysNext = retryHandler.getMaxRetriesOnNextServer(); // Use the load balancer // 使用负载均衡器,挑选出合适的Server,然后执行Server请求,将请求的数据和行为整合到ServerStats中 Observable<T> o = (server == null ? selectServer() : Observable.just(server)) .concatMap(new Func1<Server, Observable<T>>() { @Override // Called for each server being selected public Observable<T> call(Server server) { // 获取Server的统计值 context.setServer(server); final ServerStats stats = loadBalancerContext.getServerStats(server); // Called for each attempt and retry 服务调用 Observable<T> o = Observable .just(server) .concatMap(new Func1<Server, Observable<T>>() { @Override public Observable<T> call(final Server server) { context.incAttemptCount();//重试计数 loadBalancerContext.noteOpenConnection(stats);//链接统计 if (listenerInvoker != null) { try { listenerInvoker.onStartWithServer(context.toExecutionInfo()); } catch (AbortExecutionException e) { return Observable.error(e); } } //执行监控器,记录执行时间 final Stopwatch tracer = loadBalancerContext.getExecuteTracer().start(); //找到合适的server后,开始执行请求 //底层调用有结果后,做消息处理 return operation.call(server).doOnEach(new Observer<T>() { private T entity; @Override public void onCompleted() { recordStats(tracer, stats, entity, null); // 记录统计信息 } @Override public void onError(Throwable e) { recordStats(tracer, stats, null, e);//记录异常信息 logger.debug("Got error {} when executed on server {}", e, server); if (listenerInvoker != null) { listenerInvoker.onExceptionWithServer(e, context.toExecutionInfo()); } } @Override public void onNext(T entity) { this.entity = entity;//返回结果值 if (listenerInvoker != null) { listenerInvoker.onExecutionSuccess(entity, context.toExecutionInfo()); } } private void recordStats(Stopwatch tracer, ServerStats stats, Object entity, Throwable exception) { tracer.stop();//结束计时 //标记请求结束,更新统计信息 loadBalancerContext.noteRequestCompletion(stats, entity, exception, tracer.getDuration(TimeUnit.MILLISECONDS), retryHandler); } }); } }); //如果失败,根据重试策略触发重试逻辑 // 使用observable 做重试逻辑,根据predicate 做逻辑判断,这里做 if (maxRetrysSame > 0) o = o.retry(retryPolicy(maxRetrysSame, true)); return o; } }); // next请求处理,基于重试器操作 if (maxRetrysNext > 0 && server == null) o = o.retry(retryPolicy(maxRetrysNext, false)); return o.onErrorResumeNext(new Func1<Throwable, Observable<T>>() { @Override public Observable<T> call(Throwable e) { if (context.getAttemptCount() > 0) { if (maxRetrysNext > 0 && context.getServerAttemptCount() == (maxRetrysNext + 1)) { e = new ClientException(ClientException.ErrorType.NUMBEROF_RETRIES_NEXTSERVER_EXCEEDED, "Number of retries on next server exceeded max " + maxRetrysNext + " retries, while making a call for: " + context.getServer(), e); } else if (maxRetrysSame > 0 && context.getAttemptCount() == (maxRetrysSame + 1)) { e = new ClientException(ClientException.ErrorType.NUMBEROF_RETRIES_EXEEDED, "Number of retries exceeded max " + maxRetrysSame + " retries, while making a call for: " + context.getServer(), e); } } if (listenerInvoker != null) { listenerInvoker.onExecutionFailed(e, context.toFinalExecutionInfo()); } return Observable.error(e); } }); } 从一组ServerList 列表中挑选合适的Server /** * Compute the final URI from a partial URI in the request. The following steps are performed: * <ul> * <li> 如果host尚未指定,则从负载均衡器中选定 host/port * <li> 如果host 尚未指定并且尚未找到负载均衡器,则尝试从 虚拟地址中确定host/port * <li> 如果指定了HOST,并且URI的授权部分通过虚拟地址设置,并且存在负载均衡器,则通过负载就均衡器中确定host/port(指定的HOST将会被忽略) * <li> 如果host已指定,但是尚未指定负载均衡器和虚拟地址配置,则使用真实地址作为host * <li> if host is missing but none of the above applies, throws ClientException * </ul> * * @param original Original URI passed from caller */ public Server getServerFromLoadBalancer(@Nullable URI original, @Nullable Object loadBalancerKey) throws ClientException { String host = null; int port = -1; if (original != null) { host = original.getHost(); } if (original != null) { Pair<String, Integer> schemeAndPort = deriveSchemeAndPortFromPartialUri(original); port = schemeAndPort.second(); } // Various Supported Cases // The loadbalancer to use and the instances it has is based on how it was registered // In each of these cases, the client might come in using Full Url or Partial URL ILoadBalancer lb = getLoadBalancer(); if (host == null) { // 提供部分URI,缺少HOST情况下 // well we have to just get the right instances from lb - or we fall back if (lb != null){ Server svc = lb.chooseServer(loadBalancerKey);// 使用负载均衡器选择Server if (svc == null){ throw new ClientException(ClientException.ErrorType.GENERAL, "Load balancer does not have available server for client: " + clientName); } //通过负载均衡器选择的结果中选择host host = svc.getHost(); if (host == null){ throw new ClientException(ClientException.ErrorType.GENERAL, "Invalid Server for :" + svc); } logger.debug("{} using LB returned Server: {} for request {}", new Object[]{clientName, svc, original}); return svc; } else { // No Full URL - and we dont have a LoadBalancer registered to // obtain a server // if we have a vipAddress that came with the registration, we // can use that else we // bail out // 通过虚拟地址配置解析出host配置返回 if (vipAddresses != null && vipAddresses.contains(",")) { throw new ClientException( ClientException.ErrorType.GENERAL, "Method is invoked for client " + clientName + " with partial URI of (" + original + ") with no load balancer configured." + " Also, there are multiple vipAddresses and hence no vip address can be chosen" + " to complete this partial uri"); } else if (vipAddresses != null) { try { Pair<String,Integer> hostAndPort = deriveHostAndPortFromVipAddress(vipAddresses); host = hostAndPort.first(); port = hostAndPort.second(); } catch (URISyntaxException e) { throw new ClientException( ClientException.ErrorType.GENERAL, "Method is invoked for client " + clientName + " with partial URI of (" + original + ") with no load balancer configured. " + " Also, the configured/registered vipAddress is unparseable (to determine host and port)"); } } else { throw new ClientException( ClientException.ErrorType.GENERAL, this.clientName + " has no LoadBalancer registered and passed in a partial URL request (with no host:port)." + " Also has no vipAddress registered"); } } } else { // Full URL Case URL中指定了全地址,可能是虚拟地址或者是hostAndPort // This could either be a vipAddress or a hostAndPort or a real DNS // if vipAddress or hostAndPort, we just have to consult the loadbalancer // but if it does not return a server, we should just proceed anyways // and assume its a DNS // For restClients registered using a vipAddress AND executing a request // by passing in the full URL (including host and port), we should only // consult lb IFF the URL passed is registered as vipAddress in Discovery boolean shouldInterpretAsVip = false; if (lb != null) { shouldInterpretAsVip = isVipRecognized(original.getAuthority()); } if (shouldInterpretAsVip) { Server svc = lb.chooseServer(loadBalancerKey); if (svc != null){ host = svc.getHost(); if (host == null){ throw new ClientException(ClientException.ErrorType.GENERAL, "Invalid Server for :" + svc); } logger.debug("using LB returned Server: {} for request: {}", svc, original); return svc; } else { // just fall back as real DNS logger.debug("{}:{} assumed to be a valid VIP address or exists in the DNS", host, port); } } else { // consult LB to obtain vipAddress backed instance given full URL //Full URL execute request - where url!=vipAddress logger.debug("Using full URL passed in by caller (not using load balancer): {}", original); } } // end of creating final URL if (host == null){ throw new ClientException(ClientException.ErrorType.GENERAL,"Request contains no HOST to talk to"); } // just verify that at this point we have a full URL return new Server(host, port); }

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

Hadoop大数据平台实战(04):Ubuntu 18.04实战安装Spark大数据引擎并统计字符

Spark是一个开源的高性能大数据分析引擎,在Hadoop生态系统中非常的重要组成部分,主要的作用就是分析处理大数据,Spark在大数据生态中的作用是替代之前的mapreduce引擎。Spark的性能测试表名将大数据分析处理的性能提高了100倍。Apache Spark使用最先进的DAG调度程序,查询优化器和物理执行引擎,实现批处理和流数据的高性能分析处理。Spark可以使用Java,Scala,Python,R和SQL快速编写大数据应用程序。Spark提供80多个高级操作符,可以轻松构建并行应用程序。这也是我们为什么要学习Spark的原因。1、大数据分析引擎Spark介绍Apache Spark是高性能开源大数据分析引擎。 它提供Java,Scala,Python和R中的高级API,以及支持通用执行图的优化引擎。 它还支持一组丰

资源下载

更多资源
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文件系统,支持十年生命周期更新。

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部分的功能。

用户登录
用户注册