View on GitHub

spring-up

Spring Up和Zero的桥接器:http://www.spring-up.cn

SP0003 - 服务通信之Rpc

spring-up中的服务通信使用了gRpc,为了方便开发人员开发服务间的通信,简化了底层的通信细节,本教程讲解在spring-up中如何开发服务通信部分的内容。spring-up中使用的grpc的spring boot的starter信息(由于spring-up中已经引入了,所以不需要再额外修改项目中的pom.xml):

<dependency>
    <groupId>net.devh</groupId>    
    <artifactId>grpc-client-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>net.devh</groupId>
    <artifactId>grpc-server-spring-boot-starter</artifactId>
</dependency>

0.配置

在书写Rpc的相关信息之前,需要先修改当前项目的配置信息,实例如下:application.yml中:

grpc:
    server:
        port: 8801
    client:
        mbuaa:
            port[0]: 8801
        mbenv:
            port[0]: 8802
        mborg:
            port[0]: 8803

1.服务端

spring-up中开发grpc服务端很简单,一旦配置了端口过后,则可以直接写下边代码来发布服务:

package com.mbcloud.platform.ipc;

import io.spring.up.annotations.Ipc;
import io.vertx.core.json.JsonObject;
import org.springframework.stereotype.Component;

@Component
public class TestJet {

    @Ipc("IPC://TEST/CREATE")
    public JsonObject createTodo(final JsonObject envelop) {

        return new JsonObject();
    }
}

下边是一个完整的例子:(服务名称:mbenv

package com.mbcloud.platform.ipc;

import com.mbcloud.platform.domain.Menu;
import com.mbcloud.platform.domain.Todo;
import com.mbcloud.platform.domain.enumeration.TodoStatus;
import com.mbcloud.platform.service.MenuService;
import com.mbcloud.platform.service.TodoService;
import io.spring.up.annotations.Ipc;
import io.vertx.core.json.JsonObject;
import io.zero.epic.Ut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class TodoJet {
    private static final Logger log = LoggerFactory.getLogger(TodoJet.class);
    private final TodoService service;
    private final MenuService menuService;

    public TodoJet(final TodoService service, final MenuService menuService) {
        this.service = service;
        this.menuService = menuService;
    }

    @Ipc("IPC://TODO/CREATE")
    public JsonObject createTodo(final JsonObject envelop) {
        final Todo todo = Ut.deserialize(envelop, Todo.class);
        todo.setEtat(TodoStatus.PENDING);
        todo.setId(UUID.randomUUID().toString());
        // 读取Todo关联菜单
        final Menu menu = this.menuService.findByUri(Ut.netUri(todo.getUrl()));
        todo.setMenuId(null == menu ? null : menu.getId());
        return Ut.serializeJson(this.service.save(todo));
    }
}

2.客户端

上边开放了mbenv服务中的内容,那么接下来在mborg服务中调用该服务,调用的部分代码如下(只有关键部分):

// ....省略其他import
import io.grpc.Channel;
import io.reactivex.Single;
import io.spring.up.aiki.Ux;
import io.spring.up.annotations.JsonEntity;
import io.spring.up.model.Envelop;
import io.vertx.core.json.JsonObject;
import lombok.extern.slf4j.Slf4j;
import net.devh.springboot.autoconfigure.grpc.client.GrpcClient;

@RestController
@RequestMapping("/")
@Slf4j
public class RegistryResource {
    private final EnterpriseService enterpriseService;

    @GrpcClient("mbenv")
    private Channel channel;

    @PostMapping("/enterprise/registry")
    @Timed
    public Single<ResponseEntity<Enterprise>> createEnterprise(
        // 使用这个注解的前提是不使用@Valid和@RequestBody
        @JsonEntity("enterprise.registry") final Enterprise enterprise) {
        log.debug("REST request to save Enterprise : {}", enterprise);
        // 设置企业租户ID
        enterprise.setTenantId(UUID.randomUUID().toString());
        return Single.fromFuture(this.enterpriseService.save(enterprise))
            .map(item -> Ux.Rpc.getClient(this.channel).rxFlow("IPC://TODO/CREATE", this.toEnvelop(item)))
            .map(async -> ResponseEntity.ok(enterprise));
    }

    private Envelop toEnvelop(final Enterprise enterprise) {
        final JsonObject request = new JsonObject();
        request.put("createdBy", enterprise.getCreatedBy());
        request.put("createdDate", enterprise.getCreatedDate());
        request.put("tenantId", enterprise.getTenantId());
        // 构造Todo,type = ENTERPRISE-APPROVAL:审批企业专用ToDo模板
        final TodoDefine define = TodoDefine.get("ENTERPRISE-APPROVAL");
        final JsonObject params = new JsonObject();
        params.put("id", enterprise.getId());
        params.put("name", enterprise.getCnName());
        request.mergeIn(define.toData(params));
        return Envelop.success(request);
    }
}

3. 启动日志

服务端启动时应该可以看到如下日志,证明该地址上的RPC服务启动正常了: