Java面试——Spring Cloud原理及应用(二)

Spring Cloud原理及应用

4、Spring Cloud Consul

Consul是HashiCorp公司推出的用于实现分布式系统服务注册、发现和配置的开源工具。和Spring Cloud Eureka一样,Consul也是一个一站式的服务注册与发现框架,内置了服务注册与发现、分布式一致性协议实现、健康检查、Key-Value存储和多数据中心方案,因此不需要依赖第三方工具(例如ZooKeeper)便可完成服务注册与发现,简单易用。

Consul采用Go编写,支持Linux、Windows和macOS系统,可移植性强。安装包仅为一个可执行文件,方便部署,且与Docker配合方便。

4.1、Spring Cloud Consul的原理

Consul是一个支持多数据中心的高可用的分布式服务注册、发现和配置服务,采用Raft一致性协议算法来保证服务的高可用;使用Gossip协议管理成员状态和广播消息,并且支持ACL访问控制。相对于Spring Cloud Eureka或其他服务注册与发现框架,Consul有以下特点。

4.1.1、Consul的特性
  • 高效的Raft一致性算法:Consul使用Raft一致性算法来保证集群状态的一致性,在实现上比Paxos一致性算法更简单(ZooKeeper采用Paxos一致性算法实现,Etcd采用Raft一致性算法实现)。
  • 支持多数据中心:Consul支持多数据中心。多数据中心可以使集群避免单数据中心的单点故障问题,但在部署的过程中需要考虑网络延迟、数据分片等情况。ZooKeeper和Etcd均不支持多数据中心。
  • 健康检查:Consul支持健康检查,默认每10s做一次健康检查,保证注册中心的服务均可用,Etcd不提供此功能。
  • HTTP和DNS支持:Consul支持HTTP和DNS协议接口。ZooKeeper集成了DNS协议,实现复杂,Etcd只支持HTTP。

除了上面4个特性,Consul还支持其他丰富的功能。Consul与其他框架的特性对比如表所示。

4.1.2、Consul的角色

Consul按照功能可分为服务端和客户端。

  • 服务端:Server,用于保存服务配置信息的高可用集群,在局域网内与本地客户端通信,在广域网内与其他数据中心通信。每个数据中心的Server数量都推荐为3个以上以保证服务高可用。在集群中,Server又分为ServerLeader和Server。Server Leader负责同步注册信息和进行各个节点的健康检查,同时负责整个集群的写请求。 Server负责把配置信息持久化并接收读请求。Server在一个数据中心(Data Center,DC)内使用LAN Gossip协议的一致性算法,在跨数据中心内使用WAN Gossip协议的一致性算法。
  • 客户端:Client,是无状态的服务,将HTTP和DNS协议的接口请求转发给局域网内的服务端集群。

Consul的服务端和客户端还支持跨数据中心的访问,提供了跨区域的高可用功能。Consul的架构如图所示。

4.1.3、Consul的服务注册与发现流程
  • (1)服务注册:Producer在启动时会向Consul服务端发送一个POST注册请求,注册请求中包含服务地址和端口等信息。
  • (2)健康检查:Consul服务端在接收Producer的注册信息后,每10s(默认)会向Producer发送一个健康检查的请求,检验Producer是否健康。
  • (3)服务发现:当Consumer发起请求(请求格式为"/api/address")时,首先会从Consul服务端获取一个包含Producer的服务地址和端口的临时表。该表只包含通过了健康检查的Producer的可用服务列表。
  • (4)服务请求:客户端从临时表中获取一个可用的服务地址,向Producer发送请求。Producer在收到请求后返回请求响应。

4.2、Spring Cloud Consul的使用

4.2.1、Consul的服务启动

Consul是应用服务的注册中心,服务注册与发现均在Consul上被完成。Consul的使用分3步:下载安装包、启动服务端、启动客户端。

(1)下载安装包。

从官网下载安装包,有Windows版、Linux版、macOS版、Solaris版和FreeBSD版,如图所示。

(2)启动服务端。

在安装包目录下,执行以下命令启动服务端。

在上述命令中,-server表示启动服务端,-data-dir表示数据的存储地址,-node表示节点名称。除了以上基础配置,Consul还有很多其他配置。Consul的服务参数配置如表所示。

在服务启动后,在浏览器地址栏中输入http://localhost:8500/,可以看到如图所示的管理界面。

(3)启动客户端。

启动客户端只需要将Server参数去掉即可,启动命令如下。

