跨语言RPC框架Focus发布V1.1.0

原创
2023/11/04 13:26
阅读数 63

2023-11-03 Focus 发布了 V1.1.0。

改进的特性:

  1. InvokeException异常细分了ServiceException、BusinessException,有助于编程区分。
  2. 将服务注册和服务发现能力统一到了ServiceLocater和ServiceResolver,方便服务治理平台的集成。
  3. FocusClient和FocusServer实现AutoCloseable接口,增强了IDE提示,方便资源管理。

简介

Focus 是下一代跨语言、轻量级RPC框架。旨在帮助程序员快速的开发微服务应用程序,简化多运行环境下的RPC编程,可以很轻松的实现云端编程和移动端编程。

通常,评价一个 RPC 框架是否优秀、高效能,有 3 个基本标准:

  • 简单易用,无侵入:不需要过多的研究使用文档,查看快速开始或 API 就能快速用起来,框架代码无需侵入业务代码就能完成调用。

  • 抽象适度,可扩展:框架分层耦合合理、模块职责内聚、实现简洁易懂,能覆盖绝大多数场景,对特殊场景可通过设置或扩展来满足需求。

  • 性能优越,可演进:“高性能”永远是一个绕不开的关注点,框架的实现也是编码能力的体现,保持 API 不变,但实现可持续迭代改进。

Focus 框架在高效能方面做了很多的努力,坚持最小侵入性,坚持面向对象的SOLID原则,追求极简协议和代码简洁。希望使用和学习RPC框架的的同学有所收获!

特性

  • 跨语言支持。同时支持多种串行化协议:Jackson和Protobuff。
  • 模块化API。模块化的客户端和服务端API,可扩展的系统架构核心小于1 MB。
  • 分层架构。合理严谨的分层(包括API层、代理层、调用层、协议层、传输层)使得依赖最小化、可控,适用于更多运行环境。
  • 可插拔的服务发现机制。支持 Consul,Nacos,Polaris等参见注册中心。
  • 可插拔的调用拦截机制。可实现Logging、Tracing、Metrics、限流、熔断等服务安全、可观测性、服务治理功能。
  • 支持同步调用、异步调用、泛化调用。满足各种场景下的不同诉求。
  • 高效的自定义协议。二进制消息交换协议PhotonFocus的RPC协议。
  • 不同级别的服务控制。全局级别、服务级别的序列化、压缩、超时、重试设置,方法级别的超时、重试设置。
  • Spring boot 集成支持友好。简化Spring应用的集成、开发难度。

快速开始

快速开始给出一个基础的例子,大家感受一下,同一台机器上的客户端和服务端的RPC编程是多么的简单。更多的例子可以参考例子工程 focus-examples

运行快速启动的最低要求是:

  • JDK 1.8 及以上
  • Maven 或 Gradle 工程管理工具

同步调用

1.创建maven工程 focus-quickstart 并添加依赖到pom文件。

<dependency>
    <groupId>com.dinstone.focus</groupId>
    <artifactId>focus-server-photon</artifactId>
    <version>1.1.0</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.dinstone.focus</groupId>
    <artifactId>focus-client-photon</artifactId>
    <version>1.1.0</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.dinstone.focus</groupId>
    <artifactId>focus-serialize-json</artifactId>
    <version>1.1.0</version>
</dependency>

2.创建 FooService 接口类。

package focus.quickstart;

public interface FooService {

    public String hello(String name);

    public CompletableFuture<String> async(String name);
}

3.创建 FooService 实现。

package focus.quickstart.server;

import focus.quickstart.FooService;

public class FooServiceImpl implements FooService {

    public String hello(String name) {
        return "hello " + name;
    }

    public CompletableFuture<String> async(String name) {
        return CompletableFuture.completedFuture("async hello " + name);
    }
}

4.创建 Focus server 并导出服务。

package focus.quickstart.server;

import java.io.IOException;

import com.dinstone.focus.server.FocusServer;
import com.dinstone.focus.server.ServerOptions;
import com.dinstone.loghub.Logger;
import com.dinstone.loghub.LoggerFactory;

import focus.quickstart.FooService;

public class FocusServerBootstrap {

    private static final Logger LOG = LoggerFactory.getLogger(FocusServerBootstrap.class);

    public static void main(String[] args) {
		ServerOptions serverOptions = new ServerOptions("focus.quickstart.server").listen("localhost", 3333);
		FocusServer server = new FocusServer(serverOptions);

		// exporting service
		server.exporting(FooService.class, new FooServiceImpl());

		server.start();
		LOG.info("server start");
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
		server.close();
		LOG.info("server stop");
    }

}

5.创建 Focus client 导入 FooService 并进行RPC调用。

package focus.quickstart.client;

import com.dinstone.focus.client.ClientOptions;
import com.dinstone.focus.client.FocusClient;

import focus.quickstart.FooService;

public class FocusClientBootstrap {

