-
【问题来源】黑龙江农信社【问题简要】在客户云系统的报表模块里,查看的数据与手册中大屏监控接口返回数据不一致【问题类别】座席监控【AICC解决方案版本】AICC 版本:AICC 8.0.71【问题现象描述】如:通过手册中 获取座席维度的历史监控指标接口:rest/cmsapp/v1/openapi/hisindex/agent查询接通率 与 客户云系统中的接通率有差异
-
我想问一下CodeArts IDE for Java这个怎么在一个窗口里面打开多个工程。还有就是怎么能默认maven的配置,现在每次打开工程都要重新配置maven。
-
【问题来源】黑龙江农信社【问题简要】使用 AICC 22.200.0 产品文档 (OP独立部署) 01.chm 中的java 鉴权示例代码无法进行鉴权,response 响应码 401【问题类别】座席监控【AICC解决方案版本】AICC 版本:AICC 8.0.71【问题现象描述】根据文档中 鉴权的示例代码生成了 authorization 串在执行示例代码的 doPost 方法后,返回401 鉴权失败但将 authorization 粘贴到 postman 执行 就可以返回 200 成功示例代码 原封粘贴出来,并未做逻辑变动java版本是 1.8_381
-
Java实现流媒体服务器的方案随着互联网的快速发展,流媒体技术在音视频领域得到了广泛的应用。流媒体服务器作为流媒体技术的核心组成部分,可以将音视频数据实时传输给用户。本文将介绍如何使用Java实现一个流媒体服务器的方案。选择合适的流媒体框架Java中有许多成熟的流媒体框架可供选择,如Red5、Darwin Streaming Server、JWPlayer等。这些框架提供了丰富的功能和良好的性能,可以帮助我们快速搭建流媒体服务器。本文将以Red5为例,介绍如何实现一个流媒体服务器。安装和配置Red5首先,我们需要下载并安装Red5服务器。可以从官方网站下载最新版本的Red5。安装过程非常简单,只需解压缩下载的文件,然后运行其中的red5.bat(Windows系统)或run.sh(Linux系统)即可启动Red5服务器。创建流媒体应用接下来,我们需要创建一个流媒体应用。在Red5中,流媒体应用是通过扩展名为.r303的配置文件来定义的。我们可以使用文本编辑器创建一个名为mystream.r303的文件,然后添加以下内容:<?xml version="1.0" encoding="UTF-8"?> <configuration> <node-list> <node name="mystream" description="My Stream Application" type="org.red5.server.stream.Application"> <param name="playback" value="false"/> <param name="record" value="false"/> <param name="preview" value="true"/> <param name="publish" value="true"/> <param name="application" value="mystream"/> <param name="name" value="mystream"/> <param name="autoStart" value="true"/> <param name="bufferTime" value="4000"/> <param name="maxBandwidth" value="1000000"/> <param name="minBandwidth" value="10000"/> <param name="audioBitrate" value="96"/> <param name="videoBitrate" value="128"/> <param name="audioSampleRate" value="44100"/> <param name="videoFrameRate" value="30"/> <param name="keyframeInterval" value="25"/> <param name="metadataInterval" value="25"/> <param name="segmentLength" value="3600"/> <param name="segmentGap" value="60"/> <param name="location" value="/mystream"/> </node> </node-list> </configuration>这个配置文件定义了一个名为mystream的流媒体应用,设置了各种参数,如音频和视频比特率、帧率等。保存文件后,将其放置在Red5服务器的配置目录下(默认为conf)。编写Java代码处理流媒体数据为了处理流媒体数据,我们需要编写一个Java类,继承自org.red5.server.stream.ClientBroadcastStream类。在这个类中,我们可以重写onPublish方法,用于处理推流事件;重写onPlay方法,用于处理播放事件;重写其他方法,以处理其他事件。以下是一个简单的示例:package com.example; import org.red5.server.api.stream.ClientBroadcastStream; import org.red5.server.api.stream.IStreamPacket; import org.red5.server.stream.ClientBroadcastStream; import org.red5.server.stream.scope.IScope; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyStream extends ClientBroadcastStream { private static final Logger log = LoggerFactory.getLogger(MyStream.class); private IScope scope; private String streamName; private int audioChannels; private int audioSampleRate; private int audioBitRate; private int videoWidth; private int videoHeight; private int videoCodecId; private boolean isAudioActive; private boolean isVideoActive; private long lastAudioReceived; private long lastVideoReceived; private long lastAudioSent; private long lastVideoSent; private long lastAudioKeyFrameSent; private long lastVideoKeyFrameSent; private long lastMetadataSent; private long segmentStartTime; private long segmentDuration; private boolean isRecording; private boolean isPreviewing; // ...其他成员变量和方法... }在这个类中,我们可以处理各种事件,如接收到音频和视频数据、连接断开等。同时,我们还可以根据需要添加其他功能,如录制、预览等。
-
SpringBoot有几种获取Request对象的方法_CodeArts_华为云论坛 (huaweicloud.com)
-
ThreadPoolExcecutor构造方法参数 1.继承关系 Executor ↑ ExecutorService ↑ AbstractExecutorService ↑ ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize,int maxNumPoolSize, long ReepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectExecutionHandler handler){ } corePoolSize:线程池核心线程数 maxNumPoolSize:线程池最大数 ReepAliveTime:空闲线程存活时间 unit:时间单位 workQueue:线程池所使用的缓冲队列 threadFactory:线程池创建使用的工厂 handler:线程池对拒绝任务的处理策略 特性一:当池中正在运行的线程数(包括空闲线程),小于corePoolSize时,从线程池中取线程执行任务。 特性二:当池中正在运行的线程数大于等于corePoolSize时,新插入的任务进入workQueue排队。 特性三:当队列里的任务达到上限,并且池中正在运行的线程数小于maxNumPoolSize,对于新加入的任务,新建线程。 特性四:当队列里的任务数达到上限,并且池中正在运行的线程数等于maxNumPoolSize,对于新加入的任务,执行拒绝策略(默认策略跑出RejectdExcutionException) ———————————————— 版权声明:本文为CSDN博主「wsb8233696」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wsb8233696/article/details/105604858
-
为了减少创建和销毁线程的次数,让每个线程可以多次使用,可根据系统情况调整执行的线程数量,防止消耗过多内存,所以我们可以使用线程池. Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 (1) newCachedThreadPool 创建一个可缓存线程池,如果线线程池大小超过了处理任务所需的线程,那么就会回收部分空闲(一般是60秒无执行)的线程,若无可回收,则新建线程。示例代码如下: Java代码 package test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { public void run() { System.out.println(index); } }); } } } 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。 (2) newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下: Java代码 package test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; fixedThreadPool.execute(new Runnable() { public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } } 因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors() (3) newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下: Java代码 package test; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.schedule(new Runnable() { public void run() { System.out.println("delay 3 seconds"); } }, 3, TimeUnit.SECONDS); } } 表示延迟3秒执行。 定期执行示例代码如下: Java代码 package test; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ThreadPoolExecutorTest { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println("delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS); } } 表示延迟1秒后每3秒执行一次。 (4) newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下: Java代码 package test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { public void run() { try { System.out.println(index); Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } } 结果依次输出,相当于顺序执行各个任务。 ExcutorService中的excutor和submit方法的区别 两者都是将一个线程任务添加到线程池中并执行; 1、excutor没有返回值,submit有返回值,并且返回执行结果Future对象 2、excutor不能提交Callable任务,只能提交Runnable任务,submit两者任务都可以提交 3、在submit中提交Runnable任务,会返回执行结果Future对象,但是Future调用get方法将返回null(Runnable没有返回值) 使用场景: 使用多线程任务校验被保人数据; 1、每个被保人都是一个线程任务, 2、每个线程任务执行完都需要告诉主线程执行成功还是失败 3、这里需要submit提交Callable任务返回Future对象,并通过Future.get方法来获取执行结果 本地代码示例: 1.传统spring项目: 调用接口: public class HmoPushOrderServiceImpl implements HmoPushOrderService { @Override public ResponseDTO<Boolean> pushHmoUserToPingAn() { ResponseDTO<Boolean> res = new ResponseDTO<Boolean>(); ExecutorService threadPool = PingAnUserActivateTaskThreadPool.getInstance().getThreadPool(); threadPool.submit(new PingAnActivateThreadTask()); res.setResult(ResponseCode.SUCCESS, "触发成功", Boolean.TRUE); return res; } 异步线程池创建类: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class PingAnUserActivateTaskThreadPool { // 最大线程数 private static final int MAX_QUEUE_SIZE = 5; private static ExecutorService exc = null; private static volatile PingAnUserActivateTaskThreadPool instance = null; private PingAnUserActivateTaskThreadPool() { exc = Executors.newFixedThreadPool(MAX_QUEUE_SIZE); } /** * * @return */ public static PingAnUserActivateTaskThreadPool getInstance() { if (instance == null) { synchronized (PingAnUserActivateTaskThreadPool.class) { if (instance == null) { instance = new PingAnUserActivateTaskThreadPool(); } } } return instance; } public ExecutorService getThreadPool() { return exc; } } 任务执行类: public class PingAnActivateThreadTask implements Runnable { public PingAnActivateThreadTask() { hmoPushOrderManager = SpringContextUtil.getBean("hmoPushOrderManager"); msgSender = SpringContextUtil.getBean("msgSender"); configUtils = SpringContextUtil.getBean("configUtils"); apiUserBindManager = SpringContextUtil.getBean("apiUserBindManager"); } @Override public void run() { ... } } 2.spring-boot项目: 业务Controller: @RestController @RequestMapping("hfxyk/") public class HfxykDataController { @Resource private ExecutorService taskExecutor; taskExecutor.submit(new Runnable() { @Override public void run() { ... } } } 线程池配置公用类: import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @Configuration public class ThreadPoolConfig { /** * 公共业务线程池 * * @return */ @Bean(name = "taskExecutor") public ExecutorService executorService() { ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("executor-hfxyk-pool-%d").build(); return new ThreadPoolExecutor(2, 8, 1000, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20), namedThreadFactory, new ThreadPoolExecutor.DiscardPolicy()); } } 注意:DiscardPolicy策略:对拒绝任务直接无声抛弃,没有异常信息。 你可以使用JDK自带的监控工具来监控我们创建的线程数量,运行一个不终止的线程,创建指定量的线程,来观察: 工具目录:C:\Program Files\Java\jdk1.6.0_06\bin\jconsole.exe 运行程序做稍微修改: Java代码 package test; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExecutorTest { public static void main(String[] args) { ExecutorService singleThreadExecutor = Executors.newCachedThreadPool(); for (int i = 0; i < 100; i++) { final int index = i; singleThreadExecutor.execute(new Runnable() { public void run() { try { while(true) { System.out.println(index); Thread.sleep(10 * 1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } ———————————————— 版权声明:本文为CSDN博主「wsb8233696」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wsb8233696/article/details/105754061
-
Http目前协议版本是1.1,HTTP是一种无状态的协议,无状态是指Web浏览器与Web服务器之间,不需要建立持久的链接,这意味着当一个客户端向服务器端发出请求,然后Web服务器返回响应(response),链接就被关闭了,在服务器端不保留链接的有关信息。 1.建立TCP链接 在HTTP工作前,首先浏览器与服务器建立链接,该链接是通过TCP完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议方案。一般TCP连接端口号是80。 打开浏览器,地址栏输入blog.csdn.net,开始进行域名解解析: (1).浏览器自身搜dns缓存 (2).搜索操作系统的dns缓存 (3).读取本地host文件 浏览器发起一个dns系统调用,浏览器获得域名对应的ip地址后,发起一个http三次握手 tcp/ip链接建立起来后,服务器端接受到请求,根据路径参数,经过后端的处理后,把处理后的结果返回给浏览器,浏览器拿到html页面代码,解析和渲染页面,里面的js、css图片资源都需要经过上面的步骤。 2.Web浏览器向服务器发送请求命令 例如:GRT/sample/hello.jsp HTTP/1.1 3.Web浏览器发送请求头信息 浏览器发送请求命令后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送一空白行通知服务器,它已经结束了该头信息的发送。 4.Web服务器应答 应答的第一部分是协议的版本号和应答状态码 如:HTTP/1.1 200OK 5.服务器发送应答头信息(关于服务器自己的数据) 6.服务器向浏览器发送数据 服务器发送头信息后,它会发送一个空白行来表示头信息发送到此为止,接着以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。 7.关闭TCP连接 如果浏览器或服务器在其头信息加入了这行代码,Connection:keep-alive,TCP连接在发送后仍然保持打开状态 HTTP请求信息由3部分组成 1.请求方法URL 协议/版本 GET/sample.jsp HTTP/1.1 2.请求头(包含客户端环境、浏览器所用语言、正文长度等) 3.请求正文(包含客户提交的查询字符串信息) userName=qwe&passWord=123 HTTP响应3个部分构成 1.协议状态版本 HTTP/1.1 200OK 2.响应头(服务器类型、日期时间、内容类型、长度等) Server:Apache Tomcat/5.0.12 Content-Type:text/html 3.响应正文 <html> <head> <title>HTTP响应示例</title> </head> </html>
-
哪些协议是无状态协议哪些是有状态的,怎么区别? 举个例子我和朋友出去吃饭 不需要每次报上姓名 联系方式 等 朋友就知道我是谁 这是有状态的 而我去办事大厅 工作人员不会记得我是谁 每次去都要填表 出示身份证 这就是无状态的 无状态协议:在下一次链接不记住这一次链接的信息。 HTTP,UDP都是无状态协议 TCP,FTP是有状态协议 无状态服务器是指一种把每个请求作为与之前任何请求都无关的独立的事务的服务器 <<tcp/ip 协议族>>(第二版)第546页有这样一句话: 虽然HTTP使用TCP的服务,但HTTP本身是无状态协议.客户发送请求报文来初始化这个事务.服务器发送响应来回答. 暗示了TCP协议是一个有状态的协议 http协议与tcp、udp区别 http:是用于www浏览的一个协议。 tcp:是机器之间建立连接用的到的一个协议。 TCP协议与UDP协议是传输层协议。 HTTP协议是应用层协议。 Dubbo支持的协议 在通信过程中,不同的服务等级一般对应着不同的服务质量,那么选择合适的协议便是一件非常重要的事情。你可以根据你应用的创建来选择。例如,使用RMI协议,一般会受到防火墙的限制,所以对于外部与内部进行通信的场景,就不要使用RMI协议,而是基于HTTP协议或者Hessian协议。Dubbo支持8种左右的协议,如下所示: (1) dubbo:// Dubbo协议 (2) rmi:// RMI协议 (3) hessian:// Hessian协议 (4) http:// HTTP协议 (5) webservice:// WebService协议 (6) thrift:// Thrift协议 (7) memcached:// Memcached协议 (8)redis:// Redis协议 在通信过程中,不同的服务等级一般对应着不同的服务质量,那么选择合适的协议便是一件非常重要的事情。你可以根据你应用的创建来选择。 例如,使用RMI协议,一般会受到防火墙的限制,所以对于外部与内部进行通信的场景,就不要使用RMI协议,而是基于HTTP协议或者Hessian协议。 部分协议的特点和使用场景如下: 1、dubbo协议 Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。 缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互。 连接个数:单连接 连接方式:长连接 传输协议:TCP 传输方式:NIO异步传输 序列化:Hessian二进制序列化 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。 适用场景:常规远程服务方法调用 为什么要消费者比提供者个数多: 因dubbo协议采用单一长连接, 假设网络为千兆网卡(1024Mbit=128MByte), 根据测试经验数据每条连接最多只能压满7MByte(不同的环境可能不一样,供参考), 理论上1个服务提供者需要20个服务消费者才能压满网卡。 为什么不能传大包: 因dubbo协议采用单一长连接, 如果每次请求的数据包大小为500KByte,假设网络为千兆网卡(1024Mbit=128MByte),每条连接最大7MByte(不同的环境可能不一样,供参考), 单个服务提供者的TPS(每秒处理事务数)最大为:128MByte / 500KByte = 262。 单个消费者调用单个服务提供者的TPS(每秒处理事务数)最大为:7MByte / 500KByte = 14。 如果能接受,可以考虑使用,否则网络将成为瓶颈。 为什么采用异步单一长连接: 因为服务的现状大都是服务提供者少,通常只有几台机器, 而服务的消费者多,可能整个网站都在访问该服务, 比如Morgan的提供者只有6台提供者,却有上百台消费者,每天有1.5亿次调用, 如果采用常规的hessian服务,服务提供者很容易就被压跨, 通过单一连接,保证单一消费者不会压死提供者, 长连接,减少连接握手验证等, 并使用异步IO,复用线程池,防止C10K问题。 2、RMI RMI协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式 Java标准的远程调用协议。 连接个数:多连接 连接方式:短连接 传输协议:TCP 传输方式:同步传输 序列化:Java标准二进制序列化 适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。 适用场景:常规远程服务方法调用,与原生RMI服务互操作 3、hessian Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现 基于Hessian的远程调用协议。 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:Hessian二进制序列化 适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。 适用场景:页面传输,文件传输,或与原生hessian服务互操作 4、http 采用Spring的HttpInvoker实现 基于http表单的远程调用协议。 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:表单序列化(JSON) 适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。 适用场景:需同时给应用程序和浏览器JS使用的服务。 5、webservice 基于CXF的frontend-simple和transports-http实现 基于WebService的远程调用协议。 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:SOAP文本序列化 适用场景:系统集成,跨语言调用。 6、thrif Thrift是Facebook捐给Apache的一个RPC框架,当前 dubbo 支持的 thrift 协议是对 thrift 原生协议的扩展,在原生协议的基础上添加了一些额外的头信息,比如service name,magic number等。 ———————————————— 版权声明:本文为CSDN博主「wsb8233696」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wsb8233696/article/details/107820609
-
在java里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。 浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。 深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。 方式1:构造函数深拷贝 package com.lyj.demo.pojo.cloneTest; import lombok.Getter; /** * @author 凌兮 * @date 2021/4/15 14:28 * 通过构造器进行深拷贝测试 */ @Getter public class UserConstruct { private String userName; private AddressConstruct address; public UserConstruct() { } public UserConstruct(String userName, AddressConstruct address) { this.userName = userName; this.address = address; } public static void main(String[] args) { AddressConstruct address = new AddressConstruct("小区1", "小区2"); UserConstruct user = new UserConstruct("小李", address); // 调用构造函数进行深拷贝 UserConstruct copyUser = new UserConstruct(user.getUserName(), new AddressConstruct(address.getAddress1(), address.getAddress2())); // 修改源对象的值 user.getAddress().setAddress1("小区3"); // false System.out.println(user == copyUser); // false System.out.println(user.getAddress().getAddress1() == copyUser.getAddress().getAddress1()); // false System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1())); // true System.out.println(user.getAddress().getAddress2().equals(copyUser.getAddress().getAddress2())); } } package com.lyj.demo.pojo.cloneTest; import lombok.Getter; import lombok.Setter; /** * @author 凌兮 * @date 2021/4/15 14:28 */ @Getter @Setter public class AddressConstruct { private String address1; private String address2; public AddressConstruct() { } public AddressConstruct(String address1, String address2) { this.address1 = address1; this.address2 = address2; } } 方式2:重载Clone()方法深拷贝 Object父类有个clone()的拷贝方法,不过它是protected类型的 ,我们需要重写它并修改为public类型,除此之外,子类还需要实现Cloneable接口来告诉JVM这个类上是可以拷贝的。 package com.lyj.demo.pojo.cloneTest; import lombok.Getter; import lombok.Setter; /** * @author 凌兮 * @date 2021/4/15 14:49 * */ @Setter @Getter public class AddressClone implements Cloneable{ private String address1; private String address2; public AddressClone() { } public AddressClone(String address1, String address2) { this.address1 = address1; this.address2 = address2; } @Override protected AddressClone clone() throws CloneNotSupportedException { return (AddressClone) super.clone(); } } package com.lyj.demo.pojo.cloneTest; import lombok.Getter; import lombok.Setter; /** * @author 凌兮 * @date 2021/4/15 14:48 * 通过实现Clone接口实现深拷贝 */ @Setter @Getter public class UserClone implements Cloneable{ private String userName; private AddressClone address; public UserClone() { } public UserClone(String userName, AddressClone address) { this.userName = userName; this.address = address; } /** * Object父类有个clone()的拷贝方法,不过它是protected类型的, * 我们需要重写它并修改为public类型。除此之外, * 子类还需要实现Cloneable接口来告诉JVM这个类是可以拷贝的。 * @return * @throws CloneNotSupportedException */ @Override protected UserClone clone() throws CloneNotSupportedException { // 需要注意的是,super.clone()其实是浅拷贝, // 所以在重写UserClone类的clone()方法时,address对象需要调用address.clone()重新赋值 UserClone userClone = (UserClone) super.clone(); userClone.setAddress(this.address.clone()); return userClone; } public static void main(String[] args) throws CloneNotSupportedException { AddressClone address = new AddressClone("小区1", "小区2"); UserClone user = new UserClone("小李", address); UserClone copyUser = user.clone(); user.getAddress().setAddress1("小区3"); // false System.out.println(user == copyUser); // false System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1())); } } 需要注意的是,super.clone()其实是浅拷贝,所以在重写User类的clone()方法时,address对象需要调用address.clone()重新赋值。 方式3:Apache Commons Lang序列化方式深拷贝 Java提供了序列化的能力,我们可以先将源对象进行序列化,再反序列化生成拷贝对象。但是,使用序列化的前提是拷贝的类(包括其成员变量)需要实现Serializable接口。 Apache Commons Lang包对Java序列化进行了封装,我们可以直接使用它。 package com.lyj.demo.pojo.cloneTest; import lombok.Getter; import lombok.Setter; import java.io.Serializable; /** * @author 凌兮 * @date 2021/4/15 15:11 */ @Getter @Setter public class AddressSerializable implements Serializable { private String address1; private String address2; public AddressSerializable() { } public AddressSerializable(String address1, String address2) { this.address1 = address1; this.address2 = address2; } } package com.lyj.demo.pojo.cloneTest; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.SerializationUtils; import java.io.Serializable; /** * @author 凌兮 * @date 2021/4/15 15:10 * 通过Apache Commons Lang 序列化方式深拷贝 * Java提供了序列化的能力,我们可以先将源对象进行序列化,再反序列化生成拷贝对象。 * 但是,使用序列化的前提是拷贝的类(包括其成员变量)需要实现Serializable接口。 * Apache Commons Lang包对Java序列化进行了封装,我们可以直接使用它。 */ @Getter @Setter public class UserSerializable implements Serializable { private String userName; private AddressSerializable address; public UserSerializable() { } public UserSerializable(String userName, AddressSerializable address) { this.userName = userName; this.address = address; } public static void main(String[] args) { AddressSerializable address = new AddressSerializable("小区1", "小区2"); UserSerializable user = new UserSerializable("小李", address); UserSerializable copyUser = SerializationUtils.clone(user); user.getAddress().setAddress1("小区3"); // false System.out.println(user == copyUser); // false System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1())); } } ———————————————— 版权声明:本文为CSDN博主「wsb8233696」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wsb8233696/article/details/130907780
-
一、定义 双冒号运算操作符是类方法的句柄,lambda表达式的一种简写 表达式: person -> person.getName(); 可以替换成: Person::getName 表达式: () -> new HashMap<>(); 可以替换成: HashMap::new 二、如何理解 双冒号(::)运算符在Java 8中被用作方法引用(method reference),方法引用是与lambda表达式相关的一个重要特性。它提供了一种执行方法的方法,为此,方法引用需要由兼容的函数式接口组成的目标类型上下文。使用lambda表达式会创建匿名函数, 但有时候需要使用一个lambda表达式只调用一个已经存在的方法(不做其它), 所以这才有了方法引用! 其实,JVM 本身并不支持指向方法引用,过去不支持,现在也不支持。Java 8 对方法引用的支持只是编译器层面的支持,虚拟机执行引擎并不了解方法引用。编译器遇到方法引用的时候,会像上面那样自动推断出开发者的意图,将方法引用还原成接口实现对象,或者更形象地说,就是把方法引用设法包装成一个接口实现对象,这样虚拟机就可以无差别地执行字节码文件而不需要管什么是方法引用了。 需要注意的是,方法引用是用来简化接口实现代码的,并且凡是能够用方法引用来简化的接口,都有这样的特征:有且只有一个待实现的方法。这种接口在 Java 中有个专门的名称: 函数式接口。当试图用方法引用替代一个非函数式接口时,会有这样的错误提示: xxx is not a functional interface。 三、使用场景 类型 引用语法 案例 引用静态方法 类名::静态方法名 Integer::parseInt 引用特定对象实例方法 对象::实例方法名 System.out::println 引用特定类型的任意对象的实例方法 特定类型::实例方法名 String::compareToIgnoreCase 引用超类(父类)实例方法 super::方法名 引用类构造方法 类名::new ArrayList::new 引用数组构造方法 数组类型[]::new String[]::new 案例详解: 引用静态方法 import org.junit.Test; import java.util.Arrays; import java.util.List; public class Colon{ @Test public void test(){ List<String> list = Arrays.asList("a", "b","c"); //静态方法引用ClassName::methodName list.forEach(Colon:: print); //上一行等价于 //1ist.forEach((x)->Colon.print(x)); } //静态方法 public static void print(String s){ system.out.println(s); } } 引用特定对象实例方法 import org.junit.Test; import java.util.Arrays; import java.util.List; public class Colon{ @Test public void test(){ List<string> list = Arrays.asList("a", "b","c");//r实例方法引用instanceRef: :methodName list.forEach(new Colon()::print); //上一行等价于 //iist.forEach((x)->new Colon().print(x)); } //实例方法 public void print(String s){ System.out.println(s); } } 引用特定类型的任意对象的实例方法 import org.junit.Test; import java.util.Arrays; public class Colon{ @Test public void test(){ String[] arr = { "Barbara","James","Mary", "John", "Patricia","Robert","Michae1", "Linda”}; //引用String类型的任意对象的compareToIgnoreCase方法实现忽略大小写排序 Arrays.sort(arr, String::compareToIgnoreCase); //上一行等价于 //Arrays.sort(arr, (a,b)->a.compareToIgnoreCase(b)); //输出 for(String s:arr){ System.out.println(s); } } 引用超类(父类)实例方法 import org.junit.Test; import java.util.Arrays; import java.util.List; public class Colon extends BaseColon{ @Test public void test(){ List<string> list = Arrays.asList("a", "b","c"); //实例方法引用instanceRef::methodName list.forEach(super:: print); } } class Basecolon{ //实例方法 public void print(string s){ System.out.println(s); } } 引用类构造方法 一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。 //注意:该类无需实现接口 public class Colon{ private String name; private int age; //无参构造 public Colon(){ } //有参构造 public colon(String name, int age){ this.name = name; this.age = age; } public static void main(String[] args){ //无参构造引用 ColonNoParam cnp = Colon::new; colon c1 = cnp.createColon(); System.out.println(c1); //有参构造引用 ColonlithParam cwp = Colon::new; colon c2 = cwp.createColon("小明",20); System.out.println(c2); } //生成toString方法打印查看 @Override public string toString() { return "Colon{" + "name='"+ name + "\"+ ",age=" + age + '}'; } } interface colonNoParam{ //无参方法提供对象 Colon createColon(); } interface ColonwithParam{ //有参方法提供对象(数据类型要与colon有参构造函数对应) colon createColon(String s,int i); } 引用数组构造方法 我们可以借助jdk自带的java.util.function.Function类实现对数组构造函数的引用。 当然,我们也可以使用@FunctionalInterface自定义函数式接口来实现: public class Colon{ public static void main(string[] args) { MyArrayFunction<Integer,Colon[]> function = Colon[]::new; //调用apply方法创建数组,这里的5是教组的长度 colon[] arr = function.apply(5); //循环输出-初始都为null for(Colon c:arr){ System.out.println(c); } } } //自定义函教式接口 @FunctionalInterface interface MyArrayFunction<A,T>{ T apply(A a); } 参考博客:https://blog.csdn.net/yangzhe19931117/article/details/128246653 ———————————————— 版权声明:本文为CSDN博主「橙橙爱学习」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_52293201/article/details/129433338
-
🍒java中二维数组的定义和赋值 int[][] array = new int[3][]; //java行不能省略,列可以省略 array[0] = new int[]{0, 1, 2};//赋值 array[2] = new int[]{4, 5, 6}; int[][] array1={{1,1},{2,2},{3,3}};//定义并且初始化 🍒二维数组遍历的三种方法 二维数组其实就是特殊的一维数组; 在java中将这句话诠释得淋漓尽致; 🍇第一种:for循环遍历 int[][] array = new int[3][]; //java行不能省略,列可以省略 array[0] = new int[]{0, 1, 2}; array[2] = new int[]{4, 5, 6,7}; for(int i=0;i< array.length;i++){ if(array[i]==null) { System.out.println("null"+" "); continue; }//当二维数组某一行为空时直接跳过循环遍历下一行 for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j]+" "); }//二维数组的每一行元素都相当于一个一维数组, //遍历一维数组,长度就是array[i].length System.out.println(); } 运行截图: 🍇第二种方法:通过Arrays.deepToString()遍历 int[][] array = new int[3][]; //java行不能省略,列可以省略 array[0] = new int[]{0, 1, 2}; array[2] = new int[]{4, 5, 6,7}; System.out.println(Arrays.deepToString(array)); 运行截图: 🍇第三种方法:通过for( : )遍历 int[][] array = new int[3][]; //java行不能省略,列可以省略 array[0] = new int[]{0, 1, 2}; array[2] = new int[]{4, 5, 6,7}; int i=0; for(int[] ret:array){ if(array[i]==null) { System.out.println("null"+" "); i++; continue; } for(int x:ret){ System.out.print(x+" "); } System.out.println(); i++; 注意:冒号左边填写的是数组每个元数的类型,右边填写的是数组名 ———————————————— 版权声明:本文为CSDN博主「熬夜退役选手337」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_61638178/article/details/131697975
-
在 Java 中,类加载的流程有一个专门的机制叫做“类加载机制”。类加载机制是指一个类在 Java 虚拟机(JVM)中的执行流程,它也是 Java 程序能够正常执行的关键所在,那它的具体执行流程是啥?接下来我们一起来看。流程概述在 JVM 中,类加载会经历以下 5 个阶段:加载阶段(Loading)验证阶段(Verification)准备阶段(Preparation)解析阶段(Resolution)初始化阶段(Initialization)其中:验证阶段、准备阶段和解析阶段合起来又称为连接阶段,所以以上 5 个阶段又可以划分为 3 大类:加载阶段(Loading)连接阶段(Linking)验证阶段(Verification)准备阶段(Preparation)解析阶段(Resolution)初始化阶段(Initialization)这 3 大类、5 个流程的具体执行细节是这样的。1.加载阶段简单来说,加载阶段就是将类文件加载到内存中的过程。在加载阶段,JVM 需要完成以下 3 件事:通过一个类的全限定名来获取定义此类的二进制字节流;将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。2.连接阶段连接阶段又分为:验证阶段(Verification)、准备阶段(Preparation)和解析阶段(Resolution),具体执行的细节如下。2.1 验证阶段验证阶段也叫做校验阶段,它主要是用来验证加载到内存中的类是否是安全合规的文件,验证的主要动作大概有以下几个(当然,以下细节如果实在记不住也没关系):文件格式校验包括常量池中的常量类型、Class 文件的各个部分是否被删除或被追加了其他信息等;元数据校验包括父类正确性校验(检查父类是否有被 final 修饰)、抽象类校验等;字节码校验,此步骤最为关键和复杂,主要用于校验程序中的语义是否合法且符合逻辑;符号引用校验,对类自身以外比如常量池中的各种符号引用的信息进行匹配性校验。2.2 准备阶段准备阶段就开始给类中的静态变量设置默认值了,注意这里不是给静态变量设置初始值,而是设置默认值,二者还是有很大区别的。举个例子,比如代码中写的内容是:public static int number = 10;那么此时是给 number 变量设置的 int 值是默认值 0,而非初始值 10。2.3 解析阶段解析阶段就是将常量池中的符号引用更换成直接引用了,所谓的符号引用是指以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可;而直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。符号引用和直接引用有一个重要的区别:使用符号引用时被引用的目标不一定已经加载到内存中;而使用直接引用时,引用的目标必定已经存在虚拟机的内存中了。3.初始化阶段初始化阶段,Java 虚拟机真正开始执行类中编写的 Java 程序代码,将主导权移交给应用程序。到这一步骤之后,类的加载过程就算正式完成了,此时会给静态变量设置初始值,并执行静态代码块的内容。总结类加载流程总共分为 3 大类,5 个主要流程:加载阶段(Loading):将类文件加载到内存。连接阶段(Linking)验证阶段(Verification):类文件安全性效验。准备阶段(Preparation):给静态变量设置默认值。解析阶段(Resolution):将符号引用转换为直接引用。初始化阶段(Initialization):执行静态代码块和给静态变量设置初始值。转载自https://www.cnblogs.com/vipstone/p/17069838.html
-
1.两阶段提交两阶段提交(Two-Phase Commit,简称 2PC)是一种分布式事务协议,确保所有参与者在提交或回滚事务时都处于一致的状态。2PC 协议包含以下两个阶段:准备阶段(prepare phase):在这个阶段,事务协调者(Transaction Coordinator)向所有参与者(Transaction Participant)发出准备请求,询问它们是否准备好提交事务。参与者执行所有必要的操作,并回复协调者是否准备好提交事务。如果所有参与者都回复准备好提交事务,协调者将进入下一个阶段。如果任何参与者不能准备好提交事务,协调者将通知所有参与者回滚事务。提交阶段(commit phase):在这个阶段,如果所有参与者都已准备好提交事务,则协调者向所有参与者发送提交请求。参与者执行所有必要的操作,并将其结果记录在持久性存储中。一旦所有参与者都已提交事务,协调者将向它们发送确认请求。如果任何参与者未能提交事务,则协调者将通知所有参与者回滚事务。2PC 协议可以确保分布式事务的原子性和一致性,但是其效率较低,可能会出现阻塞等问题。因此,在实际应用中,可以使用其他分布式事务协议,如 3PC(Three-Phase Commit)或 Paxos 协议来代替。两阶段提交问题两阶段提交存在以下几个问题:同步阻塞问题:执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。也就是说从投票阶段到提交阶段完成这段时间,资源是被锁住的。单点故障:由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。数据不一致问题:在 2PC 最后提交阶段中,当协调者向参与者发送 commit 请求之后,发生了局部网络异常或者在发送 commit 请求过程中协调者发生了故障,这会导致只有一部分参与者接受到了 commit 请求。而在这部分参与者接到 commit 请求之后就会执行 commit 操作。但是其他部分未接到 commit 请求的机器则无法执行事务提交,于是整个分布式系统便出现了数据不一致性的现象。2.三阶段提交三阶段提交(Three-Phase Commit,简称3PC)是在 2PC 协议的基础上添加了一个额外的阶段来解决 2PC 协议可能出现的阻塞问题。3PC 协议包含三个阶段:CanCommit 阶段(询问阶段):在这个阶段,事务协调者(Transaction Coordinator)向所有参与者(Transaction Participant)发出 CanCommit 请求,询问它们是否准备好提交事务。参与者执行所有必要的操作,并回复协调者它们是否可以提交事务。PreCommit 阶段(准备阶段):如果所有参与者都回复可以提交事务,则协调者将向所有参与者发送PreCommit 请求,通知它们准备提交事务。参与者执行所有必要的操作,并回复协调者它们是否已经准备好提交事务。DoCommit 阶段(提交阶段):如果所有参与者都已经准备好提交事务,则协调者将向所有参与者发送DoCommit 请求,通知它们提交事务。参与者执行所有必要的操作,并将其结果记录在持久性存储中。一旦所有参与者都已提交事务,协调者将向它们发送确认请求。如果任何参与者未能提交事务,则协调者将通知所有参与者回滚事务。与 2PC 协议相比,3PC 协议将 CanCommit 阶段(询问阶段)添加到协议中,使参与者能够在 CanCommit 阶段发现并解决可能导致阻塞的问题。这样,3PC 协议能够更快地执行提交或回滚事务,并减少不必要的等待时间。需要注意的是,与 2PC 协议相比,3PC 协议仍然可能存在阻塞的问题。3.两阶段提交 VS 三阶段提交2PC 和 3PC 是分布式事务中两种常见的协议,3PC 可以看作是 2PC 协议的改进版本,相比于 2PC 它有两点改进:引入了超时机制,同时在协调者和参与者中都引入超时机制(2PC 只有协调者有超时机制);3PC 相比于 2PC 增加了 CanCommit 阶段,可以尽早的发现问题,从而避免了后续的阻塞和无效操作。也就是说,3PC 相比于 2PC,因为引入了超时机制,所以发生阻塞的几率变小了;同时 3PC 把之前 2PC 的准备阶段一分为二,变成了两步,这样就多了一个缓冲阶段,保证了在最后提交阶段之前各参与节点的状态是一致的。4.数据一致性问题和解决方案3PC 虽然可以减少同步阻塞问题和单点故障问题,但依然存在数据一致性问题(概率很小),而解决数据一致性问题的方案有很多,比如 Paxos 算法或柔性事物机制等。4.1 Paxos 算法Paxos 算法是一种基于消息传递的分布式一致性算法,并在 2013 年获得了图灵奖。图灵奖(ACM A.M. Turing Award)是计算机科学领域最高荣誉之一,由美国计算机协会(ACM)于 1966 年设立,每年颁发一次,表彰对计算机科学领域做出杰出贡献的人士或团体。简单来说,Paxos 算法是一种分布式共识算法,用于在分布式系统中实现数据的一致性和共识,保证分布式系统中不同节点之间的数据同步和一致性。Paxos 算法由三个角色组成:提议者、接受者和学习者。当一个节点需要发起一个提议时,它会向其他节点发送一个提议,接受者会接收到这个提议,并对其进行处理,可能会拒绝提议,也可能会接受提议。如果有足够多的节点接受了该提议,那么提议就会被确定下来,并且通知给所有学习者,最终所有节点都会达成共识。Paxos 算法看起来很简单,但它实际上是非常的复杂。Paxos 算法应用的产品也很多,比如以下几个:Redis:Redis 是一个内存数据库,使用 Paxos 算法实现了分布式锁服务和主从复制等功能。MySQL:MySQL 5.7 推出的用来取代传统的主从复制的 MySQL Group Replication 等。ZooKeeper:ZooKeeper 是一个分布式协调服务,使用 Paxos 算法实现了分布式锁服务和数据一致性等功能。Apache Cassandra:Cassandra 是一个分布式数据库系统,使用 Paxos 算法实现了数据的一致性和复制等功能。Google Chubby:Chubby 是 Google 内部使用的分布式锁服务,使用 Paxos 算法实现了分布式锁服务和命名服务等功能。4.2 柔性事务柔性事务机制:允许一定时间内不同节点的数据不一致,但要求最终一致的机制。柔性事物有 TCC 补偿事物、可靠消息事物(MQ 事物)等。小结在分布式事务中,通常使用两阶段或三阶段提交协议来保障分布式事务的正常执行。两阶段协议包含准备阶段和提交阶段,然而它存在同步阻塞问题、单点故障和数据一致性问题。而三阶段协议可以看作是两阶段协议的改进版,它将两阶段的准备阶段一分为二,多了一个询问阶段,保证了提交阶段之前各参与节点的状态是一致的,同时引入了超时机制,减少了同步阻塞问题发生的几率。但 2PC 和 3PC 都存在数据一致性问题,此时可以采用 Paxos 算法或柔性事务机制等方案来解决事务一致性问题。转载自https://www.cnblogs.com/vipstone/p/17584074.html
-
常见负载均衡策略但无论是服务器端负载均衡和客户端负载均衡,它们的负载均衡策略都是相同的,因为负载均衡策略本质上是一种思想。常见的负载均衡策略有以下几个:轮询(Round Robin):轮询策略按照顺序将每个新的请求分发给后端服务器,依次循环。这是一种最简单的负载均衡策略,适用于后端服务器的性能相近,且每个请求的处理时间大致相同的情况。随机选择(Random):随机选择策略随机选择一个后端服务器来处理每个新的请求。这种策略适用于后端服务器性能相似,且每个请求的处理时间相近的情况,但不保证请求的分发是均匀的。最少连接(Least Connections):最少连接策略将请求分发给当前连接数最少的后端服务器。这可以确保负载均衡在后端服务器的连接负载上均衡,但需要维护连接计数。IP 哈希(IP Hash):IP 哈希策略使用客户端的 IP 地址来计算哈希值,然后将请求发送到与哈希值对应的后端服务器。这种策略可用于确保来自同一客户端的请求都被发送到同一台后端服务器,适用于需要会话保持的情况。加权轮询(Weighted Round Robin):加权轮询策略给每个后端服务器分配一个权重值,然后按照权重值比例来分发请求。这可以用来处理后端服务器性能不均衡的情况,将更多的请求分发给性能更高的服务器。加权随机选择(Weighted Random):加权随机选择策略与加权轮询类似,但是按照权重值来随机选择后端服务器。这也可以用来处理后端服务器性能不均衡的情况,但是分发更随机。最短响应时间(Least Response Time):最短响应时间策略会测量每个后端服务器的响应时间,并将请求发送到响应时间最短的服务器。这种策略可以确保客户端获得最快的响应,适用于要求低延迟的应用。小结负载均衡分为服务器端负载均衡和客户端负载均衡,但无了是那种负载均衡器,它的常用策略都是一样的,有轮询、随机选择、最少连接 IP 哈希、加权轮询、加权随机和最短响应时间。
上滑加载中
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签