4.2.2、Consul服务提供者的定义

服务提供者在启动的时候会将自身的服务地址状态上报Consul Server,服务消费者在每次发起请求时都要先从Consul Server获取可用的临时服务列表(该列表维护了可用的服务提供者的地址)​,再选择一个可用的服务提供者的地址进行服务调用。实现一个服务提供者分为5步:首先在pom.xml中加入spring-cloud-starter-consul-discovery依赖,然后通过@EnableDiscoveryClient注解开启服务发现的功能,接着配置application.properties配置文件、定义服务接口,最后一步是访问和使用。

(1)pom.xml添加依赖。

在pom.xml中加入spring-cloud-starter-consul-discovery依赖。

(2)通过@EnableDiscoveryClient注解开启对服务发现的支持。

(3)application.properties配置。

配置服务名称、端口、要连接的Consul Server的地址和端口。

(4)定义服务。

上述代码定义了一个名为hello的服务,服务地址为"/hello"​。

(5)调用服务。

在浏览器地址栏中输入http://127.0.0.1:8501/hello访问服务,如图所示。

4.2.3、Consul服务消费者的定义

服务消费者是具体的服务调用方,它每次发起请求都首先从Consul Server获取可用的临时服务列表(该列表维护了可用的服务提供者的地址)​,然后选择一个可用的服务提供者的地址实现服务调用。要实现一个服务消费者分为4步:首先需要在pom.xml中加入spring-cloud-spring-cloud-starter-consul-discovery依赖,然后配置application.properties配置文件,接着获取临时服务列表,最后一步是访问和使用。

(1)pom.xml添加依赖。

在pom.xml中加入spring-cloud-spring-cloud-starter-consul-discovery依赖。

(2)application.properties配置。

配置服务名称、端口、要连接的Consul Server的地址和端口。

(3)获取临时服务列表。

上述代码通过依赖注入LoadBalancerClient来获取临时服务列表,具体是通过choose(​)方法来实现的,choose(​)方法的参数是要获取的服务提供者的服务实例名称。

(4)调用服务。

上述代码通过loadBalancer.choose("serviceName")获取一个服务实例,然后使用RestTemplate.getForObject(​)实现远程服务调用,其中,第一个参数是服务实例的地址,第二个参数是服务请求的返回值类型。

(5)验证服务。

在浏览器地址栏中输入http://127.0.0.1:8503/call访问客户端服务,如图所示。

5、Spring Cloud Feign

Feign是一种声明式、模板化的HTTP Client。它的目标是使编写Java HTTP Client变得更简单。Feign通过使用Jersey和CXF等工具实现一个HTTP Client,用于构建REST或SOAP的服务。Feign还支持用户基于常用的HTTP工具包(OkHTTP、HTTPComponents)实现自定义的HTTP Client。

Feign基于注解的方式将HTTP请求模板化。Feign将HTTP请求参数写入Template,极大地简化了HTTP请求。尽管Feign目前只支持基于文本的HTTP请求,不适合文件的上传和下载,但它为HTTP请求提供了更多可能性,比如请求回放等功能。同时,Feign使HTTP单元测试变得更加方便。

5.1、Feign的应用

Feign提供了声明式接口编程的方式,其应用一般依赖服务发现组件来实现远程接口调用,在并发要求不高的情况下可以作为RPC方案使用,实现服务之间的解耦。Feign应用分为服务提供者和服务消费者。

要实现一个服务提供者分为5步:首先在pom.xml中加入spring-cloud-starter-feign依赖,然后通过@EnableFeignClients注解开启对Feign的支持,接下来配置application.properties配置文件,再创建接口和定义需要远程调用的方法,最后一步是服务的访问和使用。

(1)pom.xml添加依赖。

在pom.xml中加入spring-cloud-starter-feign依赖。

(2)通过@EnableFeignClients注解开启对Feign的支持。注意,Feign一般和服务发现配合使用,以下代码使用@EnableEurekaClient开启了对服务发现客户端的支持。

(3)application.properties配置。

配置服务名称、端口和需要连接的服务注册中心的地址,这里注册中心使用2.3节的Eureka服务。

(4)创建接口和定义需要远程调用的方法。

上述代码首先定义了一个名为FeignClientInterface的接口,并通过FeignClient("EUREKA-CLIENT")来实现注解的配置,这里的参数"EUREKA-CLIENT"为远程服务实例的名称;然后定义了serviceProducer(​)方法,该方法通过调用服务实例名为"EUREKA-CLIENT"的"/serviceProducer"方法来实现远程调用。

