Thrift服務(三):使用實戰

實戰環境

  • win10
  • IDEA 2018.1.6
  • JDK 1.8
  • thrift 0.11.0
  • spring-boot 2.2.1

創建Thrift項目

  • 創建Thrift項目
  • 編譯thrift文件,導出成java文件,並將編譯導出的java文件打成jar包,作爲Thrift API

創建Thrift項目

新建一個maven項目,在src/main包下創建thrift文件夾和java文件夾,在thrift文件夾下編寫RPCDateService.thrift文件。我們可以編寫如下接口:

namespace java com.wl.thrift.api
service RPCDateService{
    string getDate(1:string userName)
}

pom文件需要添加以下依賴和插件

<dependencies>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.11.0</version>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.thrift.tools</groupId>
                <artifactId>maven-thrift-plugin</artifactId>
                <version>0.1.11</version>
                <configuration>
                    <!--<thriftExecutable>/usr/local/bin/thrift</thriftExecutable>-->
                    <!--<thriftSourceRoot>src/main/thrift</thriftSourceRoot>-->
                    <outputDirectory>src/main/java</outputDirectory>
                    <generator>java</generator>
                </configuration>
                <executions>
                    <execution>
                        <id>thrift-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>                    
                </executions>
            </plugin>
        </plugins>
    </build>

ps:

  • thrift文件需要編譯,採用的是maven-thrift-plugin插件
  • libthrift依賴的版本需要和本地安裝的Thrift服務版本相同,否則編譯報錯。安裝見上一篇文章
  • maven-thrift-plugin插件的執行compile階段綁定generate-sources階段。

爲什麼要綁定在這個階段?而不是compile階段呢?因爲我們thrift插件的作用是生成java文件,而在maven執行compile階段時,java文件必鬚生成完畢才能進行編譯,因此,該插件的執行必須在compile之前,所以放在generate-sources階段比較合適。

thriftExecutable:指的是thrift編譯器的位置,如果我們配置了環境變量,可以不指定。驗證環境變量可以使用thrift --version命令。
thriftSourceRoot:thrift源文件的目錄,默認會從src/main/thrift下讀取。
outputDirectory:生成java文件的目錄。其實這個一般不需要配置,因爲java文件的包名是在.thrift文件以namespace的形式定義的。

編譯thrift文件,導出成java文件,並打成jar包

在IDEA底部的Terminal工具中輸入mvn clean install命令進行打成jar包。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WdfmwNav-1574604513328)(/image/ThriftAPI.png)]

開發Thrift服務端

採用sprint-Boot編寫服務端

創建spring-boot項目

pom文件中導入依賴

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.wl</groupId>
            <artifactId>ThriftAPI</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.11.0</version>
        </dependency>

    </dependencies>

創建controller實現Thrift API接口

創建controller文件夾,創建RPCDateServiceIml.java文件,內容如下:

package com.wl.controller;

import com.wl.thrift.api.RPCDateService;
import org.apache.thrift.TException;
import org.springframework.stereotype.Controller;

import java.text.SimpleDateFormat;
import java.util.Date;

@Controller
public class RPCDateServiceIml implements RPCDateService.Iface {
    @Override
    public String getDate(String userName) throws TException {

        Date now = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("今天是"+"yyyy年MM月dd日 E kk點mm分");
        String nowTime = simpleDateFormat.format(now);
        return "Hello" + userName + "\n" + nowTime;
    }
}

編寫Thrift Server端代碼,啓動Thrift Server

創建server文件夾,創建RPCThriftServer.java文件,內容如下:

package com.wl.server;

import com.wl.controller.RPCDateServiceIml;
import com.wl.thrift.api.RPCDateService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class RPCThriftServer {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${thrift.port}")
    private int port;
    @Value("${thrift.minWorkerThreads}")
    private int minThreads;
    @Value("${thrift.maxWorkerThreads}")
    private int maxThreads;

    private TBinaryProtocol.Factory protocolFactory;
    private TTransportFactory transportFactory;

    @Autowired
    private RPCDateServiceIml rpcDateService;

    public void init(){
        protocolFactory = new TBinaryProtocol.Factory();
        transportFactory = new TTransportFactory();
    }

    public void start(){
        RPCDateService.Processor processor = new RPCDateService.Processor<RPCDateService.Iface>(rpcDateService);
        init();
        try {
            TServerTransport transport = new TServerSocket(port);
            TThreadPoolServer.Args tArgs = new TThreadPoolServer.Args(transport);
            tArgs.processor(processor);
            tArgs.protocolFactory(protocolFactory);
            tArgs.transportFactory(transportFactory);
            tArgs.minWorkerThreads(minThreads);
            tArgs.maxWorkerThreads(maxThreads);
            TServer server = new TThreadPoolServer(tArgs);
            logger.info("thrift服務啓動成功,端口={}",port);
            server.serve();
        }catch (Exception e){
            logger.error("thrift服務啓動失敗");
        }
    }
}

修改SpringApplication啓動類

內容如下:

package com.wl;

