-

- Service 组件介绍

+

Service 组件介绍

-

敬请期待……
+

       Service 是RedKale最核心的组件,依赖于Convert、SNCP协议、Resource依赖注入。Service主要处理业务逻辑和操作数据层,是微服务架构中的单一原子服务。每一个Service实例分两种模式: 本地模式远程模式。其模式由 conf/application.xml 文件来配置。调用者其实不需要区分当前Service实例是哪种模式。
+        为了能确保本地模式与远程模式自由切换,对Service的实现类有一定的约束:
+              1. Service实现类会被继承,不能修饰为 final
+              2. public String name()方法会被重载,不能修饰为 final
+              3. 带@MultiRun注解的方法会被重载,不能修饰为 final
+        RedKale进程启动时扫描可加载的Service实现类,根据配置文件配置的模式采用JDK 8内置的ASM技术动态生成相应的Service临时类进行实例化,并注册到ResourceFactory同其他Service、Servlet依赖注入。

+

Service 本地模式

+

      以一个简单的UserService类范例来说明动态生成的两种模式临时类。UserService提供查询用户、注册、登陆、修改用户名功能:

+ +
public class UserService implements Service {
+
+    private final Map<Integer, UserInfo> users = new ConcurrentHashMap<>();
+
+    public final String testLocalNodeName() {
+        return "本地节点名";
+    }
+
+    public UserInfo findUserInfo(int userid) {
+        return users.get(userid);
+    }
+
+    public RetResult<UserInfo> login(LoginBean bean) {
+        // 登陆逻辑
+        return new RetResult<>(100);
+    }
+
+    @MultiRun
+    public void register(UserInfo user) {
+        this.users.put(user.getUserid(), user);
+    }
+
+    @MultiRun(diffrun = false)
+    public UserInfo updateUsername(int userid, String username) {
+        UserInfo user = this.users.get(userid);
+        if (user != null) user.setUsername(username);
+        return user;
+    }
+}
+                
+ +

      动态生成的本地模式UserService:

+
@SncpDyn(remote = false)
+public final class _DynLocalUserService extends UserService {
+
+    @Resource
+    private BsonConvert _convert;
+
+    private Transport[] _sameGroupTransports;
+
+    private Transport[] _diffGroupTransports;
+
+    private SncpClient _client;
+
+    private String _selfstring;
+
+    @Override
+    public final String name() {
+        return "";
+    }
+
+    @Override
+    public String toString() {
+        return _selfstring == null ? super.toString() : _selfstring;
+    }
+
+    @Override
+    public void register(UserInfo user) {
+        _register(true, true, true, user);
+    }
+
+    @SncpDyn(remote = false, index = 0)
+    public void _register(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, UserInfo user) {
+        if (selfrunnable) super.register(user);
+        if (_client == null) return;
+        if (samerunnable) _client.remote(_convert, _sameGroupTransports, 0, true, false, false, user);
+        if (diffrunnable) _client.remote(_convert, _diffGroupTransports, 0, true, true, false, user);
+    }
+
+    @Override
+    public UserInfo updateUsername(int userid, String username) {
+        return _updateUsername(true, true, false, userid, username);
+    }
+
+    @SncpDyn(remote = false, index = 1)
+    public UserInfo _updateUsername(boolean selfrunnable, boolean samerunnable, boolean diffrunnable, int userid, String username) {
+        UserInfo rs = super.updateUsername(userid, username);
+        if (_client == null) return null;
+        if (samerunnable) _client.remote(_convert, _sameGroupTransports, 1, true, false, false, userid, username);
+        if (diffrunnable) _client.remote(_convert, _diffGroupTransports, 1, true, true, false, userid, username);
+        return rs;
+    }
+}
+                
+

      由以上等价的代码可见,本地模式Service会重载被@MultiRun注解的方法。@MultiRun有以下几个参数:

+
public @interface MultiRun {
+
+    boolean selfrun() default true; //当前本地实例是否运行指定操作;只有当指定操作的方法的返回值为void时,该值才能为true,否则忽略。
+
+    boolean samerun() default true;  //是否同组节点运行指定操作
+
+    boolean diffrun() default true; //是否不同组节点运行指定操作
+
+    boolean async() default true; //分布式运行是否采用异步模式
+} 
+

      在动态生成的远程模式UserService时会根据不同参数生成相应的方法。若一个Service类没有含@MultiRun注解的方法,那么动态类只会重载public String name()和toString方法。当UserService服务仅需要部署了一个进程,由于没有其他等同服务的进程因此在UserService实例化时_client会赋值为null。

+ +

Service 远程模式

+

      动态生成的远程模式UserService:

+
@SncpDyn(remote = true)
+public final class _DynRemoteUserService extends UserService {
+
+    @Resource
+    private BsonConvert _convert;
+
+    private Transport _transport;
+
+    private SncpClient _client;
+
+    private String _selfstring;
+
+    @Override
+    public final String name() {
+        return "";
+    }
+
+    @Override
+    public String toString() {
+        return _selfstring == null ? super.toString() : _selfstring;
+    }
+
+    @Override
+    public UserInfo findUserInfo(int userid) {
+        return _client.remote(_convert, _transport, 0, userid);
+    }
+
+    @Override
+    public RetResult<UserInfo> login(LoginBean bean) {
+        return _client.remote(_convert, _transport, 1, bean);
+    }
+
+    @Override
+    public void register(UserInfo user) {
+        _client.remote(_convert, _transport, 2, user);
+    }
+
+    @Override
+    public UserInfo updateUsername(int userid, String username) {
+        return _client.remote(_convert, _transport, 3, userid, username);
+    }
+}
+                
+