`

Apache Thrift - 可伸缩的跨语言服务开发框架深入解析

 
阅读更多

转:

  • 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等。其中所用到的数据传输方式包括 XML,JSON 等,然而 XML 相对体积太大,传输效率低,JSON 体积较小,新颖,但还不够完善。Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。本文将介绍由 Facebook 开发的远程服务调用框架 Apache Thrift,它采用接口描述语言定义并创建服务,支持可扩展的跨语言服务开发,所包含的代码生成引擎可以在多种语言中,如 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk 等创建高效的、无缝的服务,其传输数据采用二进制格式,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。本文将详细介绍 Thrift 的使用,并且提供丰富的实例代码加以解释说明,帮助使用者快速构建服务。

    一个简单的 Thrift 实例
    本文首先介绍一个简单的 Thrift 实现实例,使读者能够快速直观地了解什么是 Thrift 以及如何使用 Thrift 构建服务。
    创建一个简单的服务 Hello。首先根据 Thrift 的语法规范编写脚本文件 Hello.thrift,代码如下:

    清单 1. Hello.thrift

     

    				 
     namespace java service.demo 
     service Hello{ 
      string helloString(1:string para) 
      i32 helloInt(1:i32 para) 
      bool helloBoolean(1:bool para) 
      void helloVoid() 
      string helloNull() 
     } 
    



    其中定义了服务 Hello 的五个方法,每个方法包含一个方法名,参数列表和返回类型。每个参数包括参数序号,参数类型以及参数名。 Thrift 是对 IDL(Interface Definition Language) 描述性语言的一种具体实现。因此,以上的服务描述文件使用 IDL 语法编写。使用 Thrift 工具编译 Hello.thrift,就会生成相应的 Hello.java 文件。该文件包含了在 Hello.thrift 文件中描述的服务 Hello 的接口定义,即 Hello.Iface 接口,以及服务调用的底层通信细节,包括客户端的调用逻辑 Hello.Client 以及服务器端的处理逻辑 Hello.Processor,用于构建客户端和服务器端的功能。


    创建 HelloServiceImpl.java 文件并实现 Hello.java 文件中的 Hello.Iface 接口,代码如下:

    清单 2. HelloServiceImpl.java
         

    package service.demo; 
     import org.apache.thrift.TException; 
     public class HelloServiceImpl implements Hello.Iface { 
        @Override 
        public boolean helloBoolean(boolean para) throws TException { 
            return para; 
        } 
        @Override 
        public int helloInt(int para) throws TException { 
            try { 
                Thread.sleep(20000); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            return para; 
        } 
        @Override 
        public String helloNull() throws TException { 
            return null; 
        } 
        @Override 
        public String helloString(String para) throws TException { 
            return para; 
        } 
        @Override 
        public void helloVoid() throws TException { 
            System.out.println("Hello World"); 
        } 
     } 

    创建服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给 Thrift 服务器,代码如下:

    清单 3. HelloServiceServer.java 

    				 
     package service.server; 
     import org.apache.thrift.TProcessor; 
     import org.apache.thrift.protocol.TBinaryProtocol; 
     import org.apache.thrift.protocol.TBinaryProtocol.Factory; 
     import org.apache.thrift.server.TServer; 
     import org.apache.thrift.server.TThreadPoolServer; 
     import org.apache.thrift.transport.TServerSocket; 
     import org.apache.thrift.transport.TTransportException; 
     import service.demo.Hello; 
     import service.demo.HelloServiceImpl; 
    
     public class HelloServiceServer { 
        /** 
         * 启动 Thrift 服务器
         * @param args 
         */ 
        public static void main(String[] args) { 
            try { 
                // 设置服务端口为 7911 
                TServerSocket serverTransport = new TServerSocket(7911); 
                // 设置协议工厂为 TBinaryProtocol.Factory 
                Factory proFactory = new TBinaryProtocol.Factory(); 
                // 关联处理器与 Hello 服务的实现
                TProcessor processor = new Hello.Processor(new HelloServiceImpl()); 
                TServer server = new TThreadPoolServer(processor, serverTransport, 
                        proFactory); 
                System.out.println("Start server on port 7911..."); 
                server.serve(); 
            } catch (TTransportException e) { 
                e.printStackTrace(); 
            } 
        } 
     } 

    创建客户端实现代码,调用 Hello.client 访问服务端的逻辑实现,代码如下:

    清单 4. HelloServiceClient.java

    package service.client; 
     import org.apache.thrift.TException; 
     import org.apache.thrift.protocol.TBinaryProtocol; 
     import org.apache.thrift.protocol.TProtocol; 
     import org.apache.thrift.transport.TSocket; 
     import org.apache.thrift.transport.TTransport; 
     import org.apache.thrift.transport.TTransportException; 
     import service.demo.Hello; 
    
     public class HelloServiceClient { 
     /** 
         * 调用 Hello 服务
         * @param args 
         */ 
        public static void main(String[] args) { 
            try { 
                // 设置调用的服务地址为本地,端口为 7911 
                TTransport transport = new TSocket("localhost", 7911); 
                transport.open(); 
                // 设置传输协议为 TBinaryProtocol 
                TProtocol protocol = new TBinaryProtocol(transport); 
                Hello.Client client = new Hello.Client(protocol); 
                // 调用服务的 helloVoid 方法
                client.helloVoid(); 
                transport.close(); 
            } catch (TTransportException e) { 
                e.printStackTrace(); 
            } catch (TException e) { 
                e.printStackTrace(); 
            } 
        } 
     } 

    代码编写完后运行服务器,再启动客户端调用服务 Hello 的方法 helloVoid,在服务器端的控制台窗口输出“Hello World”(helloVoid 方法实现在控制台打印字符串,没有返回值,所以客户端调用方法后没有返回值输出,读者可以自己尝试其他有返回值方法的调用,其结果可以打印在客户端的控制台窗口 )。

    Thrift 架构
    Thrift 包含一个完整的堆栈结构用于构建客户端和服务器端。下图描绘了 Thrift 的整体架构。

    图 1. 架构图
     
    如图所示,图中黄色部分是用户实现的业务逻辑,褐色部分是根据 Thrift 定义的服务接口描述文件生成的客户端和服务器端代码框架,红色部分是根据 Thrift 文件生成代码实现数据的读写操作。红色部分以下是 Thrift 的传输体系、协议以及底层 I/O 通信,使用 Thrift 可以很方便的定义一个服务并且选择不同的传输协议和传输层而不用重新生成代码。


    Thrift 服务器包含用于绑定协议和传输层的基础架构,它提供阻塞、非阻塞、单线程和多线程的模式运行在服务器上,可以配合服务器 / 容器一起运行,可以和现有的 J2EE 服务器 /Web 容器无缝的结合。
    服务端和客户端具体的调用流程如下:

    图 2. Server 端启动、服务时序图(查看大图)
     
    该图所示是 HelloServiceServer 启动的过程以及服务被客户端调用时,服务器的响应过程。从图中我们可以看到,程序调用了 TThreadPoolServer 的 serve 方法后,server 进入阻塞监听状态,其阻塞在 TServerSocket 的 accept 方法上。当接收到来自客户端的消息后,服务器发起一个新线程处理这个消息请求,原线程再次进入阻塞状态。在新线程中,服务器通过 TBinaryProtocol 协议读取消息内容,调用 HelloServiceImpl 的 helloVoid 方法,并将结果写入 helloVoid_result 中传回客户端。

    图 3. Client 端调用服务时序图(查看大图)
     
    该图所示是 HelloServiceClient 调用服务的过程以及接收到服务器端的返回值后处理结果的过程。从图中我们可以看到,程序调用了 Hello.Client 的 helloVoid 方法,在 helloVoid 方法中,通过 send_helloVoid 方法发送对服务的调用请求,通过 recv_helloVoid 方法接收服务处理请求后返回的结果。

    数据类型
    Thrift 脚本可定义的数据类型包括以下几种类型:
    基本类型:
    bool:布尔值,true 或 false,对应 Java 的 boolean
    byte:8 位有符号整数,对应 Java 的 byte
    i16:16 位有符号整数,对应 Java 的 short
    i32:32 位有符号整数,对应 Java 的 int
    i64:64 位有符号整数,对应 Java 的 long
    double:64 位浮点数,对应 Java 的 double
    string:未知编码文本或二进制字符串,对应 Java 的 String
    结构体类型:
    struct:定义公共的对象,类似于 C 语言中的结构体定义,在 Java 中是一个 JavaBean
    容器类型:
    list:对应 Java 的 ArrayList
    set:对应 Java 的 HashSet
    map:对应 Java 的 HashMap
    异常类型:
    exception:对应 Java 的 Exception
    服务类型:
    service:对应服务的类

    协议
    Thrift 可以让用户选择客户端与服务端之间传输通信协议的类别,在传输协议上总体划分为文本 (text) 和二进制 (binary) 传输协议,为节约带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数,有时还会使用基于文本类型的协议,这需要根据项目 / 产品中的实际需求。常用协议有以下几种:
    TBinaryProtocol —— 二进制编码格式进行数据传输
    使用方法如清单 3 和清单 4 所示。
    TCompactProtocol —— 高效率的、密集的二进制编码格式进行数据传输
    构建 TCompactProtocol 协议的服务器和客户端只需替换清单 3 和清单 4 中 TBinaryProtocol 协议部分即可,替换成如下代码:


    清单 5. 使用 TCompactProtocol 协议构建的 HelloServiceServer.java
         
     TCompactProtocol.Factory proFactory = new TCompactProtocol.Factory();

    清单 6. 使用 TCompactProtocol 协议的 HelloServiceClient.java
         
     TCompactProtocol protocol = new TCompactProtocol(transport);

    TJSONProtocol —— 使用 JSON 的数据编码协议进行数据传输
    构建 TJSONProtocol 协议的服务器和客户端只需替换清单 3 和清单 4 中 TBinaryProtocol 协议部分即可,替换成如下代码:


    清单 7. 使用 TJSONProtocol 协议构建的 HelloServiceServer.java
         
     TJSONProtocol.Factory proFactory = new TJSONProtocol.Factory();

    清单 8. 使用 TJSONProtocol 协议的 HelloServiceClient.java
         
     TJSONProtocol protocol = new TJSONProtocol(transport);

    TSimpleJSONProtocol —— 只提供 JSON 只写的协议,适用于通过脚本语言解析

    传输层
    常用的传输层有以下几种:
    TSocket —— 使用阻塞式 I/O 进行传输,是最常见的模式
    使用方法如清单 4 所示。
    TFramedTransport —— 使用非阻塞方式,按块的大小进行传输,类似于 Java 中的 NIO
    若使用 TFramedTransport 传输层,其服务器必须修改为非阻塞的服务类型,客户端只需替换清单 4 中 TTransport 部分,代码如下,清单 9 中 TNonblockingServerTransport 类是构建非阻塞 socket 的抽象类,TNonblockingServerSocket 类继承 TNonblockingServerTransport


    清单 9. 使用 TFramedTransport 传输层构建的 HelloServiceServer.java
         

    TNonblockingServerTransport serverTransport; 
     serverTransport = new TNonblockingServerSocket(10005); 
     Hello.Processor processor = new Hello.Processor(new HelloServiceImpl()); 
     TServer server = new TNonblockingServer(processor, serverTransport); 
     System.out.println("Start server on port 10005 ..."); 
     server.serve(); 

    清单 10. 使用 TFramedTransport 传输层的 HelloServiceClient.java
         
     TTransport transport = new TFramedTransport(new TSocket("localhost", 10005));

    TNonblockingTransport —— 使用非阻塞方式,用于构建异步客户端
    使用方法请参考 Thrift 异步客户端构建

    服务端类型
    常见的服务端类型有以下几种:
    TSimpleServer —— 单线程服务器端使用标准的阻塞式 I/O
    代码如下:


    清单 11. 使用 TSimpleServer 服务端构建的 HelloServiceServer.java
        

     TServerSocket serverTransport = new TServerSocket(7911); 
     TProcessor processor = new Hello.Processor(new HelloServiceImpl()); 
     TServer server = new TSimpleServer(processor, serverTransport); 
     System.out.println("Start server on port 7911..."); 
     server.serve(); 

    客户端的构建方式可参考清单 4。
    TThreadPoolServer —— 多线程服务器端使用标准的阻塞式 I/O
    使用方法如清单 3 所示。
    TNonblockingServer —— 多线程服务器端使用非阻塞式 I/O
    使用方法请参考 Thrift 异步客户端构建

    Thrift 异步客户端构建
    Thrift 提供非阻塞的调用方式,可构建异步客户端。在这种方式中,Thrift 提供了新的类 TAsyncClientManager 用于管理客户端的请求,在一个线程上追踪请求和响应,同时通过接口 AsyncClient 传递标准的参数和 callback 对象,服务调用完成后,callback 提供了处理调用结果和异常的方法。
    首先我们看 callback 的实现:

    清单 12.CallBack 的实现:MethodCallback.java
         
     

    package service.callback; 
     import org.apache.thrift.async.AsyncMethodCallback; 
    
     public class MethodCallback implements AsyncMethodCallback { 
        Object response = null; 
    
        public Object getResult() { 
            // 返回结果值
            return this.response; 
        } 
    
        // 处理服务返回的结果值
        @Override 
        public void onComplete(Object response) { 
            this.response = response; 
        } 
        // 处理调用服务过程中出现的异常
        @Override 
        public void onError(Throwable throwable) { 
    
        } 
     } 

    如代码所示,onComplete 方法接收服务处理后的结果,此处我们将结果 response 直接赋值给 callback 的私有属性 response。onError 方法接收服务处理过程中抛出的异常,此处未对异常进行处理。
    创建非阻塞服务器端实现代码,将 HelloServiceImpl 作为具体的处理器传递给异步 Thrift 服务器,代码如下:

    清单 13.HelloServiceAsyncServer.java
         
     

    package service.server; 
     import org.apache.thrift.server.TNonblockingServer; 
     import org.apache.thrift.server.TServer; 
     import org.apache.thrift.transport.TNonblockingServerSocket; 
     import org.apache.thrift.transport.TNonblockingServerTransport; 
     import org.apache.thrift.transport.TTransportException; 
     import service.demo.Hello; 
     import service.demo.HelloServiceImpl; 
    
     public class HelloServiceAsyncServer { 
        /** 
         * 启动 Thrift 异步服务器
         * @param args 
         */ 
        public static void main(String[] args) { 
            TNonblockingServerTransport serverTransport; 
            try { 
                serverTransport = new TNonblockingServerSocket(10005); 
                Hello.Processor processor = new Hello.Processor( 
                        new HelloServiceImpl()); 
                TServer server = new TNonblockingServer(processor, serverTransport); 
                System.out.println("Start server on port 10005 ..."); 
                server.serve(); 
            } catch (TTransportException e) { 
                e.printStackTrace(); 
            } 
        } 
     } 

    HelloServiceAsyncServer 通过 java.nio.channels.ServerSocketChannel 创建非阻塞的服务器端等待客户端的连接。
    创建异步客户端实现代码,调用 Hello.AsyncClient 访问服务端的逻辑实现,将 MethodCallback 对象作为参数传入调用方法中,代码如下:

    清单 14.HelloServiceAsyncClient.java
         

    package service.client; 
     import java.io.IOException; 
     import org.apache.thrift.async.AsyncMethodCallback; 
     import org.apache.thrift.async.TAsyncClientManager; 
     import org.apache.thrift.protocol.TBinaryProtocol; 
     import org.apache.thrift.protocol.TProtocolFactory; 
     import org.apache.thrift.transport.TNonblockingSocket; 
     import org.apache.thrift.transport.TNonblockingTransport; 
     import service.callback.MethodCallback; 
     import service.demo.Hello; 
    
     public class HelloServiceAsyncClient { 
        /** 
         * 调用 Hello 服务
         * @param args 
         */ 
        public static void main(String[] args) throws Exception { 
            try { 
                TAsyncClientManager clientManager = new TAsyncClientManager(); 
                TNonblockingTransport transport = new TNonblockingSocket( 
                        "localhost", 10005); 
                TProtocolFactory protocol = new TBinaryProtocol.Factory(); 
                Hello.AsyncClient asyncClient = new Hello.AsyncClient(protocol, 
                        clientManager, transport); 
                System.out.println("Client calls ....."); 
                MethodCallback callBack = new MethodCallback(); 
                asyncClient.helloString("Hello World", callBack); 
                Object res = callBack.getResult(); 
                while (res == null) { 
                    res = callBack.getResult(); 
                } 
                System.out.println(((Hello.AsyncClient.helloString_call) res) 
                        .getResult()); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
      } 
     } 

    HelloServiceAsyncClient 通过 java.nio.channels.Socketchannel 创建异步客户端与服务器建立连接。在本文中异步客户端通过以下的循环代码实现了同步效果,读者可去除这部分代码后再运行对比。

    清单 15. 异步客户端实现同步效果代码段
    Object res = callBack.getResult();
    // 等待服务调用后的返回结果
    while (res == null) {
       res = callBack.getResult();
    }

    通过与清单 9 和清单 10 的代码比较,我们可以构建一个 TNonblockingServer 服务类型的服务端,在客户端构建一个 TFramedTransport 传输层的同步客户端和一个 TNonblockingTransport 传输层的异步客户端,那么一个服务就可以通过一个 socket 端口提供两种不同的调用方式。有兴趣的读者可以尝试一下。

    常见问题
    NULL 问题
    我们在对服务的某个方法调用时,有时会出现该方法返回 null 值的情况,在 Thrift 中,直接调用一个返回 null 值的方法会抛出 TApplicationException 异常。在清单 2 中,HelloServiceImpl 里实现了 helloNull 方法,返回 null 值,我们在 HelloServiceClient.java 中加入调用该方法的代码,出现如下图所示的异常:

    图 4. TApplicationException 异常
     
    为了处理返回 null 值情况,我们要捕获该异常,并进行相应的处理,具体客户端代码实现如下:

    清单 16. 处理服务返回值为 null 的代码
         

    package service.client; 
     import org.apache.thrift.TApplicationException; 
     import org.apache.thrift.TException; 
     import org.apache.thrift.protocol.TBinaryProtocol; 
     import org.apache.thrift.protocol.TProtocol; 
     import org.apache.thrift.transport.TSocket; 
     import org.apache.thrift.transport.TTransport; 
     import org.apache.thrift.transport.TTransportException; 
     import service.demo.Hello; 
    
     public class HelloServiceClient { 
        /** 
         * 调用 Hello 服务,并处理 null 值问题
         * @param args 
         */ 
        public static void main(String[] args) { 
            try { 
                TTransport transport = new TSocket("localhost", 7911); 
                transport.open(); 
                TProtocol protocol = new TBinaryProtocol(transport); 
                Hello.Client client = new Hello.Client(protocol); 
                System.out.println(client.helloNull()); 
                transport.close(); 
            } catch (TTransportException e) { 
                e.printStackTrace(); 
            } catch (TException e) { 
                if (e instanceof TApplicationException 
                        && ((TApplicationException) e).getType() ==   
                                     TApplicationException.MISSING_RESULT) { 
                    System.out.println("The result of helloNull function is NULL"); 
                } 
            } 
        } 
     } 

    调用 helloNull 方法后,会抛出 TApplicationException 异常,并且异常种类为 MISSING_RESULT,本段代码显示,捕获该异常后,直接在控制台打印“The result of helloNull function is NULL”信息。

    安装部署
    Apache Thrift 的官方网站为:http://thrift.apache.org/tutorial/,具体安装步骤如下:
    1.下载 thrift 源文件(http://svn.apache.org/repos/asf/thrift/tags/thrift-0.6.1/
    2.将 thrift 源文件导入 eclipse,进入 /lib/java 目录,使用 ant 编译 build.xml 获得 libthrift-0.6.1-snapshot.jar
    3.将 libthrift-0.6.1-snapshot.jar、slf4j-api-1.5.8.jar、slf4j-log4j12-1.5.8.jar 和 log4j-1.2.14.jar 导入 eclipse 开发环境
    4.下载 thrift 编译工具,该工具可将 thrift 脚本文件编译成 java 文件,下载地址:http://apache.etoak.com//thrift/0.6.0/thrift-0.6.1.exe
    5.创建 Hello.thrift 脚本文件,具体代码如上一章节所述,进入 thrift-0.6.1.exe 所在目录,执行命令"thrift-0.6.1.exe -gen java x:\Hello.thrift",在当前运行盘符下,可看见 gen-java 目录,进入目录可看到生成的 Java 代码。更多 thrift 的命令内容,请参考 thrift 自带的 help 命令
    6编写服务端和客户端代码,完成 thrift 的安装和部署
    基于 Apache Thrift 框架生成的服务包括客户端和服务器端,具体的部署模式如下所示:

    图 5. 部署图
     
    从图中我们可以看到,客户端和服务器端部署时,需要用到公共的 jar 包和 java 文件,如图“Common file”区域,其中 Hello.java 由 Hello.thrift 编译而来。在服务器端,服务必须实现 Hello.Iface 接口,同时要包括服务器的启动代码 HelloServiceServer.java。在客户端,包括客户端调用服务的代码 HelloServiceClient.java。客户端和服务器通过 Hello.java 提供的 API 实现远程服务调用。

    总结
    本文介绍了 Apache Thrift 的安装部署和架构,并通过大量实例介绍了在不同情况下如何使用 Apache Thrift 来构建服务,同时着重介绍了 Thrift 异步客户端的构建,希望能给读者带来一些帮助。

分享到:
评论

相关推荐

    thrift 一个有意思的特性:Class名称无关性

    Thrift 是一款由 Apache 开发的跨语言服务开发框架,它允许开发者轻松地构建可伸缩的跨平台服务。Thrift 提供了一种高效的数据序列化机制以及一系列的服务端与客户端库支持,使得开发者能够使用不同的编程语言来构建...

    分布式JAVA应用 基础与实践

    Java中的RPC框架如Hadoop的HDFS、Apache Thrift、Google的gRPC以及阿里巴巴的Dubbo等,都是分布式系统中不可或缺的组件。理解RPC的工作原理、服务发现机制、序列化和反序列化过程对于实现高效的跨网络调用至关重要。...

    hbase权威指南 源代码 英文

    Thrift和RESTful则提供了跨语言的交互能力,方便Web应用程序和非Java环境的开发。 书中可能会涵盖以下主题: 1. HBase安装和配置:包括集群部署、单机模式以及与其他Hadoop组件的集成。 2. 表设计:如何有效地设计...

    基于Simulink的风火水储联合调频系统中储能SOC对ACE影响的技术分析

    内容概要:本文详细探讨了在Simulink环境中构建的风火水储联合调频系统中,储能系统的荷电状态(SOC)对区域控制偏差(ACE)的影响。文中通过具体案例和MATLAB代码展示了储能系统在不同SOC水平下的表现及其对系统稳定性的作用。同时,文章比较了储能单独调频与风火水储联合调频的效果,强调了储能系统在应对风电波动性和提高系统响应速度方面的重要作用。此外,作者提出了针对SOC变化率的参数整定方法以及多电源协同工作的优化策略,旨在减少ACE波动并确保系统稳定运行。 适合人群:从事电力系统调频研究的专业人士,尤其是熟悉Simulink仿真工具的研究人员和技术人员。 使用场景及目标:适用于希望深入了解储能系统在电力系统调频中作用的研究者和技术人员,目标是通过合理的SOC管理和多电源协同工作,优化调频效果,提高系统稳定性。 其他说明:文章提供了详细的MATLAB代码片段,帮助读者更好地理解和应用所讨论的概念。同时,文中提到的实际案例和仿真结果为理论分析提供了有力支持。

    欧姆龙PLC NJ中大型程序案例:结构化与面向对象编程的深度融合及应用

    内容概要:本文深入探讨了欧姆龙PLC NJ系列中大型程序中结构化编程与面向对象编程的结合及其应用。首先介绍了结构化编程作为程序框架的基础,通过功能块(FB)实现清晰的程序结构和流程控制。接着阐述了面向对象编程的理念,将现实世界的对象映射到程序中,利用类的概念实现模块化和可扩展性。两者结合提高了程序的容错率,增强了程序的稳定性和可维护性。文中通过多个实际案例展示了如何在工业自动化领域中应用这两种编程方法,如电机控制、设备类的创建、异常处理机制、接口实现多态性、配方管理和报警处理等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些希望提升PLC编程技能的人群。 使用场景及目标:适用于需要优化PLC程序结构、提高程序可靠性和可维护性的场合。目标是帮助工程师掌握结构化编程和面向对象编程的技巧,从而写出更加高效、稳定的PLC程序。 其他说明:文章强调了在实际项目中灵活运用两种编程方法的重要性,并提醒读者注意实时性要求高的动作控制应采用结构化编程,而工艺逻辑和HMI交互则更适合面向对象编程。

    matlab与聚类分析

    matlab与聚类分析。根据我国历年职工人数(单位:万人),使用有序样品的fisher法聚类。

    卡尔曼滤波生成航迹测量程序

    卡尔曼滤波生成航迹测量程序

    基于格子玻尔兹曼方法(LBM)的多孔电极浸润特性研究及其Python实现

    内容概要:本文详细介绍了利用格子玻尔兹曼方法(LBM)对多孔电极浸润特性的模拟研究。首先阐述了LBM的基本原理,包括碰撞和迁移两个关键步骤,并提供了相应的Python伪代码。接着讨论了如何处理多孔介质中的固体边界,特别是通过随机算法生成孔隙结构以及结合CT扫描数据进行三维重构的方法。文中还探讨了表面张力、接触角等因素对浸润过程的影响,并给出了具体的数学表达式。此外,文章提到了并行计算的应用,如使用CUDA加速大规模网格计算,以提高模拟效率。最后,作者分享了一些实用技巧,如通过调整松弛时间和润湿性参数来优化模拟效果,并强调了LBM在处理复杂几何结构方面的优势。 适合人群:从事电池研发、材料科学领域的研究人员和技术人员,尤其是关注多孔电极浸润性和电解液扩散机制的人群。 使用场景及目标:适用于希望深入了解多孔电极内部流体动力学行为的研究者,旨在帮助他们更好地理解和预测电极材料的浸润特性,从而改进电池设计和性能。 其他说明:尽管LBM在处理多孔介质方面表现出色,但在某些极端条件下仍需引入额外的修正项。同时,参数的选择和边界条件的设定对最终结果有着重要影响,因此需要谨慎对待。

    基于FPGA和W5500的TCP网络通信:Zynq扩展口开发测试平台(使用Vivado 2019.2纯Verilog实现)

    内容概要:本文详细介绍了在Zynq扩展口上使用FPGA和W5500实现TCP网络通信的过程。作者通过一系列实验和技术手段,解决了多个实际问题,最终实现了稳定的数据传输。主要内容包括:硬件搭建(SPI接口配置)、数据回环处理、压力测试及优化、多路复用扩展以及上位机测试脚本的编写。文中提供了大量Verilog代码片段,展示了如何通过状态机控制SPI通信、优化数据缓存管理、处理中断等问题。 适合人群:对FPGA开发和网络通信感兴趣的工程师,尤其是有一定Verilog编程基础的研发人员。 使用场景及目标:适用于需要在嵌入式系统中实现高效、稳定的TCP通信的应用场景。目标是帮助读者掌握FPGA与W5500结合进行网络通信的具体实现方法和技术细节。 其他说明:文章不仅提供了详细的代码实现,还分享了许多实践经验,如硬件连接注意事项、信号完整性问题的解决方案等。此外,作者还提到了未来的工作方向,如UDP组播和QoS优先级控制的实现。

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤

    基于FDTD仿真的可调谐石墨烯超材料吸收体设计与实现

    内容概要:本文详细介绍了利用有限差分时域法(FDTD)进行可调谐石墨烯超材料吸收体的设计与仿真。文中解释了石墨烯超材料的基本结构(三层“三明治”结构)、关键参数(如化学势、周期、厚度等)及其对吸收性能的影响。同时展示了如何通过调整石墨烯的化学势来实现吸收峰的位置和强度的变化,以及如何优化结构参数以获得最佳的吸收效果。此外,还提供了具体的代码示例,帮助读者理解和重现相关实验结果。 适合人群:从事纳米光子学、超材料研究的专业人士,尤其是对石墨烯基超材料感兴趣的科研工作者和技术开发者。 使用场景及目标:适用于希望深入了解石墨烯超材料的工作原理及其潜在应用场景的研究人员;旨在探索新型可调谐光学器件的设计思路和发展方向。 其他说明:文中不仅分享了理论知识,还包括了许多实践经验,如避免常见错误、提高仿真相关效率的小技巧等。对于想要将研究成果应用于实际产品的团队来说,这些细节非常有价值。

    随机生成2字到10字的中文词组

    随机生成2字,3字,4字,5字,6字,7字,8字,9字,10字的中文词组20个

    【汽车电子电气架构】智能座舱域控平台设计:基于双片龍鷹一号SoC芯片的高性能硬件架构与多模态交互系统构建

    内容概要:本文详细探讨了智能座舱域控设计的发展历程和技术趋势。首先介绍了智能座舱从被动式交互到主动式交互的技术演变,包括硬件和交互方式的进步。随后,文章重点讨论了智能座舱功能发展趋势,涵盖车载显示技术的多屏化、大屏化和高端化,以及SoC芯片的多核异构架构和算力融合,强调了其在智能座舱中的核心作用。此外,还阐述了电子电气架构从分布式向集成化的转型,分析了其面临的挑战和未来趋势。最后,基于当前智能座舱的发展需求,提出了一种基于双片龍鷹一号芯片的新域控平台设计方案,详细描述了其硬件设计实现方案,旨在提供高性能、高可靠性的智能座舱解决方案。 适合人群:汽车电子工程师、智能座舱研发人员及相关领域的技术人员。 使用场景及目标:①帮助读者理解智能座舱的技术发展历程及其未来发展方向;②为智能座舱域控平台的设计和开发提供参考和技术支持;③探讨电子电气架构的转型对汽车行业的影响及应对策略。 其他说明:文章结合实际案例和技术数据,深入浅出地解释了智能座舱的各项技术细节,不仅提供了理论指导,还具有较强的实践意义。通过对智能座舱域控平台的全面剖析,有助于推动智能座舱技术的创新发展,提升用户体验。

    多智能体协同编队控制:无人机编队背后的Python实现与关键技术解析

    内容概要:本文详细介绍了多智能体协同编队控制的技术原理及其应用实例。首先通过生动形象的例子解释了编队控制的核心概念,如一致性算法、虚拟结构法和Leader-Follower模式。接着深入探讨了如何用Python实现基础的一致性控制,以及如何通过调整参数(如Kp、Ka)来优化编队效果。文中还讨论了实际工程中常见的问题,如通信延迟、避障策略和动态拓扑变化,并给出了相应的解决方案。最后,强调了参数调试的重要性,并分享了一些实用技巧,如预测补偿、力场融合算法和分布式控制策略。 适合人群:对多智能体系统、无人机编队控制感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于希望深入了解多智能体协同编队控制理论并能够将其应用于实际项目的研究人员和开发者。目标是帮助读者掌握编队控制的关键技术和实现方法,提高系统的稳定性和可靠性。 其他说明:文章不仅提供了详细的理论讲解,还附有具体的代码示例,便于读者理解和实践。同时,作者结合自身经验分享了许多宝贵的调试技巧和注意事项,有助于读者在实际应用中少走弯路。

    评估管线钢环焊缝质量及其对氢脆的敏感性.pptx

    评估管线钢环焊缝质量及其对氢脆的敏感性.pptx

    C盘清理bat脚本自动清理C盘垃圾文件

    C盘清理bat脚本自动清理C盘垃圾文件

    GBT21266-2007 辣椒及辣椒制品中辣椒素类物质测定及辣度表示方法

    GBT21266-2007 辣椒及辣椒制品中辣椒素类物质测定及辣度表示方法

    弹跳球 XNA 游戏项目 演示如何使用 C# 在 Visual Studio XNA 中构建类似 arkanoiddx-ball 的游戏

    弹跳球 XNA 游戏项目。演示如何使用 C# 在 Visual Studio XNA 中构建类似 arkanoiddx-ball 的游戏。

    【人形机器人领域】宇树科技人形机器人:技术实力、市场炒作与应用前景分析

    内容概要:文章全面解析了宇树科技人形机器人的发展现状、技术实力、市场炒作现象及其应用前景和面临的挑战。宇树科技成立于2016年,凭借春晚舞台的惊艳亮相和社交媒体的热议迅速走红,其人形机器人具备先进的运动控制算法、传感器技术和仿生结构设计。然而,市场炒作现象如高价租赁、二手市场炒作和虚假宣传等影响了市场秩序。尽管存在炒作,人形机器人在工业、服务和家庭领域仍具广阔前景,但也面临技术升级、成本控制、安全性和政策监管等挑战。 适合人群:对机器人技术、人工智能以及科技发展趋势感兴趣的读者,包括科技爱好者、投资者和相关行业的从业者。 使用场景及目标:①帮助读者了解宇树科技人形机器人的技术特点和发展历程;②揭示市场炒作现象及其影响;③探讨人形机器人的应用前景和面临的挑战。 其他说明:文章强调了宇树科技人形机器人在技术上的突破和市场上的表现,同时也提醒读者关注市场炒作现象带来的风险,呼吁各方共同努力推动人形机器人产业健康发展。

    msvcp140.dll

    msvcp140.dll丢失怎样修复

Global site tag (gtag.js) - Google Analytics