import com.wl.server.RPCThriftServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class ThriftDemoApplication {

    private static RPCThriftServer rpcThriftServer;

    public static void main(String[] args) {

        ApplicationContext context = SpringApplication.run(ThriftDemoApplication.class, args);
        try {
            rpcThriftServer = context.getBean(RPCThriftServer.class);
            rpcThriftServer.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

在application.properties中添加配置

thrift.port=6666
thrift.minWorkerThreads=10
thrift.maxWorkerThreads=100

啓動Thrift服務端

結果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

2019-11-21 21:21:41.304  INFO 56960 --- [           main] com.wl.ThriftDemoApplication             : Starting ThriftDemoApplication on D-NJ0202188 with PID 56960 (C:\Users\lei.wang\IdeaProjects\thrift_demo\target\classes started by lei.wang in C:\Users\lei.wang\IdeaProjects\thrift_demo)
2019-11-21 21:21:41.307  INFO 56960 --- [           main] com.wl.ThriftDemoApplication             : No active profile set, falling back to default profiles: default
2019-11-21 21:21:41.752  INFO 56960 --- [           main] com.wl.ThriftDemoApplication             : Started ThriftDemoApplication in 0.899 seconds (JVM running for 2.119)
2019-11-21 21:21:41.757  INFO 56960 --- [           main] com.wl.server.RPCThriftServer            : thrift服務啓動成功,端口=6666

創建Thrift客戶端

採用sprint-Boot編寫服務端

創建spring-boot項目

pom文件中導入依賴

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.wl</groupId>
            <artifactId>ThriftAPI</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.11.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

編寫RPCThriftClient:用於發出RPC調用

創建client文件夾,編寫RPCThriftClient.java類和RPCThriftClientConfig.java類。

RPCThriftClient.java類內容如下:

package com.wl.thrift_client_demo.client;

import com.wl.thrift.api.RPCDateService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;

public class RPCThriftClient {
    private RPCDateService.Client client;
    private TBinaryProtocol protocol;
    private TSocket transport;
    private String host;
    private int port;

    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }

    public void init() {
        transport = new TSocket(host, port);
        protocol = new TBinaryProtocol(transport);
        client = new RPCDateService.Client(protocol);
    }

    public RPCDateService.Client getRPCThriftService() {
        return client;
    }

    public void open() throws TTransportException {
        transport.open();
    }

    public void close() {
        transport.close();
    }
}

RPCThriftClientConfig.java類,內容如下:

package com.wl.thrift_client_demo.client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RPCThriftClientConfig {
    @Value("${thrift.host}")
    private String host;
    @Value("${thrift.port}")
    private int port;

    @Bean(initMethod = "init")
    public RPCThriftClient rpcThriftClient(){
        RPCThriftClient rpcThriftClient = new RPCThriftClient();
        rpcThriftClient.setHost(host);
        rpcThriftClient.setPort(port);
        return rpcThriftClient;
    }
}

編寫controller作爲調用入口

創建RPCThriftContoller.java
內容如下:

package com.wl.thrift_client_demo.controller;

import com.wl.thrift_client_demo.client.RPCThriftClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/index")
public class RPCThriftContoller {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private RPCThriftClient rpcThriftClient;

    @RequestMapping(value = "/thrift",method = RequestMethod.GET)
    public String thriftTest(HttpServletRequest request, HttpServletResponse response){
        try {
            rpcThriftClient.open();
            return rpcThriftClient.getRPCThriftService().getDate("XX");
        }catch (Exception e){
            logger.error("RPC調用失敗",e);
            return "error";
        }finally {
            rpcThriftClient.close();
        }
    }
}

修改SpringBootApplication啓動類

package com.wl.thrift_client_demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ThriftClientDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ThriftClientDemoApplication.class, args);
    }

}

修改配置文件application.properties

thrift.host=localhost
thrift.port=6666
server.port=9999

啓動Thrift客戶端

啓動結果如下:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.1.RELEASE)

2019-11-21 23:51:42.556  INFO 107628 --- [  restartedMain] c.w.t.ThriftClientDemoApplication        : Starting ThriftClientDemoApplication on D-NJ0202188 with PID 107628 (C:\Users\lei.wang\IdeaProjects\thrift_client_demo\target\classes started by lei.wang in C:\Users\lei.wang\IdeaProjects\thrift_client_demo)
2019-11-21 23:51:42.566  INFO 107628 --- [  restartedMain] c.w.t.ThriftClientDemoApplication        : No active profile set, falling back to default profiles: default
2019-11-21 23:51:42.686  INFO 107628 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2019-11-21 23:51:42.687  INFO 107628 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2019-11-21 23:51:44.197  INFO 107628 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9999 (http)
2019-11-21 23:51:44.210  INFO 107628 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-11-21 23:51:44.211  INFO 107628 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.27]
2019-11-21 23:51:44.336  INFO 107628 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-11-21 23:51:44.336  INFO 107628 --- [  restartedMain] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1649 ms
2019-11-21 23:51:44.611  INFO 107628 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-11-21 23:51:44.791  INFO 107628 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2019-11-21 23:51:44.854  INFO 107628 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9999 (http) with context path ''
2019-11-21 23:51:44.858  INFO 107628 --- [  restartedMain] c.w.t.ThriftClientDemoApplication        : Started ThriftClientDemoApplication in 3.013 seconds (JVM running for 5.185)

Thrift通信測試

在瀏覽器輸入url:http://localhost:9999/index/thrift

頁面打印如下結果:
HelloXX 今天是2019年11月21日 星期四 23點53分

參考:

  • https://juejin.im/post/5afa19bf51882542653995b7#heading-6
  • https://blog.csdn.net/u010900754/article/details/80172671
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章