×
Community Blog Deploy Microservices with Function Compute: Visitor Card of Cloud Customer Service

Deploy Microservices with Function Compute: Visitor Card of Cloud Customer Service

This article shows you how you can deploy microservices on Alibaba Cloud with Function Compute by using Cloud Customer Service as an example.

By Du Wan

Alibaba Cloud Function Compute is a fully hosted and serverless running environment that takes away the need to manage infrastructure and enables businesses to focus on software development. You can deploy microservices on Alibaba Cloud with Function Compute; in this article, we will be doing this with the Cloud Customer Service product as an example.

Note: At the time of writing, Cloud Customer Service is only available for Mainland China Alibaba Cloud accounts.

Alibaba Cloud's Cloud Customer Service is a complete intelligent service system that can be easily integrated into websites, applications, public accounts, and other systems. Cloud Customer Service provides complete hotline and online service functions for users to easily access other systems such as CRM. It dynamically manages the centralized knowledge bases and knowledge documents used by customers and agents. Based on Alibaba Cloud's intelligent algorithms, chatbots can accurately understand your intention and answer any questions. In addition, it collects and analyzes the data in the customer service center in real time, helping enterprise decision-makers understand the most common issues and service bottlenecks from a global perspective.

As a function of Cloud Customer Service, Visitor Card associates the users of Cloud Customer Service with those in the CRM system to help the customer service personnel understand the customers' basic information for better support.

The Visitor Card Integration Guide provided by Cloud Customer Service is a web project implemented based on Spring MVC. For users who use Node.js, they can migrate from Java to Function Compute and provide function as a service for core business calls implemented with Node.js.

Challenges

Users have tried to migrate Java by themselves but encountered the following technical challenges:

  • JAR provided by Cloud Customer Service is a private Maven warehouse and cannot be accessed by the external network. Therefore, JAR must be copied to Maven for integration.
  • How should the Maven plug-in be properly configured to generate a JAR package that is supported by Function Compute?

Dependencies on Local JAR Packages

fccsplatform-common-crypto-1.0.0.20161108.jar is a package in the Maven warehouse in Alibaba Cloud's internal network. It is only available to external network customers through Cloud Customer Service. The following XML fragment is a common way in which Maven depends on local JAR packages. Because this is not a typical scenario, additional information is required to complete it.

<dependency>
    <groupId>com.alipay.fc.csplatform</groupId>
    <artifactId>fccsplatform-common-crypto</artifactId>
    <version>1.0.0.20161108</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/fccsplatform-common-crypto-1.0.0.20161108.jar</systemPath>
</dependency>

<scope>system</scope> indicates that the JAR package is searched from the system path rather than the warehouse. This command must be used with <systemPath/> . <systemPath/> indicates the actual path of a JAR package. This command is normally used with ${project.basedir} (namely, it is relative to the project directory).

Encapsulate the Handler function

Spring MVC exposes a service as a Controller. For Function Compute, only a Handler API is required.

/**
 * This is the interface for any none event based function handler
 */
public interface StreamRequestHandler {

    /**
     * The interface to handle a function compute invoke request
     *
     * @param input The function compute input data wrapped in a stream
     * @param output The function compute output data wrapped in a stream
     * @param context The function compute execution environment context object.
     * @throws IOException IOException during I/O handling
     */
    void handleRequest(InputStream input, OutputStream output, Context context) throws IOException;
}

Visitor Card services are simple, and only require an encryption API and a decoding API without calling any third-party services.

public class Encryptor implements StreamRequestHandler {

    private CustomerInfo customerInfo = new CustomerInfo();

    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        String cInfo = CharStreams.toString(new InputStreamReader(
                input, Charset.defaultCharset()));
        try {
            output.write(customerInfo.encrypt(cInfo).getBytes(Charset.defaultCharset()));
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
    }
}
public class Decryptor implements StreamRequestHandler {

    private CustomerInfo customerInfo = new CustomerInfo();

    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        String jsonString = CharStreams.toString(new InputStreamReader(
                input, Charset.defaultCharset()));