	public static void main(String[] args) throws Exception {
		ClientOptions option = new ClientOptions("focus.quickstart.client").connect("localhost", 3333);
		FocusClient client = new FocusClient(option);
		try {
			FooService fooService = client.importing(FooService.class);
			String reply = fooService.hello("dinstone");
			System.out.println(reply);

			CompletableFuture<String> rf = fooService.async("dinstone");
			System.out.println(rf.get());
		} finally {
			client.close();
		}
	}
}

异步调用

1.另外一个种异步调用RPC的方法,创建异步调用服务接口 FooAsyncService。

package focus.quickstart.client;

import java.util.concurrent.CompletableFuture;

public interface FooAsyncService {
    public CompletableFuture<String> hello(String name);
}

2.创建 Focus client 导入 FooAsyncService 并进行异步RPC调用。

package focus.quickstart.client;

import java.util.concurrent.CompletableFuture;

import com.dinstone.focus.client.ClientOptions;
import com.dinstone.focus.client.FocusClient;
import com.dinstone.focus.client.ImportOptions;

public class FocusClientAsyncCallBootstrap {

	public static void main(String[] args) throws Exception {
		ClientOptions option = new ClientOptions("focus.quickstart.client").connect("localhost", 3333);
		FocusClient client = new FocusClient(option);
		try {
			ImportOptions importOptions = new ImportOptions("focus.quickstart.api.FooService");
			FooAsyncService fooService = client.importing(FooAsyncService.class, importOptions);
			CompletableFuture<String> replyFuture = fooService.hello("dinstone");
			System.out.println(replyFuture.get());
		} finally {
			client.close();
		}
	}

}

泛化调用

1.泛化调用不需要创建客户端接口类。简单了不是吗?!

2.创建 Focus client 导入 GenericService 并进行 同步/异步 RPC调用。

package focus.quickstart.client;

import java.util.concurrent.CompletableFuture;

import com.dinstone.focus.client.ClientOptions;
import com.dinstone.focus.client.FocusClient;
import com.dinstone.focus.client.GenericService;

public class FocusClientGenericCallBootstrap {

	public static void main(String[] args) throws Exception {
		ClientOptions option = new ClientOptions("focus.quickstart.client").connect("localhost", 3333);
		FocusClient client = new FocusClient(option);
		try {
			GenericService genericService = client.generic("focus.quickstart.server",
					"focus.quickstart.api.FooService");

			String reply = genericService.sync(String.class, "hello", "dinstone");
			System.out.println("sync call reply : " + reply);

			CompletableFuture<String> replyFuture = genericService.async(String.class, "hello", "dinstone");
			System.out.println("async call reply : " + replyFuture.get());
		} finally {
			client.close();
		}
	}

}

安全调用

1.设置服务端参数,在接受选项中启用SSL并设置证书信息。

package focus.quickstart.ssl;

import java.io.IOException;
import java.security.cert.X509Certificate;

import com.dinstone.focus.server.FocusServer;
import com.dinstone.focus.server.ServerOptions;
import com.dinstone.focus.transport.photon.PhotonAcceptOptions;

import focus.quickstart.api.FooService;
import focus.quickstart.service.FooServiceImpl;
import io.netty.handler.ssl.util.SelfSignedCertificate;

public class SslFocusServerBootstrap {

	public static void main(String[] args) throws Exception {

		// setting ssl
		SelfSignedCertificate cert = new SelfSignedCertificate();
		PhotonAcceptOptions acceptOptions = new PhotonAcceptOptions();
		acceptOptions.setEnableSsl(true);
		acceptOptions.setPrivateKey(cert.key());
		acceptOptions.setCertChain(new X509Certificate[] { cert.cert() });

		// setting accept options
		ServerOptions serverOptions = new ServerOptions("focus.quickstart.server").listen("localhost", 3333)
				.setAcceptOptions(acceptOptions);

		FocusServer server = new FocusServer(serverOptions);

		// exporting service
		server.exporting(FooService.class, new FooServiceImpl());

		server.start();
		try {
			System.in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
		server.close();
	}
}

2.设置客户端参数,在连接选项中启用SSL。

package focus.quickstart.ssl;

import java.util.concurrent.CompletableFuture;

import com.dinstone.focus.client.ClientOptions;
import com.dinstone.focus.client.FocusClient;
import com.dinstone.focus.transport.photon.PhotonConnectOptions;

import focus.quickstart.api.FooService;

public class SslFocusClientBootstrap {

	public static void main(String[] args) throws Exception {
		PhotonConnectOptions connectOptions = new PhotonConnectOptions();
		// setting ssl
		connectOptions.setEnableSsl(true);
		ClientOptions clientOptions = new ClientOptions("focus.quickstart.client").connect("localhost", 3333)
				.setConnectOptions(connectOptions);
		FocusClient client = new FocusClient(clientOptions);
		try {
			FooService fooService = client.importing(FooService.class);
			String reply = fooService.hello("dinstone");
			System.out.println(reply);

			CompletableFuture<String> rf = fooService.async("dinstone");
			System.out.println(rf.get());
		} finally {
			client.close();
		}
	}

}
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部