(5)调用服务。

上述代码通过注入FeignClientInterface依赖,并调用已经定义好的serviceProducer(​)方法来实现服务调用。启动服务,在浏览器地址栏中输入http://127.0.0.1:9004/consume/feign访问服务,如图所示。

5.2、Feign的常用注解

Feign通过类似Spring MVC的注解来实现对HTTP参数的封装和调用,常用注解如表所示。

6、Spring Cloud Hystrix

Netflix Hystrix为SOA(Service Oriented Architecture,面向服务的架构)和微服务架构提供一整套服务隔离、服务熔断和服务降级的解决方案。它是熔断器的一种实现,主要应用于微服务架构的高可用,防止出现服务雪崩等问题。

微服务架构将传统的单体服务根据业务功能和模块的不同,分解为多个独立的子服务,每个子服务都独立开发、部署和发布,子服务之间通过RPC接口实现服务间的接口调用。每个子服务都可以根据自己的需要进行独立的技术选型,服务之间相互独立,实现敏捷开发和部署。

由于业务之间往往具有复杂的依赖和调用关系,因此,微服务中的各个子服务之间的依赖关系也较为复杂。比如上游某个子服务因网络故障或者操作系统资源不足出现接口调用异常,则将导致下游服务也出现服务异常;此时,如果上游服务没有很好的请求拒绝策略,则会导致请求不断增加,大量的请求积压不但会导致当前服务宕机,还可能导致下游服务宕机,继而引起雪崩效应。

为了避免雪崩效应,提高关键业务的可靠性,可使用熔断器对部分非核心、低服务级别的业务进行服务降级。Netflix Hystrix实现了服务熔断器的功能,具体的做法是通过监控远程接口调用的状态,统计分析远程接口调用的数据,一旦发现某个服务出现宕机或故障过多的情况,则自动进行服务降级,不再调用远程接口服务,而是直接返回错误状态,避免集群雪崩效应,这样既有效保障了集群的安全性,也为恢复服务争取了时间。

6.1、Hystrix的特性

6.1.1、服务熔断

Hystrix熔断器就像家中的安全阀一样,一旦某个服务不可用,熔断器会直接切断该链路上的请求,避免大量的无效请求影响系统稳定,并且熔断器有自我检测和恢复的功能,在服务状态恢复正常后会自动关闭。

6.1.2、服务降级

Hystrix通过fallback实现服务降级。在需要进行服务降级的类中定义一个fallback方法,当请求的远程服务出现异常时,可以直接使用fallback方法返回异常信息,而不调用远程服务。fallback方法的返回值一般是系统默认的错误消息或者来自缓存中的数据,用以告知服务消费者当前服务处于不可用状态。Hystrix通过HystrixCommand实现服务降级,熔断器有闭路、开路和半开路3种状态。Hystrix熔断器的状态切换流程如图所示。

  • 当调用远程服务请求的失败数量超过一定比例(默认为50%)时,熔断器会切换到开路状态,这时所有请求都会直接返回失败信息而不调用远程服务。
  • 熔断器保持开路状态一段时间后(默认为5s),会自动切换到半开路状态。
  • 熔断器判断下一次请求的返回情况,如果请求成功,则熔断器切换回闭路状态,服务进入正常链路调用流程;否则重新切换到开路状态,并保持开路状态。
  • 熔断器判断下一次请求的返回情况,如果请求成功,则熔断器切换回闭路状态,服务进入正常链路调用流程;否则重新切换到开路状态,并保持开路状态。
6.1.3、依赖隔离

Hystrix通过线程池和信号量两种方式实现服务之间的依赖隔离,这样即使其中一个服务出现异常,资源迟迟不能释放,也不会影响其他业务线程的正常运行。

(1)线程池的隔离策略。

Hystrix线程池的资源隔离为每个依赖的服务都分配一个线程池,每个线程池都处理特定的服务,多个服务之间的线程资源互不影响,以达到资源隔离的目标。当突然发生流量洪峰、请求增多时,来不及处理的任务将在线程队列中排队等候,这样做的好处是不会丢弃客户端请求,保障所有数据最终都会得到处理。

(2)信号量的隔离策略。