        JSONObject jsonObject = JSON.parseObject(jsonString);
        try {
            String cInfo = customerInfo.decrypt(jsonObject.getString("params"), jsonObject.getString("key"));
            output.write(cInfo.getBytes(Charset.defaultCharset()));

        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }

    }
}

The preceding Encryptor.java and decryptor.java implement the StreamRequestHandler API, while the CustomerInfo.java class encapsulates the service logic.

public class CustomerInfo {

    # Retrieve PUB_KEY from Cloud Customer Service
    private static String PUB_KEY = "your PUB_KEY";


    public String encrypt(String cInfo) throws GeneralSecurityException, UnsupportedEncodingException {
        PublicKey publicKey = getPubKey(PUB_KEY);
        Map<String, String> res = CustomerInfoCryptoUtil.encryptByPublicKey(cInfo, publicKey);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("cinfo", res.get("text"));
        jsonObject.put("key", res.get("key"));

        return jsonObject.toJSONString();
    }

    public String decrypt(String params, String key) throws UnsupportedEncodingException, GeneralSecurityException {
        PublicKey publicKey = getPubKey(PUB_KEY);
        return CustomerInfoCryptoUtil.decryptByPublicKey(params, key, publicKey);
    }

    private PublicKey getPubKey(String pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(pubKey));
        KeyFactory keyFactory;
        keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        return key;
    }

Package

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
                <includeScope>compile</includeScope>
            </configuration>
        </execution>
    </executions>
</plugin>

The official Function Compute documentation recommends two packaging methods, namely, maven-assembly-plugin and maven-dependency-plugin.

  • The maven-assembly-plugin method extracts all dependent class files and repackages them into a smaller JAR package. However, this may introduce several problems.
  • The maven-dependency-plugin method packages all dependent JAR packages to the internal lib/ directory and then packages them as nested JAR packages. During runtime, Function Compute decompresses the top-layer JAR packages.

In this example, maven-assembly-plugin is not feasible because it cannot package the transitive dependency specified by systemPath, resulting in missing classes during the runtime. Therefore, the maven-dependency-plugin method is used instead.

Deploy Fun

Configure the template.yml file on Fun for description, and then run mvn package && fun deploy.

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  YunkefuSign:
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'yun ke fu Sign'
    Encryptor:
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: com.aliyun.fc.Encryptor::handleRequest
        Runtime: java8
        CodeUri: './target/yunkefu-sign-1.0-SNAPSHOT.jar'
        Timeout: 60
    Decryptor:
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: com.aliyun.fc.Decryptor::handleRequest
        Runtime: java8
        CodeUri: './target/yunkefu-sign-1.0-SNAPSHOT.jar'
        Timeout: 60

Conclusion

Using a language as a service boundary is one of the most common ways to define the boundaries for a service architecture. Function Compute supports multi-language environments and provides high scalability and availability, making it an ideal solution for supporting the multi-language architecture as a service.

Normally, developers have accumulated rich experience in familiar languages and have established a complete architecture and deployment O&M system. However, to expand the business boundary, they sometimes have to select an unfamiliar programming language and architecture. To address this challenge, Function Compute uses a single simple language to develop businesses, resolving your concerns about architecture and O&M and mitigating the developers' workload.

0 0 0
Share on

Alibaba Cloud Serverless

99 posts | 7 followers

You may also like

Comments

Alibaba Cloud Serverless

99 posts | 7 followers

Related Products

  • Function Compute

    Alibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.

    Learn More
  • API Gateway

    API Gateway provides you with high-performance and high-availability API hosting services to deploy and release your APIs on Alibaba Cloud products.

    Learn More
  • Microservices Engine (MSE)

    MSE provides a fully managed registration and configuration center, and gateway and microservices governance capabilities.

    Learn More
  • Serverless Workflow

    Visualization, O&M-free orchestration, and Coordination of Stateful Application Scenarios

    Learn More