SOFARPC(笔记)

news2024/11/13 10:10:37

文章目录

  • 一、快速开始
    • 1.1 SOFARPC
    • 1.2 基于SOFABoot
  • 二、注册中心
  • 三、通讯协议
    • 2.1 Bolt
      • 基本发布
      • 调用方式
      • 超时控制
      • 协议泛化调用
      • 序列化协议
      • 自定义线程池
    • 2.2 RESTful
      • 基本使用
    • 2.3 其他协议
    • 四、架构
  • 附录

官方样例下载地址-sofa-boot-guides

可查看 SOFARPC 方式快速入门

一、快速开始

1.1 SOFARPC

导入如下依赖

<dependency>
    <groupId>com.alipay.sofa</groupId>
    <artifactId>sofa-rpc-all</artifactId>
    <version>最新版本</version>
</dependency>

版本查看

创建一个接口

public interface HelloService {
    String sayHello(String string);
}

实现它

public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String string) {
        System.out.println("Server receive: " + string);
        return "hello " + string + " !";
    }
}

服务器代码

import com.alipay.sofa.rpc.config.ProviderConfig;
import com.alipay.sofa.rpc.config.ServerConfig;

public class QuickStartServer {
    public static void main(String[] args) {
        ServerConfig serverConfig = new ServerConfig()
                .setProtocol("bolt") // 设置一个协议,默认bolt
                .setPort(12200) // 设置一个端口,默认12200
                .setDaemon(false); // 非守护线程

        ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>()
                .setInterfaceId(HelloService.class.getName()) // 指定接口
                .setRef(new HelloServiceImpl()) // 指定实现
                .setServer(serverConfig); // 指定服务端

        providerConfig.export(); // 发布服务
    }
}

客户端代码

import com.alipay.sofa.rpc.config.ConsumerConfig;

public class QuickStartClient {
    public static void main(String[] args) {
        ConsumerConfig<HelloService> consumerConfig = new ConsumerConfig<HelloService>()
            .setInterfaceId(HelloService.class.getName()) // 指定接口
            .setProtocol("bolt") // 指定协议
            .setDirectUrl("bolt://127.0.0.1:12200"); // 指定直连地址
        // 生成代理类
        HelloService helloService = consumerConfig.refer();
        while (true) {
            System.out.println(helloService.sayHello("world"));
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
            }
        }
    }
}

在这里插入图片描述

1.2 基于SOFABoot

引入如下依赖

	<parent>
        <groupId>com.alipay.sofa</groupId>
        <artifactId>sofaboot-dependencies</artifactId>
        <version>3.2.0</version>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alipay.sofa</groupId>
            <artifactId>rpc-sofa-boot-starter</artifactId>
        </dependency>
    </dependencies>

以及基本的SpringBoot配置

spring.application.name=rpcApp
logging.path=./logs
server.port=8080

服务接口

package com.SOFABootRPCTest.service;

public interface AnnotationService {
    String sayAnnotation(String string);
}

服务实现接口

在前文中,我们用@Configuration、@Bean+@SofaService来完成的发布与引用,我们这里就直接用@Service+@SofaService的方式完成

package com.SOFABootRPCTest.serviceImpl;

import com.SOFABootRPCTest.service.AnnotationService;
import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
import org.springframework.stereotype.Service;

@SofaService(interfaceType = AnnotationService.class, uniqueId = "annotationServiceImpl", bindings = { @SofaServiceBinding(bindingType = "bolt")})
@Service
public class AnnotationServiceImpl implements AnnotationService {
    @Override
    public String sayAnnotation(String string) {
        return string;
    }
}

bolt这里是协议,我们在前文中这个地方是jvm。不同协议用法不同。可以看到,默认是jvm协议。
在这里插入图片描述

上面代表我们的接口就正式发布了。可以通过互联网进行访问。


我们现在要调用我们发布的接口,基本和jvm一样。jvmFirst默认为True,也就是优先使用jvm协议。

package com.client;

import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding;
import com.service.AnnotationService;
import org.springframework.stereotype.Component;

@Component
public class AnnotationClientImpl {