Hystrix信号量的隔离策略是为每个依赖的服务都分配一个信号量(原子计数器)​,当接收到用户请求时,先判断该请求依赖的服务所在的信号量值是否超过最大线程设置。若超过最大线程设置,则丢弃该类型的请求;若不超过,则在处理请求前执行"信号量+1"的操作,在请求返回后执行"信号量-1"的操作。当流量洪峰来临,收到的请求数量超过设置的最大值时,这种方式会直接将错误状态返回给客户端,不继续去请求依赖的服务。

6.1.4、请求缓存

Hystrix按照请求参数把请求结果缓存起来,当后面有相同的请求时不会再走完整的调用链流程,而是把上次缓存的结果直接返回,以达到服务快速响应和性能优化的目的;同时,缓存可作为服务降级的数据源,当远程服务不可用时,直接返回缓存数据,对于消费者来说,只是可能获取了过期的数据,这样就优雅地处理了系统异常。

6.1.5、请求合并

当微服务需要调用多个远程服务做结果的汇总时,需要使用请求合并。Hystrix采用异步消息订阅的方式进行请求合并。当应用程序需要请求多个接口时,采用异步调用的方式提交请求,然后订阅返回值,这时应用程序的业务可以接着执行其他任务而不用阻塞等待,当所有请求都返回时,应用程序会得到一个通知,取出返回值合并即可。

6.2、Hystrix的服务降级流程

Hystrix的服务熔断是依赖HystrixCommand指令来实现的,具体流程如下。

  • 当有服务请求时,首先会根据注解创建一个HystrixCommand指令对象,该对象设置了服务调用失败的场景(如服务请求超时等)和调用失败后服务降级的业务逻辑方法。
  • 熔断器判断状态,当熔断器处于开路状态时,直接调用服务降级的业务逻辑方法返回调用失败的反馈信息。
  • 当熔断器处于半开路或者闭路状态时,服务会进行线程池和信号量等资源检查,如果有可用资源,则调用正常业务逻辑。如果调用正常业务逻辑成功,则返回成功后的消息;如果失败,则调用服务降级的业务逻辑,进行服务降级。
  • 当熔断器处于半开路或者闭路状态时,如果当前服务线程池和信号量中没有可用资源,则执行服务降级的业务逻辑,返回失败信息。
  • 当熔断器处于半开路状态并且本次服务执行失败时,熔断器会进入开路状态。
  • 当正常业务逻辑处理超时或者出现错误时,HystrixCommand会执行服务降级的业务逻辑,返回失败信息。
  • 线程池和信号量的资源检查及正常业务逻辑会将自己的状态和调用结果反馈给监控,监控将服务状态反馈给熔断器,以便熔断器判断熔断状态。Hystrix的服务降级流程如图所示。

6.3、Hystrix的使用

Hystrix的使用主要分为服务熔断、服务降级和服务监控3个方面,使用流程如下。

(1)pom.xml添加依赖。

在pom.xml中加入Hystrix依赖,其中,spring-cloud-starter-netflix-hystrix和hystrixjavanica为Hystrix服务熔断所需的依赖,spring-cloud-netflix-hystrix-dashboard为Hystrix服务监控所需的依赖。

(2)通过@EnableHystrix注解开启对服务熔断的支持,通过@EnableHystrixDashboard注解开启对服务监控的支持。注意,Hystrix一般和服务发现配合使用,这里使用@EnableEurekaClient开启了对服务发现客户端的支持。

(3)application.properties配置。

配置服务名称、端口和需要连接的服务注册中心的地址,这里注册中心使用2.3节的Eureka服务。

(4)服务熔断和降级。

上述代码定义了一个远程调用的方法hystrixHandler(​)​,并通过@HystrixCommand(fallbackMethod="exceptionHandler")在方法上定义了一个服务降级的命令。当远程方法调用失败时,Hystrix会自动调用fallbackMethod来完成服务熔断和降级,这里会调用exceptionHandler(​)方法。

(5)服务验证。

在浏览器地址栏中输入http://127.0.0.1:9005//service/hystrix/,结果如图所示。

当关闭EUREKA-CLIENT远程服务时,远程服务将不可用,Hystrix的熔断器打开,程序直接调用fallbackMethod方法实现服务降级,结果如图所示。

6.4、异步请求

上节中的远程调用请求必须等到网络请求restTemplate.getForEntity("http://EUREKACLIENT/serviceProducer",String.class).getBody(​)返回结果后,才会执行后面的代码,即阻塞运行。而在实际使用过程中,应用程序常常希望使用非阻塞I/O来更优雅地实现功能。Hystrix为非阻塞I/O提供了两种实现方式,分别是表示将来式的Future和表示回调式的Callable。

