关于后端:Tugraph-Analytics图计算快速上手之紧密中心度算法md

作者:张武科 概述严密核心度(Closeness Centrality)计量了一个节点到其余所有节点的紧密性,即该节点到其余节点的间隔的倒数;节点对应的值越高示意紧密性越好,可能在图中流传信息的能力越强,可用以掂量信息流入或流出该节点的能力,多用与社交网络中要害节点挖掘等场景。 算法介绍对于图中一个给定节点,紧密性核心性是该节点到其余所有节点的最小间隔和的倒数: 其中,u示意待计算严密核心度的节点,d(u, v)示意节点u到节点v的最短门路间隔;理论场景中,更多地应用归一化后的严密核心度,即计算指标节点到其余节点的均匀间隔的倒数: 其中,n示意图中节点数。 算法实现首先,基于AlgorithmUserFunction接口实现ClosenessCentrality,如下: @Description(name = "closeness_centrality", description = "built-in udga for ClosenessCentrality")public class ClosenessCentrality implements AlgorithmUserFunction<Long, Long> { private AlgorithmRuntimeContext context; private long sourceId; @Override public void init(AlgorithmRuntimeContext context, Object[] params) { this.context = context; if (params.length != 1) { throw new IllegalArgumentException("Only support one arguments, usage: func(sourceId)"); } this.sourceId = ((Number) params[0]).longValue(); } @Override public void process(RowVertex vertex, Iterator<Long> messages) { List<RowEdge> edges = context.loadEdges(EdgeDirection.OUT); if (context.getCurrentIterationId() == 1L) { context.sendMessage(vertex.getId(), 1L); context.sendMessage(sourceId, 1L); } else if (context.getCurrentIterationId() == 2L) { context.updateVertexValue(ObjectRow.create(0L, 0L)); if (vertex.getId().equals(sourceId)) { long vertexNum = -2L; while (messages.hasNext()) { messages.next(); vertexNum++; } // 统计节点数 context.updateVertexValue(ObjectRow.create(0L, vertexNum)); // 向邻接点发送与指标点间隔 sendMessageToNeighbors(edges, 1L); } } else { if (vertex.getId().equals(sourceId)) { long sum = (long) vertex.getValue().getField(0, LongType.INSTANCE); while (messages.hasNext()) { sum += messages.next(); } long vertexNum = (long) vertex.getValue().getField(1, LongType.INSTANCE); // 记录最短距离和 context.updateVertexValue(ObjectRow.create(sum, vertexNum)); } else { if (((long) vertex.getValue().getField(1, LongType.INSTANCE)) < 1) { Long meg = messages.next(); context.sendMessage(sourceId, meg); // 向邻接点发送与指标点间隔 sendMessageToNeighbors(edges, meg + 1); // 标记该点已向指标点发送过音讯 context.updateVertexValue(ObjectRow.create(0L, 1L)); } } } } private void sendMessageToNeighbors(List<RowEdge> outEdges, Object message) { for (RowEdge rowEdge : outEdges) { context.sendMessage(rowEdge.getTargetId(), message); } } @Override public void finish(RowVertex vertex) { if (vertex.getId().equals(sourceId)) { long len = (long) vertex.getValue().getField(0, LongType.INSTANCE); long num = (long) vertex.getValue().getField(1, LongType.INSTANCE); context.take(ObjectRow.create(vertex.getId(), (double) num / len)); } } @Override public StructType getOutputType() { return new StructType( new TableField("id", LongType.INSTANCE, false), new TableField("cc", DoubleType.INSTANCE, false) ); }}而后,可在 DSL 中引入自定义算法,间接调用应用,语法模式如下: ...

September 19, 2023 · 3 min · jiezi

关于后端:朋友们就在今天JDK-21它终于带着重磅新特性正式发布了

你好呀,我是歪歪。 敌人们,好消息,好消息,重磅好消息。 从今年年初就始终在喊的具备革命性、将来性、创始新纪元的 JDK 21 依照官网的工夫计划表,明天终于是要正式 GA 了: https://openjdk.org/projects/jdk/21/ GA,就是我下面框起来的“General Availability”的缩写,直译成中文,尽管是“一般可用”的意思,然而在软件行业,它就代表正式版。 如果对外公布一个 GA 版本,就意味着这个版本曾经通过全面的测试,不存在任何重大的 bug,可供普通用户进行应用。 既然说到 GA 了,歪徒弟也顺便给大家遍及一下个别咱们看到的版本号的含意。 比方咱们常常会看到一些软件公布的时候都会带上 Alpha、Beta、Gamma、RC 等等这些莫名其妙的单词,它们代表什么意思呢? Alpha:软件或零碎的内部测试版本,仅内部人员应用。个别不向内部公布,通常会有很多 Bug,除非你也是测试人员,否则不倡议应用,alpha 就是 ,是希腊字母的第一位,示意最高级的版本,beta 就是 ,alpha 版就是比 beta 还早的测试版,个别都是内部测试的版本。Beta:公开测试版。 是希腊字母的第二个,顾名思义,这一版本通常是在 Alpha 版本后,该版本绝对于 Alpha 版已有了很大的改良,打消了重大的谬误,但还是存在着一缺点,须要通过屡次测试来进一步打消。这个阶段的版本会始终退出新的性能。Gamma:软件或零碎靠近于成熟的版本,只须要做一些小的改良就能发行。是 beta 版做过一些批改,成为正式公布的候选版本。RC:Release Candidate,发行候选版本。和 Beta 版最大的差异在于 Beta 阶段会始终退出新的性能,然而到了 RC 版本,简直就不会退出新的性能了,而次要着重于除错。RC 版本是最终发放给用户的最靠近正式版的版本,发行后改过 bug 就是正式版了,就是正式版之前的最初一个测试版。GA:General Available,正式公布的版本,这个版本就是正式的版本。在国外都是用 GA 来阐明 release 版本的。比方:MySQL Community Server 5.7.21 GA 这是 MySQL Community Server 5.7 第 21 个发行稳固的版本,GA 意味着 General Available,也就是官网开始举荐宽泛应用了。Release:这个版本通常就是所谓的“最终版本”,在后面版本的一系列测试版之后,终归会有一个正式版本,是最终交付用户应用的一个版本,该版本有时也称为标准版。个别状况下,Release 不会以单词模式呈现在软件封面上,取而代之的是符号(R)。Stable:稳定版。在开源软件中,都有 stable 版,这个就是开源软件的最终发行版,用户能够放心大胆的用了。这一版本基于 Beta 版,已知 Bug 都被修复,个别状况下,更新比较慢。除了下面的这些之外,咱们还常常看见一个 LTS 的版本号。 ...

September 19, 2023 · 3 min · jiezi

关于后端:Rust的注释与文档

rust中//!和///有什么区别? 在 Rust 中,//! 和 /// 是非凡正文语法,用于文档正文(Documentation Comments)。它们用于编写文档,并生成 Rust 代码的 API 文档。 //! 用于编写模块级别的文档正文,通常搁置在模块的结尾。它容许您编写与整个模块相干的文档。这些正文会被 Rust 编译器解析,生成与模块相干的 API 文档。这些文档能够在应用 cargo doc 命令生成的文档网页中看到。 以下是一个应用 //! 编写模块级别文档正文的示例: //! 这是一个示例模块级别的文档正文。//!//! 这个模块蕴含了一些函数和构造体的定义,用于演示 Rust 的某些个性。//!//! # 示例//!//! 上面是一个示例函数的应用://!//! ```//! fn main() {//! // 调用示例函数//! my_function();//! }//! ```//!//! # 注意事项//!//! 注意事项的形容...//!//! # 参考资料//!//! 额定的参考资料.../// 用于编写项级别的文档正文,通常搁置在函数、构造体、枚举、办法等定义的上方。它容许您编写与特定项相干的文档。与 //! 相似,这些正文也会被 Rust 编译器解析,并生成 API 文档。 以下是一个应用 /// 编写项级别文档正文的示例: /// 这是一个示例函数,用于展现 Rust 的某些个性。////// # 用法////// ```/// fn main() {/// // 调用示例函数/// my_function();/// }/// ```////// # 注意事项////// 注意事项的形容...////// # 参考资料////// 额定的参考资料...fn my_function() { // 函数体}总结来说,//! 用于编写模块级别的文档正文,而 /// 用于编写项级别的文档正文。它们在编写 Rust 代码时能够帮忙您编写清晰、易读和自解释的文档,并通过 cargo doc 命令生成代码的 API 文档。这样其余开发者就能够不便地查看您代码的文档,并理解如何正确应用和了解您的代码。 ...

September 19, 2023 · 3 min · jiezi

关于后端:听GPT-讲Istio源代码pilot7

File: istio/pilot/pkg/model/log.go在Istio我的项目中,istio/pilot/pkg/model/log.go文件的作用是定义了Istio Pilot的日志记录性能。 该文件中定义了一个名为log的全局日志记录器,并且还定义了一些与日志记录相干的变量,如verbose、verboseCount、disableVerbose、debug、disableDebug等。 log全局变量:log是基于github.com/istio/gogo-genproto/googleapis/logging/v2库的一个日志记录器对象。它容许Pilot在不同的级别(如error、warn、info、debug)进行日志记录,并通过配置日志输入指标(如控制台、文件)来管制日志的输入形式。 verbose变量:verbose是一个存储布尔值的全局变量,用于管制是否启用详细信息日志记录。当设置为true时,Pilot会记录更具体的日志信息。 verboseCount变量:verboseCount是一个整数变量,用于记录详细信息日志的计数。它示意在启动Pilot之后记录的详细信息日志的数量。 disableVerbose变量:disableVerbose是一个布尔变量,用于管制是否禁用详细信息日志记录。 debug变量:debug是一个存储布尔值的全局变量,用于管制是否启用调试日志记录。当设置为true时,Pilot会记录调试信息日志。 disableDebug变量:disableDebug是一个布尔变量,用于管制是否禁用调试日志记录。 通过这些变量,Istio Pilot能够不便地进行日志记录,并依据须要调整日志级别和输入形式,以便于故障排除、性能剖析和系统监控等操作。 File: istio/pilot/pkg/model/service.go在istio/pilot/pkg/model/service.go文件中,蕴含了许多构造体和函数,用于定义和操作与服务相干的模型。 serviceCmpOpts:用于比拟两个服务是否相等的选项。istioEndpointCmpOpts:用于比拟两个Istio端点是否相等的选项。endpointDiscoverabilityPolicyImplCmpOpt:用于比拟两个端点可发现性策略是否相等的选项。AlwaysDiscoverable、DiscoverableFromSameCluster等变量:定义了端点可发现性策略的选项。接下来是一些重要的构造体和它们的作用: Service:示意服务的信息,如名称、命名空间、标签等。Resolution:示意服务的解析策略,如负载平衡、子集等。Port:示意服务的端口。PortList:示意服务端口的列表。TrafficDirection:示意流量的传输方向。ServiceInstance:示意服务的实例信息,如IP地址、端口、标签等。ServiceTarget:示意服务的指标信息,包含名称、命名空间、标签等。ServicePort:示意服务端口的信息,包含名称、协定、端口号等。workloadKind:示意工作负载的类型,如Deployment、StatefulSet等。WorkloadInstance:示意工作负载的实例信息,包含名称、命名空间、标签等。Locality:示意地区的信息,如区域、可用区等。HealthStatus:示意服务实例的衰弱状态。IstioEndpoint:示意Istio的端点信息,包含名称、IP地址、标签等。EndpointMetadata:示意端点的元数据信息,如标签、注解等。EndpointDiscoverabilityPolicy:示意端点的可发现性策略。endpointDiscoverabilityPolicyImpl:示意端点可发现性策略的具体实现。ServiceAttributes、K8sAttributes:示意服务的属性,如IP地址、协定等。ServiceDiscovery:示意服务的发现策略。AmbientIndexes、NoopAmbientIndexes:示意环境指标的信息。AddressInfo、ServiceInfo、WorkloadInfo、MCSServiceInfo:示意地址、服务、工作负载、MCS服务的信息。接下来列出一些重要的函数和它们的作用: Key、CmpOpts、String:一些根本的辅助函数。SupportsTunnel:查看端口是否反对隧道。ServiceInstanceToTarget:将服务实例转换为服务指标。DeepCopy、WorkloadInstancesEqual、GetLocalityLabel:一些深拷贝、比拟和获取标签的辅助函数。EnvoyEndpoint、ComputeEnvoyEndpoint:获取Envoy端点的信息。GetLoadBalancingWeight:获取负载平衡权重。IsDiscoverableFromProxy:查看端点是否可从代理进行发现。MetadataClone、Metadata、Equals:解决元数据的函数。AddressInformation、AdditionalPodSubscriptions、Policies、Waypoint、WorkloadsForWaypoint、Aliases:与地址、订阅、策略、门路、工作负载等相干的函数。ResourceName、serviceResourceName、workloadResourceName:用于构建资源名称。Clone、ExtractWorkloadsFromAddresses、WorkloadToAddressInfo、ServiceToAddressInfo:地址信息的转换函数。GetNames、Get、GetByPort、External:用于获取服务和端口的函数。BuildSubsetKey、BuildInboundSubsetKey、BuildDNSSrvSubsetKey、IsValidSubsetKey、IsDNSSrvSubsetKey、ParseSubsetKey:用于构建和解析子集的函数。GetAddresses、GetAddressForProxy、GetExtraAddressesForProxy、getAllAddresses:用于获取地址的函数。GetTLSModeFromEndpointLabels:依据端点标签获取TLS模式。ShallowCopy、copyInternal:用于复制构造体的浅拷贝函数。File: istio/pilot/pkg/model/authentication.goauthentication.go是Istio Pilot中的一个文件,它定义了一些与身份认证相干的构造体和函数。 MutualTLSMode是一个枚举类型,用于示意一对服务之间的双向TLS(Mutual TLS)的模式。该枚举类型包含:NONE、ISTIO_MUTUAL、MUTUAL_TLS_PERMISSIVE和MUTUAL_TLS_STRICT。 AuthenticationPolicies是一个构造体,用于存储由配置文件定义的服务的身份认证策略。它包含一个DefaultPolicy字段,示意默认的身份认证策略,以及一个PermissiveMode字段,示意是否以宽容模式(Permissive Mode)运行。 String是一个函数,用于将MutualTLSMode转换为字符串示意。 ConvertToMutualTLSMode是一个函数,用于将字符串示意的MutualTLSMode转换为理论的MutualTLSMode枚举值。 initAuthenticationPolicies是一个函数,用于初始化身份认证策略。它接管一个JSON格局的配置文件作为参数,并将其解析为AuthenticationPolicies构造。 addRequestAuthentication是一个函数,用于将申请身份认证规定增加到配置中。 addPeerAuthentication是一个函数,用于将对等身份认证规定增加到配置中。 GetNamespaceMutualTLSMode是一个函数,用于获取给定名称空间的双向TLS模式。 GetJwtPoliciesForWorkload是一个函数,用于获取给定工作负载的JWT策略。 GetPeerAuthenticationsForWorkload是一个函数,用于获取给定工作负载的对等身份认证规定。 GetRootNamespace是一个函数,用于获取Istio体系结构的根名称空间。 GetVersion是一个函数,用于获取以后配置文件的版本。 GetAmbientPolicyConfigName是一个函数,用于获取环境策略配置的名称。 getConfigsForWorkload是一个函数,用于依据工作负载的名称和名称空间获取相应的配置信息。 总之,authentication.go文件中定义了与身份认证相干的构造体和函数,它们用于解决和治理Istio中的身份验证策略和配置。 File: istio/pilot/pkg/model/gateway.go在Istio我的项目中,gateway.go文件是Istio Pilot中用于解决网关相干逻辑的文件。它定义了一些构造体和函数来解析和解决网关配置信息。 typeTag变量是用于标识网关配置的类型。nameTag变量用于标识网关配置的名称。totalRejectedConfigs变量是用于记录被回绝的网关配置数量的计数器。 ServerPort构造体用于示意网关配置中的服务端口信息,包含端口号和协定。MergedServers构造体是一组合并后的服务端口信息,用于示意一个网关实例中的所有服务端口信息。 TLSServerInfo构造体示意网关配置中的TLS相干信息,包含证书和私钥等。MergedGateway构造体是合并后的网关信息,包含网关名称、监听地址和监听端口等。 GatewayPortMap构造体用于记录网关的端口映射信息,包含网关名称和端口映射表。 RecordRejectedConfig函数用于记录被回绝的网关配置数量。MergeGateways函数用于合并多个网关配置。udpSupportedPort函数用于判断指定端口是否反对UDP协定。resolvePorts函数用于解析网关配置中的端口号。 canMergeProtocols函数用于判断两个协定是否能够合并。GetSNIHostsForServer函数用于获取网关的SNI主机列表。CheckDuplicates函数用于查看网关配置是否存在反复。gatewayRDSRouteName函数用于生成网关的RDS路由名称。 ParseGatewayRDSRouteName函数用于解析网关RDS路由名称并合成为网关名称和监听端口。sanitizeServerHostNamespace函数用于规范化服务端主机名称和命名空间。 getTargetPortMap函数用于获取指标端口映射表,包含服务端口与网关端口的映射关系。 这些函数和变量的目标是为了解析和解决网关配置信息,并进行相干的合并、校验和解决操作。 File: istio/pilot/pkg/model/envoyfilter.go在Istio我的项目中,envoyfilter.go 文件是 Istio Pilot 包中的一个文件,负责解决 Envoy 配置过滤器(EnvoyFilter)相干的逻辑。 具体而言,EnvoyFilter 是 Istio 针对 Envoy 代理的一种自定义配置对象,用于通过 Envoy 扩大点实现对申请流量的转发、批改和过滤等行为。envoyfilter.go 文件中的代码次要实现了以下几个方面的性能: 定义了一些常量和变量,包含 wellKnownVersions 变量,用于存储反对的 Envoy 版本,以及相干常量用于创立 EnvoyFilter 对象时设置类型等。定义了 EnvoyFilterWrapper 构造体,作为 EnvoyFilter 的封装对象。该构造体包含了对 EnvoyFilter 的形容信息,以及利用该 EnvoyFilter 的逻辑等。定义了 EnvoyFilterConfigPatchWrapper 构造体,作为 Envoy 配置补丁的封装对象。该构造体用于对 Envoy 的配置进行批改。实现了一些函数,包含: ...

September 19, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pilot6

在 Istio 中,Pilot 是 Istio 管制立体的一个重要组件,它具备以下作用: 流量治理: Pilot 负责管理和配置服务之间的网络流量。它通过与底层的服务发现机制(如 Kubernetes 或 Consul)集成,监测服务注册和登记,并将流量路由到正确的指标。Pilot 反对多种流量治理性能,如基于版本的流量切分、A/B 测试、金丝雀部署等。负载平衡: Pilot 在服务之间执行负载平衡,并依据负载平衡策略将申请散发到后端服务实例。它能够依据流量治理规定动静地更新负载平衡策略,以实现申请的平衡散发。安全性: Pilot 通过与 Istio 的平安性能集成,确保服务之间的通信是平安的。它负责注入和治理 Sidecar 代理的 TLS 证书,实现服务间的双向认证和加密通信。Pilot 还治理 Istio 的策略和访问控制规定,以确保服务之间的通信遵循安全策略。服务发现: Pilot 通过与底层的服务注册和发现机制集成,实现服务的主动发现和注册。它监控服务的注册状态,并在服务注册或登记时更新 Istio 的服务注册表。这使得 Istio 可能动静地感知服务的拓扑和变动。遥测和监控: Pilot 收集服务和流量的遥测数据,并将其发送到 Istio 的遥测零碎,如 Prometheus 或 Jaeger。这些数据能够用于监控和剖析服务的性能、提早和流量信息。Pilot 是 Istio 管制立体的外围组件之一,负责流量治理、负载平衡、安全性、服务发现以及遥测和监控。它通过集成底层的服务发现机制和与其余 Istio 组件的合作,实现了对服务间通信的可察看性、安全性和可控性。 File: istio/pilot/pkg/leaderelection/leaderelection.go在istio我的项目中,istio/pilot/pkg/leaderelection/leaderelection.go文件的作用是实现LeaderElection机制。LeaderElection机制用于选举集群中的主节点(Leader),以确保在集群中只有一个节点负责执行某些工作。 该文件定义了多个构造体和函数,用于实现LeaderElection机制的各个性能和实现细节。 LeaderElection构造体:示意LeaderElection的一个实例,蕴含了选举相干的参数和状态信息。Run办法:启动LeaderElection机制,开始进行主节点选举。create办法:创立一个Kubernetes的Clientset,用于与Kubernetes API交互。LocationPrioritizedComparison函数:依据Pod的节点信息进行排序,以便在选举中优先选择位于以后节点的Pod作为主节点。AddRunFunction办法:向LeaderElection实例中增加一个函数,当该实例成为主节点时,这个函数将被调用。NewLeaderElection函数:创立一个LeaderElection实例,并设置相干参数。NewPerRevisionLeaderElection函数:创立一个基于Revision的LeaderElection实例,能够确保每个Revision只有一个主节点。NewLeaderElectionMulticluster函数:创立一个多集群的LeaderElection实例,用于在多个集群中进行主节点选举。newLeaderElection函数:实现LeaderElection的次要逻辑,包含选举,监听和处理结果等。isLeader函数:查看以后节点是否是主节点。通过这些构造体和函数,istio/pilot/pkg/leaderelection/leaderelection.go文件实现了LeaderElection机制,包含选举主节点、告诉和调度主节点变更等性能,以确保集群中只有一个节点负责主节点。这对于istio我的项目来说十分重要,能够保障集群中各个节点之间的合作和工作的一致性。 File: istio/pilot/pkg/leaderelection/k8sleaderelection/healthzadaptor.go在Istio我的项目中,istio/pilot/pkg/leaderelection/k8sleaderelection/healthzadaptor.go文件的作用是实现Istio Pilot的领导选举性能的健康检查适配器。 该文件中定义了几个构造体和函数,别离是: HealthzAdaptor构造体:该构造体用于封装领导选举的健康检查适配器,实现了Istio健康检查器(istio/pilot/pkg/serviceregistry/edshealth/healthcheck.go文件中的HealthChecker接口)。 Name字段:健康检查适配器的名称。Check办法:用于执行健康检查的逻辑,返回一个bool类型的值示意是否衰弱。SetLeaderElection办法:设置领导选举的状态,承受一个bool类型的参数。NewLeaderHealthzAdaptor函数:创立一个新的健康检查适配器实例。DummyAdaptor构造体:该构造体是HealthChecker接口的一个实现,用于模仿健康检查适配器。 Check办法:返回一个固定的衰弱状态。这些构造体和函数用于实现领导选举期间的健康检查逻辑,以确保被选举为领导者的实例是否衰弱。HealthzAdaptor构造体封装了健康检查适配器,通过Check办法执行健康检查逻辑,并通过SetLeaderElection办法与领导选举状态进行交互。NewLeaderHealthzAdaptor函数用于创立新的健康检查适配器实例。而DummyAdaptor构造体则是一个简略的实现,用于进行单元测试或模仿场景。 File: istio/pilot/pkg/model/destination_rule.go在Istio我的项目中,istio/pilot/pkg/model/destination_rule.go文件的作用是定义和解决DestinationRule(指标规定)的模型和相干操作。 MergeDestinationRule: 这个函数用于合并两个DestinationRule,将它们的属性进行合并并返回一个新的合并后果。ConvertConsolidatedDestRule: 这个函数用于将合并后的DestinationRule转换为能够存储在底层存储中的模式(例如etcd等)。Equals: 这个函数用于比拟两个DestinationRule是否相等,判断它们的所有属性是否雷同。GetRule: 这个函数依据给定的DestinationRule的名称、命名空间和主机名获取相应的规定。GetFrom: 这个函数用于在给定的Kubernetes监听器或XDS申请中获取DestinationRule的配置。总而言之,destination_rule.go文件定义了DestinationRule模型的构造和办法,并提供了一些具体的函数跟获取、合并、转换和比拟DestinationRule对象的操作。这些函数在Istio的流量治理中起到关键作用,用于配置和治理不同服务之间的流量路由和策略。 File: istio/pilot/pkg/model/proxy_view.go在Istio我的项目中,istio/pilot/pkg/model/proxy_view.go文件的作用是定义了与代理视图相干的数据结构和函数。 ...

September 19, 2023 · 1 min · jiezi

关于后端:JDK8升级JDK11最全实践干货来了-京东云技术团队

1、前言截至目前(2023年),Java8公布至今已有9年,2018年9月25日,Oracle公布了Java11,这是Java8之后的首个LTS版本。那么从JDK8到JDK11,到底带来了哪些个性呢?值得咱们降级吗?而且降级过程会遇到哪些问题呢?带着这些问题,本篇文章将带来残缺的JDK8降级JDK11最全实际。 2、为什么降级JDK111)性能晋升 更好的垃圾收机制、更快的类加载器, 放慢应用程序的运行速度。综合评估,从Java 8 降级到 Java 11,G1GC平均速度晋升16.1%,ParallelGC为4.5%(基于OptaPlanner的用例基准测试表明) 2)个性和改良 部分变类型推断、新的 API、HTTP/2客户端、Lambda表达式的新个性等,这些新个性能够进步开发效率。 3)反对最新的技术和框架 许多新的技术和框架曾经或行将开始依赖于JDK11或以上版本,降级后能够保障应用程序可能分利用这些新的技术和框架。 4)长期反对版本 JDK11是Oracle官网公布的一个长期反对(LTS),意味着它将取得长期的更新和反对,有助于放弃用程序的稳定性和可靠性。 5)行业趋势 数据来自 New Relic 在2023年1月公布的Java生态报告,从下图能够看出: 目前市面上有 超过 56%的应用程序应用了JDK 11,Java 8 的应用从2020年的84%升高到了当初的32%左右。大部分公司在这三年之间都降级到了JDK 11 或者 JDK 17这两个LTS版本下面。垃圾收集器应用状况来看,JDK11版本及以上 G1使用率最高,占比高达65% 3、降级后GC成果先给出论断: JDK11绝对于JDK8,所有垃圾回收器的性能都有晋升,特地是大内存机器下G1的晋升最显著8G内存以下的机器,举荐应用Parallel GC,如果特地谋求低提早,抉择就义吞吐量,能够应用G1,并设置冀望的最大垃圾回收进展工夫来管制8G及以上的大内存机器,举荐应用G1 4、不举荐应用CMS,降级后从各项数据来看,CMS收集器都不如G1我在JDOS平台上抉择了不同配置的机器(2C4G、4C8G、8C16G),并别离应用JDK8和JDK11进行部署和压测。 整个压测过程限时60分钟,用180个虚构用户并发申请一个接口,每次接口申请都创立512Kb的数据。最终产出不同GC回收器的各项指标数据,来剖析GC的性能晋升成果。 以下是压测的性能状况: * 下面给出的GC降级成果,采纳的是默认的配置,没有做任何优化,只提供参考。真正的GC调优是个技术活,须要依据业务需要、机器配置和理论压测成果等综合评估来选出最合适的GC垃圾回收器。 * 不同垃圾回收器的特点: Parallel GC - JDK 8及以下版本的默认收集器,关注吞吐量,尝试在最小提早的状况下尽快实现工作并进步吞吐量。CMS - 一个老年代收集器,基于标记-革除算法实现,关注提早,以最短回收进展工夫为指标Garbage First(G1)- JDK 9当前的默认收集器,G1 关注总体的性能,会尝试在吞吐量和提早之间做均衡。4、JDK11带来了哪些新个性4.1、GC改良默认垃圾回收器改为G1,废除CMS垃圾回收器◦ G1特点:指标是升高应用程序的进展工夫并进步吞吐量。 引入ZGC垃圾回收器(可伸缩低提早垃圾收集器) 但因为JDK11中ZGC还不够欠缺,举荐在JDK17中再应用稳定版ZGC◦ Full GC的进展不超过10毫秒 ◦ 反对TB级堆内存回收 ◦ 绝对于G1吞吐量降落不超过15% 4.2、模块化Java9引入了对于模块化软件反对,而Java11进一步扩大了这种个性。模块化让应用程序 更精简,缩小对其余类库的依赖和冗余代码,进步运行效率和安全性 。然而,目前不举荐应用模块化,因为相干组件生态还不欠缺,并且模块化带来的价值不够突出。具体起因请看前面章节的详细分析:新个性实际-模块化。 4.3、语法加强◦ 局部变量推断,引入var局部变量类型,容许开发人员省略通常不必要的局部变量类型初始化申明 ◦ Lambda表达式简化,外部能够应用var ...

September 19, 2023 · 1 min · jiezi

关于后端:代码整洁之道程序员的职业素养十

工夫治理业余的开发人员分明会议的老本昂扬,他们也明确本人的工夫是贵重的,须要用于编写代码和解决日程安排。因而,如果会议没有显著的理论成绩,他们会被动回绝加入。 邀请你加入会议的人并不负责管理你的工夫,只有你本人对工夫负责。因而,如果你收到会议邀请,务必确保加入会议对你以后的工作带来理论和显著的功效,否则没有必要参加。如果你发现加入某个会议是在浪费时间,应礼貌地找到退出会议的形式。 为了正当利用与会者的工夫,会议应该有清晰的议程,确定每个议题的工夫安顿和明确的指标。会议的内容最终应该有理论的落地打算。在会议过程中,该当指定负责人,让他们负责后续的跟进工作。 迭代打算会议用于抉择下一轮迭代中要实现的开发工作。在会议召开前,必须实现两项工作:评估可抉择工作的开发工夫,并确定这些工作的业务价值。如果组织切当,验收/组件测试应该在会议召开前实现,或者至多有初步的计划。 编程是一项须要继续投入精力和注意力的智力活动,而注意力是稀缺的资源。如果你用光了本人的注意力,就须要破费一个小时或更长时间来做一些不须要高度注意力的事件,以复原注意力: 睡眠咖啡因复原:不做耗费注意力的事件,能够进来走走,冥想等肌肉注意力:锤炼一下身材输出和输入:编程是一项创造性的工作,与其他人的创造性思维接触能够激发你对软件的创造力。业余的开发人员会评估每个工作的优先级,排除集体偏好和需要,依照实在的紧急水平来执行工作。 业余的开发人员不会执著于无奈放弃或绕过的想法。他们放弃凋谢的心态,违心听取其余意见,因而即便陷入困境,他们仍有其余抉择。 发现自己陷入泥潭但仍执意后退,是最重大的优先级错乱。继续前进只会坑骗本人、团队、公司和客户。一边走向煎熬,一边宣称所有问题都会解决。 业余的开发人员会认真治理本人的工夫和注意力。他们晓得优先级错乱的引诱,珍视本人的名誉,因而会抵制优先级错乱。他们始终有多种抉择,敞开心扉听取其余解决方案,并时刻警觉可能呈现的陷阱,一旦察觉到泥潭,就会避开。最蹩脚的状况就是看到一群开发人员辛苦工作,却越陷越深。

September 19, 2023 · 1 min · jiezi

关于后端:听GPT-讲Istio源代码pilot5

File: istio/pilot/pkg/serviceregistry/kube/controller/ambientindex.goambientindex.go文件位于istio/pilot/pkg/serviceregistry/kube/controller目录中。它是Istio中Kubernetes服务注册表控制器的一部分,负责保护工作负载和服务之间的索引,以便疾速查找和解决网络地址信息。 AmbientIndex构造体是索引的次要数据结构,用于跟踪工作负载和服务之间的关系。AmbientIndexImpl实现了AmbientIndex接口,并提供了一组治理索引的办法。 networkAddress构造体代表网络地址信息,蕴含IP地址和端口号。它作为工作负载和服务之间通信的指标。 WorkloadToAddressInfo函数承受一个工作负载并返回与该工作负载关联的网络地址信息。 ServiceToAddressInfo函数承受一个服务并返回与该服务关联的网络地址信息。 generatePodUID函数承受一个Pod对象并返回其惟一标识符。 Lookup函数承受一个网络地址并返回与之关联的工作负载和服务。 dropWorkloadFromService函数从服务与工作负载之间的关联中删除指定的工作负载。 insertWorkloadToService函数将指定的工作负载与服务建设关联。 updateWaypoint函数更新指定服务的网络地址信息。 All函数返回索引中所有的工作负载和服务。 WorkloadsForWaypoint函数依据指定的网络地址信息返回相关联的工作负载。 Waypoint函数返回特定于服务的惟一标识符。 matchesScope函数依据服务和作用域判断服务是否属于某个特定的范畴。 constructService函数依据服务名称和命名空间构建一个Service对象。 hostname函数返回给定的Pod和命名空间的主机名。 namespacedHostname函数返回给定的Pod、命名空间和服务名称的命名空间主机名。 extractWorkload函数从Pod对象中提取工作负载的惟一标识符。 setupIndex函数初始化AmbientIndex对象。 handlePod函数解决增加、更新或删除Pod时的事件,并相应地更新索引。 networkAddressFromWorkload函数从工作负载对象中提取网络地址信息。 toInternalNetworkAddresses函数将给定的网络地址转换为外部的网络地址格局。 handleService函数解决增加、更新或删除Service时的事件,并相应地更新索引。 getPodsInService函数返回指定服务的所有Pod对象。 AddressInformation函数返回与指定服务和工作负载相关联的地址信息。 constructWorkload函数依据指定的工作负载惟一标识符构建一个Workload对象。 parseIP函数依据提供的字符串解析一个IP地址。 String函数返回networkAddress构造体的字符串示意模式。 getVIPs函数返回提供的服务的虚构IP地址。 AdditionalPodSubscriptions函数返回须要进一步订阅的Pod对象(例如,它们与特定服务相关联)。 workloadNameAndType函数返回工作负载的名称和类型。 File: istio/pilot/pkg/serviceregistry/serviceentry/namespace_handler.gonamespace_handler.go这个文件在Istio我的项目中的作用是解决ServiceEntry的命名空间相干的逻辑。ServiceEntry是一个Istio的资源对象,它用于定义服务的内部入口,通过ServiceEntry,Istio能够将内部服务纳入到服务网格中。namespace_handler.go文件中的代码负责解决ServiceEntry与命名空间的关联关系。 具体来说,namespace_handler.go中的NamespaceDiscoveryHandler函数有以下几个作用: Update()函数:该函数用于解决命名空间的更新事件。当命名空间有变动时,例如命名空间被创立或删除,该办法会被调用。在该办法中,会依据更新的命名空间进行相应的解决逻辑,例如更新缓存或触发ServiceEntry的从新计算。ServiceEntryForWorkloadNamespace()函数:依据工作负载的命名空间获取ServiceEntry。该函数用于在给定的命名空间中查找与工作负载相干的ServiceEntry。它会遍历所有的ServiceEntry,而后匹配工作负载的标签和注解,以确定是否满足ServiceEntry的条件。如果找到匹配的ServiceEntry,则会返回其信息。ServiceEntries()函数:返回所有的ServiceEntry。该函数用于获取所有的ServiceEntry,能够用于遍历和拜访所有已定义的ServiceEntry对象。这些函数独特合作,通过解决命名空间变动事件以及查问和拜访ServiceEntry,来保护和治理ServiceEntry与命名空间之间的关联关系。 File: istio/pilot/pkg/features/pilot.go在Istio我的项目中,pilot.go文件是Istio Pilot组件的一部分,其作用是为Pilot提供配置和性能。 以下是与给出的变量相干的具体阐明: MaxConcurrentStreams:用于配置Envoy代理的最大并发流量。MaxRecvMsgSize:用于配置Envoy代理接管的最大音讯大小。traceSamplingVar和TraceSampling:用于设置分布式跟踪的采样率。PushThrottle:用于管制推送Envoy配置的速率限度。RequestLimit:用于限度Istio Pilot解决申请的数量。FilterGatewayClusterConfig:用于配置网关集群的过滤器。DebounceAfter和DebounceMax:用于在处理事件之前对其进行提早解决以缩小负载。EnableEDSDebounce:用于启用EDS(Endpoint Discovery Service)的去抖动。SendUnhealthyEndpoints:用于发送不衰弱的终端节点。EnablePersistentSessionFilter:用于启用长久会话过滤器。PersistentSessionLabel和PersistentSessionHeaderLabel:用于在长久会话中增加标签。DrainingLabel:用于在终端节点处于排空状态时进行标记。HTTP10:用于启用对HTTP/1.0版本的反对。EnableMysqlFilter、EnableRedisFilter和EnableMongoFilter:用于启用针对MySQL、Redis和MongoDB的过滤器。UseRemoteAddress:用于在Envoy代理上应用近程地址。SkipValidateTrustDomain:用于跳过验证可信域。ScopeGatewayToNamespace:用于限定网关的范畴。EnableHeadlessService:用于启用无头服务。JwksFetchMode:用于配置JWK(JSON Web Key)的获取模式。EnableEDSForHeadless:用于启用无头服务的EDS。EnableDistributionTracking和DistributionHistoryRetention:用于启用分布式追踪并设置追踪历史的保留工夫。MCSAPIGroup和MCSAPIVersion:用于配置多集群服务。EnableMCSAutoExport、EnableMCSServiceDiscovery、EnableMCSHost和EnableMCSClusterLocal:用于配置多集群服务的主动导出、服务发现和主机以及集群本地配置。EnableAnalysis、AnalysisInterval:用于启用和配置剖析性能。EnableStatus、StatusUpdateInterval、StatusQPS、StatusBurst和StatusMaxWorkers:用于启用和配置状态性能。IstiodServiceCustomHost:用于定义Istiod服务的自定义主机。PilotCertProvider:用于配置Pilot证书提供程序。JwtPolicy:用于配置JWT(JSON Web Token)策略。EnableGatewayAPI、EnableAlphaGatewayAPI、EnableGatewayAPIStatus、EnableGatewayAPIDeploymentController和EnableGatewayAPIGatewayClassController:用于启用和配置Gateway API。ClusterName:用于设置集群的名称。ExternalIstiod:用于配置内部Istiod。EnableCAServer:用于启用CAServer(核心受权服务器)。EnableDebugOnHTTP:用于在HTTP上启用调试。MutexProfileFraction:用于配置互斥量分析的比例。EnableUnsafeAdminEndpoints:用于启用不平安的管理员端点。XDSAuth和EnableXDSIdentityCheck:用于配置XDS(申请配置传输协定)身份验证和身份查看。trustedGatewayCIDR和TrustedGatewayCIDR:用于配置受信赖的网关CIDR范畴。CATrustedNodeAccounts:用于配置受信赖CA的帐户。EnableServiceEntrySelectPods:用于启用ServiceEntry抉择Pods。EnableK8SServiceSelectWorkloadEntries:用于启用Kubernetes服务抉择工作负载入口。InjectionWebhookConfigName和ValidationWebhookConfigName:用于配置注入和验证的Webhook配置。EnableXDSCaching、EnableCDSCaching、EnableRDSCaching、EnableXDSCacheMetrics、XDSCacheMaxSize和XDSCacheIndexClearInterval:用于启用和配置XDS缓存。XdsPushSendTimeout:用于配置XDS推送的发送超时。RemoteClusterTimeout:用于配置近程集群的超时工夫。EnableTelemetryLabel和EndpointTelemetryLabel:用于启用遥测标签和终端节点遥测标签。MetadataExchange:用于配置元数据交换。ALPNFilter:用于配置ALPN(应用层协定协商)过滤器。WorkloadEntryAutoRegistration、WorkloadEntryCleanupGracePeriod、WorkloadEntryHealthChecks和WorkloadEntryCrossCluster:用于配置工作负载入口的主动注册、清理期限、健康检查和跨集群选项。WasmRemoteLoadConversion:用于配置Wasm(WebAssembly模块)的近程加载转换。PilotJwtPubKeyRefreshInterval:用于刷新Pilot JWT公钥的距离。EnableInboundPassthrough:用于启用入站透传。EnableHBONE:用于启用HBONE(解决Body-on-End)。EnableAmbientControllers:用于启用环境控制器。EnableUnsafeAssertions和EnableUnsafeDeltaTest:用于启用不平安的断言和增量测试。DeltaXds:用于启用增量XDS。SharedMeshConfig和MultiRootMesh:用于配置共享网格和多根网格。EnableRouteCollapse:用于启用路由合并。MulticlusterHeadlessEnabled:用于启用多集群无头服务。ResolveHostnameGateways:用于解析主机名网关。MultiNetworkGatewayAPI:用于配置多网络网关API。CertSignerDomain:用于配置证书签名者域。EnableQUICListeners:用于启用QUIC(Quick UDP Internet Connections)监听器。VerifyCertAtClient:用于在客户端验证证书。EnableTLSOnSidecarIngress:用于在Sidecar Ingress中启用TLS。EnableAutoSni:用于启用主动SNI(服务器名称批示)。InsecureKubeConfigOptions:用于配置不平安的Kubeconfig选项。VerifySDSCertificate:用于验证SDS(Secret Discovery Service)证书。EnableHCMInternalNetworks:用于启用HCM(Health Check Manager)的外部网络。CanonicalServiceForMeshExternalServiceEntry:用于网格内部服务入口的标准服务。LocalClusterSecretWatcher:用于本地集群秘钥监督。EnableEnhancedResourceScoping:用于启用加强的资源范畴。EnableLeaderElection:用于启用领导选举。EnableSidecarServiceInboundListenerMerge:用于启用Sidecar服务的入站监听器合并。EnableDualStack:用于启用双栈(IPv4和IPv6)。EnableOptimizedServicePush:用于启用优化的服务推送。InformerWatchNamespace:用于Informer监督的命名空间。KubernetesClientContentType:用于配置Kubernetes客户端的内容类型。EnableNativeSidecars:用于启用本机Sidecar。MetricRotationInterval和MetricGracefulDeletionInterval:用于配置度量规范的旋转和优雅删除的距离。NativeMetadataExchange:用于配置本机元数据交换。OptimizedConfigRebuild:用于优化配置重建。EnableControllerQueueMetrics:用于启用控制器队列度量。ValidateWorkloadEntryIdentity:用于验证工作负载入口的身份。JwksResolverInsecureSkipVerify:用于JWKS解析器的跳过验证。EnableOTELBuiltinResourceLables:用于启用OTEL(OpenTelemetry)内建资源标签。UnsafeFeaturesEnabled函数依据配置文件中的特色启动不平安的性能。依据提供的变量,UnsafeFeaturesEnabled执行特定的性能初始化和配置。 请留神,这是Istio源代码的概述,并不保障在将来的版本中这些变量和函数的性能不会更改。倡议参考官网文档或源代码,以获取最新和具体的信息。 File: istio/pilot/pkg/simulation/traffic.goistio/pilot/pkg/simulation/traffic.go文件的次要作用是模仿流量并验证Istio配置的正确性。该文件中的函数和构造体定义了进行流量模仿和验证相干逻辑的实现。 以下是对每个变量和构造体的具体介绍: 变量: log:用于记录日志的实例。httpProtocols:定义了http协定的常量和函数。ErrNoListener:当无奈找到监听器时,会返回此谬误。ErrNoFilterChain:当无奈找到过滤链时,会返回此谬误。ErrNoRoute:当无奈找到路由时,会返回此谬误。ErrTLSRedirect:当产生TLS重定向谬误时,会返回此谬误。ErrNoVirtualHost:当无奈找到虚拟主机时,会返回此谬误。ErrMultipleFilterChain:当存在多个过滤链时,会返回此谬误。ErrProtocolError:当协定谬误时,会返回此谬误。ErrTLSError:当TLS谬误时,会返回此谬误。ErrMTLSError:当mTLS谬误时,会返回此谬误。CallModeGateway:示意调用模式为网关。CallModeOutbound:示意调用模式为进口。CallModeInbound:示意调用模式为入口。构造体: Protocol:定义了协定的构造体,用于示意一个协定。TLSMode:定义了TLS模式的构造体,用于示意TLS模式。Expect:示意冀望的后果。CallMode:示意调用模式。CustomFilterChainValidation:自定义过滤链验证。Call:定义了调用须要的参数和属性。Result:定义了模仿后果的构造体,包含申请和响应等信息。Simulation:定义了流量模仿的构造体,包含一系列的调用和查看。函数: IsHTTP:判断给定的协定是否为HTTP协定。FillDefaults:将给定的模仿配置参数和默认值进行合并。Matches:查看申请是否与给定的属性匹配。NewSimulationFromConfigGen:依据给定的模仿配置生成一个模仿实例。NewSimulation:依据给定的配置生成一个模仿实例。withT:给函数增加一个T参数,用于模仿测试。RunExpectations:运行模仿实例中的冀望后果。hasFilterOnPort:查看给定的端口是否有过滤器。Run:运行模仿实例。requiresMTLS:查看给定的虚拟主机是否须要进行mTLS验证。matchRoute:查看申请是否与给定的路由匹配。matchVirtualHost:查看申请是否与给定的虚拟主机匹配。matchFilterChain:查看申请是否与给定的过滤链匹配。filter:依据给定的申请和过滤器链对申请进行过滤。protocolToMTLSAlpn:将给定的协定转换为mTLS的ALPN名称。protocolToTLSAlpn:将给定的协定转换为TLS的ALPN名称。protocolToAlpn:将给定的协定转换为ALPN名称。matchListener:查看申请是否与给定的监听器匹配。matchAddress:查看申请是否与给定的地址匹配。上述的变量和函数联合在一起,能够进行流量的模仿和验证,帮忙咱们理解Istio的配置是否依照预期工作。 File: istio/pkg/bootstrap/option/instance.go在istio我的项目中,istio/pkg/bootstrap/option/instance.go文件的作用是定义了用于创立配置实例的模板参数和函数。 ...

September 19, 2023 · 2 min · jiezi

关于后端:HTTPS是怎么工作的

HTTPS是怎么工作的?明天咱们来聊聊 HTTPS 的工作机制。 HTTPS 是超文本传输协定(HTTP)的扩大。HTTPS 应用传输层平安(TLS)传输加密数据。 如果数据在网上被劫持,劫持者失去的只是二进制代码,并不能看到数据。 那么数据如何加密和解密的呢?咱们来看看下图的流程。 第 1 步客户端(浏览器)和服务器先建设 TCP 连贯。 第 2 步客户端向服务器发送 "Client Hello"信息。该信息蕴含一套加密算法和它能反对的最新 TLS 版本。服务器回应一个 "Server Hello",以便浏览器晓得它是否反对这些算法和 TLS 版本。 而后,服务器向客户端发送 SSL 证书。证书蕴含公钥、主机名、有效期等信息。客户端验证证书。 第 3 步验证 SSL 证书后,客户端生成会话密钥 (Session Key),并应用公钥对其进行加密。服务器收到加密的会话密钥后,用私钥解密。这里应用的是非对称加密。 第 4 步既然客户端和服务器都持有雷同的会话密钥,加密数据就会在平安的双向通道中传输。从这时开始,HTTPS应用的是对称加密。 对称加密是指加密和解密应用雷同密钥的加密算法。它要求发送方和接管方在平安通信之前,约定一个密钥。 HTTPS 为什么要在数据传输过程中切换到对称加密?次要有两个起因: 进步安全性: 非对称加密只能单向传输,服务器不能将加密数据回传给客户端,因为任何人都能够应用公钥在客户端解密数据。节俭服务器资源: 非对称加密会减少大量数学计算开销。它不适宜长时间的数据传输。

September 19, 2023 · 1 min · jiezi

关于后端:最强-LeetCode-会员教育版

八月の回顾上月,咱公布了 LeetCode 会员超值购。 专属渠道与官网相比,同价,但天数更长:年度会员加赠 $60$ 天、季度会员加赠 $14$ 天。 同时再叠加三重额定福利: a. 返佣红包: ![[局部] 返佣红包(最多拼接 16 图)](https://files.mdnice.com/user/9208/2e130a6b-11bc-4859-ae68-2c...) b. 得奖率超过 $30$% 实物抽奖: 没有采集友友们的晒图,八月奖品池包含: 书籍、U盘、零食礼包 这里还有一个小花絮 。 因为没啥教训,首次实物抽奖采取了「群红包 - 金额从大到小」的抽奖形式。 果不其然,遇到金额雷同(名次并列)的状况 而后我就突发奇想,让他们俩私发我「剪刀石头布」来定输赢(次要是玩一下 后果 ... ![Round 1:平局 [吃惊]](https://files.mdnice.com/user/9208/61098b1e-0578-46ee-a2c9-4e...) c. 月度流动参加券:有效期为一年,反对转让,反对一次应用多张券,可能在任意工夫点加入流动的参加券 一个粗略的统计:欧气最足的同学,破费 499 买入年度会员取得了价值超过 230 的奖品(66.66 返佣红包 + 79.9 的书籍 + 89.7 的流动参加券);中位数奖品价值也在 205 以上。 说句全网”第二“属于是虚心了 [狗头] 比“超划算”还“划算” ?!近期收到了 LeetCode 小姐姐的告诉,她们最近新出了一个开学特惠流动。 仅限可能通过教育认证的用户,基本上就是面向「学生」与「学校教职工」。 认证教育资格:https://leetcode.cn/premium/edu-auth/ 同样 给到了“官网同价”,再“叠加天数”,再维持“私人专属三重大礼包”。 专属链接(截止 2023.09.26):https://leetcode.cn/student/?userToken=xlawun0c 在通过教育认证后,应用专属链接购买(截止 2023.09.26): 首次:$365$ 购买 $365$ 天会员,额定取得 $30$ 天(2023.09.28 到账)+ 三重大礼包非首次:$365$ 购买 $365$ 天会员,额定取得三重大礼包P.S. 流动完结前(2023.09.26),可屡次购买,天数累加,三重大礼包(返佣+抽奖+体验劵)也是和天数一样有限叠加。 ...

September 19, 2023 · 1 min · jiezi

关于后端:Service-层异常抛到-Controller-层处理还是直接处理

0 前言个别初学者学习编码和[错误处理]时,先晓得[编程语言]有一种处理错误的模式或约定(如Java就抛异样),而后就开始用这些工具。但却漠视这问题实质:处理错误是为了写正确程序。可是 1 啥叫“正确”?由解决的问题决定的。问题不同,解决方案不同。 如一个web接口承受用户申请,参数age,兴许业务要求字段是0~150之间整数。如输出字符串或正数就必定不承受。个别在后端某地做输出合法性检查,不过就抛异样。 但归根到底这问题“正确”解决办法总是要以某种模式提醒用户。而提醒用户是某种前端工作,就要看界面是app,H5+AJAX还是相似于[jsp]的服务器产生界面。不论啥,你要依据需要去”设计一个修复谬误“的流程。如一个常见的流程要后端抛异样,而后一路到某个集中处理错误的代码,将其转换为某个HTTP的谬误(业务错误码)提供给前端,前端再映射做”提醒“。如用户输出非法申请,从逻辑上后端都没法本人修复,这是个“正确”的策略。 2 报500了嘞!如用户上传一个头像,后端将图片发给[云存储],后果云存储报500,咋办?你可能想重试,因为兴许仅是[网络抖动],重试就能失常执行。但若重试屡次有效,若设计了某种热备计划,可能改为发到另一个服务器。“重试”和“应用备份的依赖”都是“立即解决“。 但若重试有效,所有的[备份服务]也有效,兴许就能像下面那样把谬误抛给前端,提醒用户“服务器开小差”。从这计划易看出,你想把谬误抛到哪里是因为那个catch的中央是解决问题最不便的中央。一个问题的解决方案可能要几个不同的错误处理组合起来能力办到。 3 NPE了!你的程序抛个NPE。这个别就是程序员的bug: 要不就是程序员想表白一个货色”没有“,后果在后续解决中忘判断是否为null要不就是在写代码时感觉100%不可能为null的中央呈现了一个null不论哪种,这谬误用户总会看到一个很含混的报错信息,这远远不够。“正确”方法是程序员本人能尽快发现它,并尽快修复。要做到这点,须要[监控零碎]一直爬log,把问题报警进去。而非等用户找客服投诉。 4 OOM了!比方你的[后端程序]忽然OOM挂了。挂的程序没法复原本人。要做到“正确”,须在服务之外的容器思考这问题。 如你的服务跑在[k8s],他们会监控你程序状态,而后重启新的服务实例补救挂掉的服务,还得调整流量,把去往宕机服务的流量切换到新实例。这的复原因为跨零碎所以不能仅用异样实现,但情理一样。 但光靠重启就“正确”了?若服务是齐全无状态,问题不大。但若有状态,局部用户数据可能被执行一半的申请搞乱。因而重启要注意先“复原数据到非法状态”。这又回到你要晓得咋样才是“正确”的做法。只依附简略的语法性能不能无脑解决这事。 5 晋升维度一个工作线程的“内部容器“是管理工作线程的“master”一个网络申请的“内部容器”是一个Web Server一个用户过程的“内部容器”是[操作系统]Erlang把这种supervisor-worker的机制融入到语言的设计Web程序很大水平能把异样抛给顶层,是因为: 申请来自前端,对因为用户申请有误(数据合法性、权限、用户上下文状态)造成的问题,最终根本只能通知用户。因而抛异样到一个集中处理错误的中央,把异样转换为某个业务错误码的办法,正当后端服务个别无状态。这也是软件系统设计的个别准则。无状态才意味着可随时随地安心重启。用户数据不会因为因为下一条而会出问题后端对数据的批改依赖DB的事务。因而一个改一半的、没提交的事务不会造成副作用。但这3条件并非总成立。总能遇到: 一些解决逻辑并非无状态也并非所有的数据批改都能用一个事务爱护尤其要留神对[微服务]的调用,对内存状态的批改是没有事务爱护的,一不留神就会搞乱用户数据。比方上面代码段 6 难以排查的代码段 try { int res1 = doStep1(); this.status1 += res1; int res2 = doStep2(); this.status2 += res2; // 抛个异样 int res3 = doStep3(); this.status3 = status1 + status2 + res3;} catch ( ...) { // ...}先假如status1、status2、status3之间需保护某种不变的束缚(invariant)。而后执行这段代码时,如在doStep3抛异样,上面对status3的赋值就不会执行。这时如不能将status1、status2的批改rollback,就会造成数据违反束缚的问题。 而程序员很难发现这个数据被改坏了。坏数据还可能导致其余依赖这数据的代码逻辑出错(如本来应该给积分的,却没给)。而这种谬误个别很难排查,从大量数据里找到不正确的那一小段何其艰难。 7 更难搞定的代码段// controllervoid controllerMethod(/* 参数 */) { try { return svc.doWorkAndGetResult(/* 参数 */); } catch (Exception e) { return ErrorJsonObject.of(e); }}// svcvoid doWorkAndGetResult(/* some params*/) { int res1 = otherSvc1.doStep1(/* some params */); this.status1 += res1; int res2 = otherSvc2.doStep2(/* some params */); this.status2 += res2; int res3 = otherSvc3.doStep3(/* some params */); this.status3 = status1 + status2 + res3; return SomeResult.of(this.status1, this.status2, this.status3);}难搞在于你写的时候可能认为doStep1~3这种货色即便抛异样也能被Controller里的catch。 ...

September 18, 2023 · 2 min · jiezi

关于后端:面试题精讲为什么G1收集器不需要调优性能也很优秀

G1(Garbage-First)收集器是一种面向服务器端利用的垃圾回收器,它在JDK 7u4版本中首次引入,次要用于代替CMS(Concurrent Mark Sweep)收集器。相比于其余垃圾回收器,G1收集器具备很多长处,使得它在性能和调优方面表现出色。 首先,G1收集器采纳了分代收集的思维,将堆内存划分为多个大小相等的区域(Region),每个区域能够是Eden区、Survivor区或Old区。这种划分形式使得G1收集器可能更加高效地治理内存,缩小了全局垃圾回收的工夫。 其次,G1收集器应用了增量并发标记算法,能够在垃圾回收过程中与应用程序并发执行,缩小了垃圾回收对应用程序的影响。这种并发标记算法能够在多个CPU外围上并行执行,进步了垃圾回收的效率。 另外,G1收集器还引入了一种新的回收策略,即依据垃圾散布状况优先回收垃圾最多的区域(Garbage-First)。这种策略能够最大水平地缩小垃圾回收的工夫,进步了应用程序的响应速度。 此外,G1收集器还具备以下长处: 可预测的进展工夫:G1收集器能够通过设置指标进展工夫来管制垃圾回收的工夫,从而使得应用程序的进展工夫可预测。自适应的调整:G1收集器能够依据应用程序的运行状况主动调整各个区域的大小,以及垃圾回收的策略,从而进步垃圾回收的效率。空间整顿成果好:G1收集器在进行垃圾回收时,会对内存进行整顿,使得内存的碎片化水平较低,从而缩小了内存的节约。因为G1收集器具备以上长处,因而在大多数状况下,它不须要进行额定的调优就可能达到很好的性能。然而在某些非凡状况下,如堆内存较大、应用程序的垃圾产生较多等,可能须要对G1收集器进行一些参数调整,以进一步优化性能。 须要留神的是,G1收集器并不是实用于所有场景的最佳抉择。在某些特定的利用场景下,如对低提早有极高要求的实时零碎,可能须要思考其余垃圾回收器的抉择。因而,在抉择垃圾回收器时,须要依据具体的利用场景和需要进行评估和抉择。<!-- md tj.md --> 本文由mdnice多平台公布

September 18, 2023 · 1 min · jiezi

关于后端:日记文章更新计划

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top 文章最初有具体的更新打算 {% timeline 2023,pink %}<!-- timeline 08-30 -->第一版公布<!-- endtimeline --><!-- timeline 08-30 -->【完结~开发标准系列】<!-- endtimeline --><!-- timeline 09-04 --> Linux系列从新定位,不再只是简略的说常用命令周二rocketmq更换为nginx系列微服务内容变更,当初次要说架构不便的内容周四变更为设计模式系列<!-- endtimeline --> <!-- timeline 9月18日 -->更新Kafka系列打算,排版重构<!-- endtimeline -->{% endtimeline %} 周更【周一】Kafka系列【周二】Nginx系列【周三】深刻解读Redis系列【周四】设计模式系列【周五】深刻了解MySQL系列【周六】微服务系列【周日】Linux系列日更【面试题精讲】每天一道面试题 【日记】这个尽量日更 不定时更新【配置文件系列:次要讲讲各种利用的配置文件配置项】 待完结【ES系列】 已完结【开发标准系列】【Hibernate Validator】 Kafka系列文章更新打算名称状态预计更新日期文章地址(一)Kafka入门已实现-https://blog.zysicyj.top/kafka1(二)Kafka的根本应用已实现9月18日https://blog.zysicyj.top/kafka2(三)生产者音讯分区机制原理未更新9月25日https://blog.zysicyj.top/kafka3(四)生产者压缩算法未更新10月2日https://blog.zysicyj.top/kafka4(五)如何实现无音讯失落未更新10月9日https://blog.zysicyj.top/kafka5(六)客户端暗藏性能未更新10月16日https://blog.zysicyj.top/kafka6(七)Java生产者是如何治理TCP连贯的未更新10月23日https://blog.zysicyj.top/kafka7(八)幂等生产者和事务生产者是一回事吗未更新10月30日https://blog.zysicyj.top/kafka8(九)消费者组到底是什么未更新11月6日https://blog.zysicyj.top/kafka9(十)揭开神秘的“位移主题”面纱未更新11月13日https://blog.zysicyj.top/kafka10(十一)消费者组重均衡能防止吗未更新11月20日https://blog.zysicyj.top/kafka11(十二)Kafka中位移提交那些事儿未更新11月27日https://blog.zysicyj.top/kafka12(十三) CommitFailedException异样怎么解决未更新12月4日https://blog.zysicyj.top/kafka13(十四) 多线程开发消费者实例未更新12月11日https://blog.zysicyj.top/kafka14(十五) Java 消费者是如何治理TCP连贯的未更新12月18日https://blog.zysicyj.top/kafka15(十六) 消费者组生产进度监控都怎么实现未更新12月25日https://blog.zysicyj.top/kafka16(十七) Kafka正本机制详解未更新1月1日https://blog.zysicyj.top/kafka17(十八) 申请是怎么被解决的未更新1月8日https://blog.zysicyj.top/kafka18(十九) 消费者组重均衡全流程解析未更新1月15日https://blog.zysicyj.top/kafka19(二十) 你肯定不能错过的Kafka控制器未更新1月22日https://blog.zysicyj.top/kafka20(二十一) 对于高水位和Leader Epoch的探讨未更新1月29日https://blog.zysicyj.top/kafka21(二十二) 主题治理知多少未更新2月5日https://blog.zysicyj.top/kafka22(二十三) Kafka动静配置理解下未更新2月12日https://blog.zysicyj.top/kafka23(二十四) 怎么重设消费者组位移未更新2月19日https://blog.zysicyj.top/kafka24(二十五) 常见工具脚本大汇总未更新2月26日https://blog.zysicyj.top/kafka25(二十六) KafkaAdminClient:Kafka的运维利器未更新3月4日https://blog.zysicyj.top/kafka26(二十七) Kafka认证机制用哪家未更新3月11日https://blog.zysicyj.top/kafka27(二十八) 云环境下的受权该怎么做未更新3月18日https://blog.zysicyj.top/kafka28(二十九) 跨集群备份解决方案MirrorMaker未更新3月25日https://blog.zysicyj.top/kafka29(三十) 你应该怎么监控Kafka未更新4月1日https://blog.zysicyj.top/kafka30(三十一) 支流的Kafka监控框架未更新4月8日https://blog.zysicyj.top/kafka31(三十二) 调优Kafka,你做到了吗未更新4月15日https://blog.zysicyj.top/kafka32(三十三) 从0搭建基于Kafka的企业级实时日志流解决平台未更新4月22日https://blog.zysicyj.top/kafka33(三十四) Kafka Streams与其余流解决平台的差别在哪里未更新4月29日https://blog.zysicyj.top/kafka34(三十五) Kafka Streams DSL开发实例未更新5月6日https://blog.zysicyj.top/kafka35(三十六) Kafka Streams在金融畛域的利用未更新5月13日https://blog.zysicyj.top/kafka36本文由mdnice多平台公布

September 18, 2023 · 1 min · jiezi

关于后端:Kafka系列二Kafka的基本使用

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 文章更新打算 系列文章地址 Kafka 线上集群部署计划怎么做操作系统先说论断,Kafka 部署在 Linux 上要比 Windows 和 Mac 上性能高的多,次要是以下几个起因: 操作系统优化:Linux 操作系统在网络和文件系统性能方面通常比 Windows 和 Mac 更优良。Linux 内核对网络和磁盘 I/O 的解决更高效,可能更好地利用硬件资源,从而进步 Kafka 的性能。文件系统抉择:Linux 上罕用的文件系统如 ext4、XFS 等对大规模数据处理和高并发读写有更好的反对。而 Windows 上的 NTFS 文件系统在解决大量小文件和高并发读写时性能绝对较差。网络栈性能:Linux 的网络栈在解决高并发连贯和大规模数据传输时体现更杰出。Linux 内核对网络协议栈的优化更多,可能更好地解决网络数据包,进步 Kafka 的吞吐量和响应速度。硬件资源管理:Linux 操作系统对硬件资源的治理更加灵便和高效。Linux 上的过程调度、内存治理等机制可能更好地利用多核处理器和大内存,进步 Kafka 的并发解决能力。社区反对度I/O 模型支流的 I/O 模型通常有以下五种类型: 阻塞 I/O(Blocking I/O):在进行 I/O 操作时,应用程序会被阻塞,直到数据筹备好或者操作实现。这种模型是最简略的,然而会导致应用程序的性能降落,因为在期待 I/O 实现时,CPU 无奈解决其余工作。非阻塞 I/O(Non-blocking I/O):在进行 I/O 操作时,应用程序能够继续执行其余工作,而不会被阻塞。然而,如果数据还没有筹备好或者操作还没有实现,应用程序须要一直地轮询来查看状态,这会导致 CPU 的资源节约。I/O 多路复用(I/O Multiplexing):通过应用 select、poll 或者 epoll 等零碎调用,应用程序能够同时监督多个文件描述符的状态,当任何一个文件描述符筹备好进行 I/O 操作时,应用程序就能够进行相应的读写操作。这种模型能够无效地解决多个连贯,进步零碎的并发性能。信号驱动 I/O(Signal-driven I/O):应用程序通过注册信号处理函数,在数据筹备好时接管到一个信号,而后进行相应的读写操作。这种模型相比于非阻塞 I/O,缩小了轮询的开销,然而依然须要应用程序一直地检查数据是否筹备好。异步 I/O(Asynchronous I/O):应用程序发动一个 I/O 操作后,能够继续执行其余工作,当数据筹备好或者操作实现时,操作系统会告诉应用程序进行相应的读写操作。这种模型是最高效的,因为应用程序不须要进行轮询或者阻塞期待,能够充分利用 CPU 的资源。你不用具体理解每一种模型的实现细节,通常状况下咱们认为后一种模型会比前一种模型要高级,比方 epoll 就比 select要好,理解到这一水平应该足以应酬咱们上面的内容了。 ...

September 18, 2023 · 5 min · jiezi

关于后端:Go-expvar包

介绍与应用 expvar 是 exposed variable的简写 expvar包是 Golang 官网为裸露Go利用外部指标数据所提供的规范对外接口,能够辅助获取和调试全局变量。 其通过init函数将内置的expvarHandler(一个规范http HandlerFunc)注册到http包ListenAndServe创立的默认Server上 如以下案例: package mainimport ( "encoding/json" "expvar" "fmt" "github.com/gin-gonic/gin" "net/http" "runtime" "time")func main() { router := gin.Default() //初始化一个gin实例 router.GET("/debug/vars", GetCurrentRunningStats) //接口路由,如果url不是/debug/vars,则用metricBeat去获取会出问题 s := &http.Server{ Addr: ":" + "6666", Handler: router, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, MaxHeaderBytes: 1 << 20, } s.ListenAndServe() //开始监听}var CuMemoryPtr *map[string]stringvar BTCMemoryPtr *map[string]interface{}// 开始工夫var start = time.Now()// calculateUptime 计算运行工夫func calculateUptime() interface{} { return time.Since(start).String()}// currentGoVersion 以后 Golang 版本func currentGoVersion() interface{} { return runtime.Version()}// getNumCPUs 获取 CPU 外围数量func getNumCPUs() interface{} { return runtime.NumCPU()}// getGoOS 以后零碎类型func getGoOS() interface{} { return runtime.GOOS}// getNumGoroutins 以后 goroutine 数量func getNumGoroutins() interface{} { return runtime.NumGoroutine()}// getNumCgoCall CGo 调用次数func getNumCgoCall() interface{} { return runtime.NumCgoCall()}// 业务特定的内存数据func getCuMemoryMap() interface{} { if CuMemoryPtr == nil { return 0 } else { return len(*CuMemoryPtr) }}// 业务特定的内存数据func getBTCMemoryMap() interface{} { if BTCMemoryPtr == nil { return 0 } else { return len(*BTCMemoryPtr) }}var lastPause uint32// getLastGCPauseTime 获取上次 GC 的暂停工夫func getLastGCPauseTime() interface{} { var gcPause uint64 ms := new(runtime.MemStats) statString := expvar.Get("memstats").String() if statString != "" { json.Unmarshal([]byte(statString), ms) if lastPause == 0 || lastPause != ms.NumGC { gcPause = ms.PauseNs[(ms.NumGC+255)%256] lastPause = ms.NumGC } } return gcPause}// GetCurrentRunningStats 返回以后运行信息func GetCurrentRunningStats(c *gin.Context) { c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8") first := true report := func(key string, value interface{}) { if !first { fmt.Fprintf(c.Writer, ",\n") } first = false if str, ok := value.(string); ok { fmt.Fprintf(c.Writer, "%q: %q", key, str) } else { fmt.Fprintf(c.Writer, "%q: %v", key, value) } } fmt.Fprintf(c.Writer, "{\n") expvar.Do(func(kv expvar.KeyValue) { report(kv.Key, kv.Value) }) fmt.Fprintf(c.Writer, "\n}\n") c.String(http.StatusOK, "")}func init() { //这些都是自定义变量,公布到expvar中,每次申请接口,expvar会主动去获取这些变量,并返回 expvar.Publish("运行工夫", expvar.Func(calculateUptime)) expvar.Publish("version", expvar.Func(currentGoVersion)) expvar.Publish("cores", expvar.Func(getNumCPUs)) expvar.Publish("os", expvar.Func(getGoOS)) expvar.Publish("cgo", expvar.Func(getNumCgoCall)) expvar.Publish("goroutine", expvar.Func(getNumGoroutins)) expvar.Publish("gcpause", expvar.Func(getLastGCPauseTime)) expvar.Publish("CuMemory", expvar.Func(getCuMemoryMap)) expvar.Publish("BTCMemory", expvar.Func(getBTCMemoryMap))}运行程序,并申请127.0.0.1:6666/debug/vars ...

September 18, 2023 · 15 min · jiezi

关于后端:听GPT-讲Istio源代码pilot4

File: istio/pilot/pkg/networking/core/v1alpha3/loadbalancer/loadbalancer.goistio/pilot/pkg/networking/core/v1alpha3/loadbalancer/loadbalancer.go是Istio我的项目中负责负载平衡的文件。它定义了一些构造体和函数,用于解决负载平衡策略。 该文件中的次要构造体是WrappedLocalityLbEndpoints。WrappedLocalityLbEndpoints是用于将LocalityLbEndpoints构造体包装在一起的数据结构。它蕴含了包装后的LocalityLbEndpoints和其余一些辅助信息,例如权重、优先级等。 以下是文件中重要函数的作用: GetLocalityLbSetting:依据传入的负载平衡设置和服务名称,获取本地负载平衡的配置。返回一个包装了LocalityLbEndpoints的WrappedLocalityLbEndpoints构造体。ApplyLocalityLBSetting:将LocalityLbSetting利用到传入的网络负载均衡器实例。这个函数会依据设置配置每个权重、故障转移等。applyLocalityWeight:依据LocalityLbEndpoints的权重设置,将权重利用到传入的网络负载均衡器实例。依据权重,决定转发申请到哪个终端节点。applyLocalityFailover:在产生故障时,依据故障转移策略,将申请转发到其余可用的终端节点。applyPriorityFailover:在产生故障时,在不同优先级的终端节点之间进行故障转移。priorityLabelOverrides:返回一个依据优先级标签的权重映射。用于依据优先级调整终端节点的服务。applyPriorityFailoverPerLocality:为每个本地性调整优先级故障转移。以上这些函数一起工作,通过配置权重、故障转移策略和优先级,实现了Istio的负载平衡性能。通过这些函数,能够依据传入的设置,将传入的申请散发到不同的终端节点,以实现服务的负载平衡和故障复原。 File: istio/pilot/pkg/networking/core/v1alpha3/cluster_tls.go在Istio我的项目中,pkg/networking/core/v1alpha3/cluster_tls.go文件负责定义与集群间TLS通信相干的性能。它定义了用于构建TLS配置的类型和办法,以及管制TLS通信的函数。 当初来具体介绍每个变量和函数的作用: istioMtlsTransportSocketMatch:用于匹配Istio Mutual TLS传输套接字规定的变量。internalUpstreamSocket:用于示意用于外部上游通信的传输套接字。hboneTransportSocket:用于示意HBone传输套接字。hboneOrPlaintextSocket:用于示意同时反对HBone和Plaintext传输套接字。接下来是函数的作用: applyUpstreamTLSSettings:将上游TLS设置利用于上游集群。buildUpstreamClusterTLSContext:构建上游集群的TLS上下文。applyTLSDefaults:利用TLS默认设置。setAutoSniAndAutoSanValidation:设置主动SNI和主动SAN验证。applyHBONETransportSocketMatches:利用HBone传输套接字匹配规定。defaultUpstreamCommonTLSContext:构建默认的上游惯例TLS上下文。defaultTransportSocketMatch:返回默认的传输套接字匹配规定。buildUpstreamTLSSettings:构建上游TLS设置。hasMetadataCerts:查看是否存在元数据证书。buildMutualTLS:构建互联网TLS配置。buildIstioMutualTLS:构建Istio Mutual TLS配置。这些变量和函数是Istio中构建和利用TLS配置的要害组件,通过它们能够确保集群间的通信是平安的,并反对诸如主动验证和传输套接字匹配等性能。 File: istio/pilot/pkg/networking/core/v1alpha3/tracing.go在istio我的项目中,istio/pilot/pkg/networking/core/v1alpha3/tracing.go文件是用于配置与追踪相干的性能。该文件中定义了一些变量和函数来解决追踪配置。 clusterLookupFn是一个函数变量,用于查找特定集群的办法。allContexts是一个函数变量,用于获取所有上下文的办法。optionalPolicyTags是一个字符串切片,存储可选的策略标签。typedConfigGenFn构造体是一个函数类型,用于依据提供的配置生成配置的办法。 configureTracing函数用于依据提供的参数配置追踪性能。configureTracingFromTelemetry函数从遥测配置中获取追踪配置来配置追踪性能。configureFromProviderConfig函数从提供者配置中获取追踪配置来配置追踪性能。zipkinConfig、datadogConfig、otelConfig、opencensusConfig、stackdriverConfig、skywalkingConfig、otelLightStepConfig函数别离用于构建不同追踪提供者的配置。buildHCMTracing函数用于构建HTTP连贯管理器的追踪配置。convert函数用于将字符串切片转换为标签切片。dryRunPolicyTraceTag函数用于从申请的标头中获取追踪策略标签。buildServiceTags函数用于依据服务配置构建追踪标签。configureSampling函数用于配置采样率。proxyConfigSamplingValue函数用于从代理配置中获取采样率值。configureCustomTags函数用于配置自定义追踪标签。buildCustomTagsFromProvider函数用于从提供者配置构建自定义追踪标签。buildCustomTagsFromProxyConfig函数用于从代理配置构建自定义追踪标签。 总而言之,tracing.go文件中的变量和函数用于配置和解决追踪的性能,包含不同追踪提供者的配置、采样率、自定义标签等。 File: istio/pilot/pkg/networking/core/v1alpha3/cluster_traffic_policy.go在Istio我的项目中,istio/pilot/pkg/networking/core/v1alpha3/cluster_traffic_policy.go文件的作用是定义和实现对集群流量策略的操作和解决。 具体来说,该文件中的这些函数别离有以下作用: applyTrafficPolicy: 该函数用于利用流量策略,依据传入的策略配置对集群中的流量进行设置和调整。selectTrafficPolicyComponents: 该函数用于抉择实用于流量策略的集群组件,依据传入的流量策略配置选取实用的组件集群。applyConnectionPool: 该函数用于利用连接池配置,依据传入的连接池配置对集群中的连接池进行设置。applyH2Upgrade: 该函数用于利用H2降级配置,依据传入的降级配置对集群中的HTTP/1.x连贯进行降级为HTTP/2。shouldH2Upgrade: 该函数用于判断是否须要进行H2降级,依据传入的降级配置和连贯信息判断是否满足降级条件。applyDefaultConnectionPool: 该函数用于利用默认连接池配置,依据传入的默认连接池配置对集群中的连接池进行设置。applyLoadBalancer: 该函数用于利用负载均衡器配置,依据传入的负载均衡器配置对集群中的负载平衡进行设置。applyLocalityLBSetting: 该函数用于利用本地性负载平衡配置,依据传入的本地性负载平衡配置对集群中的负载平衡进行设置。applySimpleDefaultLoadBalancer: 该函数用于利用简略默认负载平衡配置,依据传入的简略默认负载平衡配置对集群中的负载平衡进行设置。defaultLBAlgorithm: 该函数用于获取默认的负载平衡算法。applyRoundRobinLoadBalancer: 该函数用于利用RoundRobin负载平衡配置,依据传入的负载平衡配置对集群中的负载均衡器进行设置为RoundRobin算法。applyLeastRequestLoadBalancer: 该函数用于利用LeastRequest负载平衡配置,依据传入的负载平衡配置对集群中的负载均衡器进行设置为LeastRequest算法。setSlowStartConfig: 该函数用于设置慢启动配置,依据传入的慢启动配置对集群中的负载均衡器进行设置。getDefaultCircuitBreakerThresholds: 该函数用于获取默认的熔断器阈值。applyOutlierDetection: 该函数用于利用异样检测配置,依据传入的异样检测配置对集群中的异样检测器进行设置。ApplyRingHashLoadBalancer: 该函数用于利用环形哈希负载平衡配置,依据传入的负载平衡配置对集群中的负载均衡器进行设置为环形哈希算法。MergeTrafficPolicy: 该函数用于合并流量策略,依据传入的流量策略配置将多个策略进行合并,以失去最终的策略配置。File: istio/pilot/pkg/networking/core/v1alpha3/name_table.go在Istio我的项目中,istio/pilot/pkg/networking/core/v1alpha3/name_table.go文件的作用是保护和治理代理服务的名称表。名称表是一个内存中的数据结构,用于存储服务名称和它们对应的网络地址。该文件中的函数次要用于构建和保护这个名称表。 BuildNameTable函数是此文件中的一个次要函数,它有以下几个作用: 构建名称表:BuildNameTable函数会遍历传入的所有服务配置,依据服务名称和网络地址构建一个名称表。解决和解析端口和协定:对于每个服务配置,BuildNameTable函数会遍历其中的每个端口和协定,将它们与服务名称和网络地址关联起来。解决网关配置:如果服务配置中蕴含网关配置,BuildNameTable函数还会将网关配置与服务名称、网络地址和端口关联起来。解决集群服务配置:如果服务配置中蕴含集群服务配置,BuildNameTable函数会将集群服务配置中的每个服务与主服务关联起来。此外,还有其余一些辅助函数用于帮忙构建和保护名称表,例如buildHTTPRouteTable、buildRouteTable等。它们的作用是解析和解决路由配置,依据路由规定构建名称表。 总而言之,name_table.go文件中的函数次要用于构建和保护代理服务的名称表,以便在运行时依据服务名称和网络地址查找和路由申请。 File: istio/pilot/pkg/networking/core/v1alpha3/networkfilter.go在Istio我的项目中,networkfilter.go文件位于istio/pilot/pkg/networking/core/v1alpha3目录下,它的作用是定义和构建Envoy的网络过滤器。 Envoy应用网络过滤器来解决申请和响应流量。网络过滤器能够通过插件的形式扩大Envoy的性能,例如实现负载平衡、故障注入、网络策略等。 networkfilter.go文件中的redisOpTimeout变量用于设置Redis操作的超时工夫。它代表Redis操作的最大容许工夫,当超过该工夫时操作将被中断。 对于其余函数和变量的作用,以下是它们的具体介绍: buildMetadataExchangeNetworkFilters: 构建用于元数据交换的网络过滤器。用于解决与sidecar代理和Istio Mixer之间的元数据交换,以便实现服务发现和流量管制。buildMetadataExchangeNetworkFiltersForTCPIstioMTLSGateway: 构建用于TCP流量和Istio MTLS网关之间的元数据交换的网络过滤器。buildMetricsNetworkFilters: 构建用于指标收集的网络过滤器。用于收集流量和性能指标,例如申请耗时、吞吐量等。setAccessLogAndBuildTCPFilter: 设置拜访日志并构建TCP过滤器。用于记录申请和响应的详细信息,以便进行日志剖析和故障排查。buildOutboundNetworkFiltersWithSingleDestination: 构建用于繁多指标的出站网络过滤器。用于解决与一致性哈希、故障注入、重试等相干的申请流量。buildOutboundNetworkFiltersWithWeightedClusters: 构建用于多权重指标集群的出站网络过滤器。用于依据权重路由申请流量到不同的指标集群。maybeSetHashPolicy: 配置哈希策略。用于将申请流量依照哈希算法路由到特定的指标实例,以实现会话粘性或具备雷同关联数据的申请路由到雷同的指标。buildNetworkFiltersStack: 构建网络过滤器栈。依据配置和需要,将不同类型的网络过滤器依照肯定的程序组合起来。buildOutboundNetworkFilters: 构建出站网络过滤器。依据传入的服务配置和代理配置,构建实用于出站申请的网络过滤器栈。buildMongoFilter: 构建用于MongoDB的网络过滤器。用于解决针对MongoDB服务的申请流量。buildRedisFilter: 构建用于Redis的网络过滤器。用于解决针对Redis服务的申请流量。buildMySQLFilter: 构建用于MySQL的网络过滤器。用于解决针对MySQL服务的申请流量。这些函数的作用是依据配置和需要,构建实用于不同协定和服务的网络过滤器栈,以实现流量路由、负载平衡、故障注入、访问控制等性能。 File: istio/pilot/pkg/networking/core/v1alpha3/listener_address.go在Istio我的项目中,istio/pilot/pkg/networking/core/v1alpha3/listener_address.go文件的作用是定义了ListenerAddress构造体及相干的办法,用于解决监听地址相干的逻辑。 该文件中的三个变量wildCards、localHosts和passthroughBindIPs别离用于存储通配符地址、本地地址和透传绑定IP地址的汇合。这些变量用于指定哪些地址能够被监听器应用。 ...

September 18, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pilot3

File: istio/pilot/pkg/security/authz/model/generator.go在Istio我的项目中,generator.go文件实现了Istio受权模型的生成器。该文件定义了一系列构造体和函数,用于生成受权策略、主体和权限。 上面是对每个构造体的具体介绍: generator构造体是受权模型的生成器,蕴含用于生成受权策略的办法。destIPGenerator构造体用于生成指标IP地址的受权策略。destPortGenerator构造体用于生成指标端口的受权策略。connSNIGenerator构造体用于生成连贯SNI(Server Name Indication)的受权策略。envoyFilterGenerator构造体用于生成Envoy过滤器的受权策略。srcIPGenerator构造体用于生成源IP地址的受权策略。remoteIPGenerator构造体用于生成近程IP地址的受权策略。srcNamespaceGenerator构造体用于生成源命名空间的受权策略。srcPrincipalGenerator构造体用于生成源主体的受权策略。requestPrincipalGenerator构造体用于生成申请主体的受权策略。requestAudiencesGenerator构造体用于生成申请受众的受权策略。requestPresenterGenerator构造体用于生成申请提交者的受权策略。requestHeaderGenerator构造体用于生成申请头的受权策略。requestClaimGenerator构造体用于生成申请申明的受权策略。hostGenerator构造体用于生成主机的受权策略。pathGenerator构造体用于生成门路的受权策略。methodGenerator构造体用于生成申请办法的受权策略。permission函数用于生成拜访权限对象,它接管主体和权限字符串作为参数,并返回一个带有主体和权限的Permission对象。 principal函数用于生成主体对象,它接管主体字符串作为参数,并返回一个蕴含主体的Principal对象。 这些构造体和函数的作用是为了在Istio中定义和生成受权策略。它们通过查看申请的各个属性(如源IP地址、申请头、申明等)来决定是否授予拜访权限。这些生成器提供了丰盛的受权策略选项,能够通过组合它们来创立简单的访问控制规定。 File: istio/pilot/pkg/security/authz/model/permission.go在Istio我的项目中,permission.go文件位于istio/pilot/pkg/security/authz/model目录下,它定义了一些权限查看相干的模型和函数。次要作用是帮忙Istio进行访问控制和权限认证。 permissionAny函数示意任何申请都授予拜访权限,它没有任何参数。 permissionAnd函数接管一个权限列表,并且只有当所有权限均容许拜访时,才会授予权限。它的参数是一个权限切片。 permissionOr函数接管一个权限列表,只有有一个权限容许拜访,就会授予权限。同样,它的参数是一个权限切片。 permissionNot函数接管一个权限作为参数,并返回一个不容许该权限的权限。 permissionDestinationIP函数返回一个基于指标IP地址的权限,用于查看申请是否容许拜访特定的IP地址。 permissionDestinationPort函数返回一个基于指标端口的权限,用于查看申请是否容许拜访特定的端口。 permissionRequestedServerName函数返回一个基于申请的服务器名称的权限,用于查看申请是否容许拜访特定的服务器。 permissionMetadata函数返回一个基于申请元数据的权限,可用于管制申请头、申请办法、申请体等。 permissionHeader函数返回一个基于申请头的权限,用于查看申请是否蕴含特定的申请头信息。 permissionPath函数返回一个基于申请门路的权限,用于查看申请是否拜访了特定的门路。 以上列举的函数是为了帮忙Istio进行灵便的访问控制和权限认证而设计的。开发者能够应用这些函数来定义本人的拜访策略,并依据须要组合这些权限来实现准确的权限管制。 File: istio/pilot/pkg/security/authz/builder/extauthz.go在Istio我的项目中,istio/pilot/pkg/security/authz/builder/extauthz.go文件的作用是构建External Authorization(内部受权)的配置。 rbacPolicyMatchAll变量示意在构建受权规定时,所有的RBAC策略都要匹配能力通过受权;rbacDefaultDenyAll变量示意如果没有匹配的RBAC策略,则默认回绝受权;supportedStatus变量定义了反对的HTTP状态码。 builtExtAuthz构造体用于保留构建的External Authorization配置。它蕴含了URL、RequestHeadersToAdd、RequestHeadersToRemove、SupportedAuthorization格局等信息。 processExtensionProvider函数是扩大提供者的处理函数,用于将扩大提供者的配置转换为External Authorization配置。 notAllTheSame函数用于查看是否所有的Extension Provider具备雷同的扩大配置。 getExtAuthz函数用于获取应用的扩大配置。 buildExtAuthzHTTP函数用于构建HTTP的External Authorization配置。 buildExtAuthzGRPC函数用于构建gRPC的External Authorization配置。 parsePort函数用于解析端口号。 parseStatusOnError函数用于解析谬误时的状态码。 generateHTTPConfig函数用于生成HTTP的配置。 generateGRPCConfig函数用于生成gRPC的配置。 generateHeaders函数用于生成申请头。 generateFilterMatcher函数用于生成过滤器匹配器。 timeoutOrDefault函数用于获取超时工夫配置。 withBodyRequest函数用于查看是否蕴含申请体。 File: istio/pilot/pkg/security/authz/builder/builder.go在Istio我的项目中,istio/pilot/pkg/security/authz/builder/builder.go文件的作用是构建和治理Istio的受权策略。该文件定义了一组API来帮忙开发人员生成和配置与受权相干的配置项。 在该文件中,rbacPolicyMatchNever变量是一个仅蕴含字符串"match-never"的常量,它用于定义RBAC策略中的一个非凡值,示意永远不匹配。 Option构造体是用于配置受权策略的选项,它蕴含一些字段,例如是否启用RBAC、是否启用委派等。 Builder构造体是用于构建受权规定的次要构造。它有一个字段用于配置选项,还有其余公有字段用于存储配置两头后果,如构建的HTTP规定和TCP规定等。 builtConfigs构造体保留了曾经构建的受权策略的配置。它有两个字段,一个用于HTTP规定,一个用于TCP规定。 New函数是用于创立一个新的Builder实例。 BuildHTTP函数是用于依据给定的配置生成HTTP受权规定。 BuildTCP函数是用于依据给定的配置生成TCP受权规定。 isDryRun函数用于判断以后是否为烦扰模式(dry run),烦扰模式下策略批改不会被利用。 shadowRuleStatPrefix函数用于返回一个带有暗影规定统计前缀的字符串。 build函数用于构建受权规定,并将后果保留到builtConfigs中。 buildHTTP函数用于构建HTTP受权规定,并将后果保留到builtConfigs中。 buildTCP函数用于构建TCP受权规定,并将后果保留到builtConfigs中。 policyName函数用于生成一个惟一的策略名称。 这些函数在builder.go文件中的实现,通过组合不同的配置选项和参数,来生成和治理与受权策略相干的配置,以提供受权性能。 File: istio/pilot/pkg/security/authz/builder/logger.go在Istio我的项目中,logger.go文件的作用是构建受权日志,并提供将日志输入到不同指标的性能。 authzLog是一个提供日志记录的全局变量,用于记录受权相干的日志信息。它蕴含了三个字段: debug:一个布尔值,示意是否启用调试日志级别。out:一个io.Writer接口,示意日志输入指标。errOut:一个io.Writer接口,示意谬误日志输入指标。AuthzLogger构造体是受权日志记录器,提供了四个办法: AppendDebugf(format string, args ...interface{}):将格式化的调试信息增加到日志。AppendError(err error):将错误信息增加到日志。Report() string:收集并以字符串模式返回以后日志的内容。SetOutput(output io.Writer):设置日志输入指标。AppendDebugf办法用于将格式化的调试信息追加到日志中,以不便调试和排查问题。 ...

September 18, 2023 · 2 min · jiezi

关于后端:听GPT-讲Istio源代码pilot2

File: istio/pilot/pkg/keycertbundle/watcher.go在Istio我的项目中,watcher.go文件位于istio/pilot/pkg/keycertbundle目录下,它的次要作用是治理密钥和证书的观察者(watcher)。 KeyCertBundle构造体用于保留密钥和证书的信息。它蕴含三个字段:rootCert,certChain和privateKey,别离示意根证书、证书链和私钥。 Watcher构造体用于跟踪和告诉KeyCertBundle的变动。它有两个次要字段:bun和ch。bun是以后的KeyCertBundle,ch是一个通道(channel),用于接管来自观察者的告诉。 以下是watcher.go中一些要害函数的作用: NewWatcher: 创立一个新的Watcher对象,并初始化KeyCertBundle。AddWatcher: 增加一个观察者到观察者列表中,以便在KeyCertBundle发生变化时进行告诉。RemoveWatcher: 从观察者列表中移除指定的观察者。SetAndNotify: 设置新的KeyCertBundle,并告诉所有观察者无关变动的信息。SetFromFilesAndNotify: 从文件设置新的KeyCertBundle,并告诉所有观察者无关变动的信息。GetCABundle: 获取以后KeyCertBundle中的根证书。GetKeyCertBundle: 获取以后的KeyCertBundle。Watcher次要用于在密钥和证书更新时告诉相干的观察者。当密钥和证书发生变化时,能够通过AddWatcher增加观察者,并应用SetAndNotify或SetFromFilesAndNotify告诉观察者更新密钥和证书的信息。 这种观察者模式的实现形式,使得在Istio中能够动静地更新和治理密钥和证书,而无需重启或从新加载整个零碎。 File: istio/pilot/pkg/bootstrap/config_compare.go在Istio我的项目中,istio/pilot/pkg/bootstrap/config_compare.go文件的作用是实现Istio的配置比拟。 该文件中蕴含了用于比拟两个Istio配置的函数和数据结构,次要用于检测配置的变动并决定是否须要推送(push)这些变动。 具体而言,该文件中的函数通过比拟旧配置和新配置来确定配置是否产生了变动。以下是文件中的几个重要函数的作用: needsPushConfigMap(): 该函数用于比拟两个ConfigMap对象,判断它们之间的差别是否须要推送。它会比拟ConfigMap的版本号、标签、数据内容等,并返回一个布尔值表明是否须要推送变动。needsPushSecret(): 相似于needsPushConfigMap()函数,needsPushSecret()用于比拟两个Secret对象,判断它们之间的差别是否须要推送。needsPushGateways(): 该函数用于比拟两个Gateway对象的配置,判断它们之间的差别是否须要推送。它会比拟Gateway的监听地址、服务端口等,并返回一个布尔值表明是否须要推送变动。needsPushRoutes(): 相似于needsPushGateways()函数,needsPushRoutes()用于比拟两个RouteRule对象的配置,判断它们之间的差别是否须要推送。这些函数都是通过比拟配置对象的属性来确定是否须要推送配置的变动。如果变动被检测到,函数将返回true,示意须要推送;否则,返回false,示意不须要推送。 这些函数的作用是确保Istio的配置在发生变化时可能及时推送更新,以放弃零碎的一致性和正确性。 File: istio/pilot/pkg/bootstrap/webhook.go在istio我的项目中,istio/pilot/pkg/bootstrap/webhook.go文件的作用是为Pilot组件提供一个基于Webhook的服务器。 httpServerErrorLogWriter是一个构造体,用于记录HTTP服务器谬误日志。它实现了http.Handler接口,当HTTP服务器呈现谬误时,会将错误信息写入到logWriter。 Write函数是httpServerErrorLogWriter构造体的办法,用于将HTTP服务器的错误信息写入到logWriter中。 initSecureWebhookServer函数的作用是初始化一个带有平安认证的Webhook服务器。它接管一个caBundle参数,用于验证客户端的证书链。此函数将创立和配置一个HTTP服务器,并将其绑定到指定的地址和端口,而后启动该服务器。 具体实现中,该函数会加载TLS证书和私钥,应用caBundle来配置HTTP服务器的TLS配置,并将HTTP申请路由到相应的处理器。 总结:webhook.go文件实现了Pilot的Webhook服务器性能,其中httpServerErrorLogWriter构造体用于记录HTTP服务器谬误日志,Write函数将HTTP服务器的错误信息写入到logWriter中,initSecureWebhookServer函数用于初始化一个带有平安认证的Webhook服务器。 File: istio/pilot/pkg/bootstrap/istio_ca.goistio/pilot/pkg/bootstrap/istio_ca.go文件是Istio的Pilot组件中的一个要害文件,它负责初始化和治理 Istio Certificate Authority (CA)。上面具体介绍各个局部的性能: LocalCertDir: 这是本地证书目录的门路,CA将在此目录下生成证书。useRemoteCerts: 一个布尔值,决定是否应用近程证书,如果为true,则Pilot将信赖通过内部形式提供的证书。workloadCertTTL: 工作负载证书的默认生存工夫。maxWorkloadCertTTL: 工作负载证书的最长生存工夫。SelfSignedCACertTTL: 自签名CA证书的生存工夫。selfSignedRootCertCheckInterval: 自签名根证书的查看距离。selfSignedRootCertGracePeriodPercentile: 自签名根证书的容许工夫距离百分比。enableJitterForRootCertRotator: 是否为根证书轮转启用随机抖动。k8sInCluster: 示意是否在Kubernetes集群中运行。trustedIssuer: 受信赖的证书颁发机构(Issuer)。audience: Istio CA的受众(Audience)。caRSAKeySize: CA应用的RSA密钥对的大小。externalCaType: 内部CA的类型。k8sSigner: Kubernetes签名器。caOptions构造体中的变量蕴含了创立自签名CA证书和签订Istio证书的选项。 以下是各个函数的作用: RunCA: 初始化CA并运行Istio CA服务。detectAuthEnv: 检测环境变量来确定是否启用双向认证。detectSigningCABundle: 检测CA证书绑定。loadCACerts: 加载CA证书。handleEvent: 解决文件事件。handleCACertsFileWatch: 解决CA证书文件监督。addCACertsFileWatcher: 增加CA证书文件监视器。initCACertsWatcher: 初始化CA证书监视器。createIstioCA: 创立Istio CA。createSelfSignedCACertificateOptions: 创立自签名CA证书选项。createIstioRA: 创立Istio RA。getJwtPath: 获取JWT门路。这些函数的作用是执行与CA、证书加载和治理相干的操作,以及一些与CA和证书相干的选项配置。 ...

September 18, 2023 · 2 min · jiezi

关于后端:直播预约中-腾讯大数据-x-StarRocks|构建新一代实时湖仓

随着信息时代的衰亡,数据已成为推动业务决策和翻新的外围因素;结构化、半结构化等多种类型的数据出现爆炸式增长,如何高效解决和剖析海量数据曾经成为要害挑战,联合传统数仓与数据湖劣势的湖仓一体(Lakehouse)架构锋芒毕露,成为大数据畛域势不可挡的趋势;基于湖仓一体架构,企业能够基于一份数据,满足 BI 报表、交互式数据探查、实时剖析、用户画像等所有场景的剖析需要。 腾讯作为国内当先的互联网企业,面对外部业务多样化的数据分析需要,大数据平台心愿降级湖仓一体架构,提供极速对立的数据分析;腾讯大数据平台从 2021 年起开始引入 StarRocks 作为外围数据引擎,基于 StarRocks 极速湖仓剖析、物化视图、存算拆散等要害个性,构建了新一代的实时湖仓平台,目前已部署数千节点,服务腾讯视频号、广告、微信、游戏等上百个业务场景;腾讯在应用 StarRocks 撑持业务的同时,深度参加 StarRocks 开源社区的建设,为 StarRocks 奉献了 Compute node、Iceberg 查问、Light schema change 等多项重量级个性,推动 StarRocks 湖仓能力继续晋升,与 StarRocks 社区共建共赢。 9 月 26 日下午 14:30,StarRocks 社区携手腾讯大数据邀请到了腾讯大数据、腾讯视频、腾讯游戏、同程旅行等资深大数据专家在线深入探讨 StarRocks 湖仓一体架构的要害价值与挑战: 技术大咖面对面:腾讯大数据团队负责人陈鹏与镜舟科技 CTO 张友东深度对谈,分享云原生湖仓实践经验,为企业数据驱动策略提供新视角。解锁湖仓一体前沿技术:理解湖仓一体的先进架构和技术实现形式,学习相干常识和技能,洞察湖仓技术如何为业务发明价值。多场景的的落地实际:StarRocks 极速对立湖仓在游戏数据分析、指标服务、用户画像等畛域的胜利实践经验。如果你对数据架构、数据湖、数据仓库以及实时数据处理感兴趣,点击下方海报,查看更多演讲细节!立刻预约直播! 本文由mdnice多平台公布

September 18, 2023 · 1 min · jiezi

关于后端:SmartNews-基于-Flink-的-Iceberg-实时数据湖实践

摘要:本文整顿自 SmartNews 数据平台架构师 Apache Iceberg Contributor 戢清雨,在 Flink Forward Asia 2022 实时湖仓专场的分享。本篇内容次要分为五个局部: SmartNews 数据湖介绍基于 Icebergv1 格局的数据湖实际基于 Flink 实时更新的数据湖(Iceberg v2)解决方案实时更新小文件问题的优化总结与瞻望点击查看原文视频 & 演讲PPT 一、SmartNews 数据湖介绍 2012 年,SmartNews 公司在日本东京成立。始终专一于 PGC 新闻,是一款在日本处于领先地位的新闻 APP。目前,服务的客户次要集中在日本、欧美等国家。SmartNews 公司在日本、美国和中国均设有办公室,在 2019 年入驻北京和上海。 SmartNews 数据湖次要存储所有广告数据,包含从服务器端收集到的点击/转化等事件信息,维表信息。其次要的广告信息都存储在 Kafka 上,服务器端在收集到事件后,会间接实时写入 Kafka。其余的维表信息,比方广告信息、统计信息等等,次要存储在 MySQL 或 Hive 中。这些信息个别以实时或小时级别更新。 数据湖的上游是业务端的 ETL 或实时报表数据,是上游数据的对立入口。因而,咱们尽量把所有维度都放进来,做成一个大宽表,供上游实时查问应用。 接下来介绍下数据湖须要解决的技术挑战。 第一,依照广告主键去重。上游数据依照每条广告的事件,进行收集。比方一条广告的点击或者转化会生成多条记录,因而咱们须要将这些事件打平。其次是上游的 Kafka 数据,可能蕴含了肯定水平的反复数据。第二,须要更新点击/转化工夫戳字段。比方事件的工夫戳,须要计算最新一次的工夫,须要对数据湖执行更新操作。第三,上游近实时读取。要求数据湖具备同时写入/读取的操作。而 Hive 在重写数据的过程中是会影响到上游正在产生的查问,这就要求咱们须要一个新的解决方案。二、基于 Icebergv1 格局的数据湖实际 上图是咱们第一个解决方案的整体架构。在这个解决方案中,咱们采纳了 Spark 计算引擎,把所有的广告事件依照主键进行打平并去重。而后,所有的维表进行查问 join。 除此之外,咱们将数据源切换成 S3 文件,没有用流式数据源。其次要起因如下: 第一,这个计划是一个小时级别的解决方案,并不需要实时读取流式数据。第二,咱们在设计 Spark 工作时,会定义一个最小的执行单元。将指标数据源限度在某一天的某一时间。通过 S3 文件的分区信息,就能够间接进行读取。第三,为了升高肯定的容错概率。目前,咱们的业务须要回滚过来四天的数据。比方有一个比拟大的 Spark 工作须要重写,如果 Spark 工作失败,会导致整个工作失败。如果设计为最小执行单元,每个 Spark 工作只解决某个小时的数据,容错几率会大幅晋升。为了防止一些反复计算,咱们也会去检测以后小时是否比上次 Spark 工作启动的时候有新增加文件,通过 airflow 来管制 Spark 工作的启动与重试。 ...

September 18, 2023 · 3 min · jiezi

关于后端:幸福里基于-Flink-Paimon-的流式数仓实践

摘要:本文整顿自字节跳动基础架构工程师李国君,在 Streaming Lakehouse Meetup 的分享。幸福里业务是一种典型的交易、事务类型的业务场景,这种业务场景在实时数仓建模中遇到了诸多挑战。本次分享次要介绍幸福里业务基于 Flink & Paimon 构建流式数仓的实践经验,从业务背景、流批一体数仓架构、实际中遇到的问题和解决方案,借助 Paimon 最终能拿到的收益,以及将来布局方面进行介绍。点击查看原文视频 & 演讲PPT 一、业务背景幸福里业务是字节旗下对于房产的业务线,围绕这个业务有很多针对 BP 反对的方向,其中最重要的方向之一就是工单零碎。工单零碎面向的用户是幸福里业务线一线的经纪人和门店经理等。如下图所示,咱们能够看下通过工单零碎,数据是如何产生和流转的。 首先由经纪人将已实现的代看工作提交工单,后续相应的门店经理会对该工单进行审核,在这个过程中就产生了两条数据,并将其更新到业务库的 Binlog 数据,作为实时数仓的数据源进行计算后生成数据报表或间接用于一些考核零碎。其中数据报表用于展现评估一线经纪人的工作是否达标等;考核零碎则用于门店经理为一线经纪人设定考核任务量的工作零碎,通过任务量规范主动反馈处分等。因而在以上利用的实时数仓建模上,咱们发现房产类业务有两个典型的特点: 准确性要求 100%,不能有数据失落和反复的状况产生。须要全量计算,增量数据在 MQ 留存工夫无限,须要拿到全量数据 View 进行计算。实时数仓建模特点 在理论业务的实时数仓 Pipeline 中,进入实时数仓前有多个数据源,每个数据源的特点也都不同,所以实时增量局部会存在 MQ 中,全量数据则是存在 Hive 中。 上图实时数仓中的每一层都是由一个 Flink Streaming SQL 串联起来的,DW 层的次要性能是把多个数据源进行 Join 打宽,通过计算出来的宽表实现间接输入进 MQ 中。因为 MQ 的留存工夫无限会造成一个小时级或天级的周期性工作,在一个周期完结后 MQ 中的数据最终会落到 Hive 里。DWM 这一层次要的作用是聚合计算,聚合计算的后果也会间接输入到 MQ 中。每一层的计算模式都和上一层雷同,实时数仓的计算结果会通过 Service 层服务于在线的数据利用,比方下面提到的数据报表和考核零碎。每层输入的 Hive 离线数据能够用于 BP 同学做数据排查/验证等离线查问工作。 回顾实时数仓的两个特点,一是准确性要求 100%,也就是说要求整个数仓的实时工作状态算子都要保护全量数据;二是须要全量计算,是指因为异构存储,实时数据存在 MQ,历史数据存在 Hive,那么就使得每层生产的 MQ 都须要实时生产增量数据和 Hive 全量数据。从开发工程师的视角这套实时数仓模型存在如下痛点: 在开发过程中须要时刻关注业务逻辑之外的逻辑,比方在 SQL 中对数据的反复解决;在数据去重过程中,应用繁多字段解决不够精准,须要引入 Nanotime 做非确定性计算来解决问题等。之所以存在以上问题,次要是因为在整个链路中,实时数据和离线数据是离开存储的,这种存储异构使得两局部的数据人造很难对齐。 ...

September 18, 2023 · 3 min · jiezi

关于后端:可观测性工程为软件系统开启第三只眼

「可观测性工程」(Observability Engineering) 是一个近年来在软件工程和系统管理畛域中逐步受到关注的概念。它次要关注的是:如何更好地了解、监控和调试简单的分布式系统。 DevOps 浪潮曾经给「软件工程」相干的实际带来了极大的影响。首先体现在各个职能团队越来越严密的合作和沟通,开发、测试、运维等交融在一起独立公布产品。其次软件流水线的工艺也更加自动化。 然而,不论咱们如何娴熟的应用云平台、容器平台和微服务所带来的高可靠性、自愈能力和稳定性等等劣势,当咱们在生产环境中 Debug 故障时,咱们仍然是凭教训猜想,还是不得不在多种监控工具之间解读着七长八段的数据, MTTR 故障修复工夫依然长的忍气吞声。咱们应该能逐步意识到:利用零碎的现代化所带来的也不是益处,还有更多的是「复杂度」。 软件应用零碎自身和其运行环境的复杂度在逐步攀升,支离破碎的运维治理的工具正在迅速蔓延。 简略的信号量数据的叠加和关联就足够了么?监控工具伎俩的更新换代是否就能够实现可观测性?在继续没有找到答案的时候,《observability engineering》这本书出版了。 观测云团队译-中文版可至各大电商平台购买 本书是第一本只探讨「可观测性」主题的书籍,围绕这个主题做了相当深度和广度的探讨,上面是对于核心内容的脑图。 「可观测性」 应该成为软件在交付生命周期中的不容忽视的一个重要属性。 加强可观测性的次要益处是进步零碎的可靠性、性能和安全性。 当零碎呈现问题时,领有良好的可观测性意味着能够更快地发现、定位和解决问题。随着古代软件系统变得越来越简单,可观测性工程成为了确保高可用性、性能和用户满意度的要害因素。 《可观测性工程》这本书分为五个局部,从历史到将来,从实践到落地,从团队到组织,从商业到文化,内容十分全面。对不同角色和职位的人都有不同的意义: ● 运维:能够晋升眼界和实际能力,你会更好的辨认和反思以后所处的困局,会从分门别类的监控工具集利用,转向「聚焦生产环境问题的疾速辨认和解决」。● SRE:使得对基于 SLO 的监控更加有信念,特地是降级对遥测数据采集、数据结构、后盾存储和在团队中推广等方面的认知。你将会更无效的和产品团队单干。● 开发:能够把握可观测性驱动开发的概念,当前就会对利用零碎的运行状态一目了然,它是 DevOps 和 SRE 技能组合中不可短少的一个局部。● 经理和管理者:这是在产品团队中,在整个组织里大范畴落地可观测性左移的必备常识,散布在各个章节里的实在案例剖析也是不可错过的内容。● CXO:轻易理解到投资可观测性的技术要点,用于后期的投资和收益的评判,用于中后期治理的成熟度模型。 《可观测性工程》书籍中的亮点和翻新之处在于: 将可观测性的基础知识局部,用开发一种全新的可观测性程序的形式进行形容。首先解释:这个程序最底层的构建因素的角度、剖析可观测性的最底层数据结构。而后,咱们能够很容易的将这些数据利用到用它们来形容:利用零碎在生产环境中的状态的变动过程。同时还提到了如何对接开源的 OpenTelemetry 数据;心愿开发的同学能对此种形容办法倍感亲切,同时让运维和 SRE 同学也能领有一个全新的视角。 《可观测性工程》一书的另外一个独特之处,是引入的「用第一性原理调试利用故障」。 尽管可观测性治理的根本流程也是收集、存储和剖析应用数据的过程,这看起来和其它单点的监控性能类似。然而,有没有一个对立的思路能够贯通这个过程始终,并且推动这个过程一直的循环起来?本书中所形容的「外围剖析循环」是会令你耳目一新。在生产环境排错的过程中,所有人都将关注点和焦虑点都放在「谁?什么时候?能够在零碎中定位到哪个最精确的惟一(假想)的根因(root cause)」。这种过分关注的后果想法,让咱们曾经疏忽了在 Debug 过程中,咱们应该应用什么思路,去摸索未知景象中暗藏的未知利用运行的多重故障起因。 本图源于 Honeycomb 文档网站 「外围剖析循环」并不是零碎宕机后的救命稻草,而是一种感性沉着的思考办法,咱们能够在事变的前中后任何时刻想到它。它能领导咱们进行更加深度的剖析思考,在一个理智的摸索过程中,你会更加有条理的得出一连串假如,并一一求证,在评判各种已知数据的时候,你同样须要不停的狐疑所有,颠覆所有论断的勇气。切勿让单点工具的全面察看角度、对历史教训数据的依懒性,限度了咱们 debug 生产零碎的想象力,限度了人脑更适宜做网状的简单关联剖析的能力。 上面是本书中的一些精彩片段。 ■ 【序言 - Cindy Sridharan】:本书没有关注协定或规范,甚至各种遥测信号的低级示意,而是将可观测性的三大支柱构想为结构化事件、假如的迭代验证以及「外围剖析循环」的三位一体。依据第一性原理对可观测性的构建因素进行整体重构,有助于强调仅通过遥测信号(或简略应用获取这些信号的工具)并不能最大限度地践行观测零碎的所有行为。■ 【11.6 章 – 可观测性左移】:可观测性驱动开发容许工程团队将他们的玻璃城堡变成能够互动的游乐场。生产环境不是变化无穷的,而是充斥了生机。工程师应该有能力和自信来应答任何异样并且取得胜利。■ 【14.4 章 - Slack 案例钻研论断】:我分享了Slack 如何探测CI 流水线以及如何调试分布式系统的示例。开发人员理解生产环境中的代码状况,首先要思考的应该是调试分布式系统的复杂性。然而,在公布到生产环境之前,如何正确理解和调试分布式系统同样具备挑战性。 小编集体认为:本书残缺地答复了大量的问题,可观测性是什么?如何构建?如何左移?实现可观测性治理平台中的重要技术要点?如何在团队和组织中落地和规模化可观测性?怎么构建可观测性文化?等等。 ...

September 18, 2023 · 1 min · jiezi

关于后端:LeetCode-周赛上分之旅-46-经典二分答案与质因数分解

⭐️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 BaguTree Pro 常识星球发问。 学习数据结构与算法的关键在于把握问题背地的算法思维框架,你的思考越形象,它能笼罩的问题域就越广,了解难度也更简单。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起领会上分之旅。 本文是 LeetCode 上分之旅系列的第 46 篇文章,往期回顾请移步到文章开端\~ LeetCode 周赛 363T1. 计算 K 置位下标对应元素的和(Easy) 标签:位运算T2. 让所有学生放弃开心的分组办法数(Medium) 标签:贪婪、排序、计数排序T3. 最大合金数(Medium) 标签:二分查找T4. 齐全子集的最大元素和(Hard) 标签:数学、质因素合成、散列表 T1. 计算 K 置位下标对应元素的和(Easy)https://leetcode.cn/problems/sum-of-values-at-indices-with-k-set-bits/description/题解(模仿)简略模拟题。 写法 1: class Solution { fun sumIndicesWithKSetBits(nums: List<Int>, k: Int): Int { var ret = 0 for (i in nums.indices) { if (Integer.bitCount(i) == k) ret += nums[i] } return ret }}写法 2: class Solution { fun sumIndicesWithKSetBits(nums: List<Int>, k: Int): Int { return nums.indices.fold(0) { acc, it -> if (Integer.bitCount(it) == k) acc + nums[it] else acc} }}复杂度剖析: ...

September 18, 2023 · 4 min · jiezi

关于后端:COMP-SCI-30047064-操作系统实训

COMP SCI 3004/7064 Operating SystemsPractical 2Virtual Memory Simulation AimBy doing this practical work, you will learn how to implement page replacement algorithms, gainexperience in creating and evaluating a simple simulator, and develop your skills in scientificwriting.You should work in groups of size 2 or 3. Each group will submit onesimulator and one report.Deadlines: Code is due Tuesday 5th September 2023.Report due end of week 8 - Friday 15th September. ...

September 12, 2023 · 5 min · jiezi

关于后端:系统设计面试终极指南

零碎设计面试终极指南咱们精心整顿了零碎设计面试的模版,笼罩了面试中的各种零碎设计问题,蕴含: 负载平衡API 网关通信协议内容散发网络(CDN)数据库缓存音讯队列惟一ID生成器可扩展性高可用性性能安全性容错性和弹性 如果你对细节感兴趣,欢送留言通知我。 【关注公众号:ByteByteGo】

September 12, 2023 · 1 min · jiezi

关于后端:给Hexo博客文章加密

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 原文地址 这是个啥首先, 这是 Hexo 生态圈中 最好的 博客加密插件~你可能须要写一些私密的博客, 通过明码验证的形式让人不能随便浏览.这在 wordpress, emlog 或是其余博客零碎中都很容易实现, 然而 hexo 除外. :(为了解决这个问题, 让咱们有请 "hexo-blog-encrypt".个性一旦你输出了正确的明码, 它将会被存储在本地浏览器的 localStorage中. 按个按钮, 明码将会被清空. 若博客中有脚本, 它将会被正确地执行.反对按标签加密.所有的外围性能都是由原生的 API 所提供的. 在 Node.js中, 咱们应用 Crypto. 在浏览器中, 咱们应用 Web Crypto API.PBKDF2, SHA256 被用于散发密钥, AES256-CBC 被用于加解密, 咱们还应用 HMAC 来验证密文的起源, 并确保其未被篡改.咱们宽泛地应用 Promise 来进行异步操作, 以此确保线程不被阻塞.加密页面多主题反对, 当初曾经反对的主题有 [default, xray], 更多的主题正在开发中.过期的浏览器将不能失常显示, 因而, 请降级您的浏览器.在线演示点击 Demo Page, 所有的明码都是 hello.装置npm install --save hexo-blog-encrypt或 yarn add hexo-blog-encrypt (须要) Yarn)疾速应用将 "password" 字段增加到您文章信息头就像这样.---title: Hello Worlddate: 2016-03-30 21:18:02password: hello---再应用 hexo clean && hexo g && hexo s 在本地预览加密的文章.设置优先级文章信息头 \> 按标签加密 ...

September 12, 2023 · 2 min · jiezi

关于后端:explain各字段的含义

MySQL 5.6.3以前只能EXPLAIN SELECT; 5.6.3当前就能够EXPLAIN SELECT,UPDATE,DELETE 有这样一张user表,300多万行记录,表构造及索引信息如下: 对于sql: SELECT * FROM `user` WHERE id > 20000 AND country > 1 AND grade IN ( 1, 4 ) AND city IN ( 1, 500, 1000, 1500, 3000 ) ORDER BY update_time DESC LIMIT 30;explain后果如下: <font color="#4682B4"> 1.id </font> SQL查问中的序列号 id列数字越大越先执行,如果说数字一样大,那么就从上往下顺次执行。 <font color="#4682B4"> 2.select_type </font> 查问的类型, 能够是如下的任何一种类型: <font color="#4682B4">3.table </font> 查问的表名. 并不一定是理论存在的表名. 能够为如下的值: ...

September 12, 2023 · 2 min · jiezi

关于后端:月度刷题计划同款从区间-DP-到卡特兰数

题目形容这是 LeetCode 上的 [96. 不同的二叉搜寻树]() ,难度为 中等。 Tag : 「树」、「二叉搜寻树」、「动静布局」、「区间 DP」、「数学」、「卡特兰数」 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不雷同的 二叉搜寻树 有多少种? 返回满足题意的二叉搜寻树的种数。 示例 1: 输出:n = 3输入:5示例 2: 输出:n = 1输入:1提醒: $1 <= n <= 19$区间 DP沿用 95. 不同的二叉搜寻树 II 的基本思路,只不过本题不是求具体计划,而是求个数。 除了能用 95. 不同的二叉搜寻树 II 提到的「卡特兰数」间接求解 $n$ 个节点的以外,本题还能通过惯例「区间 DP」的形式进行求解。 求数量应用 DP,求所有具体计划应用爆搜,是极其常见的一题多问搭配。定义 $f[l][r]$ 为应用数值范畴在 $[l, r]$ 之间的节点,所能构建的 BST 个数。 不失一般性思考 $f[l][r]$ 该如何求解,仍用 $[l, r]$ 中的根节点 i 为何值,作为切入点进行思考。 依据「BST 定义」及「乘法原理」可知:$[l, i - 1]$ 相干节点形成的 BST 子树只能在 i 的右边,而 $[i + 1, r]$ 相干节点形成的 BST 子树只能在 i 的左边。所有的左右子树互相独立,因而以 i 为根节点的 BST 数量为 $f[l][i - 1] \times f[i + 1][r]$,而 i 共有 $r - l + 1$ 个取值($i \in [l, r]$)。 ...

September 12, 2023 · 5 min · jiezi

关于后端:ToplingDB-分布式-Compact天然的协同

(一)背景ToplingDB 是 topling 开发的 KV 存储引擎,fork 自 RocksDB,进行了很多革新,其中一个最重要的性能是分布式 Compact,将 Compact 从 DB 结点转移到由多个 DB 共享的计算集群中执行,实现了降本增效的目标。系列文章: MyTopling 分布式 Compact(一):从多线程到多过程MyTopling 分布式 Compact(二):CompactionFilterMyTopling 分布式 Compact(三):PropertiesCollector(二)多过程善战者无赫赫之功,只有选对了方向,前面的事件就自然而然地瓜熟蒂落,兵不血刃。 在 分布式 Compact(一) 中,咱们将 Compact 服务实现为多过程,为了配合 Compact 服务的多过程架构,咱们把 ToplingZipTable 的压缩 Pipeline 也拆分成独立的过程。 (三)Compact 中反查 DB在一些利用中(例如 pika、kvrocks 等等),CompactionFilter 须要反查 DB(应用 DB::Get) 获取元数据,而在 Compact 服务中,只有 SST,没有 DB 对象,这就使得 CompactionFilter 无奈在 Compact 服务中工作。 在 Todis 中,咱们通过当时把 CompactionFilter 反查会用到的元数据捞进去,而后在 Compact 服务中拜访,代替本来的 DB::Get,为此咱们还对 Todis 的数据进行了针对性的编码。 在 kvrocks 中,因为数据的组织形式,无奈通过编码在 Compact 服务中无效地代替本来的 DB::Get,所以,只有 metadata 能力反对分布式 Compact。 ...

September 12, 2023 · 1 min · jiezi

关于后端:多种实时通信技术

SignalR 介绍SignalR 是一个开源的实时通信库,用于构建实时、双向的应用程序。它提供了简化实时通信的性能,容许服务器被动向客户端推送数据,实现实时更新和即时告诉的性能。SignalR 具备高度集成性、跨平台反对和可扩展性,实用于实时聊天、在线游戏、监控零碎等各种利用场景。 SignalR 提供了多种实时通信技术WebSocket:SignalR 应用 WebSocket 作为首选的实时通信协议,WebSocket 提供了低提早、双向通信的能力,并且在服务器和客户端之间建设长久连贯,反对实时数据推送和接管。 Server-Sent Events(SSE):当浏览器或客户端反对 SSE 但不反对 WebSocket 时,SignalR 能够应用 Server-Sent Events 进行实时通信。SSE 是一种基于 HTTP 的单向通信协议,服务器能够被动向客户端推送事件音讯。 Long Polling:对于不反对 WebSocket 和 SSE 的环境,SignalR 应用长轮询(Long Polling)作为备选办法。长轮询是一种模仿实时通信的技术,客户端发送申请给服务器,服务器放弃申请关上并期待新数据达到时再响应。 其余传输方式:除了 WebSocket、SSE 和长轮询,SignalR 还反对其余传输方式,如 Forever Frame(一个应用暗藏的 iframe 来模仿实时通信的技术)和 AJAX 短轮询(在每次申请中都进行轮询以获取最新数据)。 通过反对多种实时通信技术,SignalR 在不同的环境中可能抉择最佳的通信形式,从而实现实时、牢靠的双向通信。这使得开发者能够构建适应不同网络和浏览器的实时应用程序,并提供优良的用户体验。 集线器 hubignalR 中的集线器(Hub)是一种非凡的组件,它充当了服务器和客户端之间的中间人,用于解决实时通信的逻辑。通过应用集线器,开发人员能够简化实时通信的编程模型。SignalR 集线器提供以下性能:客户端与服务器之间的办法调用:在集线器中定义的办法能够由客户端调用,而客户端也能够定义方法供集线器调用。这使得服务器和客户端可能相互之间进行双向的办法调用,不便实现实时数据传输和通信。组治理:集线器反对将客户端连贯分组,并对组进行治理。这样,能够将特定的客户端连贯到同一个组中,以实现播送音讯或针对特定组发送音讯的性能。生命周期治理:集线器治理客户端连贯的生命周期,能够在客户端连贯建设、断开或从新连贯时触发相应的事件。这些事件能够用于执行一些初始化或清理操作,以及监控连贯状态。状态治理:集线器能够存储和治理与客户端连贯相干的状态信息,这些信息能够在不同的办法调用之间共享。这对于跟踪和治理用户状态是很有用的,例如聊天应用程序中的在线用户列表。在 SignalR 中,集线器是通过继承 Hub 类来创立的。开发人员能够在集线器中定义服务器端和客户端之间的办法,并应用相应的客户端库来调用这些办法。SignalRDemo1.创立web利用2.增加集线器hubpublic class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); }}3.Program.cs 增加注入与终结点 ...

September 12, 2023 · 1 min · jiezi

关于后端:Java程序员的MacBookPro14寸M1配置备忘录

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览欣宸的月俸尽管很低,但还是咬着牙攒够银子,动手了最低配置的MacBook Pro 14(M1芯片,刘海屏,丐版),通过一段时间折腾,终于能够用来写代码和博客了,这里将设置过程记录下来作个备忘,次要有以下内容开局必备工具homebrew终端开发(JAVA系)写作一些集体爱好的软件 开局必备首先是搜狗输入法,mac自带的简体拼音输入法,其中英文切换键是<font color="blue">Caps Lock</font>,这个习惯切实难以养成,改用搜狗吧接着还要有个趁手的文本编辑工具,我这里用的是<font color="blue">Sublime text</font>,能够在官网下载chrome也是必备的 homebrew装置brew,执行以下命令 /bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/install.sh)"装置到最初,控制台提醒如下: Warning: !!!!!!!!!!! 重要 !!!!!!!!!!!!!!!执行上面命令将 Homebrew 到 PATH 中: echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/will/.zprofile eval "$(/opt/homebrew/bin/brew shellenv)"如有疑难,能够拜访 https://brew.idayer.com/guide/m1/ 祝贺,装置胜利!运行 brew help 开始体验吧更多文档: https://docs.brew.sh https://brew.idayer.com 依照上述提醒,执行以下两行命令 echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/will/.zprofileeval "$(/opt/homebrew/bin/brew shellenv)"至此brew装置胜利,接着是换一个更好用的终端 终端优化iTerm2官网下载:https://iterm2.com/downloads/stable/iTerm2-3_4_15.zip解压,装置,并容许被迁徙到利用文件夹:关上就能够失常应用了装置wget brew install wget装置oh-my-zsh,用来加强原有的zsh,执行以下命令,期间可能呈现网络拜访超时的问题,多试几次即可 wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh装置胜利后,控制台输入如下 Looking for an existing zsh config...Using the Oh My Zsh template file and adding it to ~/.zshrc. __ ______ / /_ ____ ___ __ __ ____ _____/ /_ / __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \/ /_/ / / / / / / / / / / /_/ / / /_(__ ) / / /\____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/ /____/ ....is now installed!Before you scream Oh My Zsh! look over the `.zshrc` file to select plugins, themes, and options.• Follow us on Twitter: @ohmyzsh• Join our Discord community: Discord server• Get stickers, t-shirts, coffee mugs and more: Planet Argon ShopRun zsh to try it out.而后依照集体爱好装置插件,我这里装了罕用的autojump,用来疾速跳转,装置命令是 ...

September 12, 2023 · 2 min · jiezi

关于后端:Spring-Bean-的作用域Bean-Scope

前言大家好,我是 god23bin,明天咱们来聊一聊 Spring 框架中的 Bean 作用域(Scope)。 什么是 Bean 的作用域?咱们在以 XML 作为配置元数据的状况下,进行 Bean 的定义,是这样的: <bean id="vehicle" class="cn.god23bin.demo.domain.model.Vehicle"> <!-- 协作者写在这里... --></bean>咱们写了一个 Bean 定义(Bean Definition),就是用于创立所定义的类的实例的。 一个 Bean 定义,咱们能够类比一个类的定义,你定义了一个类,你能够依据这个类创立出许多实例对象。同理,Bean 定义也是,也是能够依据这个定义创立许多实例对象的,只不过这里是 Spring 帮咱们创立,而不是咱们手动 new 。 这些 Bean 对象实例,咱们能够了解为 Spring IoC 容器中的对象。 在写 Bean 定义的过程中,咱们能够管制各种 Bean 的依赖项和相应的值,将这些依赖项和值注入到 Bean 定义所创立的对象中。同理,这个过程也能够管制 Bean 定义创立的对象的 Scope(作用域)。Bean 的作用域定义了在容器中创立的 Bean 实例的生命周期以及在应用程序中的可见性。 6 种 Bean 的作用域Spring 反对 6 种 Bean 的作用域,其中有 4 种是在 Web 利用下能力感知到的,如下表所示: Scope阐明singleton(默认状况下)每个 Spring IoC 容器将单个 Bean 定义的 Scope 指定为单个对象实例。prototype将单个 Bean 定义的 Scope 扩充到任意数量的对象实例。request将单个 Bean 定义的 Scope 扩充到单个 HTTP 申请的生命周期。也就是说,每个 HTTP 申请都有本人的 Bean 实例,该实例是在单个 Bean 定义的根底上创立的。只在 Web 感知的 Spring ApplicationContext 的上下文中无效。session将单个 Bean 定义的 Scope 扩充到一个 HTTP 会话的生命周期。只在 Web 感知的 Spring ApplicationContext 的上下文中无效。application将单个 Bean 定义的 Scope 扩充到 ServletContext 的生命周期中。只在 Web 感知的 Spring ApplicationContext 的上下文中无效。websocket将单个 Bean 定义的 Scope 扩充到 WebSocket 的生命周期。只在 Web 感知的 Spring ApplicationContext 的上下文中无效。1. Singleton Scopesingleton 作用域的 Bean,在 Spring IoC 容器中就有且仅有一个该类型的实例对象,也就是单例的。 ...

September 11, 2023 · 3 min · jiezi

关于后端:nacus配置

nacus服务注册: 依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>yml文件 spring: cloud: nacos: discovery: server-addr: localhost:8848 application: name: user-service #注册到nacos的服务名,必填nacus服务发现: 依赖: <!--nacos配置管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>yml文件 spring: application: name: user-service #配置核心配置文件的利用名 profiles: active: dev #配置核心配置文件的环境名 #配置核心信息 cloud: nacos: config: server-addr: localhost:8848 file-extension: yaml #配置核心配置文件的扩展名

September 11, 2023 · 1 min · jiezi

关于后端:Linux内核分析与应用5中断

本系列是对 陈莉君 老师 Linux 内核剖析与利用 的学习与记录。讲的十分之好,举荐观看 留此记录,走马观花,可作抛砖引玉 中断机制概述 中断是CPU对系统产生的某个事件作出的一种反馈, 当中断产生时,CPU暂停正在执行的程序,保留现场后,主动转去执行相应事件的处理程序,解决实现后,返回断点,继续执行被打断的程序. <font color="orange">中断是操作系统的脉搏,是并发解决的根底.</font> 中断的引入,是为了反对CPU和设施之间的并行操作. 中断看似简略,但工程性十分强 5.2 中断解决机制 0x80,零碎门的编号 思考: "中断返回"除了返回现场外,从源代码角度剖析内核还做了什么? 5.3 中断下半部解决机制 软中断机制 小工作(tasklet)机制 思考: 为什么要有中断下半局部解决机制?而且有好几种机制?中断下半局部解决机制中,你认为是否还有改良的余地? 5.4 时钟中断机制 在考查了如基树树,哈希表等多种数据结构后, hrtimer应用了红黑树(rbtree). 树最右边的节点是最快到期的工夫 在内核中,除了被宽泛应用的双向链表,红黑树应用场景也十分多. 本文由mdnice多平台公布

September 11, 2023 · 1 min · jiezi

关于后端:Linux内核分析与应用4内存管理

本系列是对 陈莉君 老师 Linux 内核剖析与利用 的学习与记录。讲的十分之好,举荐观看 留此记录,走马观花,可作抛砖引玉 4.1 Linux内存管理机制lscpu 命令, 相似是优化后的 cat /proc/cpuinfo 实现虚拟内存的几种机制: 当 程序一旦跑起来,那就变成了一个过程 一个过程的用户地址空间由两个数据结构来形容, mm_struct和 vma_area_struct ,前者对过程整个用户空间进行形容,后者对用户空间的各个内存区进行形容 内存映射区(MMR,Memory Mapping Region)虚拟内存区(VMA) 对于mm_struct,最新版本的内核代码定义在[mm_types.h]这个文件中 对于vma_area_struct : mm_struct构造是由一个个VMA组成的 参考<深刻了解Linux内核>第8,9章 4.2 过程用户空间管理机制 写时复制技术(copy on write) 调用do_mmap()创立一个"虚存区" 虚存辨别三种: 公有映射,共享映射,匿名映射 上图显示了该过程 各个区的 起始地址 请页机制,实现虚存治理的重要伎俩. 当一个过程运行的时候,CPU拜访的是用户空间的虚地址, Linux仅把以后要应用的大量页面装入到内存, 须要时通过请页机制将特定的页面调入到内存;当拜访的页不在内存时,就产生一个页故障,并报告故障的起因. 如果是编程引起的异样,而且还产生在内核态,那须要毫不含糊地杀死该过程;如果产生在用户态,阐明是一个有效的内存援用,程序要进行执行;如果是一个真正的缺页引起的异样,而且有非法的权限,这时会进入到缺页异样处理程序 do_page_fault()函数 用户过程拜访内存 剖析: 用户态过程独占 虚拟地址空间,两个过程的虚拟地址空间齐全可能是雷同的. 在拜访用户态虚拟内存空间时,如果没有映射到物理地址,这时就须要通过请页机制收回缺页异样的申请, 缺页异样陷入内核,调配物理地址空间,与用户态虚拟地址空间就建设起了映射关系 ...

September 11, 2023 · 1 min · jiezi

关于后端:Spring-注入集合

应用<property>标签的value属性配置原始数据类型和ref属性配置对象援用的形式来定义Bean配置文件。这两种状况都波及将繁多值传递给Bean。那么如果您想传递多个值,例如Java汇合类型,如List、Set、Map和Properties怎么办?为了解决这种状况,Spring提供了四种类型的汇合配置元素,如下所示: 序号元素 & 形容1<list> 用于注入一组值,容许反复。2<set> 用于注入一组值,但不容许反复。3<map> 可用于注入一组名称-值对,其中名称和值能够是任何类型。4<props> 可用于注入一组名称-值对,其中名称和值都是字符串。您能够应用<list>或<set>来注入java.util.Collection的任何实现或数组。 在解决汇合时,通常会遇到两种状况:(a)传递汇合的间接值和(b)将Bean的援用作为汇合元素之一传递。 示例 假如您曾经筹备好Eclipse IDE,并采取以下步骤创立Spring应用程序: 步骤 形容 1 创立一个名为SpringExample的我的项目,在创立的我的项目中的src文件夹下创立一个名为com.tutorialspoint的包。 2 应用"Add External JARs"选项增加所需的Spring库,如Spring Hello World示例章节中所述。 3 在com.tutorialspoint包下创立Java类JavaCollection和MainApp。 4 在src文件夹下创立Beans配置文件Beans.xml。 5 最初一步是创立所有Java文件和Bean配置文件的内容,并按以下阐明运行应用程序。 以下是JavaCollection.java文件的内容: package com.tutorialspoint;import java.util.*;public class JavaCollection { List addressList; Set addressSet; Map addressMap; Properties addressProp; // 用于设置List的setter办法 public void setAddressList(List addressList) { this.addressList = addressList; } // 打印并返回列表的所有元素。 public List getAddressList() { System.out.println("List Elements :" + addressList); return addressList; } // 用于设置Set的setter办法 public void setAddressSet(Set addressSet) { this.addressSet = addressSet; } // 打印并返回Set的所有元素。 public Set getAddressSet() { System.out.println("Set Elements :" + addressSet); return addressSet; } // 用于设置Map的setter办法 public void setAddressMap(Map addressMap) { this.addressMap = addressMap; } // 打印并返回Map的所有元素。 public Map getAddressMap() { System.out.println("Map Elements :" + addressMap); return addressMap; } // 用于设置Property的setter办法 public void setAddressProp(Properties addressProp) { this.addressProp = addressProp; } // 打印并返回Property的所有元素。 public Properties getAddressProp() { System.out.println("Property Elements :" + addressProp); return addressProp; }}以下是MainApp.java文件的内容: ...

September 11, 2023 · 3 min · jiezi

关于后端:linux-系统资源命令

系统资源命令以后零碎负载w查看的是整体的负载,能够来察看以后零碎有没有压力 w 第一行显示的内容顺次为:工夫、零碎运行工夫、登录用户数、均匀负载(1分钟、5分钟、15分钟) 第二行后展现的信息为:以后登录的都有哪些用户、在哪里登录的等信息 均匀负载不要高于设施外围数系统资源查看vmstat命令应用vmstat命令能够更加细化w命令,来查看具体是哪里的压力 显示内存、分页、块传输和CPU流动的相干信息,评估cpu性能 #vmstat [刷新延时 刷新次数]# 应用vmstat检测,每1秒刷新一次,一共刷新3次vmstat 1 3 <!-- more --> 后果信息 procs 过程 r 期待cpu工夫片和运行的过程数,数量越大,零碎越忙碌,如果长期大于服务器cpu,则阐明cpu不够用了b 期待资源的过程数,如期待IO、内存等,数量越大,零碎越忙碌,如果该值长时间大于1,须要关注一下memory 内存 swpd 切换到替换分区的内存大小,单位kb,如果swpd的值不为0,或者比拟大,只有si和so的值长期为0就不必放心free 闲暇的内存容量,单位kbbuff buffers cache的内存容量,行将写入磁盘的,单位kb,个别对块设施的读写才须要缓冲cache page cached的内存容量,从磁盘中读取的,单位kb,个别作为文件系统进行缓存,频繁拜访的文件都会被缓存。如果cache值比拟大,阐明缓存的文件数较多,如果此时io中的bi比拟小,阐明文件系统效率比拟好swap 替换分区,这两个数越大,阐明内存不够用了,内存中的数据频繁替换到替换分区中,对系统性能影响极大 si 每秒从内存进入替换区的数据的容量so 每秒从替换区进入内存的数量io 磁盘IO,这两个数越大,代表磁盘IO越忙碌。如果bi+bo超过1000,而且wa值较大,示意零碎磁盘IO有问题 bi 从块设施读取数据的总量,读磁盘 kb/sbo 从块设施写入数据的总量,写磁盘 kb/ssystem 零碎信息,显示采集距离内产生的中断次数,这两个数越大,示意零碎与接口设施的通信越忙碌,由内核耗费的CPU工夫越多 in 某一时间距离内观测到的每秒被中断的过程次数cs 每秒进行事件切换次数(上下文切换的次数)cpu CPU信息,如果us+sy大于80%,阐明可能存在cpu资源有余 us 用户过程耗费CPU运算工夫的百分比,如果长期大于50%,须要思考优化程序sy 内核过程耗费CPU运算工夫的百分比id 闲暇CPU的工夫百分比wa 期待IO所耗费的CPU工夫百分比。wa值越高,阐明IO期待越重大。如果wa超过20%,阐明IO期待重大,引起IO期待的起因可能是磁盘大量随机读写造成的,也可能是磁盘或磁盘控制器的带宽瓶颈造成的st 被虚拟机所盗用的CPU占比iostat命令显示均匀磁盘流动和处理器负载状况 #iostat [刷新延时 刷新次数]# 应用iostat检测,每1秒刷新一次,一共刷新3次iostat 1 3选项-d 查看磁盘应用状况-k 以KB为单位显示-c 显示CPU应用状况-t 打印出统计信息开始执行是啊金-x device 指定要统计的磁盘设施名称 %user 在用户级别执行 %nice 以nice优先形式在用户级别执行 %system 在零碎级别执行(内核过程) %iowait 期待IO ...

September 11, 2023 · 2 min · jiezi

关于后端:如何在大众点评上找到附近的餐馆

如何在公众点评上找到左近的餐馆?上周咱们说了应用GeoHash的算法宰割地图来存储餐馆的地位,然而这种算法有调配不平衡的问题,在餐馆稠密的中央节约存储资源。这次咱们来摸索另一种数据结构四叉树 (QuadTree)。 四叉树通常用于将二维空间递归细分为四个象限的网格,直到网格内容满足特定条件为止 (见第一张图)。 四叉树是一个内存数据结构,不是数据库解决方案。它在定位服务的实例中运行,整个数据结构在定位服务启动时建设。 第二张图更具体地解释了四叉树的构建过程。根节点代表整个世界地图,被递归地细分为四个象限,直到网格内没有超过 100 个业务的节点为止。 地图构建好了当前如何搜寻餐馆呢?第一步:在内存中构建四叉树。第二步:建设四叉树后,从树根开始搜寻并遍历整个树,直到找到搜寻原点所在的叶节点。第三步:如果该叶节点有 100 个餐馆,则返回该节点。否则,从其邻近节点增加餐馆,直到返回足够多的餐馆。定位服务启动时如何重建四叉树?第一步:服务器启动时,在内存中建设一个蕴含 2 亿个餐馆的四叉树可能须要几分钟工夫。第二步:在构建四叉树的过程中,服务器无奈响应客户端申请。第三步:因而,咱们须要逐渐分批来公布定位服务的新版本,这样能够防止服务器集群的大部分服务器离线,造成服务中断。如果你对细节感兴趣,欢送留言通知我。 【关注公众号:ByteByteGo】

September 11, 2023 · 1 min · jiezi

关于后端:最简单的设计模式是单例

单例模式能够说是Java中最简略的设计模式,但同时也是技术面试中频率极高的面试题。因为它不仅波及到设计模式,还包含了对于线程平安、内存模型、类加载等机制。所以说它是最简略的吗?明天就别离从单例模式的实现办法和利用场景来介绍一下单例模式 一、单例模式介绍1.1 单例模式是什么单例模式也就是指在整个运行时域中,一个类只能有一个实例对象。 那么为什么要有单例模式呢?这是因为有的对象的创立和销毁开销比拟大,比方数据库的连贯对象。所以咱们就能够应用单例模式来对这些对象进行复用,从而防止频繁创建对象而造成大量的资源开销。 1.2 单例模式的准则为了达到单例这个全局惟一的拜访点的成果,必须让单例满足以下准则: 阻止类被通过惯例办法实例化(公有构造方法)保障实例对象的唯一性(以静态方法或者枚举返回实例)保障在创立实例时的线程平安(确保多线程环境下实例只有一个)对象不会被外界毁坏(确保在有序列化、反序列化时不会从新构建对象)二、单例模式的实现形式对于单例模式的写法,网上演绎的曾经有很多,然而感觉大多数只是列出了写法,不去解释为什么这样写的益处和原理。我偶尔在B站看了寒食君演绎的单例模式总结思路还不错,故这里借鉴他的思路来别离阐明这些单例模式的写法。 依照单例模式中是否线程平安、是否懒加载和是否被反射毁坏能够分为以下的几类 2.1 懒加载2.1.1 懒加载(线程不平安)public class Singleton { /**保障构造方法公有,不被外界类所创立**/ private Singleton() {} /**初始化对象为null**/ private static Singleton instance = null; public static Singleton getInstance() { //判断是否被结构过,保障对象的惟一 if (instance == null) { instance = new Singleton(); } return instance; }}从下面咱们能够看到,通过public class Singleton咱们能够全局拜访该类;通过私有化构造方法,可能防止该对象被外界类所创立;以及前面的getInstance办法可能保障创建对象实例的惟一。 然而咱们能够看到,这个实例不是在程序启动后就创立的,而是在第一次被调用后才真正的构建,所以这样的提早加载也叫做懒加载。 然而咱们发现getInstance这个办法在多线程环境下是线程不平安的—如果有多个线程同时执行该办法会产生多个实例。那么该怎么办呢?咱们想到能够将该办法变成线程平安的,加上synchronized关键字。 2.1.2 懒加载(线程平安)public class Singleton { /**保障构造方法公有,不被外界类所创立**/ private Singleton() {} /**初始化对象为null**/ private static Singleton instance; //判断是否被结构过,保障对象的惟一,而且synchronize也能保障线程平安 public synchronized static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}然而咱们晓得,如果一个静态方法被synchronized所润饰,会把以后类的class 对象锁住,会增大同步开销,升高程序的执行效率。所以能够从放大锁粒度角度去思考,把synchronized放到办法外面去,也就是让其润饰同步代码块,如下所示: ...

September 11, 2023 · 3 min · jiezi

关于后端:30岁程序媛求职路复盘文转码失业半年PHP如何涨薪5K

这篇文章来自一位群友的分享: 这篇文章写于上班路上,刚刚入职不久,我想再冲刺一下大厂,阳哥倡议我保持总结打卡,能够尝试写写博客。 那我就从这篇开始吧,心愿开个好头! 下班的感觉真好明天是入职的第二周,还在熟悉业务和代码,早晨上班和周末还在补业务知识和技术栈。 我就趁着在地铁上的工夫来复盘一下2023年的上半年的求职之路好了。 遐想一月一月十八号公司发表深圳研发部遣散,给了n+1抵偿,我过后很开心,因为我原本也打算换工作。 当初看来真是盲目乐观了!真是没想到,紧接着迎来了长达七个月的就业时光。 自我狐疑那段时间太苦楚了:简历投出去,已读不回,面试也没有。 这期间我恶补了好多八股文,甚至还学了些计算机网络,操作系统的常识。然而感觉学的很不零碎,东一榔头,西一杠子,有点熊瞎子掰玉米的感觉。 而后偶尔机会去敌人公司,写了一个月Go,种种原因,一个月后我又到职了,这时候差不多五月份了,我想罗唆转Go吧,两个都投简历,机会应该能多一点,就这样我明天学点PHP看看源码,今天学下Go的根底。重复摇晃,重复横跳,啥都没学好,面试也约不到,每天就是蒙头学,心里始终很惆怅... 上有老下有小的,只有我老公一个人下班,我在家跟我爸妈我娃一起,心里真的万分丧气,感觉本人像个垃圾,对本人十分悲观,而后又会本人给本人打气,说加油吧,致力学,起码能在机会来了时候致力抓住!就始终在这样自我激励和自我嫌弃中来回重复。 迎来转折工夫到了六月底,迎来了转折,我在微信群里看到阳哥在帮群友做简历优化和就业辅导。我就和阳哥分割了一下,阐明了我的状况。 阳哥倡议我不要再摇摆不定了,踏踏实实去学Go必定比持续做PHP有前途,也帮我布局了从学Go到求职找工作的学习路线。 而后我就度过了特地空虚且苦楚的一个半月,依照制订好的学习路线去学,学完一个阶段就和阳哥约模仿面试,期间也碰到了不少本人没搞懂的问题,有的问ChatGPT解决了,有的问阳哥解决了。 和之前相比,指标明确了,就不会像之前那么焦虑。 就这样我把Go根底、并发编程、数据库、缓存、音讯队列、计网、我的项目、简历的问题等等都和阳哥过了一遍,靠谱的很!我心里终于有底了,也有从新约面试的底气了! 阳哥靠谱这里我夸阳哥几句:我第一个面试的前一天,很缓和,跟阳哥吐槽了几句。过后正好赶上周日劳动,阳哥马上就说下午或者早晨回到家就给我做个模仿面试,针对这个公司的岗位需要来做个突击辅导,过后我很意外也很打动。我想着是周日,再说也是第一家面试只是刷教训包,也没有跟阳哥提先说给我面面,然而他还被动找我来做辅导,反正过后心里挺感激的,而后阳哥就腾讯会议和我聊了一个多小时:从自我介绍到专业技能、再到我的项目教训怎么开掘亮点等等,联合这家公司的要求又过了一遍,这样聊下来之后,我心里就有谱多了,也不慌了。 面试复盘我一共面了三家就找到工作了:真的是没想到在我踏踏实实学Go一个半月之后,才面试了三家就顺利入职了。 起初反思了一下,这必定和我运气好有关系,然而更重要的,和我退出训练营之后这一个多月的突击学习关系更大!这一个多月遭的罪是值得的! 第一家第一家技术点问的很少,问的都是治理教训啥的,问给你个团队怎么治理,然而就很搞笑,薪资范畴15K-20K招带团队的,你是在逗我吗!? 反正没什么有用信息感觉,就不细聊啦~ 第二家第二家就是我当初入职的公司,针对简历我的项目问了很多,这个我还是很有底的,毕竟我的简历优化迭代了好几遍,阳哥也针对我的简历做了屡次模仿面试了。 另外这家公司的一面面试官也特地好,能感觉到面试官很有程度,能开掘我的闪光点,一面的整体过程都比拟难受。 二面就一言难尽,二面的面试官齐全换了一个格调,我感觉本人始终在被打压,我的情绪就有点崩,有点上头。还好退出训练营之后和阳哥做了好几次模仿面试,硬着头皮把能答复的都答复了。另外阳哥和我说,有不懂的就和面试官被动问他们的解决方案是什么,我也问了下,也从面试中学到了货色,尽管这场面试情绪有点崩,然而该说的还是说到了! 二面整体不如一面试现实,二面到最初一面的面试官进来弛缓了一下氛围,还算画了一个不错的句号吧。 而后就让我回去等告诉了... 万万没想到,第二天就说通过了(说实话我是有些意料之外的,就像我和阳哥说的,我是不是在做梦,居然有种范进中举的感觉,哈哈) 因为我感觉不够实在,再加上第二家只是口头承诺,没有发任何实质性的货色。所以我又和阳哥约了一场模仿面试,再为前面的面试持续做筹备(万一这家公司放我鸽子呢...) 第三家第三家,有不少问题模仿面试的时候阳哥都问过我,然而我记得不牢,过后记住了,没多久又忘了,导致我答复时候都比拟不置可否,不够深刻。因为我只记得框架和整体思路,阳哥和我讲的太细节、偏底层的货色我就有点记不清了。 第三家的面试官就说我技术把握的不够深,我心里想:你再给我工夫筹备一个星期试试,我能够深到你难以想象! 反正过后出了门还是有些挫败感,沉着一会之后刺激本人加油干:裸露的问题越多越能去补救,下一个面试就能够答复很好了。 怎么说呢,第三家对我还是很有帮忙的:让我十分珍惜目前的工作机会! 第二家的转折就这样还在自我安慰和激励的同时,筹备和阳哥复盘一些不确定的问题,第二家就不只是口头承诺了,而是正式发Offer走流程了!开心!!! 而后我就开始有针对性的筹备新公司须要的技术栈了。 薪资涨幅也很称心,这只是我做Go的一个终点,但绝不是起点!等稳定下来我打算持续背阴哥求教,我要冲刺大厂!!! 小倡议:就业期间负能量多的群倡议屏蔽不看,很扰乱情绪,我过后看了满屏的就业找不到工作,很焦虑。我又去找阳哥,我说怎么办,我感觉我永远也找不到工作了,阳哥说不会,那是他们本人的问题,能找到工作的人不会在群里埋怨环境不好,有问题针对性解决就好了,你依照打算去做事,不要受他人的影响。另外还要发几句牢骚,我开始投简历前跟阳哥说,我决定拼了,深圳投完了投广州,杭州,北京,还不能有一个开发工作给我? 而后我就下班了,爱拼的女生运气不会太差!真的不要摇晃,不要像我刚开始一样既想做PHP,又想做Go,这样大概率啥都做不好!瞄准一个方向,而后踏踏实实的去做事件!做思维导图、保持总结真的是个好习惯,再次感激阳哥,这招真的太好用了,而且一旦保持下来,养成习惯,真的很香,能明显提高学习效率,梳理分明常识体系。接下来的日子,还要像之前一样:保持总结打卡,挑战写博客,把技术再深挖一下,冲刺大厂! 也算给本人立个Flag。 好了,我到站了,还在找工作的伙计们加油啦! 阳哥读后感首先很感激对我的必定,最近帮不少敌人都拿到了称心的Offer,能够说是我最有成就感的事件了。 大家有简历、待业、跳槽相干的问题能够私信我: wangzhongyang1993

September 11, 2023 · 1 min · jiezi

关于后端:面试项目黑马头条项目介绍

1 我的项目介绍B站视频黑马头条视频学习总结,侵权请分割删除1.1 我的项目背景随着智能手机的遍及,人们更加习惯于通过手机来看新闻。因为生活节奏的放慢,很多人只能利用碎片工夫来获取信息,因而,对于挪动资讯客户端的需要也越来越高。黑马头条我的项目正是在这样背景下开发进去。黑马头条我的项目采纳当下炽热的微服务+大数据技术架构实现。本我的项目次要着手于获取最新最热新闻资讯,通过大数据分析用户爱好准确推送征询新闻 1.2 我的项目概述黑马头条我的项目是对在线教育平台业务进行大数据统计分析的零碎。碎片化、切换频繁、社交化和个性化现如今成为人们浏览行为的标签。黑马头条对海量信息进行收集,通过零碎计算分类,剖析用户的趣味进行推送从而满足用户的需要。 1.3 我的项目术语定义我的项目:泛指黑马头条整个我的项目或某一我的项目模块工程:泛指黑马头条某一项目标源码工程App用户:泛指黑马头条APP用户端用户自媒体人:泛指通过黑马自媒体零碎发送文章的用户管理员:泛指黑马头条管理系统的应用用户App:泛指黑马头条APPWeMedia:泛指黑马头条自媒体零碎Admin:泛指黑马头条管理系统2 业务阐明我的项目演示地址: 平台治理:http://heima-admin-java.research.itcast.cn/ 自媒体:http://heime-media-java.research.itcast.cn/ app端:http://heima-app-java.research.itcast.cn/ 用谷歌浏览器关上,改成挪动端调试,如下图或者间接应用手机微信或浏览器关上 2.1 性能架构图 2.2 APP次要性能纲要频道栏:用户能够通过此性能增加本人感兴趣的频道,在增加标签时,零碎可根据用户爱好进行举荐文章列表:须要显示文章题目、文章图片、评论数等信息,且须要监控文章是否在APP端展示的行为搜寻文章:联想用户想搜寻的内容,并记录用户的历史搜寻信息集体核心:用户能够在其集体核心查看珍藏、关注的人、以及零碎设置等性能查看文章:用户点击文章进入查看文章页面,在此页面上可进行点赞、评论、不喜爱、分享等操作;除此之外还须要收集用户查看文章的工夫,是否看我等行为信息实名认证:用户能够进行身份证认证和实名认证,实名认证之后即可成为自媒体人,在平台上公布文章注册登录:登录时,验证内容为手机号登录/注册,通过手机号验证码进行登录/注册,首次登录用户主动注册账号。2.3 自媒体端性能纲要内容治理:自媒体用户治理文章页面,能够依据条件进行筛选,文章蕴含草稿、已公布、未通过、已撤回状态。用户能够对文章进行批改,上/下架操作、查看文章状态等操作评论治理:治理文章评论页面,显示用户已公布的全副文章,能够查看文章总评论数和粉丝评论数,能够对文章进行敞开评论等操作素材治理:治理自媒体文章公布的图片,便于用户公布带有多张图片的文章图文数据:自媒体人公布文章的数据:阅读数、评论数、珍藏了、转发量,用户能够查看对应文章的浏览数据粉丝画像:内容包含:粉丝性别散布、粉丝年龄散布、粉丝终端散布、粉丝喜爱分类散布2.4 平台治理端性能纲要用户治理:零碎后盾用来保护用户信息,能够对用户进行增删改查操作,对于违规用户能够进行解冻操用户审核:管理员审核用户信息页面,用户审核分为身份审核和实名审核,身份审核是对用户的身份信息进行审核,包含但不限于工作信息、资质信息、经验信息等;实名认证是对用户实名身份进行认证内容治理:管理员查问现有文章,并对文章进行新增、删除、批改、置顶等操作内容审核:管理员审核自媒体人公布的内容,包含但不限于文章文字、图片、敏感信息等频道治理:治理频道分类界面,能够新增频道,查看频道,新增或批改频道关联的标签网站统计:统计内容包含:日活用户、访问量、新增用户、访问量趋势、热门搜寻、用户地区散布等数据内容统计:统计内容包含:文章采集量、发布量、浏览量、浏览工夫、评论量、转发量、图片量等数据权限治理:超级管理员对后盾管理员账号进行新增或删除角色操作2.5 其它需要 3 技术结构图包含前端(Weex、Vue、Echarts、WS)、网关(GateWay)、DevOps(单元测试、代码标准) 服务层中包含中间件(Kafka)、索引、微服务、大数据存储等重难点技术 Weex+Vue+WebSocket :应用Weex跨平台开发工具,整合集成VUE框架,实现黑马头条挪动端性能开发,并集成WebSocket实现即时消息(文章举荐、私信)的推送Vue+Echarts : 自媒体零碎应用Vue开发要害,集成Echarts图表框架,实现相干粉丝画像、数据分析等性能Vue+Echarts+WebSocket : 管理系统也是应用Vue开发,集成Echarts,实现网站统计、内容统计等性能,集成WebSocket,实现零碎看板实时数据自动化更新Spring-Cloud-Gateway : 微服务之前架设的网关服务,实现服务注册中的API申请路由,以及管制流速管制和熔断解决都是罕用的架构伎俩,而这些性能Gateway人造反对PMD&P3C : 动态代码扫描工具,在我的项目中扫描我的项目代码,查看异样点、优化点、代码标准等,为开发团队提供标准对立,晋升我的项目代码品质Junit : 在继续集成思维中,单元测试偏差自动化过程,我的项目通过Junit+Maven的集成实现这种过程使用Spring Boot疾速开发框架,构建我的项目工程;并联合Spring Cloud全家桶技术,实现后端集体核心、自媒体、管理中心等微服务。使用RabbitMQ实现外部零碎音讯告诉;与客户端零碎音讯告诉;以及实时数据计算使用Redis缓存技术,实现热数据的计算,NoSession等性能,晋升零碎性能指标应用Mysql存储用户数据,以保障下层数据查问的高性能应用Mongo存储用户热数据,以保障用户热数据高扩大和高性能指标应用FastDFS/OSS作为动态资源存储器,在其上实现热动态资源缓存、淘汰等性能使用ES搜寻技术,对冷数据、文章数据建设索引,以保障冷数据、文章查问性能实现实时数据分析与利用;比方文章举荐使用AI技术,来实现零碎自动化性能,以晋升效率及节省成本。比方实名认证自动化理解更多请关注下公众号呀

September 11, 2023 · 1 min · jiezi

关于后端:一个烂分页踩了三个坑

你好呀,我是歪歪。 前段时间踩到一个比拟无语的生产 BUG,严格来说其实也不能算是 BUG,只能说开发共事对于业务共事的需要了解没有到位。 这个 BUG 其实和分页没有任何关系,然而当我去排查问题的时候,我看了一眼 SQL ,大略是这样的: select * from table order by priority limit 1;priority,就是优先级的意思。 依照优先级 order by 而后 limit 取优先级最高(数字越小,优先级越高)的第一条 ,联合业务背景和数据库外面的数据,我立马就意识到了问题所在。 想起了我当年在写分页逻辑的时候,尽管场景和这个齐全不一样,然而踩过到底层原理截然不同的坑,这玩意印象粗浅,所以立马就辨认进去了。 借着这个问题,也盘点一下我遇到过的三个对于分页查问有意思的坑。 职业生涯的第一个生产 BUG歪徒弟职业生涯的第一个生产 BUG 就是一个小小的分页查问。 过后还在做领取零碎,接手的一个需要也很简略就是做一个定时工作,定时把数据库外面状态为初始化的订单查问进去,调用另一个服务提供的接口查问订单的状态并更新。 因为流程上有数据强校验,不必思考数据不存在的状况。所以该接口可能返回的状态只有三种:胜利,失败,解决中。 很简略,很惯例的一个需要对吧,我分分钟就能写出伪代码: //获取订单状态为初始化的数据(0:初始化 1:解决中 2:胜利 3:失败)//select * from order where order_status=0;ArrayList initOrderInfoList = queryInitOrderInfoList();//循环解决这批数据for(OrderInfo orderInfo : initOrderInfoList){ //捕捉异样免得一条数据谬误导致循环完结 try{ //发动rpc调用 String orderStatus = queryOrderStatus(orderInfo.getOrderId); //更新订单状态 updateOrderInfo(orderInfo.getOrderId,orderStatus); } catch (Exception e){ //打印异样 }}来,你说下面这个程序有什么问题? 其实在绝大部分状况下都没啥大问题,数据量不多的状况下程序跑起来没有任何故障。 然而,如果数据量多起来了,一次性把所有初始化状态的订单都拿进去,是不是有点不合理了,万一把内存给你撑爆了怎么办? 所以,在我已知数据量会很大的状况下,我采取了分批次获取数据的模式,假如一次性取 100 条数据进去玩。 ...

September 11, 2023 · 3 min · jiezi

关于后端:AI平台如何赋能后端研发

随着人工智能的倒退和技术提高,越来越多的企业开始应用人工智能技术做效率的晋升和业务成果的晋升,升高企业老本,加强企业竞争力。本文将基于哈啰AI平台的能力,以接入普惠工单零碎主动转派为例,讲述如何通过算法能力赋能后端研发提效。 建模流程整个模型建模流程次要须要四大步:特色解决、模型训练、模型评估、模型部署。并且模型还须要进行一直的迭代能力保障模型成果。 特色解决包含特色存储、特征选择、特色荡涤、特色加工等模型训练包含模型根底环境、特色预处理、超参调优、训练减速等模型评估包含超参评估、成果评估、耗时评估等模型部署包含TF模型、Pytorch模型、PMML模型、GPU模型等AI平台计划 特色解决包含特色存储、特征选择、特色荡涤、特色加工等。 上面以特色存储和特色加工为例,举例如何通过页面,最简化反对特色的存储和加工。 特色存储特色平台目前反对在线特色的存储,简略来说用户能够通过在AI平台点通过页面配置化的形式,将hive表数据或者kafka、rocketmq数据,同步到hbase、hedis、redis等在线存储中,也反对将数据存储到rocksdb进行本地化存储。如下图所示: 特色加工特色荡涤的例子如下,AI平台先将局部特色工程逻辑算子化,如下图Normalizaiton为归一化算子。 落为算子后,后续自动化建模就能够间接在特色工程模块抉择Normalization算子,这样在模型进行训练之前就会对特色进行归一化解决。 模型训练包含特色预处理、镜像治理、工作空间作业建模、超参调优、分布式训练、自动化建模。 下文以自动化建模为例,讲述如何通过配置化的形式接入。 自动化建模在自动化建模模块,先通过模型品种和模型分类,抉择适合的模型类别。 抉择AutoML模式,则会主动帮用户抉择模型。下图抉择了专家模式,则须要用户本人抉择深度学习的多分类模型。 如下图所示,抉择了IntentRecognitionNNIAndRay模型,该模型是用ALBERT写的用意辨认模型。抉择用意辨认模型后,能够抉择特色的初筛、数据处理、特征选择逻辑,在自动化训练前进行特色的解决,下图展现了特色解决逻辑,能够对特色进行特色初筛、特色加工、特征选择。 模型评估超参搜寻可视化、模型多版本AB、模型主动评估、模型手动评估、模型性能诊断、模型自定义评估逻辑等。 下文展现了AI平台实现的超参搜寻可视化和模型评估。 超参搜寻可视化AI平台模型训练接入了NNI框架,将训练时的超参搜寻可视化,这样用户在训练实现后能够通过超参搜寻的散布判断模型是否存在问题,或者能够优化超参散布,从而使模型的成果更好。如下图所示: 模型主动评估通过自动化建模后,模型抉择手动评估或者主动评估。以主动保留为例,能够在评估时抉择评估的指标值,以及评估规定。后续模型训练后即可通过评估后果进行模型主动替换。 模型部署反对TF模型、Pytorch模型、PMML模型、GPU模型。AI平台模型反对TensorFlow模型、PMML模型、Pytorch模型、GPU模型,还反对Faas化部署,如下所示,能够抉择不同的类型,将模型文件上传,AI平台会将模型部署到对应的利用集群中。 用意辨认算法简略来说就是通过算法,辨认用户的需要,即明确用户想做什么。 用意辨认是人机对话形成的要害,而用户用意须要一直的对话能力真正的了解。 用意辨认场景用意辨认的利用场景对话零碎、搜索引擎等。用意辨认例子搜索引擎很好了解,举例来说,你从谷歌输出了“八角笼”,用意辨认会依据以后的热度和你的习惯进行辨认,比方你是一个电影迷,会辨认到你是想理解八角笼中的电影。 对话零碎:举例来说,你输出小米,零碎会至多有两种语义辨认进去,一种是食粮小米,一种是小米品牌,而当你持续输出雷军,零碎就理解你须要晓得的是小米品牌。 BERTBERT是自编码语言模型,通过Masked LM(随机屏蔽) 和 Next Sentence Prediction(下一句预测)两个工作来训练该模型。 Masked LM该思维来源于完形填空,简略来说,在一句话中,随机抹去这句话的一个或者多个词汇,要求依据残余的词汇进行预测抹去的词别离是什么。如下图所示:bert别离隐去了一句话中的两个字,而后让模型进行“完形填空”主动补全。 益处:这样做迫使模型更多依赖上下文信息去预测,赋予了模型肯定的纠错能力。 毛病:每批次只有15%的标记被预测,模型须要更多的预训练步骤来收敛。 Next Sentence Prediction判断第二句话是否在第一句话的前面。该工作与Masked LM工作相结合,让模型可能精确的了解和刻画语句或者文章的语义信息。 如下图所示:输出两句话,让模型可能判断是否为间断的句子,一个是正确的间断句子,一个是谬误的间断句子。 ALBERTBERT的改良版本很多,而ALBERT全称为A Lite BERT,是轻量化的版本。ALBERT采纳了两种缩小模型参数的办法,让其比BERT所需内存空间更小,并且晋升训练速度。 原来的BERT因为模型参数过多,并且模型太大,导致大量数据容易过拟合,ALBERT则能够反对更少的数据,达到更好的成果。 普惠场景接入普惠接入AI平台的场景是一个客服工单主动转派场景。该场景基于用意辨认的ALBERT算法(因为普惠工单零碎训练数据较少,因而ALBERT是很适合的模型),将客服客诉问题进行打标和打分,对合乎分数要求的场景进行主动的转派和主动问题勘误。 原流程原流程步骤原流程如下图右边所示:用户在哈啰app提交客诉->客服人员判断具体业务线->客服人员转派工单到打车业务线->打车后端值班同学转派工单->开发解决问题->客服人员确认。 该流程中,很重要的2步是打车值班同学转派工单和开发解决问题。 工单转派遇到的问题以打车后端值班同学转派工单流程为例:因为日常客诉较多,因而每周会统一安排的一个开发进行值班,而开发人员每个人做的方向是不一样的,且程度有高有低,因而很多工单会转派谬误,或者须要征询对应的同学后进行转发,不仅准确率不高,且效率较低。 工单解决遇到的问题开发解决问题也有和转派相似问题,因为开发人员的程度不统一和做的方向不统一,因而解决问题的人非常扩散,且解决周期也各不相同。因而最好的解决办法是,工单能通过零碎主动转派对应的人,且问题能够通过零碎主动勘误,这样值班人员不须要对该类问题进行工单转派,也不须要独自有人进行问题解决,零碎可能齐全进行主动的解决。 新流程新流程如下图左边所示,次要变动为将打车值班同学转派工单和开发解决问题两步进行了自动化解决。 主动转派和主动解决计划原计划打车侧的原计划为关键词匹配,即依据客服的形容,通过关键字进行匹配,该计划的准确率很低(准确率有余10%)。 算法计划主动转派逻辑业务开发对不同的形容进行打标,每个标签对应不同的开发。举例如下:右边客服零碎的形容,右侧是给该形容打的标签。而每一个标签前面都会对应相应的解决同学。 算法依据客诉形容,推理出该形容对应的标签和概率,而后对系统留下概率超过肯定值的分类(线上为0.7),进行转派。如下图所示: 主动解决逻辑依据标签的后果,对局部标签(配置化)进行调用接口自动化解决。 接入流程新场景新场景接入流程如下所示(新积淀算子流程):需要新增:后端研发依据业务场景给AI平台提需要需要评估:AI平台会依据用户需要评估可行性,并判断是否能够复用已有算子(模型)模型研发:AI平台进行模型研发,如模型过于简单,则AI平台会协调算法进行模型研发模型评估:AI平台进行成果评估,如模型成果评估通过,会积淀为算子,如不通过,会进行模型的剖析和修改算子积淀:AI平台同学依据模型积淀为算子文档积淀:AI平台会将该算子的应用计划和接入积淀文档用户接入:后端研发依据接入文档进行模型的在线推理的接入 复用算子场景新场景接入流程如下所示(复用算子流程):需要新增:后端研发依据业务场景给AI平台提需要需要评估:AI平台会依据用户需要评估可行性,并判断是否能够复用已有算子(模型)用户接入:后端研发依据接入文档进行模型的在线推理的接入 ...

September 11, 2023 · 1 min · jiezi

关于后端:dbbench-ToplingDB-vs-RocksDB

(一)背景ToplingDB,尽管 fork 自 RocksDB 并且兼容其 API,但实现了本性难移的改良,最重要的就是实现了性能更高的 MemTable 和 SST,其次是对 RocksDB 自身进行了很多代码级优化,再通过 SidePlugin 将所有的组件和配置组织起来,利用代码只须要关怀业务逻辑,和 RocksDB 简单的配置说再见(TableFactory, BlockCache, DBOptions, ColumnFamilyOptions 等等)。读性能,写性能,内存用量,都失去了大幅改良。咱们应用 db_bench 来进行一个基准测试,db_bench 是RocksDB 自带的性能测试工具,在 ToplingDB 中,为了适配对接,咱们对 db_bench 进行了小幅批改。该比照测试是可重现的,rocksdb 版本具体到 git 提交(2023-06-23),toplingdb 具体到 git 提交(2023-06-28)。(二)场景设计2.1. key_sizekey_size 咱们设置为 8,因为再长了前缀都是完全相同的。2.2. value 压缩db_bench 填充 value 时,能够设置预期的压缩比例,因为 ToplingZipTable 压缩算法的特殊性,依照 rocksdb 作者实现的 db_bench 的 value 填充算法,在默认 value_size=100 的状况下,压缩率太高,可能会让不明真相的人认为 ToplingDB 在舞弊,同时 ToplingDB value 不压缩时能够应用 zero copy,测试后果太好,也有舞弊嫌疑。所以咱们设置 value_size=20,打消这两个影响。2.3. 不执行手动 compact填充完数据之后,不执行手动 compact,这更加贴近事实场景。(三)配置参数咱们测试数据能够全副装入内存的场景,并且文件也存储在 /dev/shm 下,真正的全内存场景。该场景下,RocksDB 因为存在 BlockCache 和 page cache 双缓存,内存耗费更大,ToplingDB 只有 page cache,内存耗费更小,但该测试中咱们暂不比照内存耗费,只比照性能。ToplingDB: MemTable=cspp,SST TableFactory fast & zip,应用 dispatch 或 dispatch_all_fast 。RocksDB: MemTable=SkipList,SST TableFactory 是 BlockBasedTable,应用 min_level_to_compress 参数管制仅 L0 不压缩,还是全副不压缩,压缩选项应用 db_bench 默认值。num=100000000, write_buffer_size=768M, target_file_size_base=32M, target_file_size_multiplier=2对于 RocksDB,设置 bloom_bits=10,ToplingDB 的 SST 搜寻足够快,不须要 bloom filter(四)测试项目对于两种压缩配置(L0 不压缩,L1~L6 压缩;全副不压缩),咱们别离测试各个我的项目。写数据咱们应用 fillrandom, 别离测试 batch_size=1 和 batch_size=100读数据咱们应用 readrandom,别离测试 threads=1 和 threads=10数据扫描,别离测试 readseq 和 readreverse(五)测试后果4.1. L0 不压缩,L1~L6 压缩4.2. 都不压缩(六)总结在内存不限的状况下,不论是随机写还是随机读,ToplingDB 比 RocksDB 都有显著劣势。随机写的时候,只有每次写入多条数据(batch_size=100),ToplingDB 的劣势能力体现进去,因为写门路上有很多个环节,只有每次写入多条数据,能力突出 ToplingDB CSPP MemTable 的劣势,实际上 CSPP MemTable 自身相比 SkipList 有 6 倍的写性能,测试中的 3 倍是被其它环节拉低后的后果。随机读的时候,ToplingDB 比 RocksDB 有 5 倍的劣势,单方都有随线程数近乎线性的减速比。数据扫描中,反向扫描(readreverse)比正向扫描更慢,这次要是因为在 DBIter 中,反向扫描时,对于雷同的 UserKey,须要记忆上一个 value,而正向扫描不须要,其次是 RocksDB BlockBasedTable 反向扫描自身就比正向扫描慢。在 ToplingDB 中,咱们对扫描的全链路都做了很多优化,并且 Topling 的 SST 扫描自身就更快并且正向反向一样快。值得注意的是,不论是 ToplingDB 还是 RocksDB,压缩对于读写性能的影响都不大,这是因为服务器的 CPU 和内存资源都是过剩的(32核64线程,256G 内存)。相比 ToplingDB,这种场景对 RocksDB 更加敌对,但 ToplingDB 依然以绝对优势胜出,实际上在资源受限(CPU 弱,内存小,IOPS低)的场景下,ToplingDB 的劣势更大。 ...

September 11, 2023 · 1 min · jiezi

关于后端:这可能是最全面的Python入门手册了

无论是学习任何一门语言,基础知识肯定要扎实,根底功十分的重要,找到一个适合的学习办法和材料会让你少走很多弯路, 你的提高速度也会快很多,无论咱们学习的目标是什么,不得不说Python真的是一门值得付出工夫去学习的优良编程语言。 普通人学Python有什么用Python对于普通人而言,开启了有限的可能性,不仅晋升了职业竞争力,还能让你退职场中摸索兼职机会,为你的胜利路线添砖加瓦。 无论你的背景是什么,它都能为你带来理论的价值。通过学习Python,你能够进步工作效率,自动化重复性工作,解放工夫和精力去解决更有挑战性的工作。此外,Python还可用于数据分析和可视化,帮忙你更好地了解和解读大量数据,为企业决策提供无力反对。 学习Python还能为你关上兼职的大门。Python在多个畛域有宽泛的利用,例如数据分析、网络爬虫、人工智能等。通过学习Python,你能够参加数据分析我的项目,帮忙企业发现潜在商机;你也能够利用Python开发小型网站或应用程序,满足不同行业的需要。这些兼职机会不仅为你提供额定的支出起源,还能一直减少你的技能和教训,为你的职业倒退铺平道路。 在这个广大的互联网世界中,你能够轻松找到丰盛的Python学习资源和教训分享。这里我也分享了一些学习材料,让你在Python的世界中不断前进。 这是一份由华为大佬外部整顿的《Python入门手册》共计580页内容,涵盖根底语法、案例、习题超级多,非常适合边学边练,疾速达成技能!适用人群:无论您是计算机相关业余的大学生,还是正在从事软件开发的职场人,甚至是齐全零根底的在行小白,这份Python材料都适宜您浏览和学习《Python入门手册》高清PDF下载链接(倡议先保留,防止被河蟹):https://pan.quark.cn/s/f71753cdc969 因篇幅无限,上面仅展现局部内容: 零根底如何疾速入门Python依据SMART准则,小编打算了以下学习打算,将帮忙你在1个月内胜利入门Python。遵循打算和学习办法,置信你肯定可能获得优异的问题。 第1周学习Python根底语法和数据类型实现10道练习题目开始编写一个简略的Python程序第2周学习Python函数和模块的应用实现20道练习题目编写一个简略的Python我的项目第3周学习Python面向对象编程实现30道练习题目编写一个中等难度的Python我的项目第4周学习Python高级编程技巧实现40道练习题目实现一个简单的Python我的项目学习办法每天学习2-3个小时,放弃专一和效率通过观看视频、浏览文档和练习题目来进行学习找到一个编程社区或论坛,与其余Python爱好者交流学习教训置信只有你认真执行打算并放弃激情和急躁,后果都是顺便的,加油! 《Python入门手册》高清PDF下载链接(倡议先保留,防止被河蟹):https://pan.quark.cn/s/f71753cdc969如果对你有帮忙的话,请帮我点个赞!

September 11, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之七生命周期回调

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本篇的知识点是bean的生命周期回调:在bean生命周期的不同阶段,都能够触发自定义代码的执行触发自定义代码执行的具体形式,是用对应的注解去润饰要执行的办法,如下图所示: 有两种模式能够实现生命周期回调:拦截器模式和自定义模式,接下来通过编码顺次学习拦截器模式《拦截器(Interceptor)》已具体介绍了quarkus拦截器的自定义和应用,包含以下三个步骤<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/%E6%B5%81%E7%A8%8B%E5%9B%BE%20(19).jpg" alt="流程图 (19)" style="zoom:67%;" /> 如果要自定义bean的生命周期回调,也是遵循上述步骤执行,接下来编码实现首先定义拦截器,名为<font color="blue">TrackLifeCycle</font>,就是个一般拦截器,须要用注解<font color="red">InterceptorBinding</font>润饰package com.bolingcavalry.interceptor.define;import javax.interceptor.InterceptorBinding;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.TYPE;@InterceptorBinding@Target({TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface TrackLifeCycle {}而后是实现拦截器的性能,有几处要留神的中央稍后会提到package com.bolingcavalry.interceptor.impl;import com.bolingcavalry.interceptor.define.TrackLifeCycle;import io.quarkus.arc.Priority;import io.quarkus.logging.Log;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.interceptor.AroundConstruct;import javax.interceptor.Interceptor;import javax.interceptor.InvocationContext;@TrackLifeCycle@Interceptor@Priority(Interceptor.Priority.APPLICATION + 1)public class LifeCycleInterceptor { @AroundConstruct void execute(InvocationContext context) throws Exception { Log.info("start AroundConstruct"); try { context.proceed(); } catch (Exception e) { e.printStackTrace(); } Log.info("end AroundConstruct"); } @PostConstruct public void doPostConstruct(InvocationContext ctx) { Log.info("life cycle PostConstruct"); } @PreDestroy public void doPreDestroy(InvocationContext ctx) { Log.info("life cycle PreDestroy"); }}上述代码有以下几点须要留神用注解<font color="blue">Interceptor</font>和<font color="blue">TrackLifeCycle</font>润饰,阐明这是拦截器TrackLifeCycle的实现被拦挡bean实例化的时候,<font color="blue">AroundConstruct</font>润饰的办法execute就会被执行,这和[《拦截器》]()一文中的<font color="red">AroundInvoke</font>的用法很类似被拦挡bean创立胜利后,<font color="blue">PostConstruct</font>润饰的办法doPostConstruct就会被执行被拦挡bean在销毁之前,<font color="blue">PreDestroy</font>润饰的办法doPreDestroy就会被执行接下来是应用拦截器<font color="blue">TrackLifeCycle</font>了,用于演示的bean如下,用TrackLifeCycle润饰,有构造方法和简略的helloWorld办法@ApplicationScoped@TrackLifeCyclepublic class Hello { public Hello() { Log.info(this.getClass().getSimpleName() + " at instance"); } public void helloWorld() { Log.info("Hello world!"); }}最初再写个单元测试类验证@QuarkusTestpublic class LifeCycleTest { @Inject Hello hello; @Test public void testLifyCycle() { hello.helloWorld(); }}执行单元测试,控制台输入如下,可见拦截器的日志输入都合乎预期15:26:32,447 INFO [io.quarkus] (main) Quarkus 2.7.3.Final on JVM started in 2.899s. Listening on: http://localhost:808115:26:32,448 INFO [io.quarkus] (main) Profile test activated. 15:26:32,448 INFO [io.quarkus] (main) Installed features: [agroal, cdi, narayana-jta, resteasy, smallrye-context-propagation, vertx]15:26:32,483 INFO [com.bol.lif.Hello] (main) Hello_ClientProxy at instance15:26:33,040 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) start AroundConstruct15:26:33,040 INFO [com.bol.lif.Hello] (main) Hello_Subclass at instance15:26:33,040 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) end AroundConstruct15:26:33,041 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) life cycle PostConstruct15:26:33,041 INFO [com.bol.lif.Hello] (main) Hello world!15:26:33,097 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) life cycle PreDestroy15:26:33,128 INFO [io.quarkus] (main) Quarkus stopped in 0.075s以上就是通过拦截器制作的bean生命周期回调的全过程,接下来再看另一种形式:不必拦截器的形式自定义模式方才的拦截器模式有个显著问题:如果不同bean的生命周期回调有不同业务需要,该如何是好?为每个bean做一个拦截器吗?随着bean的减少会有大量拦截器,仿佛不是个好的计划如果您相熟spring,对上面的代码要改不生疏,这是来自spring官网的内容,间接在bean的办法上用PostConstruct和PreDestroy润饰,即可在bean的创立实现和销毁前被调用public class CachingMovieLister { @PostConstruct public void populateMovieCache() { // populates the movie cache upon initialization... } @PreDestroy public void clearMovieCache() { // clears the movie cache upon destruction... }}实际上,quarkus也反对上述形式,不过和拦截器相比有两个差别:在bean的外部,只能用PostConstruct和TrackLifeCycle,不能用AroundConstruct,只有拦截器能力用AroundConstruct在拦截器中,PostConstruct和TrackLifeCycle润饰的办法必须要有InvocationContext类型的入参,然而在bean外部则没有此要求咱们来革新<font color="blue">Hello.java</font>的源码,批改后如下,减少了两个办法,别离被PostConstruct和PreDestroy润饰@ApplicationScoped@TrackLifeCyclepublic class Hello { public Hello() { Log.info(this.getClass().getSimpleName() + " at instance"); } @PostConstruct public void doPostConstruct() { Log.info("at doPostConstruct"); } @PreDestroy public void doPreDestroy() { Log.info("at PreDestroy"); } public void helloWorld() { Log.info("Hello world!"); }}再次运行单元测试,控制台输入如下,可见Hello自定义的两个生命周期回调都执行了,同时原拦截器的三个回调也都失常执行16:27:54,134 INFO [io.quarkus] (main) Quarkus 2.7.3.Final on JVM started in 2.529s. Listening on: http://localhost:808116:27:54,135 INFO [io.quarkus] (main) Profile test activated. 16:27:54,135 INFO [io.quarkus] (main) Installed features: [agroal, cdi, narayana-jta, resteasy, smallrye-context-propagation, vertx]16:27:54,147 INFO [com.bol.lif.Hello] (main) Hello_ClientProxy at instance16:27:54,710 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) start AroundConstruct16:27:54,711 INFO [com.bol.lif.Hello] (main) Hello_Subclass at instance16:27:54,711 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) end AroundConstruct16:27:54,711 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) life cycle PostConstruct16:27:54,712 INFO [com.bol.lif.Hello] (main) at doPostConstruct16:27:54,712 INFO [com.bol.lif.Hello] (main) Hello world!16:27:54,747 INFO [com.bol.int.imp.LifeCycleInterceptor] (main) life cycle PreDestroy16:27:54,747 INFO [com.bol.lif.Hello] (main) at PreDestroy16:27:54,765 INFO [io.quarkus] (main) Quarkus stopped in 0.044sdispose注解:实现销毁前自定义操作,dispose是另一种可选计划试想这样的场景:我的bean在销毁前要做自定义操作,然而如果用之前的两种计划,可能面临以下问题:不适宜批改bean的代码,bean的类可能是第三方库也不适宜批改生命周期拦截器代码,拦截器可能也是第三方库,也可能是多个bean共用,若批改会影响其余bean好在quarkus为咱们提供了另一个计划,不必批改bean和拦截器的代码,用注解<font color="blue">dispose</font>润饰指定办法即可,接下来编码验证减少一个一般类ResourceManager.java,假如这是业务中的资源管理服务,能够关上和敞开业务资源,稍后会在配置类中将其指定为beanpackage com.bolingcavalry.service.impl;import io.quarkus.logging.Log;/** * @author zq2599@gmail.com * @Title: 资源管理类 * @Package * @Description: * @date 4/10/22 10:20 AM */public class ResourceManager { public ResourceManager () { Log.info("create instance, " + this.getClass().getSimpleName()); } /** * 假如再次办法中关上资源,如网络、文件、数据库等 */ public void open() { Log.info("open resource here"); } /** * 假如在此办法中敞开所有已关上的资源 */ public void closeAll() { Log.info("close all resource here"); }}配置类SelectBeanConfiguration.java,指定了ResourceManager的生命周期是每次http申请package com.bolingcavalry.config;import com.bolingcavalry.service.impl.ResourceManager;import javax.enterprise.context.RequestScoped;public class SelectBeanConfiguration { @RequestScoped public ResourceManager getResourceManager() { return new ResourceManager(); } }再写一个web服务类ResourceManagerController.java,这外面应用了ResourceManagerpackage com.bolingcavalry;import com.bolingcavalry.service.impl.ResourceManager;import javax.inject.Inject;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;@Path("/resourcemanager")public class ResourceManagerController { @Inject ResourceManager resourceManager; @GET @Produces(MediaType.TEXT_PLAIN) public String get() { resourceManager.open(); return "success"; }}因为ResourceManager的生命周期是<font color="blue">RequestScoped</font>,因而每次申请<font color="blue">/resourcemanager</font>都会实例化一个ResourceManager,申请完结后再将其销毁当初,业务需要是每个ResourceManager的bean在销毁前,都要求其<font color="red">closeAll</font>办法被执行<font color="red">重点来了</font>,在SelectBeanConfiguration.java中新增一个办法,入参是bean,而且要用<font color="blue">Disposes</font>注解润饰,如此,<font color="red">ResourceManager类型的bean在销毁前此办法都会被执行</font>/** * 应用了Disposes注解后,ResourceManager类型的bean在销毁前,此办法都会执行 * @param resourceManager */public void closeResource(@Disposes ResourceManager resourceManager) { // 在这里能够做一些额定的操作,不须要bean参加 Log.info("do other things that bean do not care"); // 也能够执行bean的办法 resourceManager.closeAll();}最初是单元测试类DisposeTest.java,这里用了注解<font color="blue">RepeatedTest</font>示意反复执行,属性值为3,示意反复执行3次@QuarkusTestpublic class DisposeTest { @RepeatedTest(3) public void test() { given() .when().get("/resourcemanager") .then() .statusCode(200) // 查看body内容 .body(is("success")); }}执行单元测试,控制台输入如下图,可见每次申请都有bean创立,也随同着bean销毁,每次销毁都会执行<font color="blue">closeResource</font>办法,合乎预期 ...

September 11, 2023 · 3 min · jiezi

关于后端:静态代理还是动态代理来聊聊Java中的代理设计模式

代理模式(Proxy Design Pattern)是一种结构型设计模式,为一个对象提供一个代理对象,而后应用代理对象管制对原对象的援用。即通过代理对象拜访指标对象。被代理的对象能够是近程对象、创立开销大的对象或须要安全控制的对象。一、代理模式介绍代理模式次要有两个局部: 形象主题:申明一个公共接口,给代理类和实在对象进行实现。让实在对象和代理对象一一对应实在主题:定义所要代理的实在对象,其中包含理论的业务逻辑和操作代理主题:首先代理对象有实在对象的所有接口,保障能齐全代替实在对象。此外还会有其余的办法和操作,来扩大相干的性能其次要构造的UML图如下所示: Subject:形象主题类,通过接口或抽象类申明主题和代理对象实现的业务办法RealSubject:实在主题类,实现Subject中的具体业务,是代理对象所代表的实在对象ProxySubject:代理类,其外部含有对实在主题的援用,它能够拜访、管制或扩大RealSubject的性能Client:客户端,通过应用代理类来拜访实在的主题类依照下面的类图,能够实现如下代码: //主题类接口public interface Subject { void Request();}//实在的主题类public class RealSubject implements Subject{ @Override public void Request() { System.out.println("我是实在的主题类"); }}//代理类public class Proxy implements Subject{ private RealSubject realSubject = new RealSubject(); //保障对实在对象的援用 public void PreRequest(){ ....//调用Request()前的操作 } @Override public void Request() { PreRequest(); //对实在对象的调用 realSubject.Request(); postRequest(); } public void PostRequest(){ ....//调用Request()后的操作 } }//客户端public class Client { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.Request(); }}代理模式有比拟宽泛的应用,比方Spring AOP、RPC、缓存等。在 Java 中,依据代理的创立期间,能够将代理模式分为动态代理和动静代理,上面就来别离论述。 ...

September 10, 2023 · 3 min · jiezi

关于后端:Spring-中-Bean-的生命周期

在您的应用程序中,由Spring IoC容器治理的造成其外围的对象被称为"bean"。一个bean是由Spring IoC容器实例化、组装和治理的对象。这些bean是通过您提供给容器的配置元数据创立的,例如,在后面章节中曾经看到的XML <bean/> 定义。 Bean定义蕴含了所谓的配置元数据,容器须要理解以下内容: 如何创立一个beanBean的生命周期详细信息Bean的依赖关系上述所有的配置元数据都转化为每个bean定义的以下属性汇合。 序号属性和形容1class 这是必填属性,指定要用于创立bean的bean类。2name 此属性惟一地指定bean标识符。在基于XML的配置元数据中,您能够应用id和/或name属性来指定bean标识符。3scope 此属性指定从特定bean定义创立的对象的范畴,将在bean范畴章节中探讨。4constructor-arg 这用于注入依赖项,将在后续章节中探讨。5properties 这用于注入依赖项,将在后续章节中探讨。6autowiring mode 这用于注入依赖项,将在后续章节中探讨。7lazy-initialization mode 提早初始化的bean通知IoC容器在首次申请时创立bean实例,而不是在启动时创立。8initialization method 在容器设置了bean的所有必须属性之后,要调用的回调函数。将在bean生命周期章节中探讨。9destruction method 在蕴含bean的容器销毁时要应用的回调函数。将在bean生命周期章节中探讨。Spring配置元数据 Spring IoC容器与理论编写配置元数据的格局齐全解耦。以下是向Spring容器提供配置元数据的三种重要办法: 基于XML的配置文件。基于注解的配置。基于Java的配置。您曾经看到了如何将基于XML的配置元数据提供给容器,但让咱们看一下蕴含不同bean定义的XML配置文件的另一个示例,包含提早初始化、初始化办法和销毁办法。 <?xml version = "1.0" encoding = "UTF-8"?><beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 一个简略的bean定义 --> <bean id = "..." class = "..."> <!-- 此处是该bean的协作者和配置 --> </bean> <!-- 启用提早初始化的bean定义 --> <bean id = "..." class = "..." lazy-init = "true"> <!-- 此处是该bean的协作者和配置 --> </bean> <!-- 具备初始化办法的bean定义 --> <bean id = "..." class = "..." init-method = "..."> <!-- 此处是该bean的协作者和配置 --> </bean> <!-- 具备销毁办法的bean定义 --> <bean id = "..." class = "..." destroy-method = "..."> <!-- 此处是该bean的协作者和配置 --> </bean> <!-- 更多的bean定义在此处 -->Spring中的Bean作用域 ...

September 10, 2023 · 2 min · jiezi

关于后端:hashmap

HashMap的底层是Hash表构造,元素的排列是依据哈希算法和哈希函数排序的,且不可反复。JDK8以前,Hash表的底层是【数组】+【链表】JDK8及之后,变成了【数组】+【链表】+【红黑树】存入新键值对时,如果呈现哈希抵触,会先判断键是否雷同,如果键雷同,会比拟值,值雷同则不放入,值不同则批改原值;如果键不雷同,则会以链表模式挂下来,并且1.7版本中是头插法,1.8版本是尾插法。 5.1、什么是哈希抵触?哈希抵触就是两个元素在通过哈希函数后,失去的角标是雷同的,在同一个哈希槽中。哈希抵触的四种解决思路别离是:重哈希法,凋谢地址法,建设公共溢出,链地址法。 5.2、HashMap的扩容机制是怎么样的?它什么时候会转化为红黑树?Hash表中数组的离别手动初始化,和主动初始化,主动初初始会在第一次插入元素时开拓空间,默认长度为16,扩容因子为0.75,每次扩容量为本身的2倍长度,扩容之后存入数组的新索引地位就会扭转。手动初始化的话,能够在创建对象时自定义初始数组长度,但HashMap不肯定会自主设置的数值初始化数组,而按2的n次方创立。HashMap1.7版本的的扩容机会是先判断是否达到阈值,达到先扩容,再增加元素,并且采纳的是头插法,也就是旧元素挂在新元素下。而HashMap1.8的扩容机会是先增加元素是否达到阈值,达到间接扩容,且应用的是尾插法,即新元素挂在旧元素上面。初始化后,当存入新的键值对时,会先判断数组长度是否大于64,再判断链表元素是否大于等于8时,如果两者都成立,链表会主动转换成红黑树,如果数组小于64,会从第9个开始先扩容,直到数组大于等于64时,链表长度再减少,就会转为红黑树。细节:在增加第一个元素的时候是间接增加进数组的,而不会进入到红黑树转化的判断的,所以外面的binCount并没有创立。增加第二元素并产生了哈希抵触时,才进入红黑树转化的判断,同时初始化binCount=0,它判断的是binCount>=7,也就是0至7,有8个元素时,再加上没有进行判断的1个元素,即第9个元素时,才会转化为红黑树。 5.2.1、为什么要转为红黑树呢?链表取一个数须要遍历链表,而红黑树相对效率要高。 5.2.2、为什么不间接应用红黑树呢?HashMap源码中有相干形容: “因为树节点的大小是链表节点大小的两倍,所以只有在容器中蕴含足够的节点保障应用才用它”,显然只管转为树使得查找的速度更快,然而在节点数比拟小的时候,此时对于红黑树来说内存上的劣势会超过查找等操作的劣势,天然应用链表更加好,然而在节点数比拟多的时候,综合思考,红黑树比链表要好。 5.2.3、为什么转为红黑树的条件是8而不是第9第10个呢?源码中有对这个进行计算,失常的随机哈希码下,哈希抵触多到超过8个的概率不到千万分之一,简直能够忽略不计了,再往后调整并没有很大意义。如果哈希抵触有那么多,阐明极大可能是人为设置,成心制作哈希抵触导致,这时候就转为化红黑树,来保障查问效率。5.2.3.1、那什么时候退出红黑树呢?当哈希抵触个数从第8个变到第6个时,红黑树转化为链表。 5.2.3.1、6与8之间的第7个抵触时,会是什么状态?分状况看。8退6,是红黑树转链表,6进8,是链表转红黑树,两头的7是避免频繁变动做的一个预留位,如果是8退6,两头的7就是红黑树;如果是6进8,两头的7就是链表。 5.2.4、为什么1.7是头插法,1.8是尾插法?1.7版本应用头插法是因为头插法是操作速度最快的,找到数组地位就间接找到插入地位了,但这样插入方法在并发场景下会因为多个线程同时扩容呈现循环列表,也就是Hashmap的死锁问题。1.8版本退出了红黑树来优化哈希桶中的遍历效率,相比头插法而言,尾插法在操作额定的遍历耗费(指遍历哈希桶)曾经小很多,也能够防止之前的循环列表问题,同时如果曾经变成红黑树了,也不能再用头插法了,而是按红黑树本人的规定排列了。 5.2.4.1、如果是头插法,怎么能力获取之前的旧元素呢?因为1.7版本的头插法,是新元素在下面,旧元素挂新元素前面,所以新元素始终是在数组上的,能够通过在对象上重写toString办法,加上对象的HashCode值,这样只有打印进去雷同的HashCode阐明产生了哈希抵触,这时候只须要遍历即可,要取哪个就指定那个HashCode,雷同就取出,而上一个老元素就是第二个获取的元素。 5.2.4.2、什么是HashMap双链循环/死锁?双链循环是JDK1.7及更早的版本之前才有的问题。在多线程扩容的状况下,一个线程执行到一半,还未扩容,而另一个线程却抢走后行扩容了,这时候可能呈现第一个线程的元素与第二个线程中的元素互相援用的状况,互相援用就会造成死锁。比方一个数线长度为4,有两个数,一个为2,一个为10,那么这两个数都会在索引2上造成哈希桶构造,此时进行扩容,原本在新数组中是2指向10的,后果但之前那个前程正好断在10指向新数组的两头,这就会导至10又从新指向2,最终导while判断中的e永远不会等于null,造成死循环。JDK1.8版本防止了双链循环,但不是完全避免,看过一些测试文章,红黑树之间也可能呈现死循环,只是比拟1.7版本,几率升高。 5.2.5、为什么1.7是先扩容再增加,1.8却改成先增加再扩容?因为1.7版本中的扩容机制有两个条件:1、 寄存新值的时候以后已有元素的个数必须大于等于阈值(数组长度*0.75)。2、 寄存新值的时候以后存放数据产生hash碰撞(以后key计算的hash值换算进去的数组下标地位曾经存在值)要满足以上两个条件,很可能呈现数组16个元素都填满的状况(正好无碰撞填满数组),如果是先增加再扩容,就会导致第17个元素必然产生哈希抵触,这不是咱们要的后果,咱们要的是尽量减少哈希抵触,所以须要先扩容,再放入元素。而在1.8版本中,扩容的条件改成了理论数量大于等于阈值就扩容,所以容许了先增加再扩容这种状况,也可能是作者认为没有1.7那么强制性须要先扩容了,为了更合乎思考逻辑,改成了先增加,再扩容。 5.2.6、1.8版本是否完全避免死循环问题?不能。1.8版本中引进了红黑树,能够升高死循环呈现的机率,但不能完全避免,红黑树之间也可能呈现死循环。 5.3、HashMap为什么数组长度始终是2的n次方?在HashMap的底层对于数组的操作其实是(n-1)&hash,当数组的长度为2的n次时,减1转为二进制后,他被任何数字&上都不会超过这个数字,比方数组长度为8,减1后为7,那么它的数组长度就是0-7,共8个,即元素能够在这个数组上全副排满,而如果是奇数,或者不是2的n次的偶数,肯定会有一个二进制为0,也就是无论另一个数是什么,都不会被存入数组,会节约掉的地位。 5.4、HashMap的扩容为每次是原来的2倍?首先,HashMap的初始化的数组长度肯定是2的n次的,每次扩容仍是原来的2倍的话,就不会毁坏这个法则,每次扩容后,原数据都会进行数据迁徙,依据二进制的计算,扩容后数据要么在原来地位,要么在【原来地位+扩容长度】,这样就不须要从新hash,效率上更高。 5.4、HashMap是怎么让存取效率最高的?如果元素都是平均存储在数据的角标位而不产生抵触,就是最好的。1、尽可能少的产生hash抵触hash函数计算出来的角标尽可能做到平均。2、的确产生了hash抵触——数据结构来解决 数组+链表+红黑树3、HashMap的底层通过扰动函数(即高下位运算)来让数组更平均的被调配。 (h = key.hashCode()) ^ (h >>> 16)扰动函数将本人的前即低16位与高16位运算,能够让数组在65535(int)范畴内更平均的调配。高下位运算:16刚好在32位的两头,前16位和本人的后16位比照,而后再把对比值和数组的比照。 5.5、多线程下的HashMap线程平安吗?为什么?HashMap自身就是不平安的,多线程下,在增加元素时容易呈现数据笼罩状况而失落数据,也可能在扩容时,迁徙数据呈现数据笼罩状况而失落数据。

September 10, 2023 · 1 min · jiezi

关于后端:做难而正确的事-读详谈左晖

《详谈》系列是一个长期的常识工程,是一部以人为单位的当代商业史。作者李翔会找到这个时代优良的商业实践者和价值创造者,与他们深度对话,把他们的成就、教训、办法和挫败一一出现给你。 左晖,链家地产创始人、董事长,贝壳找房创始人、董事长。 作者李翔,资深媒体人,失去 App 总编辑。 本书副标题是:做难而正确的事。这一点最早是从《黑客与画家》中看到,初看不知文中意,再见已是坑中人。当初看过然而齐全不了解,起初因为很多决策上的问题踩了很大的坑,付出了比拟惨重的代价,才晓得原来当初书里说的是这个意思。 另外本书吸引我的一点是,左晖曾提出让从事中介这个职业的人活得有尊严的观点,这让我看到了不一样的中介形象。加上始终都在应用链家团体的服务,更加增强了想要理解一下本书的想法。 左晖的厉害之处:有能力构建起一个宏大的线下服务网络 宏大意味着规模,治理 100 人和治理 10 万人齐全是两码事。 线下意味着这些人要在一个实在的物理空间中工作。 服务意味着这个 10 万级的团队须要有很好的跟人打交道的能力。 网络意味着这个宏大的个人须要彼此之间存在合作而不仅仅是并列关系,存在合作就存在如何建设信赖,如何激励合作而不是变成内耗。 贝壳的使命愿景价值观 使命:有尊严的服务者、更美妙的寓居。 愿景:服务 3 亿个家庭的品质寓居平台。 价值观:客户至上、诚恳可信、单干共赢、拼搏进取。 贝壳从传统的房产中介,赚中介费的一锤子买卖的角色,转变成陪伴客户从选房、交易、寓居的整体服务,格局更大,设想空间更大,机会也更多了。 “有尊严的服务者”的背地,是须要员工自身配得上顾客的“尊重” 咱们一直和经纪人说,你卖了什么房子不重要,你不卖什么房子才是最重要的;你通知消费者这个房子该买不重要,你通知消费者这个房子不该买才是最重要的。站在顾客角度思考,真正从为了中介费服务到为了顾客服务转变,博得了顾客的尊重,本身也能失去相应的取得感。 产业互联网中所有先横着做的人都没戏 李:如果是反过来,先做平台,再做本人的业务,这样的门路可能吗? 左:不可能,先纵后横这个是确定的。明天所有先横着做的人都没戏。 李:淘宝不是先横后纵吗? 左:我感觉产业互联网跟生产互联网还是有很大的差异,产业互联网要更简单一些。 这一点集体有些感触,互联网上的平台通过连贯小 C 来成就平台自身,小 C 越多平台越有价值。 能源的源泉在于置信 贝壳找房做的是平台,其余房产中介能够接入到贝壳上来,然而贝壳有一套从链家衍生进去的治理办法和平台标准,比方公开房屋信息,24 秒钟响应顾客的留言等等,很多中介一开始十分不适应,也十分不认同,阻力十分大。但左晖感觉要让大家置信,好品质就能赢。好服务肯定能失去消费者的信赖。这也是做难而正确的事的一个小的体现。 别把本人干死 只有钱够厚,只有不死就还有机会,这一点跟《创新者的困境》书中提到的观点相似,尝试翻新成功率是很低的,记得留一部分资源,做第二次、第三次尝试。 stay on the table 就有翻盘的机会。 抵赖先进、学习先进、赶超先进 一个优良的人从他人身上学到的货色不会比你学到的少。 一个真正强的团队都是能做到这三点的,包含真正强的民族也是如此。 本文由mdnice多平台公布

September 10, 2023 · 1 min · jiezi

关于后端:为什么颠覆式创新往往发生在新兴企业-读创新者的窘境

作者克莱顿·克里斯坦森(Clayton M. Christensen) 出生于美国盐湖城,1975 年在杨百翰大学以优异体现取得经济学荣誉学士,1979 年在哈佛商学院以优异成绩取得 MBA 学位,1992 年重返哈佛商学院取得 DBA 学位之后并任哈佛商学院传授,任职于哈佛商学院总经理及技术与经营管理部 1995 年度麦肯锡奖得主。克里斯坦森是"颠覆性技术"这一理念的首创者。他的钻研和教学畛域集中在新产品和技术开发治理以及如何为新技术开辟 市场等方面。代表作为《创新者的困境》和《创新者的解答》。 书中通过很多优良成熟的企业在面对破坏性翻新时往往无奈抓住机遇,甚至可能丢掉市场直至毁掉整个公司的例子,论述了延续性翻新和破坏性翻新的差别,并给出一些剖析倡议,对于如何分别破坏性翻新,面对破坏性翻新应该如何抓住机遇,助力企业在一次次科技翻新浪潮中放弃创新能力,基业长青。 先定义什么是”好“的治理 为什么那些被认为是锐意进取、踊跃翻新、认真听取客户意见的企业,会对极具战略意义的技术创新置若罔闻,或是贻误良机呢? 我认为首先应该对“好”的治理下一个定义。能够将认真听取客户意见、客户说什么就做什么定义成”好“的治理,也能够将可能在将来 3 个月或 6 个月内业绩翻倍定义成”好“的治理,还能够将开办一家具备倔强生命力的、受人尊敬的、能够传世的企业定义成”好“的治理。显然书中一开始是将前两者定义成了”好“的治理,那么在这种将谋求企业短期利益是好的治理的评判规范下,将企业放在是否可能取得长期利益的规范下来评判,得进去的测量后果必然是反差很大的。本书上来就抛出这么一个观点,集体认为有点“题目党”的意思,但这也无伤大雅,并不障碍书中前面论述的观点和实践的精彩和价值。 什么是延续性翻新和破坏性翻新 对硬盘行业历史上历次技术改革的钻研结果表明,这一行业存在两种类型的技术改革,这两种改革对行业当先企业的影响也各不相同。第一种技术连续了硬盘行业对产品性能的改善幅度(总容量和磁录密度是最常见的两种指标),而且性能改善的难度可划为一个从渐进到冲破的范畴。在研发和采纳这些技术方面,硬盘行业的支流企业总是处于领先地位。与之相比,第二种翻新则毁坏或从新定义了性能改善模式——这经常导致行业当先企业走向失败。 一般来说,破坏性翻新并不波及特地简单的技术改革,其次要表现形式就是将成品元件组装在一起,但相比之前的产品,产品构造通常会变得更加简略。破坏性翻新并不能为支流市场的客户提供更好的产品,因而这种翻新首先产生在支流市场的可能性很小。相同,破坏性翻新提供的是一种齐全不同的产品组合,只有远离支流市场或对支流市场没有太大意义的新兴市场,客户才会器重这些产品组合的属性。 价值网络的概念 因为客户的反馈较为淡漠,希捷公司的项目经理升高了对 3.5 英寸硬盘的销售预期,而公司的管理层则罗唆勾销了这一我的项目打算。他们这么做的理由是什么呢?因为 5.25 英寸硬盘产品的市场规模更大,而且相比开发新型 3.5 英寸硬盘产品,开发新一代 5.25 英寸硬盘产品能给公司带来更大的销售收入。 因为企业能够通过建设组织构造和确立团队单干的形式,来推动劣势产品的设计,后果可能会最终产生逆转:组织构造及其团队单干形式可能会反过来影响到企业是否设计出新产品。手里拿着锤子,看什么都像钉子。沿着既有的教训和资源提供认知范畴内最佳计划,但在视线以外其实有更颠覆的解决方案,当下最优计划,放在将来看不肯定是。 成熟企业在延续性翻新中所体现出的强势和在破坏性翻新中所体现出的弱势,以及新兴企业与之正好齐全相同的体现,均不是由成熟企业和新兴企业之间技术或组织能力的差别所导致的,真正的起因还是它们处在行业不同的价值网络中。 企业的产品定位不同,面向的客户群体不同,带来产品的差异化和价值的差异化,进而逐步演化成了企业的价值观,耳濡目染的领导着产品的倒退和决策。 另一方面,所谓的以客户为核心的主旨慢慢偏离了轨道,演变成了以客户短期需要为核心,甚至变成了以赚钱为核心,没有将眼光放久远,没有看到将来的趋势。 成熟企业致力于在成熟市场引入破坏性技术,而胜利的新兴企业则发现了一个看重这种技术的新市场。 破坏性技术在支流市场中的劣势,恰好成为了在新兴市场中的劣势。在破坏性技术倒退的初期,支流客户素来都不会抉择应用破坏性产品。 右上角的磁石:高端市场+稳固客源+高利润率 感性的管理者很少能找到充沛的理由进入规模小、需要不明确,而且利润率更低的低端市场。 因而,小型钢铁厂惟一能找到的一个市场可能就是钢筋(螺纹钢)市场了——它在品质、老本和利润率等方面均处于市场最底端。对成熟企业而言,这是最没吸引力的一块市场。这个市场不仅利润率很低,而且客户的忠诚度也是最低的:他们常常随便更换供应商,哪家供应商的售价低他们就与哪家做生意。综合性钢铁制造商简直是急不可待地解脱螺纹钢业务。 在优良企业,凝聚人力物力的总是那些打算进步产品性能,迈向高端市场,并且能给企业带来更高利润率的提案。确实,通过进入高端市场价值网络进步财务绩效的吸引力是如此之大,以至于人们感觉到硬盘行业和挖掘机行业倒退轨线图的右上角,仿佛存在一块微小的磁石。 在高端市场利润率也高,加之有着规模劣势,赚钱绝对容易,干嘛还要花精力去搞费劲不讨好的事呢? 企业员工也有相似的诉求,指望那些心愿在大企业一展宏图的员工全力支持(包含利用他们所把握的资源,并付出微小的工夫和精力)规模较小、市场定位不明确的破坏性我的项目,无异于今人手缚羽翼、挥动翅膀的航行痴梦。 小市场+低利润率无奈激发大企业心中的浪花 除了要应答以后客户的影响外,增长导向型大型企业还必须面对小市场无奈解决大机构的短期增长需要这一难题。所有由破坏性技术催生的市场在最开始时的规模都很小,当先企业在这些市场上接到的第一笔订单也都是小订单,培养了这些新兴市场的企业所建设的老本构造也必须能使企业以很小的规模实现赢利。所有这些因素都要求企业采取措施,将商业开发破坏性翻新我的项目的职责交由小型机构,因为这些小机构会把这些我的项目视为通往增长与胜利的必经之路,而不是企业支流业务之外一个可有可无的鸡肋。 这一点在英特尔晚期守业过程中也有体现。英特尔晚期主营业务是内存,而对于微处理器这种新事物并不感兴趣,而且也并没有看到有什么前景可言。 对于将 8008 这类芯片销售给工程界这个主见,英特尔的市场部反馈淡漠。英特尔成立的主旨是生产内存芯片,这类芯片像刮胡刀那样既易用又滞销。而微处理器则须要用户学习如何应用,对英特尔这家年老的公司来说,必然会面临大量客户反对问题。内存芯片则不会如此。 而芯片的设计师霍夫则不批准这种观点,他提出了别人从未想到的新的微处理器应用领域。比如说,升降机的控制器就能基于微处理器来做。而且,这种处理器能节约老本。如霍夫在 8008 芯片的设计方案中指出的一样,它能够取代大量的一般芯片。工程师能够想方法将这款微处理器退出到他们的产品设计中。反正霍夫本人必定会这么干的。 你无奈对尚不存在的市场进行剖析 最初,越来越多的人都心愿领有本人的小型本田“超级幼兽”与他们的敌人一起在野外飙车,这与本田公司美国团队最后预计的市场截然不同。兴许在北美存在一个尚未开发的越野娱乐用摩托车市场,而本田的小型 50cc “超级幼兽”恰好合乎这个市场的要求。 这一点让我联想到乔布斯对于皮克斯晚期的定位一样。皮克斯晚期的次要精力放在图形计算的电脑硬件和渲染软件,数字动画业务——制作动画短片的团队——最后只是副业,其次要目标是对外展现本人的硬件和软件。而事实上皮克斯的硬件和软件业务始终都在巨额的亏损,反倒是动画业务最终获得了不凡的胜利。 起初乔布斯示意,回首过来,如果本人能理解得更多,就会更早地专一于动画,而不会费神去推动皮克斯的硬件和软件应用。但另一方面,如果乔布斯早就晓得硬件和软件都不会赢利,那么他也不会接手皮克斯。“命运仿佛诱骗我去做这件事,而这兴许是为了把它做得更好。” 亨利·福特曾说过,“如果我最后问消费者他们想要什么,他们应该是会通知我,‘要一匹更快的马!’“。 乔布斯也曾说过,”人们不晓得想要什么,直到你把它摆在他们背后”。 保留实力并珍惜出牌的机会 胜利企业与失败企业的次要差异通常并不在于它们最后的策略有如许完满。在初始阶段剖析什么是正确的策略,其实并不是取得成功的必要条件,更重要的是保留足够的资源(或是与值得信赖的支持者或投资者建设良好的关系),这样,新业务我的项目便能在第 2 次或第 3 次尝试中找到正确的方向。那些在可能调转航向,转而采纳可行的策略之前便用尽了资源或信用度的我的项目,就是失败的我的项目。 ...

September 10, 2023 · 1 min · jiezi

关于后端:Spring-Boot-中使用-Poitl-渲染数据并生成-Word-文档

<article class=“article fmt article-content”><blockquote>本文 Demo 已收录到 demo-for-all-in-java 我的项目中,欢送大家 <code>star</code> 反对!后续将继续更新!</blockquote><h2>前言</h2><blockquote>产品经理急冲冲地走了过去。「当初须要将按这些数据生成一个 Word 报告文档,你来安顿下」</blockquote><p>我的项目中有这么一个需要,须要将用户填写的数据填充到一个 Word 文档中,而这个 Word 文档是人家给定了的。<strong>换句话说,让你依照这个文档的内容格局生成新的文档。</strong></p><h2>什么是 Poi-tl ?</h2><blockquote>官网:http://deepoove.com/poi-tl/1.9.x/</blockquote><p><code>poi-tl</code>(poi template language)是一种 Word 模板引擎,能够基于 Word 模板和数据生成新的文档,它的底层是通过 Apache POI 来实现的。</p><p>Apache POI 不仅封装了易用的文档 API (文本、图片、表格、页眉、页脚、图表等),也能够在底层间接操作文档XML构造。</p><p><code>poi-tl</code> 领有如下个性(<strong>理解瞄一眼就行</strong>):</p><table><thead><tr><th>内容</th><th>形容</th></tr></thead><tbody><tr><td>文本</td><td>将标签渲染为文本</td></tr><tr><td>图片</td><td>将标签渲染为图片</td></tr><tr><td>表格</td><td>将标签渲染为表格</td></tr><tr><td>列表</td><td>将标签渲染为列表</td></tr><tr><td>图表</td><td>条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、饼图(3D饼图)等图表渲染</td></tr><tr><td>If Condition判断</td><td>暗藏或者显示某些文档内容(包含文本、段落、图片、表格、列表、图表等)</td></tr><tr><td>Foreach Loop循环</td><td>循环某些文档内容(包含文本、段落、图片、表格、列表、图表等)</td></tr><tr><td>Loop表格行</td><td>循环渲染表格的某一行</td></tr><tr><td>Loop表格列</td><td>循环渲染表格的某一列</td></tr><tr><td>Loop有序列表</td><td>反对有序列表的循环,同时反对多级列表</td></tr><tr><td>图片替换</td><td>将原有图片替换成另一张图片</td></tr><tr><td>书签、锚点、超链接</td><td>反对设置书签,文档内锚点和超链接性能</td></tr><tr><td>弱小的表达式</td><td>齐全反对SpringEL表达式,能够扩大更多的表达式:OGNL, MVEL…</td></tr><tr><td>标签定制</td><td>反对自定义标签前后缀</td></tr><tr><td>文本框</td><td>文本框内标签反对</td></tr><tr><td>款式</td><td>模板即款式,同时代码也能够设置款式</td></tr><tr><td>模板嵌套</td><td>模板蕴含子模板,子模板再蕴含子模板</td></tr><tr><td>合并</td><td>Word合并Merge,也能够在指定地位进行合并</td></tr><tr><td>用户自定义函数(插件)</td><td>在文档任何地位执行函数</td></tr></tbody></table><p>咱们就能够应用这个它来实现这个需要。</p><h2>如何应用 Poi-tl ?</h2><p>本篇文章将以 Spring Boot 我的项目作为演示,屏幕前的敌人们能够一起跟着我的步骤来,实际一番!</p><ol><li><strong>首先创立一个 Spring Boot 我的项目,版本目前我的 Demo 是 2.2.1,你能够更改你的 Spring Boot 版本,那当初我这里曾经创立好了。</strong></li></ol><p>其中, <code>pom.xml</code> 只有两个依赖项,一个 web 和一个 test :</p><pre><code class=“xml”><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!– Spring Boot Test 依赖 –><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency></code></pre><ol start=“2”><li><strong>接着在 <code>pom.xml</code> 中引入 Poi-tl 的依赖项</strong>:</li></ol><pre><code class=“xml”><!– Poi-tl Word 模板引擎–><dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.9.1</version></dependency></code></pre><ol start=“3”><li><strong>筹备一个 Word 模板</strong></li></ol><p>这一步你能够本人动手做一个 Word 模板,这里我先演示下。就先创立一个名为 <code>Hello World.docx</code> 的 Word 文档,模板内容如下:</p><p></p><p>找一个你喜爱的地位寄存这个模板,我当初把它放到我的项目的 <code>resource</code> 目录。</p><blockquote><code>{{title}}</code> 这种由两个大括号包住的,目前能够看成占位符,这个模板中有 4 个占位符,后续的数据就渲染到这些中央上。</blockquote><ol start=“4”><li><strong>获取模板所在的门路,并将数据渲染到模板上</strong></li></ol><p>渲染只需一行代码,就是应用 <code>XWPFTemplate</code> 的 API 就能够了,通过 <code>complie</code> 和 <code>render</code> 办法,就能够将数据渲染到模板中,失去渲染好的新文档。</p><pre><code class=“java”>@SpringBootTestpublic class PoiTlApplicationTest { @Test public void test() { // 获取 Word 模板所在门路 String filepath = this.getClass().getClassLoader().getResource(“hello-world.docx”).getPath(); // 通过 XWPFTemplate 编译文件并渲染数据到模板中 XWPFTemplate template = XWPFTemplate.compile(filepath).render( new HashMap<String, Object>(){{ put(“title”, “Hello, poi-tl Word模板引擎”); put(“text”, “Hello World”); put(“author”, “god23bin”); put(“description”, “这还不关注 god23bin ?再不关注我可要求你关注了!”); }}); try { // 将实现数据渲染的文档写出 template.writeAndClose(new FileOutputStream(“output.docx”)); } catch (IOException e) { e.printStackTrace(); } } }</code></pre><p>执行这个单元测试,就能够看到在我的项目所在目录下输入了新的文档 <code>output.docx</code>,关上这个文档,咱们就能够看到如下图所示的内容:</p><p></p><p><strong>功败垂成,这就是渲染好的新文档了,是不是很简略,一行代码就实现了依据模板进行数据的渲染!</strong></p><h2>相干概念</h2><h3>模板</h3><p>模板是 Docx 格局的 Word 文档,咱们能够应用 Microsoft office、WPS Office 等软件来制作模板。</p><h3>标签</h3><p>下面说到 <code>{{title}}</code> 这种了解成占位符,实际上,官网是称之为「<strong>标签</strong>」。</p><p>所有的标签都是以 <code>{{</code> 结尾,以 <code>}}</code> 结尾,标签能够呈现在任何地位,包含页眉,页脚,表格外部,文本框等。</p><blockquote>表格布局能够设计出很多优良业余的文档,举荐应用表格布局。</blockquote><p>poi-tl 模板遵循 <code>所见即所得</code> 的设计,模板和标签的款式会被齐全保留,就如我下面演示的,<strong>一级题目和字体色彩的款式就被保留下来了。</strong></p><h3>数据模型</h3><p>数据模型,也就是咱们须要渲染到模板中的数据,能够是哈希表,也能够是一般的 Java 对象。</p><ol><li>哈希表(key 名是标签名):</li></ol><pre><code class=“java”>Map<String, Object> data = new HashMap<>();data.put(“title”, “Hello, poi-tl Word模板引擎”);data.put(“text”, “Hello World”);data.put(“author”, “god23bin”);data.put(“description”, “这还不关注 god23bin ?再不关注我可要求你关注了!”);</code></pre><ol start=“2”><li>Java 对象(属性名是标签名):</li></ol><pre><code class=“java”>public class DataModel { private String title; private String text; private String author; private String description; // 省略 getter 和 setter}DataModel data = new DataModel();data.setTitle(“Hello, poi-tl Word模板引擎”);data.setText(“Hello World”);data.setAuthor(“god23bin”);data.setDescription(“这还不关注 god23bin ?再不关注我可要求你关注了!”);</code></pre><p>有了哈希表和或者 Java 对象的数据模型后,<strong>将这个数据丢给渲染的 API</strong>,就能够实现数据的渲染了。</p><h2>标签的写法</h2><p>poi-tl 里只有标签,那么咱们须要晓得标签的写法是怎么的。在 Word 文档里,能够有:文本、图片、表格、列表等元素,那么对应的,咱们的标签也有这些。</p><h3>文本标签 {{var}}</h3><p>简略粗犷,间接 <code>{{标签名}}</code> 就是文本标签了。</p><h3>图片标签 {{@var}}</h3><p><code>{{@标签名}}</code> 就是图片标签,<code>@</code> 标识了这个标签的类型是图片,其余的也是同理,不同的符号标识不同类型的标签。</p><h3>表格标签 {{#var}}</h3><p>应用 <code>#</code> 标识这是一个表格标签。</p><h3>列表标签 {{var}}</h3><p>应用 <code></code> 标识这是一个列表标签。</p><h3>其余的标签</h3><p>剩下的标签还有很多,具体的内容你能够浏览官网文档,这里就不一一介绍了。</p><p>上面我将写下我用过的内容。</p><h2>插件</h2><p>插件,又称为<strong>自定义函数</strong>,它容许咱们在模板标签地位处执行事后定义好的函数。因为插件机制的存在,咱们简直能够在模板的任何地位执行任意操作。</p><p><strong>插件是 poi-tl 的外围</strong>,默认的标签和援用标签都是通过插件加载。</p><h3>默认插件</h3><p>poi-tl 默认提供了八个策略插件,用来解决文本、图片、列表、表格、文档嵌套、援用图片、援用多系列图表、援用单系列图表等:</p><ul><li>TextRenderPolicy</li><li>PictureRenderPolicy</li><li>NumberingRenderPolicy</li><li>TableRenderPolicy</li><li>DocxRenderPolicy</li><li>MultiSeriesChartTemplateRenderPolicy</li><li>SingleSeriesChartTemplateRenderPolicy</li><li>DefaultPictureTemplateRenderPolicy</li></ul><p>因为这 8 个插件是常常用到的,所以这些插件被注册为不同的标签类型,也就是咱们看到过的 <code>{{var}}、{{@var}}、{{#var}}</code> 等不同类型的标签,从而搭建了 poi-tl 的标签体系。</p><p>除了这 8 个通用的策略插件外,还内置了一些额定用处的插件:</p><table><thead><tr><th><code>DynamicTableRenderPolicy</code></th><th>动静表格插件,容许间接操作表格对象</th><th>示例-动静表格</th></tr></thead><tbody><tr><td><code>HackLoopTableRenderPolicy</code></td><td>循环表格行,下文会具体介绍</td><td>示例-表格行循环</td></tr><tr><td><code>LoopColumnTableRenderPolicy</code></td><td>循环表格列</td><td>示例-表格列循环</td></tr><tr><td><code>BookmarkRenderPolicy</code></td><td>书签和锚点</td><td>示例-Swagger文档</td></tr><tr><td><code>JSONRenderPolicy</code></td><td>高亮显示JSON代码块</td><td>示例-Swagger文档</td></tr><tr><td><code>AbstractChartTemplateRenderPolicy</code></td><td>援用图表插件,容许间接操作图表对象</td><td> </td></tr><tr><td><code>ParagraphRenderPolicy</code></td><td>渲染一个段落,能够蕴含不同款式文本,图片等</td><td> </td></tr><tr><td><code>DocumentRenderPolicy</code></td><td>渲染多个段落和表格</td><td> </td></tr><tr><td><code>TOCRenderPolicy</code></td><td>Beta试验性能:目录,打开文档时须要更新域</td><td> </td></tr></tbody></table><h3>应用插件</h3><p>为了让插件在某个标签处执行,咱们须要将<strong>插件与标签绑定</strong>。</p><p>当咱们有个模板标签为 <code>{{description}}</code>,默认是文本标签,如果心愿在这个地位做些不一样或者更简单的事件,咱们能够<strong>将插件利用到这个模板标签</strong>,比方渲染 HTML:</p><pre><code class=“java”>ConfigureBuilder builder = Configure.builder();builder.bind(“description”, new HtmlRenderPolicy());</code></pre><p><strong>此时,<code>{{description}}</code> 将不再是一个文本标签,而是一个自定义的反对 HTML 渲染的标签。</strong></p><p>当然,这里的 HTML 渲染的插件,默认是没有提供的,须要引入以下的依赖项,能力反对 HTML 的渲染。</p><pre><code class=“xml”><!– 反对渲染 HTML 的插件 –><dependency> <groupId>io.github.draco1023</groupId> <artifactId>poi-tl-ext</artifactId> <version>0.3.3</version></dependency></code></pre><p>示例:咱们对 {{author}} 这个标签绑定上反对 HTML 渲染的插件,这样就能渲染 HTML 的文本了。</p><pre><code class=“java”>@SpringBootTestpublic class PoiTlApplicationTest { @Test public void test() { // 获取 Word 模板所在门路 String filepath = this.getClass().getClassLoader().getResource(“hello-world.docx”).getPath(); // 给标签绑定插件 Configure configure = Configure.builder().bind(“author”, new HtmlRenderPolicy()).build(); // 通过 XWPFTemplate 编译文件并渲染数据到模板中 XWPFTemplate template = XWPFTemplate.compile(filepath, configure).render( new HashMap<String, Object>(){{ put(“title”, “Hello, poi-tl Word模板引擎”); put(“text”, “Hello World”); put(“author”, “<h2>god23bin</h2>”); put(“description”, “这还不关注 god23bin ?再不关注我可要求你关注了!”); }}); try { // 将实现数据渲染的文档写出 template.writeAndClose(new FileOutputStream(“output.docx”)); } catch (IOException e) { e.printStackTrace(); } } }</code></pre><p>生成的 Word 文档如下图所示,能够看到 {{author}} 这个标签的 HTML 文本曾经渲染胜利了!(蓝框框)</p><p></p><h2>表格行循环</h2><p>当有相似如下需要的时候,在表格里展现多行同类型的数据,那么就须要用到表格的行循环了。</p><p></p><p>这里也是波及到插件的,具体就是应用 <code>HackLoopTableRenderPolicy</code> 这个插件策略,这个策略可能依据汇合数据进行循环渲染,这样就渲染数据到表格的行上了,汇合有多少个元素,那么就有多少行。</p><p>咱们来看下这个表格行循环的模板是怎么写的,是这样的:</p><p></p><p>能够看到 <code>{{articles}}</code> 和 <code>{{columns}}</code> 是规范的文本标签,咱们这里将这两个标签置于<strong>循环行的上一行</strong>,循环行里设置要循环的标签和内容,留神这里的标签是应用 <code>[]</code> 的,以此来辨别规范的标签语法。</p><p><strong>同时 <code>{{articles}}</code> 和 <code>{{columns}}</code> 标签对应的数据就是文章和专栏的汇合。</strong></p><p>咱们写一个该模板的数据模型,以 Java 对象来写,同时模仿数据从数据库中读取。</p><p><strong>数据模型:AcWordModel</strong></p><pre><code class=“java”>public class AcWordModel { /** * 文章明细数据模型-表格行循环 / private List<Article> articles; /* * 专栏明细数据模型 / private List<SpecialColumn> columns; // 省略 getter 和 setter}</code></pre><p>其中的 Article 和 SpecialColumn 模型如下:</p><pre><code class=“java”>public class Article { private String title; private String tags; private Integer reading; private Integer likes; // 省略 getter 和 setter}</code></pre><pre><code class=“java”>public class SpecialColumn { private String name; private Integer subscription; private Integer nums; // 省略 getter 和 setter}</code></pre><p>进行测试,获取数据和模板,让标签和表格行循环的插件进行绑定</p><pre><code class=“java”> @Test public void rowLoopTest() { // 获取数据,这里伪装是从数据库中查问失去的 AcWordModel data = getFromDB(); // 获取 Word 模板所在门路 String filepath = this.getClass().getClassLoader().getResource(“table-row-loop.docx”).getPath(); // 给标签绑定插件,这里就绑定表格行循环的插件 Configure configure = Configure.builder() .bind(“articles”, new HackLoopTableRenderPolicy()) .bind(“columns”, new HackLoopTableRenderPolicy()) .build(); // 通过 XWPFTemplate 编译文件并渲染数据到模板中 XWPFTemplate template = XWPFTemplate.compile(filepath, configure).render(data); try { // 将实现数据渲染的文档写出 template.writeAndClose(new FileOutputStream(“ac-word.docx”)); } catch (IOException e) { e.printStackTrace(); } }</code></pre><p>这样,就能实现表格的行循环了!</p><h2>封装 Word 渲染生成新文档的工具</h2><p>咱们能够再封装下这个 API,写一个工具类,如下:</p><pre><code class=“java”>package cn.god23bin.demo.util;import com.deepoove.poi.XWPFTemplate;import com.deepoove.poi.config.Configure;import java.io.FileOutputStream;import java.io.IOException;import java.util.Map;public class WordUtil { /* * 生成 word 文档 * @param wordTemplatePath word 模板门路 * @param targetWordFilePath 生成指标文档门路 * @param data 待渲染的数据模型-哈希表模式 / public static void generateWordFile(String wordTemplatePath, String targetWordFilePath, Map<String, Object> data) { XWPFTemplate template = XWPFTemplate.compile(wordTemplatePath).render(data); try { template.writeAndClose(new FileOutputStream(targetWordFilePath)); } catch (IOException e) { e.printStackTrace(); } } /* * 生成 word 文档 * @param wordTemplatePath word 模板门路 * @param targetWordFilePath 生成指标文档门路 * @param data 待渲染的数据模型-Java对象模式 / public static void generateWordFile(String wordTemplatePath, String targetWordFilePath, Object data) { XWPFTemplate template = XWPFTemplate.compile(wordTemplatePath).render(data); try { template.writeAndClose(new FileOutputStream(targetWordFilePath)); } catch (IOException e) { e.printStackTrace(); } } /* * 生成 word 文档 * @param wordTemplatePath word 模板门路 * @param targetWordFilePath 生成指标文档门路 * @param data 待渲染的数据模型-哈希表模式 * @param configure 渲染配置 / public static void generateWordFile(String wordTemplatePath, String targetWordFilePath, Map<String, Object> data, Configure configure) { XWPFTemplate template = XWPFTemplate.compile(wordTemplatePath, configure).render(data); try { template.writeAndClose(new FileOutputStream(targetWordFilePath)); } catch (IOException e) { e.printStackTrace(); } } /* * 生成 word 文档 * @param wordTemplatePath word 模板门路 * @param targetWordFilePath 生成指标文档门路 * @param data 待渲染的数据模型-Java对象模式 * @param configure 渲染配置 */ public static void generateWordFile(String wordTemplatePath, String targetWordFilePath, Object data, Configure configure) { XWPFTemplate template = XWPFTemplate.compile(wordTemplatePath, configure).render(data); try { template.writeAndClose(new FileOutputStream(targetWordFilePath)); } catch (IOException e) { e.printStackTrace(); } }}</code></pre><h2>最初的最初</h2><p><strong>心愿各位屏幕前的</strong><code>靓仔靓女们</code><strong>给个三连!你轻轻地点了个赞,那将在我的心里世界削减一颗亮堂而夺目的星!</strong></p><p><strong>咱们下期再见!</strong></p></article> ...

September 10, 2023 · 4 min · jiezi

关于后端:EECS-370模拟器

Project 1 EECS 370 (Fall 2023)Worth: 100 points 0. Starter Codestarter_1a.tar.gz files DescriptionMakefile Makefile to compile the projectspec.as Spec test case assembly filespec.mc.correct Correct machine code output for spec test casestarter_assembler.c Starter code for the LC-2K assemblerstarter_1s.tar.gzfilesDescriptionMakefile Makefile to compile the projectspec.mcSpec test case machine code file, this is the same as spec.mc.correctfrom P1Aspec.out.correctCorrect output for spec test case - note that your simulator shouldwrite to standard outstarter_assembler.c Starter code for the LC-2K simulatorThere is no starter code for project 1M, the assembly multiplication program.Feel free to use wget and tar as follows:Try clicking the line numbers to copy terminal commands!$ wgethttps://eecs370.github.io/project_1_spec/starter_1a.tar.gzSaving to: ‘starter_1a.tar.gz’terminal ...

September 10, 2023 · 6 min · jiezi

关于后端:Linux内核分析与应用3进程管理

本系列是对 陈莉君 老师 Linux 内核剖析与利用 的学习与记录。讲的十分之好,举荐观看 留此记录,走马观花,可作抛砖引玉 3.1 过程概述一个程序通过编译器将其编译成汇编程序,通过汇编器将其汇编成指标代码,通过链接器造成可执行文件a.out或者elf格局,最初交给操作系统来执行 过程最根本的状态有三种: 就绪态,睡眠态和运行态,在具体的操作系统中,可能实例化出多个状态. PCB: Process Control Block task_struct构造体位于sched.h中 对于过程来说,它的动态体现就是程序,平时都安安静静呆在磁盘上,而一旦运行起来,就变成了计算机里的数据和状态的总和; 运行着的程序就是一个过程. 3.2 Linux过程创立 对于过程,线程,内核线程,内核应用惟一的数据结构task_struct来别离示意,也应用雷同的调度算法对其进行调度. 只管看起来差别很大,但最初都通过do_fork别离创立. 创立过程和创立线程调用了不同的函数,别离为fork和pthread_create,而对应的零碎调用别离为fork和clone. 所有的零碎调用进入内核只有一个入口,但进入当前就各奔前程,各有各的服务历程;而离别是临时的,最终还是会归到一处,do_fork就是它们的聚合点. 父子过程共享内存的地址空间,但父过程的页表除外 copy_process()函数次要是为子过程创立父过程PCB的正本 3.3 Linux过程调度 所谓调度,理论就是从就绪队列中,抉择一个过程投入到CPU中运行. "主战场"是就绪队列,外围是调度算法,本质是过程的切换 O(1)调度: 将单链表变为多链表来实现,从O(n)升高到了O(1) 机制与策略拆散 齐全偏心调度---CFS, 没有了工夫片的概念,而是调配CPU应用的比例 同一时刻,一个CPU上运行的过程只能有一个. 当一个过程占用CPU的时候,其余过程必须期待 应用到了红黑树 CFS中的就绪队列,就是一棵已虚构工夫为键值的红黑树, 虚构工夫越小的过程,越凑近红黑树的左端, 调度器每次抉择位于红黑树左端的过程. ...

September 10, 2023 · 1 min · jiezi

关于后端:Linux内核分析与应用2内存寻址

本系列是对 陈莉君 老师 Linux 内核剖析与利用 的学习与记录。讲的十分之好,举荐观看 留此记录,走马观花,可作抛砖引玉 2.1 内存寻址 <font color='6666ff'>数据间断存储和抉择读取思维,是目前咱们应用的简直所有机器运行背地的灵魂</font> 计算机体系结构中的外围问题之一,就是如何无效地进行内存寻址; 内存寻址技术,从某种程度上代表了计算机技术. "段"的引入: 段形容了一块无限的内存区域,区域的起始地位存在专门的寄存器,也就是段寄存器中. "保护模式"的引入: 拜访内存时不能间接从段寄存器中取得段的起始地址,而需通过额定的转化或查看 "黄金时代": Linux内核中的C和汇编语言用的GNU的扩大C汇编语言用的是AT&T的汇编格局与Intel的汇编格局稍有差别在C语言中,也能够嵌入汇编语言,叫做GCC嵌入式汇编 2.2 段机制将虚地址转换为线性地址 应用readelf和objdump解析指标文件 MMU: 内存治理单元,和CPU是在一起的.MMU把虚地址转化成物理地址,送给存储器. (Intel)I386的体系结构 2.3 分页机制分页在分段之后进行,其作用是实现从线性地址到物理地址的转换 必须在保护模式下能力启动分页性能 在32位零碎上个别默认为4K大小,也能够是2MB或4MB 64位零碎上,能够是4KB,8KB,最大能够是256MB 分页使得每个过程能够领有本人独立的虚拟地址空间 (更多可参考 为什么 Linux 默认页大小是 4KB) 两级页表: Linux四级分页模式 I386体系结构(下) 2.4 入手实际-将虚拟地址转换成物理地址 页全局目录 所有的过程都共享一个内核页表 最新的CPU曾经反对五级页表 64位零碎中曾经不再用"高级内存" mknod命令 章节测试: <1>.操作系统启动时,处理器处于保护模式 (错) <2>.X86中段的形容蕴含基地址和界线 (错) ...

September 10, 2023 · 1 min · jiezi

关于后端:quarkus依赖注入之六发布和消费事件

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本文是《quarkus依赖注入》系列的第六篇,次要内容是学习事件的公布和接管如果您用过Kafka、RabbitMQ等消息中间件,对音讯的作用应该不会生疏,通过音讯的订阅和公布能够升高零碎之间的耦合性,这种形式也能够用在利用外部的多个模块之间,在quarkus框架下就是<font color="blue">事件的公布和接管</font>本篇会演示quarkus利用中如何公布事件、如何接管事件,全文由以下章节形成同步事件异步事件同一种事件类,用在不同的业务场景优化事件元数据同步事件同步事件是指事件公布后,事件接受者会在同一个线程处理事件,对事件发布者来说,相当于公布之后的代码不会立刻执行,要等到事件处理的代码执行结束后同步事件公布和承受的开发流程如下图<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/%E6%B5%81%E7%A8%8B%E5%9B%BE%20(20).jpg" alt="流程图 (20)" style="zoom:50%;" /> 接下来编码实际,先定义事件类MyEvent.java,如下所示,该类有两个字段,source示意起源,consumeNum作为计数器能够累加public class MyEvent { /** * 事件源 */ private String source; /** * 事件被生产的总次数 */ private AtomicInteger consumeNum; public MyEvent(String source) { this.source = source; consumeNum = new AtomicInteger(); } /** * 事件被生产次数加一 * @return */ public int addNum() { return consumeNum.incrementAndGet(); } /** * 获取事件被生产次数 * @return */ public int getNum() { return consumeNum.get(); } @Override public String toString() { return "MyEvent{" + "source='" + source + '\'' + ", consumeNum=" + getNum() + '}'; }}而后是公布事件类,有几处要留神的中央稍后会提到package com.bolingcavalry.event.producer;import com.bolingcavalry.event.bean.MyEvent;import io.quarkus.logging.Log;import javax.enterprise.context.ApplicationScoped;import javax.enterprise.event.Event;import javax.inject.Inject;@ApplicationScopedpublic class MyProducer { @Inject Event<MyEvent> event; /** * 发送同步音讯 * @param source 音讯源 * @return 被生产次数 */ public int syncProduce(String source) { MyEvent myEvent = new MyEvent("syncEvent"); Log.infov("before sync fire, {0}", myEvent); event.fire(myEvent); Log.infov("after sync fire, {0}", myEvent); return myEvent.getNum(); }}上述代码有以下几点要留神:注入Event,用于公布事件,通过泛型指定事件类型是<font color="blue">MyEvent</font>公布同步事件很简略,调用<font color="blue">fire</font>即可因为是同步事件,会期待事件的消费者将生产的代码执行结束后,fire办法才会返回如果消费者减少了myEvent的记数,那么myEvent.getNum()应该等于计数的调用次数接下来是生产事件的代码,如下所示,只有办法的入参是事件类<font color="blue">MyEvent</font>,并且用<font color="red">@Observes</font>润饰该入参,即可成为MyEvent事件的同步消费者,这里用sleep来模仿执行了一个耗时的业务操作package com.bolingcavalry.event.consumer;import com.bolingcavalry.event.bean.MyEvent;import io.quarkus.logging.Log;import javax.enterprise.context.ApplicationScoped;import javax.enterprise.event.Observes;@ApplicationScopedpublic class MyConsumer { /** * 生产同步事件 * @param myEvent */ public void syncConsume(@Observes MyEvent myEvent) { Log.infov("receive sync event, {0}", myEvent); // 模仿业务执行,耗时100毫秒 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 计数加一 myEvent.addNum(); }}最初,写单元测试类验证性能,在MyProducer的syncProduce办法中,因为是同步事件,MyConsumer.syncConsume办法执行结束才会继续执行event.fire前面的代码,所以syncProduce的返回值应该等于1package com.bolingcavalry;import com.bolingcavalry.event.consumer.MyConsumer;import com.bolingcavalry.event.producer.MyProducer;import com.bolingcavalry.service.HelloInstance;import com.bolingcavalry.service.impl.HelloInstanceA;import com.bolingcavalry.service.impl.HelloInstanceB;import io.quarkus.test.junit.QuarkusTest;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.Test;import javax.enterprise.inject.Instance;import javax.inject.Inject;@QuarkusTestpublic class EventTest { @Inject MyProducer myProducer; @Inject MyConsumer myConsumer; @Test public void testSync() { Assertions.assertEquals(1, myProducer.syncProduce("testSync")); }}执行单元测试,如下所示,合乎预期,事件的发送和生产在同一线程内程序执行,另外请关注日志的工夫戳,可见MyProducer的第二条日志,是在MyConsumer日志之后的一百多毫秒,这也证实了程序执行的逻辑 ...

September 10, 2023 · 4 min · jiezi

关于后端:Linux内核分析与应用

Linux 内核剖析与利用 走马观花,可作抛砖引玉 1.概述 用到的几个命令:insmod dmesglsmod 章节测试:局部可参考 <1>. Linux得以风行,是因为遵循了GPL协定,并不是因为遵循POSIX规范 (错) linux操作系统概述 linux概述 <2>. 从Linux操作系统的整体构造来看,分两大部分,用户空间的应用程序和内核空间的os内核,二者之间是一种c/s构造,os是服务者,应用程序是客户,是一种申请和响应的关系。 (对) Linux用户空间与内核空间 阮一峰-User space 与 Kernel space <3>.<font color="9966ff">Linux内核提供机制而不是策略,零碎调用是一种策略</font> (错) 对于Unix/Linux的设计有一句通用的格言“提供机制而不是策略”。换句话说,零碎调用形象出了用于实现某种确定目标的函数。至干这些函数怎么用齐全不须要内核去关怀。区别对待机制(mechanism)和策略(policy)是Unix/Linux设计中的一大亮点。大部分的编程问题都能够被切割成两个局部:“须要提供什么性能”(机制)和“怎么实现这些性能”(策略)。 <4>.内核源码中的双向链表和哈希表都相当于内核源码中的根本类型,对其操作只须要调用内核提供的相应API就能够。 (对) Linux内核中对双向链表的应用,几乎和int型一样频繁 <5>.Linux内核把双链表作为根本类型寄存于types.h文件中,是为了暗藏双链表的指针个性。 (对) Linux双向链表的定义次要波及到两个文件: include/linux/types.hinclude/linux/list.hLinux内核中双向链表的经典实现 <6>. list.h中的list_entry()宏通过一个构造体中字段的地址能够求出该构造体的地址,从而能够拜访构造体的其余成员,是一种逆向思维。 (对) Linux内核中的list_head构造体以及list_entry宏 <7>.Linux内核是单内核构造,执行效率高,可维护性好 (错) 微内核效率不如单内核,但可维护性要好。minix,qnx,l4,还有谷歌刚推出的fuchsia,均为微内核。linux大多数为单内核 <8>.内核文档中https://www.kernel.org/doc/html/latest/ 只蕴含各个子系统的文档 (错) <9>.可加装的内核模块在内核运行时候可加载和卸载,是开发一个新的文件系统,驱动程序的根本机制。 (对) <10>.内核模块的修饰符__init可加可不加,对模块的运行没有什么影响 (错) linux kernel __init和__exit宏的作用 Linux开发实战指南文档(这篇不错) <11>.编写Linux内核模块时,不须要独自写一个Makefile文件,间接编译就能够 (错) <12>.Linux内核模块运行在用户空间 (错) <13>. 微内核比单内核的效率高 (错) ...

September 9, 2023 · 1 min · jiezi

关于后端:10分钟从实现和使用场景聊聊并发包下的阻塞队列

上篇文章12分钟从Executor自顶向下彻底搞懂线程池中咱们聊到线程池,而线程池中蕴含阻塞队列 这篇文章咱们次要聊聊并发包下的阻塞队列 阻塞队列什么是队列? 队列的实现能够是数组、也能够是链表,能够实现先进先出的程序队列,也能够实现先进后出的栈队列 那什么是阻塞队列? 在经典的生产者/消费者模型中,生产者们将生产的元素放入队列,而消费者们从队列获取元素生产 当队列已满,咱们会手动阻塞生产者,直到消费者生产再来手动唤醒生产者 当队列为空,咱们会手动阻塞消费者,直到生产者生产再来手动唤醒消费者 在这个过程中因为应用的是一般队列,阻塞与唤醒咱们须要手动操作,保障同步机制 阻塞队列在队列的根底上提供期待/告诉性能,用于线程间的通信,防止线程竞争死锁 生产者能够看成往线程池增加工作的用户线程,而消费者则是线程池中的工作线程 当阻塞队列为空时阻塞工作线程获取工作,当阻塞队列已满时阻塞用户线程向队列中增加工作(创立非核心线程、回绝策略) API阻塞队列提供一下四种增加、删除元素的API,咱们罕用阻塞期待/超时阻塞期待的API 办法名抛出异样返回true/false阻塞期待超时阻塞期待增加add(Object)offer(Object)put(Object)offer(Object,long,TimeUnit)删除remove()poll()take()poll(long,TimeUnit)抛出异样:队满add 抛出异样IllegalStateExceptio ;队空remove 抛出异样NoSuchElementException返回值: 队满offer返回false,队空poll返回null阻塞期待: 队满时put会阻塞线程 或 队空时take会阻塞线程超时阻塞期待: 在阻塞期待、返回true/false的根底上减少超时期待(期待肯定工夫就退出期待)阻塞队列的偏心与不偏心什么是阻塞队列的偏心与不偏心? 当阻塞队列已满时,如果是偏心的,那么阻塞的线程依据先后顺序从阻塞队列中获取元素,不偏心则反之 实际上阻塞队列的偏心与不偏心,要看实现阻塞队列的锁是否偏心 阻塞队列个别默认应用不偏心锁 ArrayBlockingQueue从名称看就能够晓得它是数组实现的,咱们先来看看它有哪些重要字段  public class ArrayBlockingQueue<E> extends AbstractQueue<E>         implements BlockingQueue<E>, java.io.Serializable {      //存储元素的数组     final Object[] items;      //记录元素出队的下标     int takeIndex;      //记录元素入队的下标     int putIndex;      //队列中元素数量     int count;      //应用的锁     final ReentrantLock lock;      //出队的期待队列,作用于消费者     private final Condition notEmpty;      //入队的期待队列,作用于生产者     private final Condition notFull;      }看完关键字段,咱们能够晓得:ArrayBlockingQueue由数组实现、应用并发包下的可重入锁、同时用两个期待队列作用生产者和消费者 ...

September 9, 2023 · 9 min · jiezi

关于后端:垃圾回收之Python-PHP-Java-Go对比

本文比照了四种语言在垃圾回收方面的实现,其指标都是雷同的,即心愿做到精确又高效的辨认和清理内存中的垃圾对象,不同语言之间在实现思路上有相似之处,又各自有不同的侧重点。 常见的垃圾回收算法援用计数给每个对象构造体附加一个援用计数的属性,当对象被赋值或援用时会减少援用计数,当对象销毁时缩小援用计数,当援用计数变为 0 时回收。 长处:实现简略,性能良好毛病:无奈辨认循环援用的状况代表语言:Python、PHP标记-革除从内存中一组 root object 根对象开始向下遍历并标记所有可能拜访到的对象,即可达对象,相同没有被标记的对象即为不可达对象,标记实现后将不可达对象革除。 长处:能够解决循环援用问题毛病:须要 STW (Stop The World)暂停程序的执行,有性能损耗,这也是大部分标记革除类算法都在试图优化的中央。代表语言:Go 的三色标记法是标记革除的变体;Python 和 PHP 也都有各自的标记革除变体实现,次要为了解决循环援用的问题。分代回收针对对象的生命周期长短不同将其划分到不同代,如年老代,老年代等;不同代采纳不同回收策略,例如年老代的对象可能刚调配不久就不再应用应该能够被回收,所以年老代触发 GC 较为高频,老年代的对象可能有历久弥坚的个性,始终存活到最初,所以触发 GC 较为低频。总的来说分代回收针对不同特点的数据启用不同策略,缩短 GC 工夫。 长处:缩小 STW 工夫,性能较稳固毛病:实现逻辑较简单代表语言:Java 是典型的分代回收的例子;Python 应用简化的分代回收策略来晋升回收效率复制回收将内存分为两块,每次只应用其中一块。垃圾回收时,将存活对象从一个块复制到另一个块,而后革除未复制的块。 长处:能够疾速回收对象,且没有内存碎片毛病:须要额定的内存空间,复制对象时开销较大代表语言:Lisp、SmalltalkPython 的垃圾回收不同的 Python 解释器实现有不同的垃圾回收形式,在 CPython 中以援用计数为主,附加标记革除的变体解决循环援用问题,另外附加分代回收进步垃圾回收的执行效率。 以援用计数为主:对象链表 refchain 和对象的援用计数 ob_refcntPython 中应用 refchain 双向循环链表保护所有对象,在对象的构造体中, ob_refcnt 是援用计数器 Python 对象的构造示意: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ \ | *_gc_next | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PyGC_Head | *_gc_prev | |object -----> +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / | ob_refcnt | \ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PyObject_HEAD | *ob_type | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / | ... |应用标记革除的变体解决循环援用问题循环援用只可能产生在容器类对象中,如 list、set、dict、类实例等,为了辨认并解决循环援用,Python 保护了两个双向链表,一个蕴含所有要扫描的对象 Objects to Scan,另一个蕴含临时无法访问的对象 Unreachable。 ...

September 9, 2023 · 2 min · jiezi

关于后端:他是个希望让大家都快乐的人-读岩田先生

岩田聪,1959 年 12 月 6 日出生于日本北海道札幌,前 HAL 研究所社长,于 2002 年至 2015 年间负责任天堂社长,被誉为“蠢才程序员”。2015 年 7 月 11 日,岩田聪因胆管癌在京都大学医学部从属医院去世,享年55岁。 本书取材于 HOBO 日刊 ITOI 新闻所刊载的岩田聪学生的大量访谈,以及任天堂官网上登出的《向社长询问》栏目,将“岩田学生的话”依照工夫、主题的程序,从新编排,会集成册。从来自札幌的高中生“蠢才程序员”,到扭转巨额负债情况的小型企业社长,再到世界顶尖游戏公司任天堂主理人。岩田聪传奇的毕生,他的经验与教训,价值观与哲学,经营理念,以及对于创意的思考,尽在这本书中。书中还特地收录了宫本茂和糸井重里谈岩田学生的追忆文章。 岩田学生忽然辞世的音讯传来,咱们与全世界的游戏爱好者们一样,陷入了凌乱情绪,像是心脏的一部分被夺去了一样。一段时间过后,悲伤弛缓,却感到岩田学生的存在离咱们慢慢远去。这使咱们深感,做一本对于岩田学生的书是一项极为重要的工作。毕竟,咱们这里收藏着大量岩田学生的话。 成为 HAL 研究所社长之前高中用计算器编程写游戏并失去同桌的称誉 高中时代,个人电脑一词尚未诞生,而那时,我遇到了“能编程的计算器”。上课时用它编写游戏,与邻座的同学一起玩,回想起来,那就是我与游戏和程序最后的相遇。 那时有个对我制作的计算器游戏兴高采烈的敌人,他刚巧就坐在我的邻座。这一点也至关重要。我那个敌人是个很乏味的家伙……怎么说呢,他能观赏我做的货色,对我而言,他是弥足珍贵的第一位客人、第一号用户。 人呢,究竟须要有能赞叹本人所做的事件的人,否则就无奈迈向更高的台阶。因而,高中时代与他相遇对我的人生有着十分踊跃的影响。 这可能印证了阿德勒在《被厌恶的勇气》一书中论述的观点,人所有的懊恼和开心都来源于人际关系,人的懊恼或高兴都源于他人的认识、感触、态度。 大学在电脑卖场遇见事业上的搭档 正是在那个卖场,我遇见了人生中几个最重要的人物。首先是一位日后给我许多鞭策的编程高手。有一天,他正用卖场的电脑编写程序。程序始终不能顺利运行,他歪着头苦思。我站在前面察看了一会儿,就明确了:“这里出了问题。”“只有把这里改过来,不就能运行了吗?”“啊,果真如此。”这么一来,咱们成了敌人。过后他在读大二,我在读大一。**在那个卖场共用电脑的人,自然而然地造成了一个相似于客户群体的汇合。接着,咱们这群人和卖场的店员也成了好敌人。到我大学三年级的时候,这位店员创建了一家公司。这家公司就是 HAL 研究所。** 这一段很像苹果公司的成立也源自于一个计算机俱乐部,也就是home brew计算机俱乐部,外面都是一些集体计算机的爱好者,其中就包含苹果公司的两个 Steve。另外雷军也是在大学假期泡在电脑城,结识了独特守业的搭档王全国。 HAL 研究所与红白机问世 HAL 研究所是一家小型公司,只管我十分年老,也要负起责任对各种各样的事件做出决策。因为没有专门负责“研发”工作的前辈,我就成了研发部门的第一号员工。与研发工作相干的所有都要我来做决断,没有一个能磋商的人。 我又迎来了人生中的另一个重要际遇。在我成为正式员工的第二年,任天堂的红白机问世了。 过后,比起几十万日元的个人电脑,只需 1.5 万日元的红白机在游戏性能上具备压倒性的劣势。我察觉到这台机器具备扭转世界的力量,于是心想“肯定要做点与它相干的事件”。 为红白机制作游戏软件切实是十分愉悦的经验,更重要的是本人经手的作品能够滞销全世界。尽管是以内部承包模式接手的工作,卖得好我也不会多赚钱,但单是“让大家都晓得我的作品”这一点就让人无比欣慰。已经只有邻座同学晓得的游戏现在行销全世界,对我来说没有比这更开心的事件了。能在红白机发售后不久就参加相干的工作,目击红白机迅速成长的过程,并碰巧助上一臂之力,切实是我的运气。 长者教诲咱们说:”一个人的命运啊,当然要靠自我奋斗,然而也要思考到历史的行程“。赶上红白机问世再加上岩田学生过人的技术和虚心的心态,开启了红白机辉煌的时代。而且岩田学生真是怀着初心在做事,让更多的人玩到本人做的游戏就曾经很开心了。 接任社长与 15 亿日元负债 我三十二岁的时候,HAL 研究所陷入了经营危机。一年后,三十三岁的我接任了社长。但过后公司那种状况,当上社长丝毫不是值得庆贺的事件。让我负责社长的理由,简略而言就是除我之外没有他人了。我向来如此,不是喜爱不喜爱的问题,而是只有认定“这件事由我来做最正当”,就即刻下决心去做。 公司陷入经营危机,我成为社长要重建公司。在研发部门里,我算得上综合能力最高的人物,在这一点上失去了大家的信赖,因而我说的话大家还算听得进去。可另一方面,公司总体而言没有失去员工的信赖。一个陷入经营危机的公司,在员工眼中看来几乎是集不信赖之大成。毕竟,“依照公司的批示干活,后果就是这样?”,会这么想也是天经地义。因而我到任社长后,破费了一个月左右的工夫与每位员工谈话。在这个过程里,发现了很多事件。 大略是在面谈的过程中,我领悟到“做判断就是收集信息进行剖析,排列出优先水平”,也明确了“只有依照上述优先水平对事件做出判断,逐步推进就好”。 岩田学生总结的干脆利落的做事步骤:收集信息-剖析-排出优先级-逐步推进执行。有时候就是想得太多,做得太少 半年一次的整体员工面谈 与员工面谈应该是优先级极高的一项工作,我负责 HAL 研究所社长期间,每半年一回,与整体员工进行面谈。员工多的时候有八十至九十人,每人的面谈工夫短的二十分钟,长的三小时左右。这项工作继续了六到七年。 我在与整体员工谈话的过程中,发现了许多“通过面谈才头一回意识到的事件”。就算对方是一贯放弃着沟通的人,也有在一对一的场合才讲得进口的话。这样说或者不太失当,但我重新认识到:“如果不制作开诚布公的机会,人是不会敞开心扉的。” 如果问我想在什么样的公司工作,那我心愿是“下属能好好了解本人”,“下属能好好为我的幸福着想”的公司。 另外,我认为“每个人都是不同的个体,并且会产生扭转”。当然,始终不变的人也有许多,但如果领导者不能了解人是会扭转的这一点,那么我不想在这样的公司工作。大家必定心愿能在即使本人产生扭转,也会对此示意了解的下属手下工作。因而我也心愿时时刻刻了解员工的想法,这就是我进行面谈的初衷。尽管很不容易,但我本身也从中播种了许多。 与整体员工进行面谈,谈话的主题每个人都不同。但在面谈的我的项目中,惟一固定不变的是第一个问题:“你当初高兴吗?” 我不打算讲什么经营理念之类过于巨大的话。不过在面谈中我意识到:“所谓公司,就是怀着独特的指标,大家各担其任、群策群力的中央,因而要定下独特的指标才行。”于是我说:“通过制作商品,身为制作者的咱们与身为玩家的客户一起取得高兴,这就是HAL研究所的指标。” 人们在决定是否要承受别人意见时,首先会判断“发言者是出于本人的利益才这么讲”,还是“从心底认为这是对的才这么讲”。两者之中属于哪种,是判断的关键所在。 所以我始终认为:“打消谋求个人利益的念头,对公司治理而言极为重要。” 通过面谈与员工独自交换,我才觉悟“做出这个决策背地的理由,没能让员工体会”,“原来我的话受到了误会,以至造成了那样的不满情绪”。为什么讲那些话、决策的背地有什么理由,当然我不是什么都能讲,但我会尽可能地解释它的背景。这就像是问对方:“在汇合了这些条件的状况下,如果是你会怎么做?”如果失去的答案是“换作我也会这么做”,肯定会感到很安心吧。明确了咱们有着独特的价值观,彼此都会很快慰。 我曾向糸井学生讲述了本人的工作理念。“我心愿做让大家开心的工作。或者是玩家,或者是工作搭档,或者是将工作委托给咱们的人,不管是谁,我就是喜爱让四周的人开心起来。身边的人看起来很幸福,那就是我的能量起源。”我仿佛说了这样一番话。 无论是对用户,还是对把工作托付给咱们的合作伙伴,我都心愿给对方期待以上的回报。 ...

September 9, 2023 · 1 min · jiezi

关于后端:HTTP-演进史

HTTP 的倒退要追溯到万维网的创造,1989 年,过后在 CERN 工作的 Tim Berners-Lee 博士写了一份对于建设一个通过网络传输超文本零碎的报告。这个零碎起初被命名为 Mesh,在随后的 1990 年我的项目施行期间被更名为万维网(World Wide Web)。 万维网在现有的 TCP 和 IP 协定根底之上建设,由四个局部组成: 一个用来示意超文本文档的文本格式,超文本标记语言(HTML)。一个用来替换超文本文档的简略协定,超文本传输协定(HTTP)。一个显示(以及编辑)超文本文档的客户端,即网络浏览器。第一个网络浏览器被称为 WorldWideWeb。一个服务器用于提供可拜访的文档,即 httpd 的前身。HTTP/0.9 1991年最后的 HTTP 协定并没有版本号,0.9 实际上是为了跟后续的 1.0 版本作辨别。总的来说 0.9 版本非常简陋,性能繁多。 特点: 只反对 GET 申请,在其前面跟上指标资源的门路没有 HTTP 头部有余: 因为没有 HTTP 头部,所以除了文本类型无奈辨别和传输其余类型没有状态码和错误码,一旦呈现问题,只能返回一个固定的谬误页面一个典型的申请: GET /mypage.html一个典型的响应: <html> 这是一个非常简单的 HTML 页面</html>HTTP/1.0 1996年在 0.9 根底上做了扩大,反对传输更多类型的内容。 特点: 在申请中明确了版本号减少响应状态码减少 HTTP 头,使传输资源更加灵便,如: Content-type:通过指定不同的 MIME type,表明资源的格局,如 text/html、text/css、image/png、application/javascript、application/octet-stream 等Accept-Encoding / Content-Encoding:表明客户端反对的压缩类型和响应中应用的压缩类型有余: 每个 TCP 连贯只能发送一个申请,造成了连贯效率低下。后续在申请和响应头中减少了一个非标准的 Connection: keep-alive,告知单方申请能够复用同一条 TCP 连贯而不是每次申请响应后都敞开连贯。不过因为不是规范字段,不同实现的行为可能不统一,因而没有从根本上解决。一个典型的文本类型的申请和响应 GET /mypage.html HTTP/1.0User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)200 OKDate: Tue, 15 Nov 1994 08:12:31 GMTServer: CERN/3.0 libwww/2.17Content-Type: text/html<HTML>一个蕴含图片的页面 <IMG SRC="/myimage.gif"></HTML>典型的图片类型的申请和响应 ...

September 9, 2023 · 2 min · jiezi

关于后端:Go-中几种常见的编程模式

模式能够了解成最佳实际,或者是约定俗成的标准或套路,相熟一些常见模式能够不便了解我的项目代码。本文是参考左耳朵耗子的专栏文章做的笔记,另外也缅怀一下耗子叔。 slice 切片的数据共享与扩容迁徙切片的数据共享 切片就像是在数组上开的窗口,透过切片窗口能够看到和批改底层数组。 这段代码中,foo 和 bar 都是来源于一个底层数组的切片,在 foo 或 bar 任意一个切片做批改,都会影响到另一个切片,或者说在另一个切片也能看到其余切片做出的批改。 foo = make([]int, 5)foo[3] = 42foo[4] = 100bar := foo[1:4]bar[1] = 99左图是未修改时的示例,右图是批改后的示例。 append 笼罩后续切片景象 给一个切片 append 元素时,如果 append 后超出原有切片的容量则会产生扩容,确切来说应该是重分配内存把原有元素迁徙到新地址,而如果 append 后没超过原有容量则不产生扩容迁徙。 上面代码是一个原空间有余,而产生扩容迁徙例子 a := make([]int, 32)b := a[1:16]a = append(a, 1)a[2] = 42 往 a 中 append 元素,a 本来曾经是满格 32 容量了,append 之后产生扩容迁徙,与 b 不再共享数据,之后在 a 上批改反映不到 b 上。 上面代码示意的是 append 后容量足够,在原位批改且因为数据共享导致笼罩掉了前面的切片 func main() { path := []byte("AAAA/BBBBBBBBB") sepIndex := bytes.IndexByte(path,'/') dir1 := path[:sepIndex] dir2 := path[sepIndex+1:] fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAA fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => BBBBBBBBB dir1 = append(dir1,"suffix"...) fmt.Println("dir1 =>",string(dir1)) //prints: dir1 => AAAAsuffix fmt.Println("dir2 =>",string(dir2)) //prints: dir2 => uffixBBBB} ...

September 9, 2023 · 8 min · jiezi

关于后端:Go-Module-Package-Workspace-参考笔记

这篇笔记整顿记录了在浏览 go 官网文档中对于依赖治理、包引入、多模块开发时的工作区等相干内容。 module pathmodule path 能够惟一标识一个 module,也是定位一个 module 下的 package 时的前缀。 module path 应该能够表明该 module 是做什么的以及去哪里能够下载到,个别由代码仓库中的地位以及主版本号组成,当主版本号是 v1 时可省略,从 v2 之后须要明确指出。 module maingo 1.20package 命名标准go 的源码被组织成 package 包的模式,包名在 go 源文件中定义,反过来说每一个 go 源文件都须要表明其所在的包。 包名标准 包名应该尽量简短清晰,且应用小写字母,不蕴含下划线,也不应用驼峰表示法,例如 time 包提供工夫相干工具,list 包是对双向链表的实现,http 包提供了 HTTP 客户端和服务端的实现。反观 computeServiceClient 和 priority_queue 都不是一个好的包名。包名能够适当做简略缩写:strconv (string conversion)、syscall (system call)、fmt (formatted I/O) 包中的函数名或变量名不要反复包名,因为当内部客户端援用包内的函数或变量时,个别都是通过包名调用的,所以包内的内容也就不须要再反复一遍包名了。例如 http 包中如果有一个名为 HTTPServer 的办法就不是很好,而应间接叫做 Server 办法就能够了。 如果某个叫 pkg 的包中的办法返回值类型是 pkg.Pkg 或者是 *pkg.Pkg,那么办法名能够简写,例如 start := time.Now() // start is a time.Timet, err := time.Parse(time.Kitchen, "6:06PM") // t is a time.Timectx = context.WithTimeout(ctx, 10*time.Millisecond) // ctx is a context.Contextip, ok := userip.FromContext(ctx) // ip is a net.IP绝对的如果函数返回的是 pkg.T,而 T 不是 Pkg 的时候,函数名最好可能体现返回值是什么 ...

September 9, 2023 · 4 min · jiezi

关于后端:Java-中的反射与注解

一、反射 Reflection 和 元类 ClassClass 元类是对一般类的形象,是类的类。Class 蕴含了一个类的所有属性,包含类名、包名、父类、实现的接口、所有办法、属性等。拿到一个类的 Class 元类,就拿到了这个类所有信息,就能够通过这些信息动静做一些解决。 通过一个类的 Class 实例获取类信息的办法就称为反射(Reflection)。 获取类的 Class 元类对象 办法一:间接通过动态变量class获取: Class cls = String.class;办法二:如果咱们有一个实例变量,能够通过该实例变量提供的getClass()办法获取: String s = "Hello";Class cls = s.getClass();办法三:如果晓得一个类的残缺类名,能够通过静态方法Class.forName()获取: Class cls = Class.forName("java.lang.String");操作 Field 和 Method 拿到了类的 Class 元类实例就是调用如下办法获取类的属性和办法等。 Field getField(name):依据字段名获取某个public的field(包含父类)Field getDeclaredField(name):依据字段名获取以后类的某个field(不包含父类)Field[] getFields():获取所有public的field(包含父类)Field[] getDeclaredFields():获取以后类的所有field(不包含父类)Method getMethod(name, Class...):获取某个public的Method(包含父类)Method getDeclaredMethod(name, Class...):获取以后类的某个Method(不包含父类)Method[] getMethods():获取所有public的Method(包含父类)Method[] getDeclaredMethods():获取以后类的所有Method(不包含父类)操作类的属性,实现动静扭转类 失去 Field 对象或 Method 对象后,get set 值时都须要指定一个该类的实例,也就是 get set 针对哪个对象操作。 Demo d = new Demo();d.name = "testname";clazz.getDeclaredField("name").get(d);// 参数 d 就是指定在 d 实例上做 get name 操作clazz.getMethod("hello").invoke(d); // 参数 d 示意在 d 实例上调用 hello 对象通过 Class 生成类实例 ...

September 9, 2023 · 2 min · jiezi

关于后端:Python-type-和元类-metaclass

Python 所有皆对象,包含类 class 也是对象家喻户晓 Python 跟 Java 一样,所有皆对象,所以 class 类也是对象,而对象能够动态创建,所以一个 class 类也能够被动态创建进去。 通过 type() 创立类type 的定义,type 是一个类 class,只不过能够 callable 。 class type(name, bases, dict, **kwds)type 传入一个参数时,返回的是参数的类型。 >>> type(int)<class 'type'>>>> type(list)<class 'type'>>>> type(T)<class 'type'>>>> type(C)<class 'type'>>>> type(object)<class 'type'>type 传入三个参数时,用来创立类: 第一个参数 name 是被创立的类的名字,str 类型 第二个参数 bases 是被创立的类的父类,tuple 类型,不传默认是 (object,) 第三个参数 dict 是被创立的类的属性和办法,dict 类型 上面两种创立类的形式,后果是一样的 class X: a = 1X = type('X', (), dict(a=1))通过 metaclass 创立类咱们晓得能够用 class 类来创立 object 对象,而 class 类自身也是对象,那么 class 这个对象由谁来创立呢?答案就是 metaclass,metaclass 是 class 的 class,metaclass 创立 class,class 创立 object,metaclass→class→object: ...

September 9, 2023 · 4 min · jiezi

关于后端:IO网络

I/O网络阻塞与非阻塞:阻塞:拜访IO的线程是否会阻塞(期待)。 同步和异步:数据的申请形式。 同步会期待资源返回的后果。异步通过回调的形式获取返回的后果BIO同步阻塞。传统的socket编程,实现模式为一个连贯一个线程,客户端有连贯申请时服务器就启动一个线程解决,如果这个连贯不做任何事件就会造成不必要的线程开销,能够通过线程池改善(实现多个客户连贯服务器)。 存在的问题: 针对每个申请都须要创立一个线程。并发较大时须要创立大量线程解决,占用资源大连贯建设后,如果以后线程临时没有数据可读,则线程阻塞在read,造成线程资源节约NIO同步非阻塞。实现模式为一个线程解决多个申请(连贯),客户端发送的申请都会注册到多路复用器上多路复用器轮询到连贯有I/O申请就进行解决。 AIO异步非阻塞。引入了异步通道的概念,应用Proactor模式,简化了程序编写,无效的申请才启动线程,特点是现有操作系统实现后再告诉服务端程序启动线程去解决,用于连接数较多且连接时间较长的利用。 Proactor : 音讯异步告诉的设计模式,Proactor 告诉的不是就绪事件,而是实现事件。场景剖析BIO实用于连接数小且固定的架构,对服务器资源要求高,并发局限于利用。JDK1.4以前。NIO实用于连贯数目多且连贯比拟短的架构,比方聊天服务器,弹幕零碎,服务器间通信。应用较多AIO实用于连贯数目多且和长连贯的架构,比方相册服务器,充沛调用OS参加并发操作。NIO编程介绍外围局部:Channel通道,buffer缓冲区,selector选择器面向缓冲区编程。数据读取到缓冲区,须要时可在缓冲区中前后挪动,减少了处理过程中的灵活性,提供非阻塞式的高伸缩性网络。当一个申请从通道发送申请或者读取数据时:如果有数据就读取,没有数据就去做其余的事件,不会阻塞线程。写操作也是NIO与BIO比拟BIO以流的形式解决数据,NIO以缓冲区的形式解决数据。NIO效率更高。BIO是阻塞的,NIO是非阻塞的。BIO是基于字节和字符流操作,NIO基于channel和buffer缓冲区进行操作。 数据总是从通道读取到缓冲区,或者从缓冲区写入到通道,selector用于监听多个通道的事件,因而单线程就能够监听多个客户端通道 流程: 客户端与服务器建设连贯,先获取一个通道,通道注册到selector,selector 轮询查看通道的事件(状态),如果客户端向channel的buffer写入了数据,selector监听到了对应事件(例如写事件),则由server端的线程进行操作。如果没有监听到事件则不会让服务端的线程解决。 即:IO多路复用缓冲区BufferBuffer是内存块。Buffer对象就是用来操作内存块的。 介绍:缓冲区实质上是一个能够读写数据的内存块,能够了解为一个数组,Buffer对象提供了能够读写内存块的API,并且能够跟踪记录缓冲区的状态变动。Channel读写数据必须通过buffer。 常见API蕴含7个子类(byte,short,int,long,float,double,char)罕用子类 ByteBuffer. ByteBuffer.alloate(长度)创立byte类型的指定长度的缓冲区。没数据的 ByteBuffer.wrap(byte[] array)创立一个有内容的byte类型缓冲区。有数据的。 写模式的时候position相当于是以后在那个地位,而后limit了解为length+1 flip()切换读模式: 将position设置成0就是从头开始读,而后limit设置成原来position的地位 相当于是记录有多少个数据当position=limit就示意读完了。 clear()切换写模式:将position 设置成0 就是从头开始笼罩写,而后limit设置成最大容量。 Channel通道能够读也能够写,流一半是单向的,只能读或写,所以须要别离创立一个输出流和输入流。通道能够异步读写,都是基于缓冲区Buffer来读写 常见的实现类有:FileChannel,ServerSocketChannel,SocketChannel。罕用的ServerSocket 和Socket就能够实现客户端服务端的通信编写。 应用server创立ServerSocketChannel绑定端口配置成非阻塞模式configureBlocking(false)while true外面accept。如果有accpet会返回一个channel如果channel不为空阐明有传过来的数据创立ByteBuffer用channel读取 read() 返回值: 负数 无效字节数 0 没有读到数据 -1 读到开端给客户端回写数据write()开释资源client关上通道SocketChannel.open()设置ip端口号写出数据 write()读取server写回的数据 read()开释资源Selector检测多个注册到服务端的通道上是否有事件产生,而后对每个事件进行相应的解决。用一个线程,解决多个客户端连贯和申请。 所以次要作用:监听通道事件,依据不同事件做不同解决。这样只有在通道监听到读写事件才会进行读写操作,不必节俭资源。 APISelector.open 失去一个选择器 Selector.select()阻塞监听所有注册的通道,当有事件产生,放入到了selectionkey的汇合中。 Selector.slectedKeys返回事件汇合。 isAcceptable 连贯持续事件:就是发动连贯 ==》ACCEPTisConnectable 连贯就绪事件:就是连贯胜利==》CONNECTisReadable 读就绪事件==》READisWriteable写就绪事件==》WRITE事件用完后删除,避免二次解决。流程serverSocketChannel.open关上一个通道selector.open创立一个selectorserverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);服务端注册连贯事件while true判断外面有没有事件如果是isAcceptable,获取到的客户端通道设置成非阻塞而后注册到selector并设置读事件。如果是isReadable,取得客户端通道key.channel 读取数据到缓冲区。回写数据。敞开资源。Netty原生NIO存在的bug NIO类库和API应用简单。须要把握多线程以及reactor模式开发工作了难度大:例如客户端重连断连,半包读写,失败缓存。等JDK-NIO有Epoll Bug 导致selector空轮询CPU100%。Netty是Jboos提供的异步的基于NIO事件驱动的网络应用程序框架,疾速开发高性能高可靠性的网络IO程序。简化了NIO的开发过程。 劣势: 提供阻塞和非阻塞的Socket,可灵便扩大事件,可定制的线程模型具备更高的性能吞吐量,应用零拷贝,节俭资源。SSL反对多种协定,预置多种编解码性能,反对开发公有协定。线程模型传统阻塞IO 详情见BIOReactor模型 是一种散发的模式(Dispatcher模式)一个或多个输出(也就是申请)同时传递给服务端的模式。服务端程序处理多个申请,同步散发到相应的解决线程。高并发的解决的要害是应用IO复用来监听事件,收到事件后分发给某个线程。 Reactor中 蕴含一个Reactor由selector和dispatcher组成,selector用于监听申请,dispatch用于散发申请,如果申请是连贯申请 会分发给Acceptor 由Acceptor建设连贯,IO的读写申请则分发给handler由handler进行读取-解决-响应 ...

September 9, 2023 · 1 min · jiezi

关于后端:四种常用限流算法对比

Leaky Bucket 漏桶漏桶可了解为是一个限定容量的申请队列。 设想有一个桶,有水(指申请或数据)从下面流进来,水从桶上面的一个孔流进去。水流进桶的速度能够是随机的,然而水流出桶的速度是恒定的。当水流进桶的速度较慢,桶不会被填满,申请就能够被解决。当水流进桶的速度过快时,桶会逐步被填满,当水超过桶的容量就会溢出,即被抛弃。 class LeakyBucketRateLimiter(object): def __init__(self, capacity, leak_rate): # 桶容量 self.capacity = capacity # 水流出的速率 每秒n个单位 self.rate = leak_rate # 上一次漏水的工夫,用来跟本次工夫做差值,乘以水流速率计算出这段时间内流出了多少水 self.last_leak_time = int(time.time()) # 桶中以后残余的水 self.remain_water = 0 def allow_request(self, require_units=1): now = int(time.time()) leaked_water = (now - self.last_leak_time) * self.rate self.remain_water = max(0, self.remain_water - leaked_water) self.last_leak_time = now print(f"刚刚流出{leaked_water}, 桶容量已达{self.remain_water}") if self.remain_water + require_units <= self.capacity: self.remain_water += require_units return True return Falseif __name__ == "__main__": leaky_bucket = LeakyBucketRateLimiter(3, 1) for i in range(10): print(f"限流后果:", leaky_bucket.allow_request()) print("----") s = random.randint(1, 5) / 10 time.sleep(s)后果 ...

September 9, 2023 · 3 min · jiezi

关于后端:PHP7内核实现原理内存管理

应用程序通过与 Zend MM(Zend Memory Manager)交互,来间接实现对操作系统内存的应用、屏蔽掉操作系统细节,简化了开发,并提供内存池技术,性能失去大幅晋升。 三种内存对应三种粒度: Huge(chunk): 占用 2M,一个 chunk 由 512 个 page 组成。申请内存大于 2M 时,间接调用零碎调配,调配若干个 chunkLarge(page): 占用 4K。申请内存大于 3092B(3/4 page_size),小于 2044KB(511 page_size)时,调配若干个 pageSmall(slot): 申请内存小于等于 3092B(3/4 page_size),内存池提前定义好了 30 种等同大小的内存(8,16,24,32,...3072),他们调配在不同的 page 上(不同大小的内存可能会调配在多个间断的 page),申请内存时间接在对应 page 上查找可用地位面包店比喻:chunk 相当于面粉仓库,page 相当于一袋面粉,slot 相当于做好的小面包。顾客购买面包时,优先从 slot 中抉择匹配的,如果不满足,则再从新和面甚至从仓库取面粉。同时有一个准则:返回满足需要 size 的最小规格,如申请 7k 内存,会返回 8k 内容,申请 30k 内存,会返回32k。 三种尺寸通过 zend_mm_heap 构造保留,三者间的关系: 调配过程: 在 Zend/zend_alloc_sizes.h 中定义了small 内存的 size,第一列从 0 到 29 示意一共 30 种 size,第二列从 8 字节到 3072 字节示意每种 size 的大小,第三列示意预留了多少个这种 size,第四列示意须要用多少个 page。 ...

September 9, 2023 · 3 min · jiezi

关于后端:PHP7内核实现原理词法和语法分析

词法剖析应用正则表达式辨认出 Token,语法分析应用 BNF 范式辨认出 Token 间的档次组合关系。 词法剖析词法剖析次要目标是从源代码中辨认出一个个的 Token,个别应用正则表达式来辨认 Token LNUM [0-9]+DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})HNUM "0x"[0-9a-fA-F]+BNUM "0b"[01]+LABEL [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*WHITESPACE [ \n\r\t]+TABS_AND_SPACES [ \t]*TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]ANY_CHAR [^]NEWLINE ("\r"|"\n"|"\r\n")有了正则表达式,接下来就是根据正则来一个个字符匹配验证,可应用 NFA 和 DFA 来辨认一段文本是否满足正则表达式,如对于正则(a|b)*abb 举例: NFA 不确定有穷自动机 因为在 0 地位,接到 a 有可能向 1 走,也有可能循环,走到哪是不确定的。 DFA 确定有穷自动机 在之前根底上做了改良,演进方向确定了。 将正则转换为有穷自动机比较复杂,然而又有法则可循,可由工具代替,如 re2c。 re2c re2c 能够解析正则,生成 C 语言实现的 DFA。相似的词法分析器还有 Lex(Lexical Analyzar),与re2c 相似,也是通过正则生成 C 语言 DFA 代码,C 语言解析正则个别应用 regex.h 库。 如下代码中,char *scan 中定义了一系列正则,针对输出的内容做类型判断,保留为 a.l 文件 #include <stdio.h>char *scan(char *p){#define YYCTYPE char#define YYCURSOR p#define YYLIMIT p#define YYMARKER q#define YYFILL(n) /*!re2c [0-9]+ {return "number";} [a-z]+ {return "lower";} [A-Z]+ {return "upper";} [^] {return "unkown";} */}int main(int argc, char* argv[]){ printf("%s\n", scan(argv[1])); return 0;}应用 re2c a.l -o a.c -i 解析正则生成 C 语言的 DFA : ...

September 9, 2023 · 4 min · jiezi

关于后端:PHP7内核实现原理数组的实现

PHP 的数组是基于 HashTable 实现的,并且在其上减少了程序拜访的个性。这里分 PHP 5 和 PHP 7 两个版本看数组的演进。 PHP 5.6.31 源码:https://github.com/php/php-src/blob/php-5.6.31/Zend/zend_hash.h#L67 PHP 7.2.1 源码: https://github.com/php/php-src/blob/php-7.2.1/Zend/zend_types.h#L234 PHP 数组特点PHP 中的数组有两个最突出的特点,也即 PHP 数组满足两个语义: PHP 数组是一个字典,反对 key value 拜访,key 反对整型或字符串。PHP 数组是有序的,即遍历数组时会依照增加程序遍历,不像传统意义上的字典是无序的。传统 HashTable一个传统的 HashTable 大抵构造如下: 首先一个 key 通过哈希函数计算,得出属于哪个 slot。key 值和 value 值应用 bucket 构造体保留,放在对应的 slot 下。如果不同 key 通过哈希计算后失去雷同 slot 值,即产生哈希抵触时,应用链表法接在 slot 的 bucket 链前面。这里提一句有的语言解决哈希抵触会应用红黑树。 PHP 中的 HashTablePHP 中的 HashTable 在此基础上做了一些调整,减少了一个哈希函数,以及这个新增哈希函数对应的哈希值 h : 其中 key 通过 hash1 函数失去 h 值,h 值是一个无符号整型(ulong),之后 h 值再通过hash2函数计算失去 slot,调配时与之前一样。另外 bucket 中也减少了对 h 值的保留。 ...

September 9, 2023 · 5 min · jiezi

关于后端:PHP7内核实现原理变量的基本结构

PHP 5 的变量构造PHP 5 中一个变量的内存占用比拟节约,比方 long 和 double 类型的变量是不须要援用计数的 PHP 7 的变量变动:变量名 zval、变量值 zend_valuePHP 7 应用名为 zval 的构造存储变量名,应用名为 zend_value 的构造体存储变量值。zval 中有一个 zend_value 类型的属性,将 zval 和 zend_value 关联起来。 在 PHP 中所有类型的变量都是用 zval 来存储,zval 中蕴含一个 type 属性,示意本变量的类型。这就是 PHP 弱类型的外围。 //zend_types.htypedef struct _zval_struct zval;/*** 变量值构造体 zend_value ***/typedef union _zend_value { /*** 这里就是寄存具体值的中央的了, 除了zend_log整型和double浮点型是间接存储具体值, 其余类型都是应用指针指向额定的构造体地址 ***/ zend_long lval; //如果是整型 则其值寄存在这里 double dval; //如果是浮点型 则其值寄存在这里 //如果上面类型时,值则应用指针指向额定的内存 zend_refcounted *counted; zend_string *str; //string字符串 zend_array *arr; //array数组 zend_object *obj; //object对象 zend_resource *res; //resource资源类型 zend_reference *ref; //援用类型,通过&$var_name定义的 zend_ast_ref *ast; //上面几个都是内核应用的value zval *zv; void *ptr; zend_class_entry *ce; zend_function *func; struct { uint32_t w1; uint32_t w2; } ww;} zend_value;/*** 变量名构造体 zval ***/struct _zval_struct { zend_value value; /*** 变量理论的value,指向zend_value构造体地址 ***/ union { struct { ZEND_ENDIAN_LOHI_4( //这个是为了兼容大小字节序,小字节序就是上面的程序,大字节序则上面4个程序翻转 zend_uchar type, /*** 变量类型 ***/ zend_uchar type_flags, /*** 变量类型掩码,不同的类型会有不同的几种属性。比方以后类型是否反对援用计数、是否反对写时复制。次要在内存治理时会用 ***/ zend_uchar const_flags, /*** 常量类型掩码 ***/ zend_uchar reserved) //call info,zend执行流程会用到 } v; uint32_t type_info; //下面4个值的组合值,能够间接依据type_info取到4个对应地位的值 } u1; union { uint32_t var_flags; uint32_t next; //哈希表中解决哈希抵触时用到 uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ uint32_t num_args; /* arguments number for EX(This) */ uint32_t fe_pos; /* foreach position */ uint32_t fe_iter_idx; /* foreach iterator index */ } u2; //一些辅助值};zval 中 u1 和 u2 都是联合体,联合体特点是外部给字段复用存储空间,故 v 和 type_info 是共享一块空间的,v 和 type_info 的关系: ...

September 9, 2023 · 4 min · jiezi

关于后端:Mysql系列二日志系统一条更新语句是如何执行的

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top这篇文章是从Github ReadMe拷贝的,内容实际下载是没问题的,可能失常发送短信,而且也不须要服务器,本地也能跑起来 首发博客地址 系列文章地址 上篇文章咱们介绍了一个查问语句的执行流程,并介绍了执行过程中波及的解决模块。一条查问语句的执行过程个别是通过连接器、分析器、优化器、执行器等功能模块,最初达到存储引擎。 那么,一条语句的更新流程是什么样的? MySQL能够复原到半个月内任意一秒的状态,是怎么做到的? 咱们先温习下查问流程 这里咱们须要留神的是,更新语句的流程和查问流程有两个区别,更新流程波及两个重要的日志模块: redo log(重做日志)binlog(归档日志)置信大家在这个面试,学习MySQL的过程中都重复听到这两个词 WAL技术在MySQL中,WAL(Write-Ahead Logging)技术是一种罕用的长久化数据的机制,用于确保数据库的事务操作可能长久化到磁盘并保持数据的一致性。WAL技术的核心思想是在事务进行批改之前,先将批改操作记录到日志中,而后再将批改利用到数据库中。 具体来说,MySQL中的WAL技术次要包含以下几个组件和步骤: Redo Log(重做日志):Redo Log是一种事务日志,用于记录数据库中产生的批改操作。在事务提交之前,MySQL会将批改操作写入Redo Log,而不是间接写入磁盘。这样能够进步性能,因为磁盘写入是绝对较慢的操作。Write-Ahead Logging(预写式日志):WAL技术要求在事务提交之前,Redo Log必须先写入磁盘,而后再将批改操作利用到数据库中。这样即便在事务提交后产生零碎解体,MySQL也能够通过Redo Log来复原数据。Redo Log Buffer(重做日志缓冲区):Redo Log Buffer是一个内存缓冲区,用于暂存待写入Redo Log的批改操作。当事务提交时,Redo Log Buffer中的内容会被刷新到磁盘的Redo Log文件中。Checkpoint(检查点):Checkpoint是一个标记点,示意在这个点之前的所有事务曾经长久化到磁盘。MySQL会定期将Checkpoint的地位更新到磁盘,以确保曾经长久化的数据不会失落。Crash Recovery(解体复原):当数据库产生解体或重启时,MySQL会通过读取Redo Log来复原数据的一致性。它会依照Redo Log中的程序,将每个事务的批改操作从新利用到数据库中,以还原数据的最新状态。WAL技术的长处是能够进步数据库的性能和可靠性。通过将批改操作先记录到Redo Log中,能够防止频繁地写入磁盘,从而进步性能。同时,WAL技术还能够确保数据的持久性和一致性,即便在零碎解体或断电的状况下也可能复原数据。 MySQL中的WAL技术通过应用Redo Log和预写式日志的机制,确保事务的批改操作可能长久化到磁盘并保持数据的一致性。它是一种进步性能和可靠性的重要技术。 Redo log执行流程当一个事务开始时,MySQL会为该事务调配一个惟一的事务ID,并将该事务的相干信息存储在内存中的事务管制块(Transaction Control Block,TCB)中。在事务执行过程中,所有的批改操作都会被写入redo log缓冲区。这些批改操作包含插入、更新和删除等操作。当事务提交时,MySQL会将该事务的所有批改操作依照程序写入redo log文件中。这些批改操作会被写入到redo log缓冲区,而后通过后盾线程定期将缓冲区中的内容刷新到磁盘上的redo log文件中。这个过程称为redo log的刷新。在事务提交之前,MySQL会将redo log的刷新操作和数据页的刷新操作进行协调,以保证数据的一致性。这是通过应用write-ahead logging(预写式日志)的机制来实现的。即在事务提交之前,redo log必须先写入磁盘,而后再将批改操作利用到数据库中。当数据库产生解体或重启时,MySQL会在启动过程中读取redo log文件,并将其中的批改操作从新利用到数据库中,以复原数据的一致性。这个过程称为解体复原。Write Pos和CheckPoint在MySQL的redo log中,有两个重要的概念:write pos(写入地位)和checkpoint(检查点)。 Write Pos(写入地位):Write Pos是指以后事务写入redo log的地位。当一个事务提交时,其批改操作会被写入redo log中的某个地位,Write Pos指向这个地位。下一个事务的批改操作将会从Write Pos指向的地位开始写入。Checkpoint(检查点):Checkpoint是指一个标记点,示意在这个点之前的所有事务曾经长久化到磁盘。当一个事务提交时,它的批改操作会被写入redo log,并且会更新Checkpoint的地位。这样,在Checkpoint之前的redo log中的操作能够被认为是曾经长久化到磁盘的。Checkpoint的作用是用于数据库的复原和解体复原。当数据库产生解体或重启时,MySQL会从Checkpoint的地位开始,读取redo log中的操作,并将其利用到数据库中,以还原数据的一致性。 Write Pos和Checkpoint之间的关系是,Write Pos会一直向前挪动,指向最新的写入地位,而Checkpoint会依据肯定的策略进行更新,以标记曾经长久化到磁盘的操作。 须要留神的是,Write Pos和Checkpoint的地位是绝对于redo log文件的偏移量,而不是相对的字节地位。它们的值通常以字节为单位,示意绝对于redo log文件起始地位的偏移量。 ...

September 9, 2023 · 2 min · jiezi

关于后端:如何实现每天定时给女友老婆发消息

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 开源地址:https://github.com/zysicyj/Vitality-reminder 元气揭示利用微信订阅号的形式,给女朋友每天定时定时推送音讯。 如果还没有女朋友的这个能够祝你一臂之力,早日脱单。 成果展现[](https://camo.githubusercontent.com/f99627e70c0925f77ce8cb868c...) 每日定时发送元气揭示,(发送的工夫可配置)非凡工夫也会发送非凡揭示,目前已有:发薪日、在一起纪念日、生日。之后会陆续减少有变成能力的能够本人改变代码,实现更多的揭示应用步骤将仓库克隆至本地npm install或cnpm install装置依赖配置文件批改config.js的订阅号配置文件批改fnc.js集体重要信息节点配置文件创立订阅号测试号,配置群发音讯模板代码文件上传至集体服务器,先绑定一个订阅号,获取accect_token设置指定发送的人员,指定发送的工夫服务器挂上app.js脚本,配置全副实现!*批改配置config.js[](https://camo.githubusercontent.com/e7870126dbdbcc670d896c124d...) appid和AppSecret都是申请微信公众号申请胜利就能够获取的,然而这个群发的接口如果是以集体的名义申请的公众号是不能获取到这个接口权限的,这时候能够用一个测试开发公众号,下面有简直所有的接口权限。微信公众平台接口测试帐号申请 网址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login。第三方天气接口我是在聚合数据平台申请的,是收费的接口,这里替换成各自的聚合数据接口的天气接口key即可聚合数据 地址:https://www.juhe.cn/docs?bd_vid=7775114093417537769这里就有了这些根本的id,间接复制即可。批改fnc.js批改base对象的birthday、love、pay字段替换为集体的即可创立微信公众号测试号,配置群发音讯模板微信公众平台接口测试帐号申请 网址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login。[](https://camo.githubusercontent.com/70542e4d8cdd0c1e10042f4eaa...) 元气揭示 {{dateTime.DATA}} 明天是 咱们相恋的第{{love.DATA}}天 间隔上交工资还有{{pay.DATA}}天 间隔你的生日还有{{birthday.DATA}}天 今日天气 {{weather.DATA}} 今日温度 {{temp.DATA}}度 空气湿度 {{humidity.DATA}} 风向 {{wind.DATA}} 每日一句 {{message.DATA}} 工资模板 {{dateTime.DATA}} 敬爱的,明天要发工资了,咱们账户上又多了一笔!留神查收~! 生日模板 {{dateTime.DATA}} 据说明天是你人生当中第 {{individual.DATA}} 个生日?天呐, 我差点遗记!因为你永远18岁~。 只管,日历通知我:你又涨了一岁,但你还是那个天真可恶的小仙女,生日快乐! 纪念日模板 {{dateTime.DATA}} 明天是在一起{{anniversary.DATA}}周年纪念日。 经验了风风雨雨,最终仍然走在一起,很侥幸,很幸福!咱们的大家庭要始终幸福上来。 这里的模板id就是别离对应的config.js的那四个模板id 获取公众号的accect_token的权限accect_token是获取咱们拜访公众号接口的一个必填字段,须要先获取。获取这个须要有url,所以须要筹备一台集体的云服务器将整个我的项目放到云服务器上进入这个我的项目的目录查看config.js文件中的token字段的值是不是和公众号接口配置中的值是一样的,须要时统一的。用node运行一下connect.js脚本提交一下接口配置信息的认证。期待页面提醒胜利勾销node的connect.js脚本此处我省略了一些内容,connect.js监听的是8080,然而接口配置只能是80端口或者443端口,所以基于这个须要做个接口的转发,利用宝塔面板能够很容易的实现接口的反向代理。 设置指定发送的人员进入api.js,批改两个template对象的touser字段 [](https://camo.githubusercontent.com/247facdfa86f8bed4736a0a054...) 这里没有写进配置文件是思考到可能有要发给不同的人的需要?进入app.js,批改CromJob构造函数的第一个参数来设置每日发送工夫。 [](https://camo.githubusercontent.com/d56e6481123ee5c39be058806e...) 利用pm2运行app.js脚本先装置一下pm2进入我的项目目录运行pm2 start app.js测试以上步骤如果都实现的了,能够手动在浏览器输出url:8080/base和url:8080/base/important,或者调整app.js的监听工夫改成行将到的工夫来测试 总结本我的项目实质是写好一个能够拜访公众号群发音讯模板的接口,而后利用CronJob实现每日定时发送模板信息。 目前模板的内容无限,模板的内容会一直新增,有能力的小伙伴如果有趣味也能够本人批改代码实现更多的性能。 更新日志新增自定义情话(2022.10.05) 再config.js中可自定义配置love_message每日情话,每日随机从中取出一条发送本文由mdnice多平台公布

September 8, 2023 · 1 min · jiezi

关于后端:PHP7内核实现原理启动过程

FPM 启动和初始化 worker 的过程 代码在源码 /sapi/fpm/fpm/fpm_main.c 中 fpm_conf_init_main() 函数解析 php-fpm.conf 配置文件,调配 worker pool 的内存空间。每个worker pool 用构造体 fpm_worker_pool_s 示意,每个 pool 中的有一个 fpm_scoreboard_s 构造体,用来治理具体一个 workerfpm_scoreboard_init_main() 函数调配每个 worker 的内存,在 pool 的 fpm_scoreboard_s 构造体中,每个 worker 应用 fpm_scoreboard_proc_s 构造体示意之后 master 给每个 worker pool 创立 socket、注册监听的信号等。即解析 php-fpm.conf → 初始化worker pool→ 初始化worker 关系相似:fpm_worker_pool_s(fpm_scoreboard_s(fpm_scoreboard_proc_s)) FPM worker/PHP 解决申请的过程期待申请:worker 阻塞在 fcgi_accept_request 函数期待申请到来。解析申请:FastCGI 接到申请并解析申请数据。申请初始化:执行 php_request_startup 此阶段会调用每个扩大的:PHP_RINIT_FUNCTION 函数 即 RINIT。编译、执行:由 php_execute_script 实现 PHP 脚本的编译、执行敞开申请:申请实现后执行 php_request_shutdown ,此阶段会调用每个扩大的:PHP_RSHUTDOWN_FUNCTION 即 RSHUTDOWN,从新进入下一轮期待。// master执行本函数 创立并初始化workerint fpm_run(int *max_requests){ struct fpm_worker_pool_s *wp; for (wp = fpm_worker_all_pools; wp; wp = wp->next) { //调用fpm_children_make() fork子过程 is_parent = fpm_children_create_initial(wp); if (!is_parent) { goto run_child; } } //master过程将进入event循环,不再往下走 fpm_event_loop(0);run_child: //只有worker过程会到这里 *max_requests = fpm_globals.max_requests; return fpm_globals.listening_socket; //返回监听的套接字}int main(int argc, char *argv[]){ ... fcgi_fd = fpm_run(&max_requests); parent = 0; //初始化fastcgi申请 request = fpm_init_request(fcgi_fd); //worker过程将阻塞在这,期待申请 while (EXPECTED(fcgi_accept_request(request) >= 0)) { SG(server_context) = (void *) request; init_request_info(); //申请开始 RINIT if (UNEXPECTED(php_request_startup() == FAILURE)) { ... } ... fpm_request_executing(); //编译、执行PHP脚本 php_execute_script(&file_handle); ... //申请完结 RSHUTDOWN php_request_shutdown((void *) 0); ... } ... //worker过程退出 MSHUTDOWN php_module_shutdown(); ...}PHP 执行的几个阶段或生命周期从申请放宽到整个 PHP 的执行阶段,在下面申请的解决前后,减少模块的初始化和敞开阶段: ...

September 8, 2023 · 3 min · jiezi

关于后端:12分钟从Executor自顶向下彻底搞懂线程池

前言上篇文章 13分钟聊聊并发包中罕用同步组件并手写一个自定义同步组件 聊到并发包中罕用的同步组件,并且还手把手实现了自定义的同步组件 本篇文章来聊聊并发包下的另一个外围-线程池 浏览本文大略12分钟 通读本篇文章前先来看看几个问题,看看你是否以及了解线程池 什么是池化技术?它有什么特点,哪些场景应用?Executor是什么?它的设计思维是什么样的?工作工作有几种?有什么特点?如何适配而后交给Executor的?线程池是如何实现的?有哪些外围参数,该如何配置?工作流程是怎么的?线程池如何优雅的解决异样?如何敞开线程池?解决定时的线程池是如何实现的?池化技术线程的创立、销毁都会带来肯定的开销 如果当咱们须要应用到多线程时再去创立,应用完又去销毁,这样去应用不仅会拉长业务流程,还会减少创立、销毁线程的开销 于是有了池化技术的思维,将线程提前创立进去,放在一个池子(容器)中进行治理 当须要应用时,从池子里拿取一个线程来执行工作,执行结束后再放回池子 不仅是线程有池化的思维,连贯也有池化的思维,也就是连接池 池化技术不仅能复用资源、进步响应,还方便管理 Executor框架Executor框架是什么? 能够临时把Executor看成线程池的形象,它定义如何去执行工作   public interface Executor {      void execute(Runnable command);  }Executor将工作工作与线程池进行拆散解耦 工作工作被分为两种:无返回后果的Runnable和有返回后果的Callable 在线程池中容许执行这两种工作,其中它们都是函数式接口,能够应用lambda表达式来实现 有的同学可能会有疑难,上文Executor框架定义的执行办法不是只容许传入Runnable工作吗? 那Callable工作调用哪个办法来执行呢? Future接口用来定义获取异步工作的后果,它的实现类常是FutureTask FutureTask实现Runnable的同时,还用字段存储Callable,在其实现Runnable时实际上会去执行Callable工作 线程池在执行Callable工作时,会将应用FutureTask将其封装成Runnable执行(具体源码咱们前面再聊),因而Executor的执行办法入参只有Runnable FutureTask相当于适配器,将Callable转换为Runnable再进行执行 Executor 定义线程池,而它的重要实现是ThreadPoolExecutor 在ThreadPoolExecutor的根底上,还有个做定时的线程池ScheduledThreadPoolExecutor ThreadPoolExecutor外围参数ThreadPoolExecutor次要有七个重要的参数   public ThreadPoolExecutor(int corePoolSize,                                int maximumPoolSize,                                long keepAliveTime,                                TimeUnit unit,                                BlockingQueue<Runnable> workQueue,                                ThreadFactory threadFactory,                                RejectedExecutionHandler handler)corePoolSize 线程池外围线程数量maximumPoolSize 线程池容许创立的最大线程数keepAliveTime 超时工夫,TimeUnit工夫单位:非核心线程闲暇后存活的工夫workQueue 寄存期待执行工作的阻塞队列threadFactory线程工厂:规定如何创立线程,能够依据业务不同规定 不同的线程组名称RejectedExecutionHandler 回绝策略:当线程不够用,并且阻塞队列爆满时如何回绝工作的策略回绝策略作用AbortPolicy 默认抛出异样CallerRunsPolicy调用线程来执行工作DiscardPolicy不解决,抛弃DiscardOldestPolicy抛弃队列中最近一个工作,并立刻执行当前任务线程池中除了结构时的外围参数外,还应用外部类Worker来封装线程和工作,并应用HashSet容器workes工作队列存储工作线程worker ...

September 8, 2023 · 15 min · jiezi

关于后端:PHP7内核实现原理基本架构

发展史PHP 最早是由 Lerdorf 于 1995年,应用 Perl 语言,以 Personal Home Page Tools (PHP Tools) 的模式创立的,目标是为了不便记录集体网站的访客记录和反对留言本等性能,此时称为 PHP 1。 起初越来越多的网站开始应用 PHP 并心愿能提供更多的性能,之后 Lerdorf 将 PHP 开源,此时称为 PHP 2。 1997 年两个以色列程序员 Zeev Suraski 和 Andi Gutmans 重写了 PHP 的解析器,并于 1998 年正公布,此为 PHP 3,并从此开始 PHP 改为 Hypertext Preprocessor,新版的解析器命名为 Zend Engine。Zend 的命名来自于两位作者的名字。 2000 年,以 Zend 1.0 为根底的 PHP 4 公布。2004 年,以 Zend 2.0 为根底的 PHP 5 公布,至此 PHP 反对了面向对象、PDO、命名空间等个性,性能方面也大幅晋升。 2015 年 12 月 3 日 PHP 7 公布,重构了 PHP 中很多重要且罕用的数据结构,内存占用失去显著优化,性能也失去了大幅晋升。 ...

September 8, 2023 · 2 min · jiezi

关于后端:PHP7内核实现原理基本环境和C基础

编译装置 PHP 7.1.0下载 7.1.0 源码压缩包:www.php.net/releases/ ./configure --prefix=/Users/lisong/Documents/workspace/php-src/output --enable-fpm 编译,报错:configure: error: Please specify the install prefix of iconv with --with-iconv= iconv 是个国际化扩大,临时用不到,先禁用之: 从新编译 ./configure --prefix=/Users/lisong/Documents/workspace/php-src/output --enable-fpm --without-iconv 装置 gdb 调试装置步骤,前期须要配置 gdb 证书。https://blog.csdn.net/qq_33154343/article/details/104784641 在 output 目录中开始调试 sudo gdb bin/php ,第一次会卡在 [New Thread 处,追随教程中解决,先 cntrl z 退出,kill 掉之后,在从新开始调试。 应用 echo 断点调试技巧 echo 底层实现利用了 ZEND_ECHO_SPEC_CV_HANDLER 函数,能够在 PHP 代码中应用 echo 打印变量,之后在 gdb 中设置 b ZEND_ECHO_SPEC_CV_HANDLER 断点,当执行到 echo 时,就会被断住,之后能够尝试解析变量。 查看字符串残缺内容 : p *z.value.str.val@12 @后接字符串长度 装置 vld 扩大,查看 opcodegit clone https://github.com/derickr/vld.gitcd vld../output/bin/phpize./configure --with-php-config=xxxx/output/bin/php-config --enable-vldmake && make install编译完批改 ini ,使之失效。 ...

September 8, 2023 · 1 min · jiezi

关于后端:为什么-Kafka-很快

为什么 Kafka 很快?2011 年初,LinkedIn 开源了 Kafka,这是一个分布式事件流平台。它以作家弗朗茨-卡夫卡(Franz Kafka)的名字命名。顾名思义,Kafka 是为写而优化的。它为解决实时数据馈送提供了一个高吞吐量、低提早的平台,在互联网公司中失去广泛应用。 Kafka 通过程序 I/O (Sequential I/O)和零拷贝 (Zero Copy)实现了低提早的消息传递。许多其余音讯平台通常也采纳雷同的技术。 咱们用下图的数据传输过程来解释零拷贝。 步骤 1.1 - 1.3生产者写入数据 步骤 2消费者读取数据,不应用零拷贝技术 2.1: 数据从磁盘加载到操作系统缓存2.2 数据从操作系统缓存复制到 Kafka过程2.3 Kafka过程将数据复制到套接字缓冲区 (Socket Buffer)2.4 数据从套接字缓冲区复制到网卡2.5 网卡向用户发送数据步骤 3消费者应用零拷贝技术读取数据 3.1: 数据从磁盘加载到操作系统缓存3.2 操作系统缓存通过 sendfile() 命令间接将数据复制到网卡3.3 网卡向用户发送数据零拷贝节俭了应用程序和内核上下文之间屡次数据拷贝。这种办法可将工夫缩短约 65% 。 如果你对细节感兴趣,欢送留言通知我。 【关注公众号:ByteByteGo】

September 8, 2023 · 1 min · jiezi

关于后端:算法AB实验平台进化历程和挑战

1 AB平台简介AB试验平台这几年在互联网公司失去了越来越宽泛的利用,采纳AB试验来评估产品和技术迭代成果也成为支流的业务新性能成果评估形式,数据驱动的文化在这几年失去了不少公司的宽泛的认同,通过数据和指标来阐明产品成果也失去了越来越多的公司的认可和利用。 AB试验在其中就是一种很常见的产品成果数据评估工具,在各大公司的产品迭代过程中也失去了越来越宽泛的利用。 2 1.0时代 从无到有在AB试验刚开始的时候,须要解决的问题很简略: 通过某种用户流量分组形式,将不同的用户划分到不同的流量组,在不同的流量组通过控制变量的形式利用不同的产品策略,随后察看两个组的产品成果差异。 这种十分奢侈的试验思路就是最根本的AB试验的分流,须要留神的是在过程中须要保障控制变量和稳固的流量比例。 2.1 一个根本AB试验实例 一个根本的AB试验须要有以下因素: 1.试验指标和试验假如 a.试验指标决定到达到什么样的成果试验才算胜利,举个例子,我心愿付款率晋升5%,这就是指标,其中的试验指标是付款率,做试验之前肯定要有试验指标,没有试验指标没方法确定试验是否胜利,试验指标蕴含指标和变动幅度两个因素。 b.试验假如是猜测通过管制哪些因素来达到试验指标,比方咱们假如付款按钮的色彩会影响用户的付款志愿进而影响付款率,那这里的试验假如就是付款按钮色彩会影响用户付款志愿。 2.试验对象(试验对象是能够用来利用策略的用户或者申请或者其余对象) a.试验对象并不是仅仅指用户,用户的每一次申请也能够独自做试验,甚至每一次用户申请的每一个曝光地位都能够看做一个试验流量,这个对象取决于具体的业务。 3.对照组和实验组(AB试验的外围要求是控制变量做成果对照,所以至多有一个或多个对照组策略和试验组策略) a.对照组:个别是没有任何策略的组,代表了当初的试验成果。 b.实验组:个别是利用了新策略的组,代表了新策略的试验成果。 c.统计效用:在进行实验组和对照组的流量调配的时候要留神,因为咱们的AB试验是从整体用户中取一部分进行试验,而后采纳统计学形式进行成果评估,所以无论是实验组还是对照组样本量要满足最根本的统计效用,后续的试验才有意义,而统计效用无奈在试验之后计算,须要咱们在试验进行之前就做短缺的调研。 2.2 算法的AB1.0次要性能1.通过控制变量的形式进行AB分流试验,并通过离线的模仿分流规定提供用户试验分组信息,使得数据分析能够计算试验的指标报表。 2.买通根本的工程试验链路,能够让算法通过试验配置自主的管制试验流量和试验策略。 2.3 1.0 AB试验的策略失效流程在晚期的试验过程有以下链路:1.通过配置核心配置约定好的AB试验配置信息,线上的服务通过配置核心的变更信息,实时变更试验配置,从下次分流开始利用新的分流策略,同时记录试验日志。 2.报表计算形式,将试验配置信息同步到ODPS,第二天用前一天的试验配置对昨天的用户进行从新分流计算,取得昨天的用户试验分流信息(之所以这样是因为试验变更是以天为单位,离线计算能够比拟方面的撑持后续的试验剖析)。 算法和一般业务的AB分流因为业务个性起因有较多的需要不同的中央,针对两者区别咱们也进行了一些非凡的算法试验优化设计。具体如下: 晚期的AB实验设计解决了根本的试验分流问题也提供了一套配套的试验指标和试验置信度计算计划,撑持了晚期的简略业务能够通过AB试验的形式比拟迷信的观测算法模型成果。 3 2.0 时代 从有到全,反对简单业务性能3.1 新的业务需要随着公司业务倒退和各个系统迭代优化,用户对于根底的AB试验零碎开始衍生出了一些新的,更细化更简单的业务需要,用户也心愿AB零碎能够帮忙撑持更高效的试验迭代。 1.流量饥渴,更丰盛的流量需要:在1.0版本的AB试验中曾经解决了根本的试验分流和配置的问题,然而因为一个场景中总用户流量无限,可能会有多种业务试验同时进行,理论试验运行时须要在同时运行的试验数量和每个试验的流量大小之间做一个取舍,业务高速倒退期间常常会有用户心愿进步同时运行的试验数量,同时保障每个试验有短缺的流量,于是咱们扩大了原来的试验流量分流模型设计,采纳分层分域的正交的业务试验划分形式来撑持上述的流量需要。 2.更实时更精确的试验报表:在晚期的试验中通过第二天的配置重算的形式失去前一天的用户试验分组数据,这种办法能够撑持十分微小的用户和试验数量,然而时效性上比拟难以保障。随着业务疾速迭代,算法的实时试验成果监控的需要也逐步减少,离线的试验报表计算反馈须要等到至多1天后能力观测,试验反馈周期太长。于是咱们调整了试验分流和报表的计算链路,采纳实时试验日志埋点通过flink等实时计算平台实时计算试验成果,这种做法能够实时捕获试验流量的变动状况,对于验证试验分流成果有较大的效率晋升。 3.简单试验模式:联结实,多集群试验, 指定用户试验需要:随着算法工程链路的规范化,业务链路中的一些业务层之间开始进行联结调优试验,催生出了多参数跨层联结试验的需要,须要在分层试验的根底上反对联结参数的失效机制,这在个别的分层实验设计中是很难撑持的。随着工程链路稳定性我的项目的停顿,大部分业务同时都具备多个不同集群,此时又须要AB零碎也能够针对不同集群提供同场景不同试验配置的性能撑持。还有随着精细化经营的开展,越来越多的试验只针对更精准的特定用户群能力失效,这给原来的试验分流和试验剖析都带来了不小的需要和挑战。 3.2 更大更通用的分流模型为了满足更丰盛的流量调配需要,咱们设计了一套比拟灵便通用的试验分流模型, 这套模型通过多个公司的业务验证,能够确保在将来较长的一段时间内,充沛撑持咱们所有业务的个各种AB试验分流需要。同时依据咱们本人的业务倒退需要,也反对了条件层,自定义分流机制等为更简单业务设计的一些分流机制。 多层正交的试验流量模型 上述的分流模型将一个场景流量分为层和域两种嵌套构造,通过层来隔离不同业务配置,通过域来隔离不同用户群。用户在该模型进行分流的过程采纳从外到内,从上到下的逐渐命中,每一次进入一个业务层都会触发一次选桶逻辑,命中桶当前,读取桶上的配置,如果桶内还有层配置持续顺次命中层,触发外部的选桶逻辑。 该模型能够反对如下次要特点: 1.分层分域,相互嵌套的流量设计,反对业务域分层的正交流量,每一层都是一个独自的业务,解决流量饥渴问题,同时反对自在的流量域划分,流量域和流量层能够相互嵌套,实现极其灵便的流量划分形式。 2.每一个流量层采纳hash模板+流量槽,层内试验通过圈槽的模式决定试验在该层的流量比例,容许算法用户自定义试验分流的规定,反对依据用户的用户特色信息进行分流,同时反对灵便的跨层流量对齐机制。这种形式能够实现极为灵便的分流形式,反对各种对象和分流形式(比方用户分流,申请分流,设施分流,作者分流,按地区分流等)。 3.反对白名单,容许用户绕开分流机制,指定用户的固定试验链路,用于在线上进行非凡用户的试验验证。 4.反对条件层,容许合乎某种条件的用户独自进行特定试验,比方只针对新用户进行的试验。 从该模型上线以来,2年多的工夫内曾经完满撑持了算法300多个场景的AB流量调配需要,通过了充沛的业务验证,从分流层面解决了许多有非凡需要的分流业务遇到的问题。 具体层中的分流规定如下:每一个流量层依据层中的分流配置信息和用户信息计算命中的流量槽,而后依据流量槽命中圈选了流量槽的试验,试验通过领有的流量槽数量决定试验流量比例。 3.3规范试验的工程链路通过AB试验的后盾革新,咱们从新思考并调整了整个试验链路的工程设计,在新的工程设计中,绝对于上一个版本次要有以下几个方面须要改良: 1.采纳试验分流日志而不是离线的试验配置来计算用户的试验分组信息。 a.试验日志能够捕捉每一个时刻的用户的试验分流状况,能够较为敏感的捕捉到试验变更的状况。 b.试验日志可观测性强,用户配置完试验当前能够立即通过日志观测试验的命中状况。 c.能够在日志中附加更多的试验环境相干信息,做更丰盛的试验剖析,能够简化离线的试验分组计算逻辑。 2.线上利用减少试验信息的具体埋点信息, 埋点分为两局部: a.一部分透传给客户端,其中蕴含用户命中的试验信息,称之为ACM埋点,客户端在用户进行点击曝光等操作时上报信息中回传服务端下发的ACM字段,这样咱们能够通过神策上报的行为日志,分明的晓得每个试验曝光几次,被点击几次,能够及时失去试验的线上体现,这部分行为日志还能够帮忙咱们实时的计算试验策略成果报表。 b.另一部分作为利用的后盾日志记录,记录了每一次申请中用户命中的试验相干信息,用于计算试验分组信息。 3.设计了AB试验的后盾操作治理界面,不必再通过手动批改配置核心的配置来进行试验配置。并将试验公布,试验批改,试验配置回滚等性能做成具体的按钮性能,极大地提高了用户的试验操作应用体验。 4.拆分了试验参数和代码执行链路,形象出了AB参数和代码链路运行计划两种概念,将AB变成一个弱依赖,升高试验参数配置谬误对线上业务的影响。 Ps: 为什么要同时采纳两种试验信息反馈链路,起因是第一种ACM上报的用户试验信息依赖于用户上报,如果用户遇到利用crash或者提早上报,或者网络状况忽然不好,咱们没方法取得未上报的这部分信息,第二种很显著,没方法晓得发放下来的带有试验信息的内容的后续反馈状况。两种链路都没方法齐全的笼罩全副用户,只有互相配合能力残缺的笼罩全量用户,至于为什么采纳离线日志来做试验报表,ACM来做实时报表纯正是工程效率方面的思考。 ACM通用埋点规范为了解决试验的实时成果观测问题, 咱们须要想方法将后盾的试验命中标识信息传递给客户端。思考到其余业务场景也会有相似的埋点需要,为了埋点通用性思考,咱们布局了一个算法的埋点规范,次要想简化算法埋点流程和对算法的埋点信息进行对立的治理。 ACM埋点次要是通过算法与客户端约定一个固定的埋点内容字段ACM,后端算法在开发时候,通过提供的SDK工具,将须要埋点的信息和内容通过SDK采纳特定的标准造成一串可辨认的字符串内容,客户端同学对ACM这个约定好的字段进行事件(曝光,点击等)上报,后端就能够依据上报的用户行为日志通过实时计算工具疾速的取得某个试验的后续用户反馈信息。 ACM埋点标准例子: 版本.业务域.内容资源类型.资源位.试验.自定义值版本:标记本条ACM的遵循的标准版本,不同版本具备不同的解析规定,不便udf解析。业务域:业务零碎代称,尽量简短,比方 搜寻srh。内容资源类型:内容类型或资源,比方 user_10098, cspu_1020,spu_771等。资源位:广告位,榜单位。试验:资源本次采纳的AB试验策略,多个试验用-隔开。自定义值: ...

September 8, 2023 · 1 min · jiezi

关于后端:我与ChatGPT聊了一下JMM

内存模型有多少种内存模型通常指计算中的存储器模型,常见的有以下几种: Von Neumann 模型:该模型将程序和数据存储在同一块存储器中,应用雷同的总线进行数据传输。Harvard 模型:该模型将程序和数据存储在不同的存储器中,应用不同的总线进行数据传输。混合模型:该模型联合了 Von Neumann 和 Harvard 模型的特点,既能够共享存储器,也能够离开存储程序和数据。NUMA 模型:该模型应用多个处理器和本地存储器,每个处理器能够拜访本地存储器和共享存储器。分布式模型:该模型应用多台计算机形成的集群,每台计算机都有本人的存储器,通过网络进行通信和协同计算。不同的内存模型实用于不同的计算机架构和利用场景,抉择适合的内存模型能够进步计算机的性能和可靠性。 java应用的是哪种Java 应用的是 Von Neumann 模型。在 Java 中,程序和数据都存储在同一块内存中,被称为 Java 虚拟机内存(JVM Memory),这些内存被划分为不同的区域,包含堆、栈、办法区等,每个区域有不同的作用和生命周期。Java 程序通过指针(援用)来拜访内存中的对象和数据,应用 JVM 外部的垃圾回收机制来治理堆内存的调配和开释,进步了程序的安全性和稳定性。 能够聊一下 JMMJMM 是 Java 内存模型(Java Memory Model)的缩写,它定义了在多线程环境下,线程之间如何拜访共享内存。JMM 基于 Von Neumann 模型,为 Java 提供了一个形象的内存模型,规定了如何操作内存和如何保障内存操作的可见性和有序性。 JMM 规定了一组规定,称为 happens-before 规定,用于确定一个操作的后果对于其余操作的可见性和有序性。happens-before 规定包含以下几种: 程序程序规定(Program Order Rule):在一个线程中,依照程序代码的先后顺序执行的操作,肯定会依照这个程序被其余线程所察看到。volatile 变量规定(Volatile Variable Rule):对一个 volatile 变量的写操作先于对同一个变量的读操作,保障了在多线程环境下的可见性。锁规定(Lock Rule):一个 unlock 操作先于后续的 lock 操作,保障了线程间的同步和可见性。传递性规定(Transitive Rule):如果 A happens-before B,且 B happens-before C,则 A happens-before C。线程启动规定(Thread Start Rule):一个线程的启动操作先于该线程执行的任何操作。线程终止规定(Thread Termination Rule):一个线程的所有操作都先于该线程的终止操作。中断规定(Interruption Rule):对线程 interrupt() 办法的调用先于被中断线程的代码检测到中断事件。JMM 为多线程程序提供了统一的内存拜访规定和保障,防止了因为指令重排、内存可见性等问题导致的线程平安问题。同时,JMM 也对程序员提出了更高的要求,须要正当地应用同步机制、volatile 变量等机制来保障程序的正确性和可靠性。 ...

September 8, 2023 · 4 min · jiezi

关于后端:面试高频题二叉树神级遍历入门

题目形容这是 LeetCode 上的 99. 复原二叉搜寻树 ,难度为 中等。 Tag : 「二叉树」、「树的搜寻」、「递归」、「迭代」、「中序遍历」、「Morris 遍历」 给你二叉搜寻树的根节点 root,该树中的 恰好 两个节点的值被谬误地替换。请在不扭转其构造的状况下,复原这棵树 。 示例 1: 输出:root = [1,3,null,null,2]输入:[3,1,null,null,2]解释:3 不能是 1 的左孩子,因为 3 > 1 。替换 1 和 3 使二叉搜寻树无效。示例 2: 输出:root = [3,1,4,null,null,2]输入:[2,1,4,null,null,3]解释:2 不能在 3 的右子树中,因为 2 < 3 。替换 2 和 3 使二叉搜寻树无效。提醒: 树上节点的数目在范畴 $[2, 1000]$ 内$-2^{31} <= Node.val <= 2^{31} - 1$进阶:应用 $O(n)$ 空间复杂度的解法很容易实现。你能想出一个只应用 $O(1)$ 空间的解决方案吗? 根本剖析首先,别想简单了。 所谓的复原二叉树(两节点调换),只须要将两节点的 val 进行调换即可,而不须要对节点自身进行调换。 中序遍历 - 递归 & 迭代二叉搜寻树,其中序遍历是有序的。 ...

September 8, 2023 · 3 min · jiezi

关于后端:MyBatis相关

MyBatismybatis相比拟传统jdbc 传统数据库配置信息存在硬编码,包含sql语句,设置参数,获取后果集须要手动封装后果集,较为繁琐。须要频繁创立数据库连贯。解决方案: 配置文件解决硬编码,数据库连贯应用连接池。后果集能够应用反射。解析数据库配置 mapper.xml中的sql sqlsession在getMapper时 应用动静代理生成代理对象(其中外部类中蕴含invoke办法),代理对象在调用接口中的任意办法都会执行invoke办法.这样就能够吧创立数据库连贯放在外面 为什么myabtais mapper中的namespace与 id 要与接口名与办法名雷同? 因为在通过动静代理时只有依据办法能力获取到以后的类名曾经办法名,而这两个组成成为了sql mapper的惟一标识,才晓得执行哪个语句,说白了就是为了做辨别. 在做形象封装是达成的约定. mybatis: 基于ORM的半自动、轻量级、长久层框架(对象关系映射) 为什么调用办法是能够间接返回对象. 从技术层面来说是因为用了反射,但实际上是因为做了束缚 实体中的字段与数据库字段做了映射关系,利用这层关系,实现后果集封装.为什么是半自动,全自动(hibernate).不必sql语句的话,没法优化. 轻量级: 占用资源少 底层还是jdbc的封装,躲避了常见的问题 API传统开发方式Resoures工具类加载配置文件SqlConfigMapSqlSessionFactoryBuilder解析创立SqlSessionFactorySqlSessionFactory生产一个SqlSession openSession() 默认开启一个事务,不会主动提交,须要手动提交 openSession(true)则默认主动提交 SqlSession调用办法代理开发方式Mapper 接⼝开发须要遵循以下标准: Mapper.xml⽂件中的namespace与mapper接⼝的全限定名雷同Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id雷同Mapper接⼝⽅法的输⼊参数类型和mapper.xml中定义的每个sql的parameterType的类型雷同Mapper接⼝⽅法的输入参数类型和mapper.xml中定义的每个sql的resultType的类型雷同通过sqlsession.getMapper(dao.class).获取代理对象 Mybatis缓存一级缓存介绍一级缓存是sqlsession级别的缓存,通过hashmap存储缓存对象,不同sqlsession之间的缓存数据区不受影响,一级缓存默认开启 先去一级缓存中查问,如果没有就查询数据库,并进行一级缓存 cacheKey: statementId,params,bonundsql,rowbounds(分页参数[两个])组成 如果配置文件中配置了Environment,则会增加Environment IDvalue:查问后果 第二次查问间接命中 能够通过比拟后果地址验证。缓存的是对象如果两头有commit操作,会清空一级缓存。防止脏读。 除了commit 也能够手动调用sqlsession.clearCache或者close办法手动刷新一级缓存。源码数据结构HashMap, 二级缓存⼆级缓存是基于mapper⽂件的namespace,多个sqlsession共享二级缓存区域.二级缓存须要手动开启. 多个sqlsession中如果产生commit操作会清空二级缓存. 二级缓存缓存的是数据并不是对象. 开启形式xml开发全局配置文件sqlMapConfig中 <!--开启⼆级缓存--><settings> <setting name="cacheEnabled" value="true"/></settings>其次在UserMapper.xml⽂件中开启缓存 <!--开启⼆级缓存--><cache></cache>注解开发应用@CacheNamespace开启二级缓存 usecache(默认为false)和flushcache(默认为true)xml:能够在单个statement中配置应用 注解: 增加@options注解 源码:底层数据结构还是hashmap 存在的问题二级缓存是单服务器工作,无奈实现共享所以无奈实现分布式缓存.解决办法redis、memcached、ehcache 自定义二级缓存mybatis提供了redis实现类,能够间接应用mybatis-redis依赖 架构原理三层构造API接口层 提供给内部使⽤的接⼝ API,开发⼈员通过这些本地API来操纵数据库。接⼝层⼀接管 到 调⽤申请就会调⽤数据处理层来实现具体的数据处理 数据处理层 负责具体的SQL查找、SQL解析、SQL执⾏和执⾏后果映射解决等。它次要的⽬的是根 据调⽤的申请实现⼀次数据库操作 根底撑持 包含连贯治理、事务管理、配置加载和缓存解决,这些都是共⽤的东⻄,将他们抽取进去作为最根底的组件。为下层的数据处理层提供最根底的⽀撑 总体流程加载配置初始化 配置来源于两个地⽅,⼀个是配置⽂件(主配置⽂件conf.xml,mapper⽂件*.xml),—个是java代码中的 注解,将主配置⽂件内容解析封装到Configuration,将sql的配置信息加载成为⼀个mappedstatement 对象,存储在内存之中 接管调⽤申请 为SQL的ID和传⼊参数对象 ...

September 8, 2023 · 1 min · jiezi

关于后端:后端面经数据库Redis数据结构和底层数据类型

TOC申明:Redis的相干常识是面试的一大热门知识点,同时也是一个宏大的体系,所波及的知识点十分多,如果用一篇文章列举,往往会陷入常识陆地中无奈感知其全貌,因而,这段时间我会试着拆分Redis的相干章节,辅以思维导图的模式介绍Redis的相干知识点,知识点范畴包含如下几局部 Redis基本概念和特点Redis数据结构和底层数据类型Redis长久化(AOF和RDB)Redis集群和高可用性Redis缓存Redis分布式锁Redis实现异步队列Redis运维问题明天次要介绍的是Redis数据结构和底层数据类型 1. Redis数据类型在之前的Redis基本概念解说中,咱们晓得Redis的存储单位是键值对。其中,键key只能是字符串类型,而值value则反对丰盛的数据类型,包含根本数据类型和非凡数据类型。 1.1 根本数据类型1. string字符串类型,容量大小不超过512MB。次要存储内容为三类: 字符串:一般字符串 or 简单的字符串(JSON/XML等);数字:整数 or 浮点数;二进制文件:图片、视频、音频等。利用场景:缓存、计数器、session共享等。 相干命令: set key value:依据key查找指定键,设置值为valueget key:依据key查找指定键,取得其存储的value值del key:依据key查找指定键,删除其存储的value值incr key:依据key查找指定键,将其存储的value值自增1decr key:依据key查找指定键,将其存储的value值自减1incrby key amount:依据key查找指定键,将其存储的value值自增amountdecrby key amount: 依据key查找指定键,将其存储的value值自减amount2. hash之前咱们提到过Redis的存储单位是键值对,hash指的是值自身又是一个键值对。利用场景:缓存、存储对象信息等。 相干命令:- hset key field value:依据key查找指定键,这个键的值是一个哈希表,增加键值对field:value- hget key field:依据key查找指定键,这个键的值是一个哈希表,获取键field对应的值- hgetall key:依据key查找指定键,这个键的值是一个哈希表,获取哈希表中所有的键值对- hdel key field:依据key查找指定键,这个键的值是一个哈希表,删除键field对应的键值对3. list在Redis中应用双端链表实现list,列表的插入和删除能够引申出栈、队列等非凡的数据结构。利用场景:音讯队列、工夫列表等。 相干命令: lpush key value:依据key查找指定键,这个键的值是一个列表,把value值插入到列表的左端(左端push)rpush key value:依据key查找指定键,这个键的值是一个列表,把value值插入到列表的右端(右端push)lpop key:依据key查找指定键,取得键的对应值是一个列表,将列表的左侧首元素弹出rpop key:依据key查找指定键,取得键的对应值是一个列表,将列表的右侧首元素弹出lrange key start end:依据key查找指定键,取得键的对应值是一个列表,获取列表中指定范畴的元素lindex key index:依据key查找指定键,取得键的对应值是一个列表,获取列表中指定索引的元素,反对正数下标示意倒数第x个元素。4. set通过哈希表实现set,不容许反复元素。利用场景:独特好友、独特关注等。 相干命令: sadd key value:依据key查找指定键,这个键的值是一个汇合,把value值插入到汇合中scard key:依据key查找指定键,取得键的对应值是一个汇合,获取汇合中元素的个数smembers key:依据key查找指定键,取得键的对应值是一个汇合,获取汇合中所有元素sismember key member:依据key查找指定键,取得键的对应值是一个汇合,判断member是否在汇合中5. sortset/Zset通过压缩列表或者跳跃表实现Zset,在第二局部会讲到。Zset不容许反复元素,然而每个元素都会关联一个double类型的分数,示意权重。元素自身不能反复,然而double类型的分数能够反复。Zset中的成员,依据分数从小到大排序。利用场景:排行榜、带权重的音讯队列等。 相干命令: zadd zset-key score member:依据key查找指定键,这个键的值是一个有序汇合,把member值插入到汇合中,同时关联一个double类型的分数scorezrange zset-key start end:依据key查找指定键,取得键的对应值是一个有序汇合,获取汇合中指定范畴的元素zrem zset-key member:依据key查找指定键,取得键的对应值是一个有序汇合,删除汇合中指定的元素1.2 非凡数据类型1. bitmap位图数据结构,操作二进制位进行记录,每一位都只有0·1两种状态,能够节俭存储空间。利用场景:统计用户的签到状况、统计用户的在线状况等。(今日已签/未签、今日在线/不在线)。 ...

September 8, 2023 · 3 min · jiezi

关于后端:可观测性在灰度发布中的应用

前言随着云计算的倒退、云原生时代的降临,企业数字化转型过程不断深入,利用开发也越来越多地基于微服务化模式,疾速迭代的能力使得利用开发更高效、更灵便。同时,也不得不面临利用版本疾速降级所带来的的微小挑战。传统的公布形式是通过新版本全量替换旧版本,这种模式存在停机工夫较长的问题,业务端的压力愈发显著。同时,在新版本公布时,如果间接将应用程序从以后版本全量降级到新版本,危险存在的可能性和严重性也不容忽视。传统公布形式存在如下一些典型的弊病: 影响用户体验:如果新版本存在性能或性能问题,那么,所有新版本服务实例都会存在同样问题,从而影响所有用户的应用。影响服务可用性:全量公布个别须要做停机降级(要么同时都为新版本,要么同时都为老版本),导致业务中断,影响服务可用性。所以,尽可能升高公布对业务造成的影响就变得越来越重要,“业务无感知”的灰度公布策略就公众的视线中。 灰度公布概述灰度公布,是一种软件部署策略。惯例做法是将新版本的应用程序投入生产环境,保留以后版本,并将一小部分流量重定向到新版本中。在此过程中,所有发送到新版本的申请都将被监测,确认新版本可用后,将逐步将越来越多的流量疏导到新版本中。 通过灰度公布,有助于辨认可能存在的潜在谬误、性能问题或其余问题,以便在全面部署之前及时解决这些问题,从而极大地缩小对更宽广用户的应用影响,进步用户体验和满意度,减速迭代速度。 可观测性对于灰度公布的胜利十分重要,可能为团队提供实时的服务运行状态的数据反对,从而更好地观测和剖析新版本的性能、稳定性和用户反馈等指标,更快地发现和解决问题,进步公布的成功率和用户体验。 可观测性在灰度公布的应用价值在灰度公布过程中,须要对公布的新版本具备评估剖析能力,包含对新版本的性能、稳定性和用户反馈等指标进行剖析。可观测性能够帮忙团队更好地观测和剖析这些指标,从而更快地发现和解决问题。具体来说,可观测性能够帮忙团队实现以下指标: 监控应用程序的性能和稳定性:通过监控应用程序的指标,例如响应工夫、错误率、CPU 使用率等,能够及时发现性能和稳定性问题,并采取相应的措施。实现疾速故障排除:通过可观测性工具,能够疾速定位和解决问题,缩小对用户的影响。反对数据驱动的决策:通过可观测性工具,能够收集和剖析大量的数据,为团队提供数据反对,反对数据驱动的决策。因而,可观测性对于灰度公布的胜利十分重要,可能帮忙团队更好地监控和剖析新版本的性能、稳定性和用户反馈等指标,从而更快地发现和解决问题,进步公布的成功率和用户体验。 可观测性在灰度公布中的利用要评估灰度公布中不同版本的性能及故障,须要收集和剖析运行数据。通过观测云的 one agent 数据采集和标签化能力,可能疾速、不便地采集不同服务版本中的运行数据,从而加以分析后,对新版本做出评估。 4.1 测试环境利用部署阐明测试环境中的所有服务是部署在 K8s 中。部署构造如下图所示: 前端 Web 页面申请通过 Gateway 网关拜访后端的Auth和System服务,前端 Web 是 Vue 开发的,后端服务是 Java 开发。 4.2 服务版本公布阐明测试将通过对System服务进行灰度公布。公布示意图阐明如下: 4.3 服务链路的接入和数据标签化4.3.1 服务链路的接入配置阐明在接入 Java 利用 APM 时,须要应用到dd-java-agent.jar包。在 Kubernetes 的环境中,为了不侵入利用的镜像,罕用的形式是在部署利用的 yaml 中应用 initContainers,利用雷同 Pod 中的容器共享存储的形式来应用dd-java-agent.jar。 观测云提供 DataKit Operator 的形式向非凡 Pod 提供注入 dd-lib 文件和 environment ,这种形式能够更不便、更快捷地接入利用链路。 4.3.2 标签化阐明标签能够帮忙对数据进行分类和组织,通过对服务运行的监控数据打标签,咱们能够更好地理解数据的起源、类型、状态等信息,从而更好地进行数据分析。这里,咱们就是通过对System服务公布的不同版本打上对应的标签,来实现后续对不同版本运行状况进行观测和剖析。 该文中的测试环境中,在服务对应 pod 部署的 yaml 文件中,原始运行服务的版本通过-Ddd.tag参数,打上版本为 version:v1.0的标签。如下图所示: 对新公布的服务版本通过-Ddd.tag参数,打上版本为v2.0 的标签。如下图所示: 通过上述的标签配置,服务对应的所有链路中都会带有对应的版本信息。对应成果如下图所示: 在服务运行的过程中,能够通过对不同版本进行分组来做实时比照观测和剖析。 4.4 对服务灰度公布的观测和剖析通过比照新旧两个版本的 QPS、服务执行耗时、服务错误率等指标数据进行实时监测,能够帮忙疾速发现问题和异样。 ...

September 8, 2023 · 1 min · jiezi

关于后端:Java-中的日期时间总结

前言大家好,我是 god23bin,在日常开发中,咱们常常须要解决日期和工夫,日期和工夫能够说是肯定会用到的,当初总结下 Java 中日期与工夫的基本概念与一些罕用的用法。 基本概念日期(年月日,某一天):2023-01-05工夫(时分秒,可具体到某一天某一刻):18:00:00、2023-01-05 18:00:00本地工夫:平时咱们说的,比方当初说今天早上七点钟,这里说的工夫就是本地工夫,在咱们中国,指的就是北京工夫。然而在今天早上七点钟,对于其余国家的人来说,他们的本地工夫就不一样了。时区:因为世界各个国家与地区经度不同,本地工夫也有所不同,所以划分了不同的时区,目前划分的是24个时区,咱们就位于东八区。目前须要理解的时区的表达方式晓得两种就能够了。 以 GMT 或者 UTC 加时区偏移量示意,例如:GMT+08:00 或者 UTC+08:00 示意东八区以 洲/城市 示意,例如,Asia/Shanghai,示意上海所在地的时区。不过这里的城市名称不是任意的城市,而是由国际标准组织规定的城市。Java 8 之前日期工夫相干的类在 Java 8 之前,次要应用的日期和工夫 API 包含: java.util.Datejava.util.Calendarjava.text.SimpleDateFormat1. DateDate 是 Java 中示意日期和工夫的类,个别用于获取以后的日期和工夫,比方更新数据库中记录的时候,须要更新某个日期工夫,那么就间接 new Date(),这样实例化的 Date 对象就是以后的这一时刻。 Date date = new Date();// 能够打印以后日期工夫System.out.println(date.toString()); // 控制台输入 Thu Jan 05 18:41:11 CST 20232. SimpleDateFormatSimpleDateFormat 是 Java 中用于格式化日期和工夫的类,此处所谓格式化,就是字面意思,对立格局,即它容许你将日期和工夫依照指定的格局转换成字符串,也能够将对应格局的字符串解析成日期和工夫对象。 次要用法就是: 格式化日期和工夫解析字符串格局的日期和工夫format 办法-格式化日期工夫,从 Date 到 String应用 public final String format(Date date) 办法格式化日期工夫。下面输入的格局,不是咱们想要的,所以须要进行日期工夫的格式化。 最罕用的一个格式化的模型是:yyyy-MM-dd HH:mm:ss 其中,yyyy 是年份,MM 是月份,dd 是天数,前面同理,HH:mm:ss 是时、分、秒。 ...

September 8, 2023 · 3 min · jiezi

关于后端:ToplingDB-CSPP-MemTable-有多快

(一)背景ToplingDB,尽管 fork 自 RocksDB 并且兼容其 API,但实现了本性难移的改良,最重要的就是实现了性能更高的 MemTable 和 SST。咱们在 db_bench: ToplingDB vs RocksDB 测试中,看到了 cspp memtable 的单线程性能,本文中,咱们测试它的多线程性能。(二)配置参数cspp memtable 的写性能太强,咱们必须配置多线程 flush 能力跟得上,而每个 memtable 又最多只能有 1 个线程来 flush,如此,又必须配置足够多的 memtable(write_buffer_num),能力充分发挥多线程 flush 的作用。咱们测试的是小 KV,key_size=8,value_size=20,所以评估指标优先应用 OPS,即每秒操作数,也就是每秒钟向 DB 中写入多少条 KV。咱们这次只测试写性能,为了不便大家重现该测试,咱们应用阿里云的 ecs.g7.16xlarge 进行测试。CPU 核数 & 超线程数32 核 64 超线程CPU 型号Intel(R) Xeon(R) Platinum 8369B CPU @ 2.70GHz内存256GToplingDB 和 RocksDB 雷同的参数:benchmarksfillrandomkey_size8value_size20num100000000threads40target_file_size_base33554432 (32M)target_file_size_multiplier2write_buffer_size1Gwrite_buffer_num17max_background_flushes16max_subcompations13max_background_compactions13enable_pipelined_writetrueToplingDB 和 RocksDB 不同的参数:ToplingDBRocksDBmemtable_factoryCSPP MemTableSkipListtable_factorydispatch_all_fast, no zipBlockBasedTable, no zipdb 目录放在 /dev/shm,全内存模式,打消 IO 带来的不确定性,其它参数均应用默认值,最初,设置不同的 batch_size 运行屡次。rocksdb 命令行:./db_bench -key_size=8 -value_size=20 -num=100000000 \ -db=/dev/shm/db_bench_rocksdb -bloom_bits=10 -write_buffer_size=1073741824 \ -target_file_size_base=33554432 -target_file_size_multiplier=2 \ -min_level_to_compress=10 -cache_size=34359738368 -enable_pipelined_write=true \ -max_write_buffer_number=17 -max_background_flushes=16 -subcompactions=13 \ -max_background_compactions=13 -disable_wal=true \ -benchmarks=fillrandom -threads=40 -batch_size=100ToplingDB 命令行(命令行中没有的参数在 db_bench_enterprise.yaml 中批改):./db_bench -json=sideplugin/rockside/sample-conf/db_bench_enterprise.yaml \ -key_size=8 -value_size=20 -num=100000000 -disable_wal=true \ -benchmarks=fillrandom -threads=40 -batch_size=100(三)测试后果3.1. fillrandom结果显示,当 batch_size=500 时,应用 CSPP,DB 的写性能超过 2000万 OPS,也就每秒钟能够向 DB 写入超过 2000万 条 KV。能够看到,只有 batch_size 足够大时,CSPP MemTable 的性能稳固地超过 SkipList 3 倍,实际上,CSPP MemTable 自身相比 SkipList 有 6 倍的写性能,测试中的 3 倍是被其它环节拉低后的后果。3.2 readwhilewritingreadwhilewriting 测试的是:多个线程读(-threads=40),一个线程写(-batch_size=100)可见,CSPP MemTable 不仅仅是写性能高,读性能更高,当然,读的时候除了搜寻 MemTable,还须要搜寻 SST,ToplingDB 的 SST,比 RocksDB 的 BlockBasedTable 更快。因为只有一个写线程,所以不会象 fillrandom 那样写得太快须要多线程 flush。(四)可期的改良:省略 MemTable Flush很久以前,咱们就有个 ToplingDB 省略 L0 Flush 的改良打算,然而这将会是对 RocksDB 伤筋动骨的一个批改,所以始终未付诸行动。从这个测试中咱们能够看到,当应用 CSPP MemTable 时,Flush 是一个显著的瓶颈,咱们配置了 16 个线程来执行 Flush,理论运行中个别用到 8 个左右(通过 LOG 或 ToplingDB 的 WebView 能够看到),这些 Flush 实际上是以 Pipeline 的形式执行的,因为不同 Flush 线程操作的是不同工夫的 MemTable,相互之间有时间差,从而形成一个实际上的 Pipeline。如果省略了 MemTable Flush,而后 MemTable 会间接与 L1 的 SST 执行 Compact,就 fillrandom 测试来说,性能再进步 30% 是问题不大的。更进一步,在实在场景中,省去 MemTable Flush,还能大幅减小 IO,因为 L0 简直必定是不压缩的,Flush 对 IO 的耗费相当可观。 ...

September 8, 2023 · 1 min · jiezi

关于后端:使用JavaStream将List转为Map

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 应用Java Stream将List转换为Map能够应用Collectors.toMap()办法。toMap()办法承受两个参数,第一个参数是用于提取Map的键的函数,第二个参数是用于提取Map的值的函数。上面是一个示例: import java.util.*;import java.util.stream.Collectors;public class Main { public static void main(String[] args) { List<Person> people = Arrays.asList( new Person("Alice", 25), new Person("Bob", 30), new Person("Charlie", 35) ); Map<String, Integer> ageByName = people.stream() .collect(Collectors.toMap(Person::getName, Person::getAge)); System.out.println(ageByName); }}class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; }}在下面的示例中,咱们有一个Person类示意人员信息,蕴含姓名和年龄。咱们将一个List<Person>转换为一个Map<String, Integer>,其中姓名作为键,年龄作为值。应用Person::getName作为键提取函数,Person::getAge作为值提取函数。最初,咱们将后果打印进去。 ...

September 8, 2023 · 1 min · jiezi

关于后端:面试题精讲如何使用Stream的聚合功能

有的时候博客内容会有变动,首发博客是最新的,其余博客地址可能会未同步,认准https://blog.zysicyj.top首发博客地址 系列文章地址 求和(Sum):List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int sum = numbers.stream().mapToInt(Integer::intValue).sum();System.out.println("Sum: " + sum);求平均值(Average):List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);double average = numbers.stream().mapToInt(Integer::intValue).average().orElse(0.0);System.out.println("Average: " + average);最大值(Max):List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int max = numbers.stream().mapToInt(Integer::intValue).max().orElse(0);System.out.println("Max: " + max);最小值(Min):List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int min = numbers.stream().mapToInt(Integer::intValue).min().orElse(0);System.out.println("Min: " + min);计数(Count):能够应用count()办法来计算Stream中元素的个数。List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);long count = numbers.stream().count();System.out.println("Count: " + count);连贯字符串(Joining):能够应用collect()办法联合Collectors.joining()来将Stream中的元素连接成一个字符串。List<String> names = Arrays.asList("Alice", "Bob", "Charlie");String joinedNames = names.stream().collect(Collectors.joining(", "));System.out.println("Joined Names: " + joinedNames);分组(Grouping):能够应用collect()办法联合Collectors.groupingBy()来依据某个属性对Stream中的元素进行分组。List<Person> people = Arrays.asList( new Person("Alice", 25), new Person("Bob", 30), new Person("Charlie", 25));Map<Integer, List<Person>> peopleByAge = people.stream().collect(Collectors.groupingBy(Person::getAge));System.out.println("People grouped by age: " + peopleByAge);求和(Summarizing):能够应用collect()办法联合Collectors.summarizingInt()等办法来获取元素的汇总信息,如求和、平均值、最大值、最小值等。List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));System.out.println("Sum: " + stats.getSum());System.out.println("Average: " + stats.getAverage());System.out.println("Max: " + stats.getMax());System.out.println("Min: " + stats.getMin());本文由mdnice多平台公布 ...

September 8, 2023 · 1 min · jiezi

关于后端:jcommander-命令

前言如果你想构建一个反对命令行参数的程序,那么 jcommander 非常适合你,jcommander 是一个只有几十 kb 的 Java 命令行参数解析工具,能够通过注解的形式疾速实现命令行参数解析。这篇教程会通过介绍 jcommadner ,疾速的创立一个命令行程序,最初反对的命令参数性能如下图。这个命令行工具仿照 git 操作命令,次要提供了如下性能命令:git-app.jar -help 查看命令帮忙信息。git-app.jar -version 查看以后版本号。git-app.jar clone http://xxxx 通过 URL 克隆一个仓库。git-app.jar add file1 file2 暂存 file1 文件 file2 文件。git-app.jar commit -m "正文" 提交并增加正文。jcommander 引入截止文章编写工夫,最新版本如下:<!-- https://mvnrepository.com/artifact/com.beust/jcommander --><dependency> <groupId>com.beust</groupId><artifactId>jcommander</artifactId><version>1.82</version></dependency>这个命令行工具仿照 git 操作命令,次要提供了如下性能命令: git-app.jar -help 查看命令帮忙信息。git-app.jar -version 查看以后版本号。git-app.jar clone http://xxxx 通过 URL 克隆一个仓库。git-app.jar add file1 file2 暂存 file1 文件 file2 文件。git-app.jar commit -m "正文" 提交并增加正文。 jcommander 引入截止文章编写工夫,最新版本如下: <!-- https://mvnrepository.com/artifact/com.beust/jcommander --><dependency> <groupId>com.beust</groupId> <artifactId>jcommander</artifactId> <version>1.82</version></dependency>commander 参数绑定命令行解析中,参数解析与绑定是最实用的一个场景,jcommander 应用 Parameter 注解进行参数绑定。咱们定义一个 GitCommandOptions.java 类来测试参数绑定。 ...

September 8, 2023 · 1 min · jiezi

关于后端:探索-Gateway-API-在-Service-Mesh-中的工作机制

前几天 Gateway API 发表在 0.8.0 中反对服务网格,这意味着 GAMMA(Gateway API for Mesh Management and Administration)有了新进展,尽管目前还是试验阶段。去年 6 月 Gateway API 公布 0.5.0 时,我还写了一篇 SMI 与 Gateway API 的 GAMMA 倡导意味着什么?。现在,SMI 作为 sandbox 我的项目的年度审查曾经 过了几个月仍未提交,唏嘘。 废话不多说,咱们来看下 0.8.0 下的 Gateway API 如何在 Service Mesh 中工作。 TL;DRGateway API 对服务网格的反对依然是试验阶段,然而曾经有厂商跟进(当然也都是试验阶段)。 相比 Gateway API 解决南北向流量将路由绑定到 Gateway 资源 相比,在网格中路由则是与 Service 进行绑定。简略了解成 Service 代理了 Gateway 的角色,不过该 Service 是指标 Service。 Gateway API 中的服务网格要说服务网格,咱们先来看下服务 Service。 形象 ServiceService 中 Kubernetes 中是一个独立的资源,这里说的形象是从逻辑上进行形象,形象成前端和后端两局部。 前端(Frontend)通常就是 Service 的 DNS 名字或者 ClusterIP;后端(Backend)则是通过标签选择器抉择的 Endpoint 或者 EndpointSlice。 ...

September 8, 2023 · 2 min · jiezi

关于后端:quarkus依赖注入之五拦截器Interceptor

欢送拜访我的GitHub这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos本篇概览本文是《quarkus依赖注入》系列的第五篇,通过后面的学习,咱们相熟了依赖注入的根本个性,接下来进一步理解相干的高级个性,先从本篇的拦截器开始如果您相熟spring的话,对拦截器应该不会生疏,通过拦截器能够将各种附加性能与被拦挡代码的主体解耦合,例如异样解决、日志、数据同步等多种场景本篇会演示如何自定义拦截器,以及如何对bean的办法进行进行拦挡,由以下章节形成定义和应用拦截器的操作步骤介绍拦挡异样拦挡构造方法获取被拦挡办法的参数多个拦截器之间传递参数定义和应用拦截器的操作步骤介绍定义和应用拦截器一共要做三件事:定义:新增一个注解(假如名为A),要用@InterceptorBinding润饰该注解实现:拦截器A到底要做什么事件,须要在一个类中实现,该类要用两个注解来润饰:A和Interceptor应用:用A来润饰要拦截器的bean整个流程如下图所示<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/%E6%B5%81%E7%A8%8B%E5%9B%BE%20(19).jpg" alt="流程图 (19)" style="zoom:67%;" /> 接下来通过实战把握拦截器的开发和应用,从最常见的拦挡异样开始拦挡异样写一个拦截器,在程序产生异样的时候能够捕捉到并将异样打印进去首先是定义一个拦截器,这里的拦截器名为<font color="blue">HandleError</font>,留神要用<font color="red">InterceptorBinding</font>润饰package com.bolingcavalry.interceptor.define;import javax.interceptor.InterceptorBinding;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.TYPE;@InterceptorBinding@Target({TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface HandleError {}其次是实现拦截器的具体性能,上面代码有几处要留神的中央稍后会提到package com.bolingcavalry.interceptor.impl;import com.bolingcavalry.interceptor.define.HandleError;import io.quarkus.arc.Priority;import io.quarkus.logging.Log;import javax.interceptor.AroundInvoke;import javax.interceptor.Interceptor;import javax.interceptor.InvocationContext;@HandleError@Interceptor@Priority(Interceptor.Priority.APPLICATION +1)public class HandleErrorInterceptor { @AroundInvoke Object execute(InvocationContext context) { try { // 留神proceed办法的含意:调用下一个拦截器,直到最初一个才会执行被拦挡的办法 return context.proceed(); } catch (Exception exception) { Log.errorf(exception, "method error from %s.%s\n", context.getTarget().getClass().getSimpleName(), context.getMethod().getName()); } return null; }}上述代码有以下四点须要留神:<font color="blue">Priority</font>注解的作用是设定HandleError拦截器的优先级(<font color="red">值越小优先级越高</font>),能够同时用多个拦截器拦挡同一个办法<font color="blue">AroundInvoke</font>注解的作用,是表明execute会在拦挡bean办法时被调用<font color="blue">proceed</font>办法的作用,并非是执行被拦挡的办法,而是执行下一个拦截器,直到最初一个拦截器才会执行被拦挡的办法能够从入参context处获得被拦挡实例和办法的信息而后是应用拦截器,这里创立个bean来演示拦截器如何应用,bean外面有个业务办法会抛出异样,可见拦截器应用起来很简略:用HandleError润饰bean即可@ApplicationScoped@HandleErrorpublic class HandleErrorDemo { public void executeThrowError() { throw new IllegalArgumentException("this is business logic exception"); }}验证拦截器的单元测试代码如下,只有执行HandleErrorDemo的executeThrowError办法就会抛出异样,而后察看日志中是否有拦截器日志信息即可验证拦截器是否合乎预期@QuarkusTestpublic class InterceptorTest { @Inject HandleErrorDemo handleErrorDemo; @Test public void testHandleError() { handleErrorDemo.executeThrowError(); }}执行单元测试,如下图红框所示,拦截器捕捉了异样并打印出异样信息<img src="https://typora-pictures-1253575040.cos.ap-guangzhou.myqcloud.com/image-20220327145313820.png" alt="image-20220327145313820" style="zoom:67%;" /> ...

September 8, 2023 · 3 min · jiezi

关于后端:Java-中反射注解动态代理AOP-之间的联系

AOP 和 Aspect 是什么?AOP 即 Aspect Orient Programming 是以一种编程范式,在不同业务中横着切一刀造成一个切面,在此切面上做一些雷同的事件。Aspect 就是切面。 规定了一些概念性的货色: Pointcut:是一个(组)基于正则表达式的表达式,有点绕,就是说他自身是一个表达式,然而他是基于正则语法的。通常一个pointcut,会选取程序中的某些咱们感兴趣的执行点,或者说是程序执行点的汇合。JoinPoint:通过pointcut选取进去的汇合中的具体的一个执行点,咱们就叫JoinPoint.Advice:在选取进去的JoinPoint上要执行的操作、逻辑。对于5种类型,我不多说,不懂的同学本人补根底。Aspect:就是咱们关注点的模块化。这个关注点可能会横切多个对象和模块,事务管理是横切关注点的很好的例子。它是一个形象的概念,从软件的角度来说是指在应用程序不同模块中的某一个畛域或方面。又pointcut 和advice组成。Weaving:把切面利用到指标对象来创立新的 advised 对象的过程。这些都是概念性的货色。本意是冀望通过抽离雷同业务逻辑,通过将加强代码动静织入(将加强代理和原有代码联合到一起造成加强后的代码),实现一次编写到处应用。 动静代理和 AOP 关系动静代理跟 AOP 的思维跟代理有相似之处,都是代码复用。一套加强代码复用到不同中央。区别在于指定复用的形式不同。 动静代理指定加强代码复用在哪里是通过手动编写被代理类来的,而 AOP 则是申明式的,之后通过其余形式主动创立出代理类。相似于一个是命令式,一个是申明式。AOP 是动静代理的一次简化,暗藏了实现细节,让编写和应用动静代理更加简便。 但无论怎么简化,基本都是要生成代理类,只不过这个过程是编译期做,还是在运行时做,是开发人员手动编写还是框架主动生成。 AspectJ 就是编译期生成,能够由开发人员手动执行命令,也能够放在 maven 等主动执行。 Spring AOP 则是应用 JDK 或 CGLib 动静代理,在运行时动静生成的。 AspectJ 和 Spring AOP 都是什么关系AspectJ 是 eclipse 下的我的项目,是一个 AOP 的实现框架,是一种对 Java 语言的扩大语言,在编译器将原来的 Java 代码中织入加强代码,生成加强后的 class 文件。 AspectJ 分为 编译时织入:通过 ajc 用编译生成 class 文件编译后织入:曾经 javac 生成 class 文件后,通过解决 class 文件失去新的织入后的 class 文件加载时织入(LTW):通过java agent机制在内存中操作类文件,能够不须要ajc的反对做到动静织入。AspectJ 有本人的语法和编译命令,pointcut 定义切点,after 定义告诉等。 ...

September 8, 2023 · 3 min · jiezi

关于后端:Java-动态代理原理

代理模式代理模式类图: 被代理类和代理类都实现同一个接口,通过在代理类对象中注入一个被代理对象,通过调用代理对象的办法,在其办法中间接调用被代理对象,从而实现代理的作用。 代理模式要点: 代理和被代理类实现同一接口代理对象中持有被代理对象的实例动态代理动态代理就是代理模式的具体实现。首先定义一个接口 /** * 创立Person接口 * @author Gonjan */public interface Person { //上交班费 void giveMoney();}接口的实现类,也是被代理类 public class Student implements Person { private String name; public Student(String name) { this.name = name; } @Override public void giveMoney() { System.out.println(name + "上交班费50元"); }}再定义一个代理类,同样实现接口: /** * 学生代理类,也实现了Person接口,保留一个学生实体,这样既能够代理学生产生行为 * @author Gonjan * */public class StudentsProxy implements Person{ //被代理的学生 Student stu; public StudentsProxy(Person stu) { // 只代理学生对象 if(stu.getClass() == Student.class) { this.stu = (Student)stu; } } //代理上交班费,调用被代理学生的上交班费行为 public void giveMoney() { // 这里写加强代码 stu.giveMoney(); }}具体应用代理类: ...

September 8, 2023 · 2 min · jiezi

关于后端:PHP-使用-nikicphpparser-处理-AST

先来相熟 php-parser 的 APInikic/PHP-Parser 能够解析 PHP 代码并生成 AST,还反对批改 AST 再还原成PHP源码,从而实现元编程,可用来做 AOP 和动态代码查看等。Swoft 框架中 AOP 也是基于 PHP-parser 开发的。 https://github.com/nikic/PHP-Parser 首先应用 composer 装置 php-parser composer require nikic/php-parser在代码中引入 autoload.php,开始测试代码 <?phprequire __DIR__ . '/vendor/autoload.php';use PhpParser\Error;use PhpParser\NodeDumper;use PhpParser\ParserFactory;// 定义一段PHP代码$code = <<<'CODE'<?phpfunction printLine($msg) { echo $msg, "\n";}printLine('Hello World!!!');CODE;// 创立一个解析器parser,须要指定优先版本$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);try { // 解析下面定义的PHP代码 $ast = $parser->parse($code);} catch (Error $error) { echo "Parse error: {$error->getMessage()}\n"; return;}$dumper = new NodeDumper;// 打印出生成的 ASTecho $dumper->dump($ast) . "\n========\n";打印出后果: ...

September 8, 2023 · 6 min · jiezi

关于后端:MongoDB-官方文档笔记之分片-Sharding

为什么要分片大数据量和高吞吐量会对机器性能造成较大压力,通过将数据调配到多台机器上,来升高单机的负载,进步整体性能,还能够通过减少分片来实现零碎扩容,另外分片也进步了整体服务的可用性。 晋升读写性能存储容量扩容高可用分片集群架构shard:即分片,真正存储数据的中央,其中数据以 chunk 为单位存储。部署时每个分片能够部署成一个正本集群,进步单个分片的可用性。mongos:查问路由,相当于一层代理,让客户端无感知读写分片集群。config servers:存储配置元数据,mongos 通过与之交互,失去分片的地位和信息。config servers 也可部署成正本集群。 分片中通过块 Chunk 来组织数据在一个shard中,数据是通过 chunk 的模式存储的,每个chunk 有肯定容量,存储一系列文档数据。chunk 默认大小是 64M。 分片中有两个比拟重要的过程:splitting 和 balancer。 splitting 过程: splitting 过程在 chunk 的大小超过最大值或 chunk 中文档个数超过肯定数量时,会将 chunk 做切分解决: balancer 过程 balancer 过程负责迁徙 chunk。如果分片集群中最大的 shard 和最小 shard 的 chunk 数量超过迁徙阈值,balancer 过程将会触发 chunk 迁徙,使集群中 shard 之间的容量更加均衡。 分片键分片键决定了文档在分片集群中散布状况。分片键要么是单字段索引,要么是复合字段索引。 每个分片键的值,与数据块 chunk 对应。也就是说一个分片键的计算结果,映射到一个 chunk 上。 指定分片键: sh.shardCollection( namespace, key )# namespace 为<database>.<collection> 指定数据库汇合# key 为一个索引 前面跟分片类型 { <shard key field1>: <1|"hashed">, ... } 定向操作和播送操作 Targeted Operations & Broadcast Operationsmongos 上的操作,如果可能间接定位到具体一个 shard ,这种操作是最快的,这种被称为定向操作 Targeted Operations。 ...

September 8, 2023 · 1 min · jiezi

关于后端:MongoDB-官方文档笔记之复制-Replication

正本集 Replica Set一组保护雷同数据的 mongod 过程,正本集提供了冗余和高可用。 一个主节点 Primary,接管所有写操作 多个从节点 Secondary,承受所有读操作 一个仲裁节点 Arbiter,不持有数据,只在选举时投票 倡议起码配置一主两从三成员正本集,但如果只有一主一从两个节点,则能够退出一个仲裁节点。仲裁节点参加选举,但不持有数据。 正本集中最多 50 个成员,但仅能有7个可投票成员。 正本集中的主从节点主节点会将所有写操作记录到日志中,即 oplog,从节点复制主节点的 oplog,并将这些操作利用在从节点上。主节点挂掉之后,从节点会通过选举产生新的主节点。 主从节点关系: 从节点间关系: 仲裁节点: 专门为投票存在的,一个仲裁节点一票。 正本集中的日志 Oplog主节点上的更新日志 oplog,会异步同步给从节点。 日志大小 启动时可指定日志大小,如未指定则采纳默认配置大小。 https://docs.mongoing.com/replication/replica-set-oplog#ri-zh... 慢日志 oplog中执行较慢的操作,会被记录到诊断日志中,相似MySQL的慢日志 复制提早 复制提早是指将写操作从主节点拷贝到从节点上的过程。 故障转移如果主节点与集群中其余节点通信超时,超过 electionTimeoutMillis 配置的工夫,从节点会产生选举。 跨数据中心的状况:https://www.pdai.tech/md/db/nosql-mongo/mongo-z-rep.html#跨数据中心 事务反对多文档事务,在事务提交之前批改对事务外不可见。 数据同步初始化同步 从正本集中的一节点复制所有数据到另外一个成员。可通过参数 initialSyncSourceReadPreference 指定优先的初始化同步源。同步源抉择:https://docs.mongoing.com/replication/replica-set-data-synchr... 具体过程: 克隆出所有除 local 库以外的数据库。依据 oplog,对数据集利用所有的更改一般复制 在初始化复制实现之后,从节点会再同步源复制 oplog,异步的利用这些操作。也反对多线程并发复制。 本文由mdnice多平台公布

September 8, 2023 · 1 min · jiezi

关于后端:MongoDB-官方文档笔记之存储-Storage

两种存储引擎WiredTiger 存储引擎,默认 In-memory 内存存储引擎 WiredTiger文档级并发模型 反对多个客户端同时批改汇合的不同文档。 快照和检查点 checkpoint WiredTiger应用MultiVersion(MVVC)并发管制。 检查点能够充当复原点 日志 Journal 日志与检查点联合应用,确保数据持久性。日志保留检查点之间的数据批改 日志通过疾速压缩库进行压缩,通过 storage.wiredTiger.engineConfig.journalCompressor 配置压缩算法或不压缩。 压缩 MongoDB反对对汇合和索引压缩,压缩能够缩小存储空间,但减少CPU开销。 MongoDB Wiredtiger存储引擎实现原理:https://mongoing.com/archives/2540 MongoDB 存储引擎 WiredTiger 原理解析:https://mongoing.com/archives/5367 In-Memory内存存储引擎文档级并发模型 同样反对文档级并发 持久性 没有长久化反对,所有数据均在内存中,包含应用程序数据和零碎数据,例如用户,权限,索引,正本集配置,分片群集配置等。 日志性能不实用内存引擎 日志应用日志记录的复原过程: 1.在数据文件中查找最初一个检查点 checkpoint 的标识符。 2.在日记 journal 文件中搜寻与最初一个检查点 checkpoint 的标识符匹配的记录。 3.从上一个检查点 checkpoint 开始,将操作利用于日志文件。 应用日志性能,WiredTiger为每个客户端发动的写操作创立一个日记记录。日志记录包含由初始写入引起的任何外部写入操作。 例如,对汇合中文档的更新可能会导致对索引的批改;WiredTiger创立单个日志记录,其中蕴含更新操作及其关联的索引批改。 https://docs.mongoing.com/cun-chu/journaling 本文由mdnice多平台公布

September 8, 2023 · 1 min · jiezi

关于后端:MongoDB-官方文档笔记之索引-Indexes

本文是在浏览 MongoDB 官网文档时记录的一些次要概念,更多细节能够查看文中的参考链接。 查看以后 db 索引db.COLLECTION_NAME.getIndexes()[ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "newDB.sites" }, { "v" : 1, "key" : { "name" : 1, "domain" : -1 }, "name" : "name_1_domain_-1", "ns" : "newDB.sites" }]单字段索引 single field 在单个字段上创立索引,1示意升序,-1示意降序。 对于单字段索引来说,指定升序降序无关紧要,查问时抉择升序降序性能是一样的。 但对于复合索引来说,查问须要合乎索引的程序能力走上索引。 # 创立索引db.records.createIndex( { score: 1 } )# 查问应用索引db.records.find( { score: 2 } )db.records.find( { score: { $gt: 10 } } )嵌入式文档的外部字段上的索引什么是嵌入式字段?就是这个字段的值也是一个文档。MongoDB 反对在嵌入式文档的外部字段上建设索引 ...

September 8, 2023 · 3 min · jiezi

关于后端:7Eleven-便利店背后的经营之道-读零售的哲学

本书作者是寰球最大的便利店连锁公司 7-Eleven 创始人——铃木敏文,联合 40 多年的批发教训,讲述了击中生产心理的批发哲学。铃木敏文的很多翻新,当初曾经成为商界常识,本书把那些不堪设想的批发翻新娓娓道来。对于批发的所有:选址、订货、销售、物流、治理……他一次又一次地在一片反对声中发明出批发界的新纪录。 铃木敏文-世界级企业家,日本 7-Eleven 创办人。他被日本媒体称为继松下幸之助之后的“日本新经营之神”,美国《哈佛商业评论》评估其为“交融东西方治理精力的最佳榜样”。他领导的日本最大的批发团体 SEVEN&I 控股公司为寰球第四大、亚洲最大的批发王国,营业额约等同日本 GDP 的1.25%,富可敌国。他曾三次领军企业改革,没有一次失败;而他所建设的“单品治理”概念,甚至让英语世界发明了一个新的名词“Tanpin Kanri”(“单品治理”日文发音)。 日本第一家7-Eleven 丰洲店 书中的知识点非常密集,满满的经营哲学和人生智慧,就算不是做批发行业工作,单单对做人来说,读过之后也是十分有价值的: 不要任劳任怨,正视本人的弱点,而后做出改善 当事业倒退碰壁时,任劳任怨是最轻松便捷的办法,然而轻松的背地即是停滞不前。只有正视本身的弱点,致力做出改善,并一直地向新指标发动挑战,能力好高鹜远地后退,失去稳固的成行。抵赖本人的谬误和有余,错了就要认,挨打要站稳 解读变动,预测将来 关键点在于从变动预测将来,环环相扣地考虑应答变动的办法,如此周而复始才会萌生新的商机。 造成产品畅销、生意萧条的起因只有一个,即是当初的工作办法曾经无奈满足时代和消费者需要的变动。 基于变动→假如→执行→验证 如文中以日本日益严重的少子化,老龄化问题做终点,针对这种变动做出将来人们对家庭周边的便捷服务的需要必将日益减少的判断。 之前经常说要「拥抱变动」,落到执行层面就成了被动的接管变动,强制本人适应变动,这其实是一种懈怠的行为,也是一种有效的拥抱。现在对拥抱变动有了新的解读,不是被动的承受,而是被动去剖析解读,做出假如,预测将来。 就像苹果公司在 2005 年,iPod 销量通知增长的时候,察看到手机的变动,过后的手机曾经具备了肯定的音视频性能,如果照这个趋势倒退上来,将来就不再须要 iPod 听音乐了。苹果公司基于这种变动的前提下做出 iPod 将来将不再被须要的假如,联合其余一系列的研发和致力,最终开发出了具备划时代意义的 iPhone 。 另外通过观察,再提出假如,最初去论证的方法论,在自然科学倒退中也能看到他的影子。自然科学家依据已知的迷信事实和迷信原理,对所钻研的天然景象及其规律性提出的揣测和阐明,也就是假说,自然科学史上有很多驰名的假说正是利用了这种思维,比方当初再平时不过的万有引力实践,最早也是通过观察天然景象提出的假说,之后加以证实得出的。再比方普朗克为解释黑体辐射提出的量子假说,也即量子论,对近现代自然科学的倒退产生了深远的影响。当然也有一些失败的假说,比方以太假说,尽管起初通过试验被证实是不成立的,但同样具备迷信摸索精力。 工作的真谛 无论产生什么都要认真对待,这就是工作的真谛。我深信人生没有无奈实现的事,如果始终踏踏实实地做好工作,眼前的路线必定会关上。 作者在刚刚退出新公司伊藤洋华堂时工作不顺,但还是踏踏实实做好本职工作。 不为本人设限 作者在伊藤洋华堂工作初期,业务赶上迅猛发展,一人身兼数职,做了推广、宣传、人事、财务简直所有治理职务。 这与字节跳动创始人张一鸣晚期在酷讯工作时的经验很像。张一鸣在酷讯工作时,不管工作是不是他该做的,在他实现本人的工作后,对于大部分共事的问题,只有是他能帮忙的,他都会去做。起初张一鸣本人回顾时提到这段经验对他帮忙成长很大。 同时这种不对本人设限的做法,在美团创始人王兴常常提到的《无限与有限游戏》中提到的观点也有相似之处,无限游戏是在边界内玩,而无线游戏则是和边界玩,摸索和扭转边界自身。不给本人设限,就有有限可能。 小型商店为提效做的头疼医头脚疼医脚的决策: 小型商店的生产效率较为低下。过后的政府行政机关领导店铺“缩短营业时间”以及“周日开业”,尽管其目的旨在提高效率、确保从业人员的权利,但理论却与顾客的需要南辕北辙。如此一来,反而起到了负面成果,进一步升高了小型商店的生产效率。 头疼医头脚疼医脚的事件还有很多,比方春运或节假日期间,很多车站客运站左近严打黑车或拼车,但其实黑车或拼车之所以会呈现,是因为在交通运力无奈满足突增的乘客乘车需要的背景下,乘客和司机自发造成的一种经济行为,监管部门一味地打击黑车而始终无奈满足乘客的乘车需要,“黑车”还是会以另一种模式呈现。 打破常规的提效策略 守业之初,因为生产厂商和一系列的批发商各自为营,每天来 1 号店送货的货车高达 70 辆。牛奶就是一个经典的例子。过后的牛奶有全农、森永、明治等品牌,尽管对消费者而言都属于同类产品,但却必须有不同公司别离发送货品。我发现这种配送形式十分没有效率,因而倡议把同一地区同类厂家的产品混装在一起履行独特配送。而后,零售业门外汉的想法再次受到了强力拥护。 40 年间,我每提出简历一个新事业的消防简直总会受到外界的强烈拥护。有些是因为没有先例可循,有些则是人们预计发展过程中会产生许多微小的妨碍等等。 这位“门外汉”经常可能打破常规,不会被历史的教训所解放,能力找到他人发现不了的办法。文中第三章的题目“大多数人拥护的事业往往可能获得成功”,与《黑客与画家》中“不能说的话”一章中的观点很类似,放弃对不能说的话的质疑,往往不能说的话背地是另一个真谛。 对立认知,贯彻经营理念 文中提到 7-Eleven 为了给顾客提供真正的“便当”,打算在店内引入水电煤气缴费和装置 ATM 取款机。在这过程中,大部分工作人员都是很认同因为顾客有需要,而要想满足顾客需要提供便当,必然要做这件事,而做这件事则必然要进入银行业,成立银行。 充沛了解并置信后去执行,与充斥纳闷并不置信去执行,成果会相差十分多。少数人因看见而置信,多数人因置信而看见。置信的力量是超乎设想的 善用数据,凉飕飕的数据背地是一个个鲜活的人 进来在服务行业中,许多公司为了进步顾客的忠诚度,在剖析备货时风行应用联合积分卡的大数据解析法。然而,无论呈现如许高科技的剖析零碎,如果只会单纯地依附电脑算出的数据,对备货精确度并无太大助益。 如在游览淡季,门店大量洽购能够随时在户外食用的三明治和面包。这时如果没有同步减少顾客可能会搭配购买的咖啡等音频的订货数量,那么届时饮料类的产品将会很快断货。如此只关注了主食的销售动静,却漠视与之有极大关联的饮料,显然会导致微小的机会损失。总之,必须时刻铭刻“单品治理”应用来应答“消费者将来需要”的办法。 世上没有疾速进步利润的特效药。胜利的关键在于是否能时刻放弃发现问题的意识,制订出切中要点的初步假如。为了实现这一步,咱们必须致力磨难商业“嗅觉”,更敏锐地感知世间的变动。 数字化治理是辅助提效的,基本还是关注变动,解读变动。不要看着某一数字的高下做繁多的判断,更不要为了某些数字的高下好坏而做轻重倒置的决策。 洞察生产心理 日本在非凡期间政府进步了 5% 的消费税,这样很多顾客的生产欲望缩小,7-Eleven 门店一开始为产品贴上提价 10% 的促销标签,也简直无人问津。而起初作者提出倡议改成生产后返 5% 的消费税,一开始共事还是十分拥护,起初只在北海道一些地区做了试点,后果顾客反响强烈,营业额比去年增长了 75%。 ...

September 7, 2023 · 1 min · jiezi

关于后端:使用基于-tideways-的-phpmonitor-搭建-PHP-性能监控平台

tideways、xhprof、xhgui 介绍tideways 是一家提供 PHP 利用性能监控相干服务的公司,最次要的产品是 tideways PHP 性能监控扩大,tideways 扩大可能监控申请耗时,SQL 执行耗时,CPU 和内存占用。监控数据存储反对MySQL 和 MongoDB。 提到 PHP 性能监控,不得不提性能监控工具 xhprof。xhprof 是 facebook 开发并开源的 PHP 性能监控扩大,配合 xhgui 做数据的可视化。但因为 facebook 前期将自家 PHP 替换成 HHVM,xhprof 也不再保护了。之后 tideways 演化出了两个分支,一个是本来的 tideways 扩大,一个是继承自xhprof 的 tideways_xhprof 扩大,tideways_xhprof 内的性能与 xhprof 统一。在演化成两个分支后,原有的 tideways 逐步演化成了付费的 SaaS 服务,而 tideways_xhprof 兼容了 xhprof 的一些应用习惯,并会始终保护。 产生分支前的最初一个版本:https://github.com/tideways/php-xhprof-extension/tree/v4.1.7 产生分支后的第一个版本:https://github.com/tideways/php-xhprof-extension/tree/v5.0-beta1 php-monitor 介绍在 xhprof 不保护之后,其对应的数据可视化 xhgui 也就随之不再更新。php-monitor 的作者最开始是为了做一版汉化的 xhgui:xhgui-branch。之后作者又联合 tideways 扩大做了 php-monitor,一个 PHP 性能监控平台,同时反对监控数据收集和数据可视化展现。 配置过程tideways 扩大 先装置 tideways 扩大。如果应用 PHP 5.6,请下载 tideways v4.1.5。如果应用 PHP7+ ,请下载v4.1.7(更高的版本无奈显示SQL)。 ...

September 7, 2023 · 2 min · jiezi