    @SofaReference(interfaceType = AnnotationService.class, jvmFirst = false,uniqueId = "annotationServiceImpl",
            binding = @SofaReferenceBinding(bindingType = "bolt")
    )
    private AnnotationService annotationService;

    public String sayClientAnnotation(String str) {
        return annotationService.sayAnnotation(str);
    }
}

使用起来很像Fegin直接调用方法即可。

文档给的代码如下。也可以用 阿里官方给的 SOFARPC快速入门里面的代码。

将下列main中代码放入当前MainApplication中,即可。

package com.SOFABootRPCTest.client;

import com.SOFABootRPCTest.Contoller.AnnotationClientImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;

public class AnotationClientApplication {

    public static void main(String[] args) {
    	// 临时切换地址,避免端口重复
        System.setProperty("server.port", "8081");
        SpringApplication springApplication = new SpringApplication(
            AnotationClientApplication.class);
        ApplicationContext applicationContext = springApplication.run(args);

        AnnotationClientImpl annotationService = applicationContext
            .getBean(AnnotationClientImpl.class);
        String result = annotationService.sayClientAnnotation("annotation");
        System.out.println("invoke result:" + result);
    }
}

在这里插入图片描述

二、注册中心

笔者使用Nacos作为注册中心,其他注册中心可参考注册中心

使用时注意版本要求

图方便可以用本地文件作为注册中心

三、通讯协议

我们此处仅尝试注解方式的发布引用。

可以自行参考协议基本使用

可以创建如下结构项目
在这里插入图片描述

2.1 Bolt

基本发布

api中创建

package com.serviceApi;

public interface SampleService {
    String HelloWorld();
}

producer中创建

package com.producer.serviceImpl;


import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
import com.serviceApi.SampleService;
import org.springframework.stereotype.Service;

@Service
@SofaService(uniqueId = "sampleService",bindings = {@SofaServiceBinding(bindingType = "bolt")})
public class SampleServiceImpl implements SampleService {
    @Override
    public String HelloWorld() {
        System.out.println("==========================\nhello world!\n==========================\n");
        return "hello world";
    }
}

consumer中使用

package com.consumer;


import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding;
import com.serviceApi.SampleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class test {

    @SofaReference(uniqueId = "sampleService",binding = @SofaReferenceBinding(bindingType = "bolt"))
    private SampleService sampleService;
    @Test
    public void testRPC(){
        sampleService.HelloWorld();
    }
}


我们启动服务producer服务,然后consumer使用Test(上述代码)

在这里插入图片描述
可以看到成功调用

使用端口可通过如下配置进行修改

com.alipay.sofa.rpc.bolt.port=端口号

调用方式

  • 同步

见前文

  • 异步

异步调用的方式下,客户端发起调用后不会等到服务端的结果,继续执行后面的业务逻辑。服务端返回的结果会被 SOFARPC 缓存,当客户端需要结果的时候,再主动调用 API 获取。

异步方式如下:

	package com.consumer;