6.4.1、Future

当用Future去请求一个网络I/O的任务时,Future会以多线程的形式异步实现服务调用,主线程不必阻塞等待,在结果返回后再通过Future的get(​)方法获取Future的返回结果。具体实现如下。

(1)定义HystrixCommand。

上述代码通过继承HystrixCommand定义一个CommandFuture来实现异步请求,其中,正常业务执行的逻辑在覆写的run(​)方法体中被执行,服务降级方法在getFallback(​)中被执行。需要注意的是,这里使用andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")​)实现了使用HystrixCommandKey工厂定义依赖名称,每个CommandKey都代表一个依赖抽象,相同的依赖要使用相同的CommandKey名称。依赖隔离的本质就是对相同CommandKey的依赖进行隔离。使用andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")​)实现了基于HystrixThreadPoolKey工厂定义线程池名称。

当对同一业务的依赖进行资源隔离时,使用CommandGroup进行区分,但是当对同一依赖进行不同远程调用时(例如,一个是Redis服务,一个是HTTP服务)​,则可以使用HystrixThreadPoolKey进行隔离区分,虽然在业务上都是相同的组,但是当需要在资源上进行隔离时,则可以使用HystrixThreadPoolKey进行区分。

(2)使用HystrixCommand。

上述代码通过new CommandFuture("future",restTemplate).queue(​)定义一个异步服务请求,请求在提交后会以队列的形式在线程池中等待被执行,在执行完成后通过get(​)方法获取即可。

6.4.2、Callable

预定义一个回调任务,Callable在发出请求后,主线程继续执行,在请求被执行完成并返回结果后,Callable会自动调用回调任务。具体使用如下。

(1)定义HystrixObservableCommand。

上述代码定义了名为CommandObservable的类,该类继承自HystrixObservableCommand接口,并通过覆写HystrixObservableCommand接口中的construct(​)方法实现观察者模式。具体实现为通过Observable.create(​)创建并返回一个Observable<String>对象,在创建对象时,通过new Observable.OnSubscribe<String>(​)方法实现消息的监听和处理。其中,call方法用于消息的接收和业务的处理,在消息处理完成后通过subscriber.onNext(result)将调用结果传递下去,当所有任务都执行完成时通过subscriber.onCompleted(​)将总体执行结果发布出去。

resumeWithFallback方法是服务降级处理逻辑,当服务出现异常时,通过subscriber.onNext("hystrix:远程服务异常")进行服务熔断和异常消息的发布,实现服务降级处理。

(2)使用HystrixObservableCommand。

上述代码通过new CommandObservable("observer",restTemplate).observe(​)定义了一个实现服务发布的命令。通过调用observable.subscribe(​)方法来实现基于观察者模式的请求结果订阅,其中,订阅的数据结果在onNext(​)方法中被通知,总体调用结果在onCompleted(​)中被通知,服务处理异常结果在onError(​)中被通知。

6.5、Hystrix的常用配置

6.5.1、熔断的配置参数
  • circuitBreakerEnabled:是否允许熔断(默认为true)。
  • circuitBreakerRequestVolumeThreshold:最小熔断请求数(默认为20)。当一个统计窗口内处理的请求数达到该阈值时,Hystrix会触发是否需要熔断的判断。
  • circuitBreakerErrorThresholdPercentage:熔断的阈值百分比(默认为50)。当一个统计窗口内有50%的请求处理失败时,Hystrix会触发熔断。
  • circuitBreakerForceOpen:是否强制开启熔断器(默认为false)。如果为true,则会拒绝所有请求。
  • circuitBreakerForceClosed:强制熔断器进入closed状态(默认为false)。如果设置为true,则会忽略错误百分比(circuitBreakerErrorThresholdPercentage),优先级比强制开启熔断器(circuitBreakerForceOpen)低。也就是说,当circuitBreakerForceOpen设置为true时,circuitBreakerForceClosed这个设置是无效的。
  • circuitBreakerSleepWindowInMilliseconds:熔断时间(默认为5s)。当满足熔断条件时,熔断器在中断请求5s后会自动进入半开路状态,允许部分流量进行重试。
6.5.2、执行的配置参数
  • (1)executionIsolationSemaphoreMaxConcurrentRequests:当隔离策略为Execution IsolationStrategy.SEMAPHORE时,允许进入HystrixCommand.run()方法的最大并发请求数量。
  • (2)executionIsolationStrategy:隔离策略。HystrixCommand的默认值为THREAD,HystrixObservableCommand的默认值为SEMAPHORE。
  • (3)executionIsolationThreadInterruptOnTimeout:在隔离执行超时后是否中断(默认为true)。
  • (4)executionTimeoutInMilliseconds:执行超时时间(单位为ms)。当任务执行超过指定时间时,执行fallback函数进行熔断。
  • (5)executionTimeoutEnabled:是否允许超时执行。
  • (6)executionIsolationThreadPoolKeyOverride:指定任务执行的线程池。Hystrix通过线程池名称来判断使用哪一个线程池来执行,如果没有对应的线程池,则会为其创建一个线程池。
  • (7)fallbackIsolationSemaphoreMaxConcurrentRequests:HystrixCommand.getFallback()执行的最大并发数(默认为10),如果超过该并发数,则直接抛出异常,不执行fallback函数。
  • (8)fallbackEnabled:是否允许fallback。(9)metricsRollingStatisticalWindowInMilliseconds:熔断统计时间窗口(默认为10s),也就是以10s为单位统计信息。
  • (9)metricsRollingStatisticalWindowInMilliseconds:熔断统计时间窗口(默认为10s),也就是以10s为单位统计信息。
  • (10)metricsRollingStatisticalWindowBuckets:一个熔断统计窗口内的Bucket数量(默认为10)。
  • (11)metricsRollingPercentileEnabled:是否开启执行延迟统计(默认为true),如果为true,则服务的执行延迟会被追踪计算;如果为false,则所有统计均值百分比都会返回-1。
  • (12)metricsRollingPercentileWindowInMilliseconds:执行时间统计窗口(默认为60s)。
  • (13)metricsRollingPercentileWindowBuckets:执行时间统计窗口内的Bucket数量(默认为6)。
  • (14)metricsRollingPercentileBucketSize:执行时间内保留Bucket的最大值。
  • (15)metricsHealthSnapshotIntervalInMilliseconds:计算成功失败百分比的时间间隔(默认为500ms)。
  • (16)requestCacheEnabled:是否开启请求缓存(默认为true)。
  • (17)requestLogEnabled:是否开启请求日志(默认为true)。
  • (18)maxRequestsInBatch:批量执行命令的最大值(默认为Integer.MAX_VALUE)。
  • (19)timerDelayInMilliseconds:执行命令延迟时间(默认为10ms)。
  • (20)requestCacheEnabled:是否开启请求缓存(默认为true)。

6.7、Hystrix Dashboard

Hystrix Dashboard主要用来实时监控Hystrix的各项运行指标。通过Hystrix Dashboard可以查询Hystrix的实时信息,用于快速定位和发现问题。Hystrix Dashboard的使用简单方便,首先在pom.xml中引入spring-cloud-netflix-hystrix-dashboard服务依赖,然后使用@EnableHystrixDashboard注解开启Dashboard功能即可。由于上节的代码中已经实现了该功能,这里不做赘述。在服务启动后,在浏览器地址栏中输入http://127.0.0.1:9005/hystrix,可以看到如图所示的界面。

相关推荐
东小西2 小时前
【SAA实战】第 1 篇:ReactAgent 入门——先撸个"会调工具的助手"跑起来
java·人工智能·spring
黄敬峰2 小时前
一文搞懂 Docker + Dockerfile:从镜像构建到全栈部署
面试
mqiqe2 小时前
AgentScope Java 2.0 协议集成全景解析:A2A、AG-UI、Agent Protocol 三大开放协议实战指南
java·开发语言·ui
脉动数据行情3 小时前
Java 实现台股 TWSE/TPEx 行情采集(个股 + K 线)
java·开发语言·twse·tpex·台股
月华路4 小时前
G1 GC 对数组与大对象(Humongous)的处理
java·jvm·算法
liangshanbo12155 小时前
虚拟列表深度面试题整理
java·开发语言·前端
gugucoding5 小时前
59. 【Java】Spring Boot 入门:第一个 Web 应用
java·开发语言·spring boot
kyriewen6 小时前
我踩了3次同一个坑才明白:JavaScript里比0.1+0.2更隐蔽的5个数字陷阱
前端·javascript·面试
10mAh6 小时前
【Java】HashMap 的 put 到底做了什么?——冲突、扩容与树化实测
java·开发语言·hash