The introduction

When the back-end Java service uses Dubbo protocol as the basis of RPC scheme, but some consumers are front-end Restful PHP services, which cannot be called directly, so the Router service is set up in the middle to provide a unified http-based back-end call entrance. The Router calls the back-end Java service using Dubbo’s advanced feature, the generalization call

  • The direct consumer (Router service) does not need to import the interface JAR package
  • All service requests are handled through the GenericService interface
  • The method name and method parameters in the REQUEST body from PHP to Router are taken as the input parameters of the Router’s remote call to the back-end Java service. Finally, the result of the remote call is returned to PHP

This article uses a small Demo to demonstrate the generalization call application scenario described above

Zero. Dubbo profile

DUBBO is a distributed service framework that is committed to providing high-performance and transparent RPC remote service invocation solutions. It is the core framework of Alibaba’s SOA service governance solutions, supporting more than 3,000,000,000+ page views for more than 2,000 services per day, and is widely used in alibaba group’s member sites. – Dubbo official description

What Dubbo does:

  • Transparent remote method calls
    • Call a remote method as if it were a local method
    • Simple configuration, no API intrusion.
  • Soft load balancing and fault tolerance
    • It can replace hardware load balancers such as F5 on the Intranet
  • Automatic service registration and discovery
    • Instead of writing out the service provider address, the registry queries the IP address of the service provider based on the interface name and can smoothly add or remove service providers

— Dubbo Features (official profile)

Note: The basic usage of Dubbo is beyond the scope of this article, please refer to it yourself if necessaryOfficial data

The generic interface invocation method is mainly used when the client does not have API interfaces and model class elements. All POJOs in parameters and return values are represented by Map. It is usually used for framework integration, for example, to achieve a universal service testing framework that can invoke all service implementations through GenericService. – Dubbo User Guide

One. Back-end apis

public interface UserInfoService {
    public Map<String, String> getUser(String id);
    public Map<String, String>[] getUsers();
}
Copy the code

Configure duBBO on the Router

dubboconf.properties:

application.name=router
registry.address=zookeeper://address1?buckup=address2,address3
Copy the code

Example of a Request Body posted by the front-end service to the Router:

{
    "interfaceName": "foo", 
    "methodName": "bar", 
    "methodParams": [
        {
            "id": "xxx"
        }
    ]
}
Copy the code

Dtos for processing front-end parameters

RequestDto.java:

import java.util.Map; /** * Created by Luo */ public class RequestDto { private String interfaceName; private String methodName private Map[] methodParams; public String getInterfaceName() { return interfaceName; } public void setInterfaceName(String interfaceName) { this.interfaceName = interfaceName; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Map[] getMethodParams() { return methodParams; } public void setMethodParam(Map[] methodParams) { this.methodParams = methodParams; }}Copy the code

V. Router Service entry

RouterController.java:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by Luo */ @RestController public class App { @RequestMapping(value = "/router/", method = RequestMethod.POST) public Object getUser(@ModelAttribute RequestDto dto) { Map map = new HashMap<>(); map.put("ParamType", "java.lang.String"); Map.put ("Object", To.getMethodParams ()[0].get("id")); // The argument used to call the back-end interface List<Map<String, Object>> paramInfos= new ArrayList<>(); paramInfos.add(map); DubboServiceFactory dubbo = DubboServiceFactory.getInstance(); return dubbo.genericInvoke(dto.getInterfaceName(), dto.getMethodName(), paramInfos); }}Copy the code

Note: this article is intended to demonstrate an application of the generalized call, for the sake of simplicity, the code directly from the DTO obtain the specified parameters, and did not complete the implementation of its routing function, please forgive me.

Make a generalization call through GenericService

DubboServiceFactory.java

package local.demo.genericservice; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ReferenceConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.utils.ReferenceConfigCache; import com.alibaba.dubbo.rpc.service.GenericService; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Properties; /** * Created by Luo */ public class DubboServiceFactory { private ApplicationConfig application; private RegistryConfig registry; private static class SingletonHolder { private static DubboServiceFactory INSTANCE = new DubboServiceFactory(); } private DubboServiceFactory(){ Properties prop = new Properties(); ClassLoader loader = DubboServiceFactory.class.getClassLoader(); try { prop.load(loader.getResourceAsStream("dubboconf.properties")); } catch (IOException e) { e.printStackTrace(); } ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName(prop.getProperty("application.name")); // Dubbo application information is configured *(demo only name is configured)*, Therefore demo has no additional dubo.xml configuration file RegistryConfig RegistryConfig = new RegistryConfig(); registryConfig.setAddress(prop.getProperty("registry.address")); // Dubbo registry information is configured here, so demo has no additional dubbo. this.registry = registryConfig; } public static DubboServiceFactory getInstance() { return SingletonHolder.INSTANCE; } public Object genericInvoke(String interfaceClass, String methodName, List<Map<String, Object>> parameters){ ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); reference.setApplication(application); reference.setRegistry(registry); reference.setInterface(interfaceClass); // Interface name reference.setgeneric (true); //ReferenceConfig instances are heavy, encapsulating connections to the registry as well as to the provider, // Caching is required, otherwise repeated generation of ReferenceConfig may cause performance problems and memory and connection leaks. // It is easy to ignore this problem when programming in API mode. / / used here dubbo built-in simple cache utility class cache ReferenceConfigCache cache = ReferenceConfigCache. GetCache (); GenericService genericService = cache.get(reference); . / / com. Alibaba. Dubbo. RPC service. The interface GenericService can replace all references to int len = parameters. The size (); String[] invokeParamTyeps = new String[len]; Object[] invokeParams = new Object[len]; for(int i = 0; i < len; i++){ invokeParamTyeps[i] = parameters.get(i).get("ParamType") + ""; invokeParams[i] = parameters.get(i).get("Object"); } return genericService.$invoke(methodName, invokeParamTyeps, invokeParams); }}Copy the code

Deployment of seven.

The Router can be deployed to a container such as Jetty/Tomcat, or developed directly using SpringBoot and published as a separate JAR package embedded with Jetty/Tomcat to provide services to the front-end services.