import com.alipay.sofa.rpc.api.future.SofaResponseFuture;
import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding;
import com.serviceApi.SampleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class test {

    @SofaReference(uniqueId = "sampleService",binding = @SofaReferenceBinding(bindingType = "bolt",invokeType = "future"))
    private SampleService sampleService;
    @Test
    public void testRPC(){
        try {
            sampleService.HelloWorld();
             // true表示清除
            String result = (String) SofaResponseFuture.getResponse(10000, true);
            System.out.println(result);
        }catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

注意,观察源码会发现内部是用ThreadLocalMap,如果一个线程发布了两个异步请求,但其间没有获取结果,其结果后到的一项会覆盖前一项。

我们进行如下测试。

为SampleService再添一个实例

package com.producer.serviceImpl;

import com.alipay.sofa.runtime.api.annotation.SofaService;
import com.alipay.sofa.runtime.api.annotation.SofaServiceBinding;
import com.serviceApi.SampleService;
import org.springframework.stereotype.Service;

@Service
@SofaService(uniqueId = "sampleService2",bindings = @SofaServiceBinding(bindingType = "bolt"))
public class SampleServiceImpl2 implements SampleService {
    @Override
    public String HelloWorld() {
        System.out.println("==========================\nhello Java!\n==========================\n");
        return "hello Java!";
    }
}

我们将测试部分改成这样的代码(睡眠了一秒为了保证前一项执行完毕)

package com.consumer;


import com.alipay.sofa.rpc.api.future.SofaResponseFuture;
import com.alipay.sofa.runtime.api.annotation.SofaReference;
import com.alipay.sofa.runtime.api.annotation.SofaReferenceBinding;
import com.serviceApi.SampleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class test {

    @SofaReference(uniqueId = "sampleService",binding = @SofaReferenceBinding(bindingType = "bolt",invokeType = "future"))
    private SampleService sampleService;

    @SofaReference(uniqueId = "sampleService2",binding = @SofaReferenceBinding(bindingType = "bolt",invokeType = "future"))
    private SampleService sampleService2;
    @Test
    public void testRPC(){
        try {
            sampleService.HelloWorld();
            Thread.sleep(1000);
            sampleService2.HelloWorld();
            String result = (String) SofaResponseFuture.getResponse(10000, true);
            System.out.println(result);
        }catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}


服务器端没有问题
在这里插入图片描述
结果却输出了hello Java
在这里插入图片描述

如果我们去两次会报错,说明确实覆盖了。(当然如果是false就不会被清除)

 public void testRPC(){
        try {
            sampleService.HelloWorld();
            Thread.sleep(1000);
            sampleService2.HelloWorld();
            String result = (String) SofaResponseFuture.getResponse(10000, true);

            String result2 = (String) SofaResponseFuture.getResponse(10000, true);
            System.out.println(result);
            System.out.println(result2);
        }catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

在这里插入图片描述

我们可以发布后交给Java原来的异步调用来管理。

			 Future future = SofaResponseFuture.getFuture(true);
             future.get(10000, TimeUnit.MILLISECONDS);
  • 回调

需要实现SofaResponseCallback类

package com.consumer.callback;

import com.alipay.sofa.rpc.core.exception.SofaRpcException;
import com.alipay.sofa.rpc.core.invoke.SofaResponseCallback;
import com.alipay.sofa.rpc.core.request.RequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;;


@Configuration
public class CallbackConfiguration  {

    Logger log = LoggerFactory.getLogger(CallbackConfiguration.class);

    @Bean("sampleCallback")
    public  SofaResponseCallback getSampleCallback(){
        return new SofaResponseCallback() {
            @Override
            public void onAppResponse(Object o, String s, RequestBase requestBase) {
                log.info("调用回调");
                log.info("{}",o.toString());
            }

            @Override
            public void onAppException(Throwable throwable, String s, RequestBase requestBase) {
                System.out.println("APP错误");
            }

            @Override
            public void onSofaException(SofaRpcException e, String s, RequestBase requestBase) {
                System.out.println("SOFA错误");
            }
        };
    }
}

SOFARPC 为设置回调接口提供了两种方式,

  • Callback Class:Callback Class 的方式直接设置回调的类名,SOFARPC 会通过调用回调类的默认构造函数的方式生成回调类的实例。
  • Callback Ref:Callback Ref 的方式则为用户直接提供回调类的实例。callbackRef 属性的值需要是回调类的 Bean 名称。

  • 单向

当客户端发送请求后不关心服务端返回的结果时,可以使用单向的调用方式,这种方式会在发起调用后立即返回 null,并且忽略服务端的返回结果。

使用单向的方式只需要将调用方式设置为 oneway 即可,设置方式和将调用方式设置为 future 或者 callback 一样,这里不再重复讲述,可以参考上面的文档中提供的设置方式。

需要特别注意的是,由于单向的调用方式会立即返回,所以所有的超时设置在单向的情况下都是无效的。

超时控制

使用 Bolt 协议进行通信的时候,SOFARPC 的超时时间默认为 3 秒,用户可以在引用服务的时候去设置超时时间,又分别可以在服务以及方法的维度设置超时时间,SOFARPC 的超时时间的设置的单位都为毫秒。

可自行查看-Bolt 协议超时控制

  • 服务维度

如果需要在发布服务的时候在服务维度设置超时时间,设置对应的 timeout 参数到对应的值即可。

@SofaReference(binding = @SofaReferenceBinding(bindingType = "bolt", timeout = 2000))
private SampleService sampleService;
  • 方法维度

注解模式暂无

协议泛化调用

发布可以不变

xml无法读入时,可以尝试如下方式(*代表查找所有,无*代表使用找到的第一个)

@ImportResource({ "classpath*:rpc-starter-example.xml" })

在引用时需要配置XML


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sofa="http://sofastack.io/schema/sofaboot"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://sofastack.io/schema/sofaboot http://sofastack.io/schema/sofaboot.xsd"
       default-autowire="byName">

<sofa:reference jvm-first="false" id="sampleGenericServiceReference" interface="com.serviceApi.SampleService">
    <sofa:binding.bolt>
        <sofa:global-attrs generic-interface="com.serviceApi.SampleService"/>
    </sofa:binding.bolt>
</sofa:reference>

</beans>
	@Test
    public void testRPC() {
        GenericService sampleGenericServiceReference = (GenericService) SpringUtil.getBean("sampleGenericServiceReference");
        // 需要传入方法名,方法类型,方法参数
        String result = sampleGenericServiceReference.$genericInvoke("HelloWorld",new String[]{},new Object[]{},String.class);
        System.out.println(result);
    }

其他规则可参考官方给出的例子

/**
* Java Bean
*/
public class People {
    private String name;
    private int    age;

    // getters and setters
}


/**
 * 服务方提供的接口
 */
interface SampleService {
   String hello(String arg);
   People hello(People people);
   String[] hello(String[] args);
}

/**
 * 客户端
 */
public class ConsumerClass {
   GenericService genericService;

   public void do() {
      // 1. $invoke仅支持方法参数类型在当前应用的 ClassLoader 中存在的情况

      genericService.$invoke("hello", new String[]{ String.class.getName() }, new Object[]{"I'm an arg"});


      // 2. $genericInvoke支持方法参数类型在当前应用的 ClassLoader 中不存在的情况。
      // 2.1 构造参数
      GenericObject genericObject = new GenericObject("com.alipay.sofa.rpc.test.generic.bean.People"); // 构造函数中指定全路径类名
      genericObject.putField("name", "Lilei"); // 调用putField,指定field值
      genericObject.putField("age", 15);

      // 2.2 进行调用,不指定返回类型,返回结果类型为GenericObject
      Object obj = genericService.$genericInvoke("hello", new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"}, new Object[] { genericObject });
      Assert.assertTrue(obj.getClass == GenericObject.class);
	
				  // 如果返回的是泛化的自定义对象,可以如下方式取出。
				  String name = result.getField("name");

      // 2.3 进行调用,指定返回类型
      People people = genericService.$genericInvoke("hello", new String[]{"com.alipay.sofa.rpc.test.generic.bean.People"}, new Object[] { genericObject }, People.class);

      // 2.4 进行调用,参数类型是数组类型
      String[] result = (String[]) proxy.$genericInvoke("hello", new String[]{new String[0].getClass().getName()}, new Object[]{ new String[]{"args"} });
   }
}

序列化协议

SOFARPC 可以在使用 Bolt 通信协议的情况下,可以选择不同的序列化协议,

  • hessian2
  • protobuf

默认的情况下,SOFARPC 使用 hessian2 作为序列化协议

配置

@SofaService(bindings = @SofaServiceBinding(bindingType = "bolt",serializeType = "protobuf"))
public class SampleServiceImpl implements SampleService {
}


@SofaReference(binding = @SofaReferenceBinding(bindingType = "bolt", serializeType = "protobuf"))
private SampleService sampleService;

自定义线程池

SOFARPC 支持自定义业务线程池。可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的。多个服务可以共用一个独立的线程池。

SOFARPC 要求自定义线程池的类型必须是 com.alipay.sofa.rpc.server.UserThreadPool。

配置

@SofaService(bindings = {@SofaServiceBinding(bindingType = "bolt", userThreadPool = "customThreadPool")})
public class SampleServiceImpl implements SampleService {
}

2.2 RESTful

基本使用

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/sample")
public interface SampleService {
    @GET
    @Path("/hello")
    String HelloWorld();
}

@Service
@SofaService(uniqueId = "sampleService",bindings = @SofaServiceBinding(bindingType = "rest"))
public class SampleServiceImpl implements SampleService {
    @Override
    public String HelloWorld() {
        System.out.println("==========================\nhello world!\n==========================\n");
        return "hello world";
    }
}

上述代码需放在同一项目中。

可以使用浏览器访问

http://localhost:8341/sample/hello

SOFARPC 的 RESTful 服务的默认端口为 8341。

可配置进行修改

com.alipay.sofa.rpc.rest.port=端口号

也可以用如下方式调用

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class test {

    @SofaReference(uniqueId = "sampleService",binding = @SofaReferenceBinding(bindingType = "rest"))
    private SampleService sampleService;

    @Test
    public void testRPC(){
        System.out.println(sampleService.HelloWorld());
    }

}

2.3 其他协议

除Http外,用法与Bolt类似。可参看协议基本使用

四、架构

在这里插入图片描述

附录

SOFARPC 方式快速入门
阿里云官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/909806.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch(十二)搜索---搜索匹配功能③--布尔查询及filter查询原理

一、前言 本节主要学习ES匹配查询中的布尔查询以及布尔查询中比较特殊的filter查询及其原理。 复合搜索&#xff0c;顾名思义是一种在一个搜索语句中包含一种或多种搜索子句的搜索。 布尔查询是常用的复合查询&#xff0c;它把多个子查询组合成一个布尔表达式&#xff0c;这些…

docker安装clickhouse

安装 docker安装 创建clickhouse目录 mkdir -P /data/clickhouse/datamkdir -P /data/clickhouse/confmkdir -P /data/clickhouse/log 拉取镜像 这里直接拉取最新镜像, 如果需要某个特定版本, 则再拉取的时候指定版本号即可. docker pull clickhouse/clickhouse-server 启动临…

最新AI系统ChatGPT网站程序源码/搭建教程/支持GPT4.0/Dall-E2绘画/支持MJ以图生图/H5端/自定义训练知识库

一、正文 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01…

Redis系列(四):哨兵机制详解

首发博客地址 https://blog.zysicyj.top/ 前面我们说过&#xff0c;redis采用了读写分离的方式实现高可靠。后面我们说了&#xff0c;为了防止主节点压力过大&#xff0c;优化成了主-从-从模式 思考一个问题&#xff0c;主节点此时挂了怎么办 这里主从模式下涉及到的几个问题&a…

华为OD-整数对最小和

题目描述 给定两个整数数组array1、array2&#xff0c;数组元素按升序排列。假设从array1、array2中分别取出一个元素可构成一对元素&#xff0c;现在需要取出k对元素&#xff0c;并对取出的所有元素求和&#xff0c;计算和的最小值 代码实现 # coding:utf-8 class Solution:…

ISVE2023展商 | 皮克智能:零售及互联网领域数字化变革开拓者

ISVE2023展商 | 皮克智能&#xff1a;零售及互联网领域数字化变革开拓者 01 公司介绍 Exhibitor Profile 皮克智能是优质的智能硬件产品及系统解决方案提供商&#xff0c;具备自主研发创新、软硬件方案集成及全产业链资源整合的能力。 公司总部位于中国深圳&#xff0c;主要服…

小程序中通过canvas生成并保存图片

1. html <canvas class"canvas" id"photo" type"2d" style"width:200px;height: 300px;"></canvas> <button bindtap"saveImage">保存</button> <!-- 用来展示生成的那张图片 --> <image…

构建 NodeJS 影院预订微服务并使用 docker 部署(03/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 你好社区&#xff0c;这是&#x1f3f0;“构建 NodeJS 影院微服务”系列的第三篇文章。本系列文章演示了…

Ae 效果:CC Line Sweep

过渡/CC Line Sweep Transition/CC Line Sweep CC Line Sweep&#xff08;CC 线条扫描&#xff09;通过线条的扫描动作来制作一个过渡效果&#xff0c;线条可以根据设定的方向、厚度、倾斜度和方向翻转来扫过画面&#xff0c;从而将一个场景过渡到另一个。 ◆ ◆ ◆ 效果属性…

数据治理核心知识点总结-1

管理数据的人员必须由业务人员和信息技术人员两类角色共同承担&#xff1b; 数据管理的12个原则&#xff0c;这12个原则分为数据管理原则、数据价值、数据管理需求是业务的需求、数据管理依赖于不同的技能&#xff0c;数据管理是生命周期管理5个方面&#xff1b;这5个方面中&am…

6-3 使用函数输出水仙花数

分数 20 全屏浏览题目 切换布局 作者 张高燕 单位 浙大城市学院 水仙花数是指一个N位正整数&#xff08;N≥3&#xff09;&#xff0c;它的每个位上的数字的N次幂之和等于它本身。例如&#xff1a;153135333。 本题要求编写两个函数&#xff0c;一个判断给定整数是否水仙花数…

深度学习-实验1

一、Pytorch基本操作考察&#xff08;平台课专业课&#xff09; 使用&#x1d413;&#x1d41e;&#x1d427;&#x1d42c;&#x1d428;&#x1d42b;初始化一个 &#x1d7cf;&#x1d7d1;的矩阵 &#x1d474;和一个 &#x1d7d0;&#x1d7cf;的矩阵 &#x1d475;&am…

node配合charles写文件并下载

利用charles的Copy URL 和Copy cURL Request 进行抓取喜马拉雅的m4a文件 将抓取的下载链接粘贴进txt,利用如下代码去重,并生成新的sh文件,执行sh文件即可下载 const fs require("fs");//need config const inputFile "input.txt"; const outputFile &q…

JCTools Mpsc源码详解(一)

Jctools介绍--jctools是一个Java开源并发非阻塞数据结构实现,其中主要实现了非阻塞Map和非阻塞queue,旨在为Java提供高性能并发数据结构实现; jctool的特点--为什么性能高: lazyset--putOrderedObject,使用loadload内存屏障,写不会立即可见大量的位运算伪共享-通过pad类实现内…

嵌入式系统中常见内存的划分方法

看到有小伙伴在讨论关于单片机内存的话题&#xff0c;今天就结合STM32给大家描述一下常见的划分区域。 在一个STM32程序代码中&#xff0c;从内存高地址到内存低地址&#xff0c;依次分布着栈区、堆区、全局区&#xff08;静态区&#xff09;、常量区、代码区&#xff0c;其中全…

npm install 安装依赖,报错 Host key verification failed

设置 git 的身份和邮箱 git config --global user.name "你的名字" > 用户名 git config --global user.email “你的邮箱" > 邮箱进入 > 用户 > [你的用户名] > .ssh文件夹下,删除 known_hosts 文件即可 进入之后有可能会看到 known_hosts…

亿赛通电子文档安全管理系统 RCE漏洞

亿赛通电子文档安全管理系统 RCE漏洞 一、 产品简介二、 漏洞概述三、 复现环境四、 漏洞复现小龙POC检测: 五、 修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失…

【学会动态规划】 最长递增子序列(26)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…

【Django】 Task5 DefaultRouter路由组件和自定义函数

文章目录 【Django】 Task5 DefaultRouter路由组件和自定义函数1.路由组件1.1路由组件介绍1.2SimpleRouter1.3DefaultRouter1.4DefaultRouter示例1.5查看访问服务接口url 2.自定义函数 【Django】 Task5 DefaultRouter路由组件和自定义函数 Task5 主要了解了DefaultRouter路由…

如何使用LLM实现文本自动生成视频

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 介绍 基于扩散的图像生成模型代表了计算机视觉领域的革命性突破。这些进步由Imagen&#xff0c;DallE和MidJourney等模型开创&#xff0c;展示了文本条件图像生成的卓越功能。有关这些模型内部工作的…